mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-03-26 22:49:01 +08:00
[libgdx] Added IkConstraintPose and data classes use a setup pose field.
This commit is contained in:
parent
cab5944663
commit
08af7407b3
@ -563,7 +563,7 @@ public class Animation {
|
|||||||
Bone bone = skeleton.bones.get(boneIndex);
|
Bone bone = skeleton.bones.get(boneIndex);
|
||||||
if (bone.active) {
|
if (bone.active) {
|
||||||
BonePose pose = appliedPose ? bone.applied : bone.pose;
|
BonePose pose = appliedPose ? bone.applied : bone.pose;
|
||||||
pose.rotation = getRelativeValue(time, alpha, blend, pose.rotation, bone.data.rotation);
|
pose.rotation = getRelativeValue(time, alpha, blend, pose.rotation, bone.data.setup.rotation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -588,18 +588,18 @@ public class Animation {
|
|||||||
|
|
||||||
Bone bone = skeleton.bones.get(boneIndex);
|
Bone bone = skeleton.bones.get(boneIndex);
|
||||||
if (!bone.active) return;
|
if (!bone.active) return;
|
||||||
BonePose pose = appliedPose ? bone.applied : bone.pose;
|
BonePose pose = appliedPose ? bone.applied : bone.pose, setup = bone.data.setup;
|
||||||
|
|
||||||
float[] frames = this.frames;
|
float[] frames = this.frames;
|
||||||
if (time < frames[0]) {
|
if (time < frames[0]) {
|
||||||
switch (blend) {
|
switch (blend) {
|
||||||
case setup:
|
case setup:
|
||||||
pose.x = bone.data.x;
|
pose.x = setup.x;
|
||||||
pose.y = bone.data.y;
|
pose.y = setup.y;
|
||||||
return;
|
return;
|
||||||
case first:
|
case first:
|
||||||
pose.x += (bone.data.x - pose.x) * alpha;
|
pose.x += (setup.x - pose.x) * alpha;
|
||||||
pose.y += (bone.data.y - pose.y) * alpha;
|
pose.y += (setup.y - pose.y) * alpha;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -626,13 +626,13 @@ public class Animation {
|
|||||||
|
|
||||||
switch (blend) {
|
switch (blend) {
|
||||||
case setup:
|
case setup:
|
||||||
pose.x = bone.data.x + x * alpha;
|
pose.x = setup.x + x * alpha;
|
||||||
pose.y = bone.data.y + y * alpha;
|
pose.y = setup.y + y * alpha;
|
||||||
break;
|
break;
|
||||||
case first:
|
case first:
|
||||||
case replace:
|
case replace:
|
||||||
pose.x += (bone.data.x + x - pose.x) * alpha;
|
pose.x += (setup.x + x - pose.x) * alpha;
|
||||||
pose.y += (bone.data.y + y - pose.y) * alpha;
|
pose.y += (setup.y + y - pose.y) * alpha;
|
||||||
break;
|
break;
|
||||||
case add:
|
case add:
|
||||||
pose.x += x * alpha;
|
pose.x += x * alpha;
|
||||||
@ -660,7 +660,7 @@ public class Animation {
|
|||||||
Bone bone = skeleton.bones.get(boneIndex);
|
Bone bone = skeleton.bones.get(boneIndex);
|
||||||
if (bone.active) {
|
if (bone.active) {
|
||||||
BonePose pose = appliedPose ? bone.applied : bone.pose;
|
BonePose pose = appliedPose ? bone.applied : bone.pose;
|
||||||
pose.x = getRelativeValue(time, alpha, blend, pose.x, bone.data.x);
|
pose.x = getRelativeValue(time, alpha, blend, pose.x, bone.data.setup.x);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -684,7 +684,7 @@ public class Animation {
|
|||||||
Bone bone = skeleton.bones.get(boneIndex);
|
Bone bone = skeleton.bones.get(boneIndex);
|
||||||
if (bone.active) {
|
if (bone.active) {
|
||||||
BonePose pose = appliedPose ? bone.applied : bone.pose;
|
BonePose pose = appliedPose ? bone.applied : bone.pose;
|
||||||
pose.y = getRelativeValue(time, alpha, blend, pose.y, bone.data.y);
|
pose.y = getRelativeValue(time, alpha, blend, pose.y, bone.data.setup.y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -709,18 +709,18 @@ public class Animation {
|
|||||||
|
|
||||||
Bone bone = skeleton.bones.get(boneIndex);
|
Bone bone = skeleton.bones.get(boneIndex);
|
||||||
if (!bone.active) return;
|
if (!bone.active) return;
|
||||||
BonePose pose = appliedPose ? bone.applied : bone.pose;
|
BonePose pose = appliedPose ? bone.applied : bone.pose, setup = bone.data.setup;
|
||||||
|
|
||||||
float[] frames = this.frames;
|
float[] frames = this.frames;
|
||||||
if (time < frames[0]) {
|
if (time < frames[0]) {
|
||||||
switch (blend) {
|
switch (blend) {
|
||||||
case setup:
|
case setup:
|
||||||
pose.scaleX = bone.data.scaleX;
|
pose.scaleX = setup.scaleX;
|
||||||
pose.scaleY = bone.data.scaleY;
|
pose.scaleY = setup.scaleY;
|
||||||
return;
|
return;
|
||||||
case first:
|
case first:
|
||||||
pose.scaleX += (bone.data.scaleX - pose.scaleX) * alpha;
|
pose.scaleX += (setup.scaleX - pose.scaleX) * alpha;
|
||||||
pose.scaleY += (bone.data.scaleY - pose.scaleY) * alpha;
|
pose.scaleY += (setup.scaleY - pose.scaleY) * alpha;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -744,13 +744,13 @@ public class Animation {
|
|||||||
x = getBezierValue(time, i, VALUE1, curveType - BEZIER);
|
x = getBezierValue(time, i, VALUE1, curveType - BEZIER);
|
||||||
y = getBezierValue(time, i, VALUE2, curveType + BEZIER_SIZE - BEZIER);
|
y = getBezierValue(time, i, VALUE2, curveType + BEZIER_SIZE - BEZIER);
|
||||||
}
|
}
|
||||||
x *= bone.data.scaleX;
|
x *= setup.scaleX;
|
||||||
y *= bone.data.scaleY;
|
y *= setup.scaleY;
|
||||||
|
|
||||||
if (alpha == 1) {
|
if (alpha == 1) {
|
||||||
if (blend == add) {
|
if (blend == add) {
|
||||||
pose.scaleX += x - bone.data.scaleX;
|
pose.scaleX += x - setup.scaleX;
|
||||||
pose.scaleY += y - bone.data.scaleY;
|
pose.scaleY += y - setup.scaleY;
|
||||||
} else {
|
} else {
|
||||||
pose.scaleX = x;
|
pose.scaleX = x;
|
||||||
pose.scaleY = y;
|
pose.scaleY = y;
|
||||||
@ -761,8 +761,8 @@ public class Animation {
|
|||||||
if (direction == out) {
|
if (direction == out) {
|
||||||
switch (blend) {
|
switch (blend) {
|
||||||
case setup:
|
case setup:
|
||||||
bx = bone.data.scaleX;
|
bx = setup.scaleX;
|
||||||
by = bone.data.scaleY;
|
by = setup.scaleY;
|
||||||
pose.scaleX = bx + (Math.abs(x) * Math.signum(bx) - bx) * alpha;
|
pose.scaleX = bx + (Math.abs(x) * Math.signum(bx) - bx) * alpha;
|
||||||
pose.scaleY = by + (Math.abs(y) * Math.signum(by) - by) * alpha;
|
pose.scaleY = by + (Math.abs(y) * Math.signum(by) - by) * alpha;
|
||||||
break;
|
break;
|
||||||
@ -774,14 +774,14 @@ public class Animation {
|
|||||||
pose.scaleY = by + (Math.abs(y) * Math.signum(by) - by) * alpha;
|
pose.scaleY = by + (Math.abs(y) * Math.signum(by) - by) * alpha;
|
||||||
break;
|
break;
|
||||||
case add:
|
case add:
|
||||||
pose.scaleX += (x - bone.data.scaleX) * alpha;
|
pose.scaleX += (x - setup.scaleX) * alpha;
|
||||||
pose.scaleY += (y - bone.data.scaleY) * alpha;
|
pose.scaleY += (y - setup.scaleY) * alpha;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
switch (blend) {
|
switch (blend) {
|
||||||
case setup:
|
case setup:
|
||||||
bx = Math.abs(bone.data.scaleX) * Math.signum(x);
|
bx = Math.abs(setup.scaleX) * Math.signum(x);
|
||||||
by = Math.abs(bone.data.scaleY) * Math.signum(y);
|
by = Math.abs(setup.scaleY) * Math.signum(y);
|
||||||
pose.scaleX = bx + (x - bx) * alpha;
|
pose.scaleX = bx + (x - bx) * alpha;
|
||||||
pose.scaleY = by + (y - by) * alpha;
|
pose.scaleY = by + (y - by) * alpha;
|
||||||
break;
|
break;
|
||||||
@ -793,8 +793,8 @@ public class Animation {
|
|||||||
pose.scaleY = by + (y - by) * alpha;
|
pose.scaleY = by + (y - by) * alpha;
|
||||||
break;
|
break;
|
||||||
case add:
|
case add:
|
||||||
pose.scaleX += (x - bone.data.scaleX) * alpha;
|
pose.scaleX += (x - setup.scaleX) * alpha;
|
||||||
pose.scaleY += (y - bone.data.scaleY) * alpha;
|
pose.scaleY += (y - setup.scaleY) * alpha;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -820,7 +820,7 @@ public class Animation {
|
|||||||
Bone bone = skeleton.bones.get(boneIndex);
|
Bone bone = skeleton.bones.get(boneIndex);
|
||||||
if (bone.active) {
|
if (bone.active) {
|
||||||
BonePose pose = appliedPose ? bone.applied : bone.pose;
|
BonePose pose = appliedPose ? bone.applied : bone.pose;
|
||||||
pose.scaleX = getScaleValue(time, alpha, blend, direction, pose.scaleX, bone.data.scaleX);
|
pose.scaleX = getScaleValue(time, alpha, blend, direction, pose.scaleX, bone.data.setup.scaleX);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -844,7 +844,7 @@ public class Animation {
|
|||||||
Bone bone = skeleton.bones.get(boneIndex);
|
Bone bone = skeleton.bones.get(boneIndex);
|
||||||
if (bone.active) {
|
if (bone.active) {
|
||||||
BonePose pose = appliedPose ? bone.applied : bone.pose;
|
BonePose pose = appliedPose ? bone.applied : bone.pose;
|
||||||
pose.scaleY = getScaleValue(time, alpha, blend, direction, pose.scaleY, bone.data.scaleY);
|
pose.scaleY = getScaleValue(time, alpha, blend, direction, pose.scaleY, bone.data.setup.scaleY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -869,18 +869,18 @@ public class Animation {
|
|||||||
|
|
||||||
Bone bone = skeleton.bones.get(boneIndex);
|
Bone bone = skeleton.bones.get(boneIndex);
|
||||||
if (!bone.active) return;
|
if (!bone.active) return;
|
||||||
BonePose pose = appliedPose ? bone.applied : bone.pose;
|
BonePose pose = appliedPose ? bone.applied : bone.pose, setup = bone.data.setup;
|
||||||
|
|
||||||
float[] frames = this.frames;
|
float[] frames = this.frames;
|
||||||
if (time < frames[0]) {
|
if (time < frames[0]) {
|
||||||
switch (blend) {
|
switch (blend) {
|
||||||
case setup:
|
case setup:
|
||||||
pose.shearX = bone.data.shearX;
|
pose.shearX = setup.shearX;
|
||||||
pose.shearY = bone.data.shearY;
|
pose.shearY = setup.shearY;
|
||||||
return;
|
return;
|
||||||
case first:
|
case first:
|
||||||
pose.shearX += (bone.data.shearX - pose.shearX) * alpha;
|
pose.shearX += (setup.shearX - pose.shearX) * alpha;
|
||||||
pose.shearY += (bone.data.shearY - pose.shearY) * alpha;
|
pose.shearY += (setup.shearY - pose.shearY) * alpha;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -907,13 +907,13 @@ public class Animation {
|
|||||||
|
|
||||||
switch (blend) {
|
switch (blend) {
|
||||||
case setup:
|
case setup:
|
||||||
pose.shearX = bone.data.shearX + x * alpha;
|
pose.shearX = setup.shearX + x * alpha;
|
||||||
pose.shearY = bone.data.shearY + y * alpha;
|
pose.shearY = setup.shearY + y * alpha;
|
||||||
break;
|
break;
|
||||||
case first:
|
case first:
|
||||||
case replace:
|
case replace:
|
||||||
pose.shearX += (bone.data.shearX + x - pose.shearX) * alpha;
|
pose.shearX += (setup.shearX + x - pose.shearX) * alpha;
|
||||||
pose.shearY += (bone.data.shearY + y - pose.shearY) * alpha;
|
pose.shearY += (setup.shearY + y - pose.shearY) * alpha;
|
||||||
break;
|
break;
|
||||||
case add:
|
case add:
|
||||||
pose.shearX += x * alpha;
|
pose.shearX += x * alpha;
|
||||||
@ -941,7 +941,7 @@ public class Animation {
|
|||||||
Bone bone = skeleton.bones.get(boneIndex);
|
Bone bone = skeleton.bones.get(boneIndex);
|
||||||
if (bone.active) {
|
if (bone.active) {
|
||||||
BonePose pose = appliedPose ? bone.applied : bone.pose;
|
BonePose pose = appliedPose ? bone.applied : bone.pose;
|
||||||
pose.shearX = getRelativeValue(time, alpha, blend, pose.shearX, bone.data.shearX);
|
pose.shearX = getRelativeValue(time, alpha, blend, pose.shearX, bone.data.setup.shearX);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -965,7 +965,7 @@ public class Animation {
|
|||||||
Bone bone = skeleton.bones.get(boneIndex);
|
Bone bone = skeleton.bones.get(boneIndex);
|
||||||
if (bone.active) {
|
if (bone.active) {
|
||||||
BonePose pose = appliedPose ? bone.applied : bone.pose;
|
BonePose pose = appliedPose ? bone.applied : bone.pose;
|
||||||
pose.shearY = getRelativeValue(time, alpha, blend, pose.shearY, bone.data.shearY);
|
pose.shearY = getRelativeValue(time, alpha, blend, pose.shearY, bone.data.setup.shearY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1007,13 +1007,13 @@ public class Animation {
|
|||||||
BonePose pose = appliedPose ? bone.applied : bone.pose;
|
BonePose pose = appliedPose ? bone.applied : bone.pose;
|
||||||
|
|
||||||
if (direction == out) {
|
if (direction == out) {
|
||||||
if (blend == setup) pose.inherit = bone.data.inherit;
|
if (blend == setup) pose.inherit = bone.data.setup.inherit;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
float[] frames = this.frames;
|
float[] frames = this.frames;
|
||||||
if (time < frames[0]) {
|
if (time < frames[0]) {
|
||||||
if (blend == setup || blend == first) pose.inherit = bone.data.inherit;
|
if (blend == setup || blend == first) pose.inherit = bone.data.setup.inherit;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
pose.inherit = Inherit.values[(int)frames[search(frames, time, ENTRIES) + INHERIT]];
|
pose.inherit = Inherit.values[(int)frames[search(frames, time, ENTRIES) + INHERIT]];
|
||||||
@ -1064,7 +1064,7 @@ public class Animation {
|
|||||||
float[] frames = this.frames;
|
float[] frames = this.frames;
|
||||||
Color color = pose.color;
|
Color color = pose.color;
|
||||||
if (time < frames[0]) {
|
if (time < frames[0]) {
|
||||||
Color setup = slot.data.color;
|
Color setup = slot.data.setup.color;
|
||||||
switch (blend) {
|
switch (blend) {
|
||||||
case setup:
|
case setup:
|
||||||
color.set(setup);
|
color.set(setup);
|
||||||
@ -1107,7 +1107,7 @@ public class Animation {
|
|||||||
if (alpha == 1)
|
if (alpha == 1)
|
||||||
color.set(r, g, b, a);
|
color.set(r, g, b, a);
|
||||||
else {
|
else {
|
||||||
if (blend == setup) color.set(slot.data.color);
|
if (blend == setup) color.set(slot.data.setup.color);
|
||||||
color.add((r - color.r) * alpha, (g - color.g) * alpha, (b - color.b) * alpha, (a - color.a) * alpha);
|
color.add((r - color.r) * alpha, (g - color.g) * alpha, (b - color.b) * alpha, (a - color.a) * alpha);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1154,7 +1154,7 @@ public class Animation {
|
|||||||
float[] frames = this.frames;
|
float[] frames = this.frames;
|
||||||
Color color = pose.color;
|
Color color = pose.color;
|
||||||
if (time < frames[0]) {
|
if (time < frames[0]) {
|
||||||
Color setup = slot.data.color;
|
Color setup = slot.data.setup.color;
|
||||||
switch (blend) {
|
switch (blend) {
|
||||||
case setup:
|
case setup:
|
||||||
color.r = setup.r;
|
color.r = setup.r;
|
||||||
@ -1199,7 +1199,7 @@ public class Animation {
|
|||||||
color.b = b;
|
color.b = b;
|
||||||
} else {
|
} else {
|
||||||
if (blend == setup) {
|
if (blend == setup) {
|
||||||
Color setup = slot.data.color;
|
Color setup = slot.data.setup.color;
|
||||||
color.r = setup.r;
|
color.r = setup.r;
|
||||||
color.g = setup.g;
|
color.g = setup.g;
|
||||||
color.b = setup.b;
|
color.b = setup.b;
|
||||||
@ -1234,7 +1234,7 @@ public class Animation {
|
|||||||
float[] frames = this.frames;
|
float[] frames = this.frames;
|
||||||
Color color = pose.color;
|
Color color = pose.color;
|
||||||
if (time < frames[0]) {
|
if (time < frames[0]) {
|
||||||
Color setup = slot.data.color;
|
Color setup = slot.data.setup.color;
|
||||||
switch (blend) {
|
switch (blend) {
|
||||||
case setup:
|
case setup:
|
||||||
color.a = setup.a;
|
color.a = setup.a;
|
||||||
@ -1249,7 +1249,7 @@ public class Animation {
|
|||||||
if (alpha == 1)
|
if (alpha == 1)
|
||||||
color.a = a;
|
color.a = a;
|
||||||
else {
|
else {
|
||||||
if (blend == setup) color.a = slot.data.color.a;
|
if (blend == setup) color.a = slot.data.setup.color.a;
|
||||||
color.a += (a - color.a) * alpha;
|
color.a += (a - color.a) * alpha;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1305,7 +1305,8 @@ public class Animation {
|
|||||||
float[] frames = this.frames;
|
float[] frames = this.frames;
|
||||||
Color light = pose.color, dark = pose.darkColor;
|
Color light = pose.color, dark = pose.darkColor;
|
||||||
if (time < frames[0]) {
|
if (time < frames[0]) {
|
||||||
Color setupLight = slot.data.color, setupDark = slot.data.darkColor;
|
SlotPose setup = slot.data.setup;
|
||||||
|
Color setupLight = setup.color, setupDark = setup.darkColor;
|
||||||
switch (blend) {
|
switch (blend) {
|
||||||
case setup:
|
case setup:
|
||||||
light.set(setupLight);
|
light.set(setupLight);
|
||||||
@ -1370,8 +1371,9 @@ public class Animation {
|
|||||||
dark.b = b2;
|
dark.b = b2;
|
||||||
} else {
|
} else {
|
||||||
if (blend == setup) {
|
if (blend == setup) {
|
||||||
light.set(slot.data.color);
|
SlotPose setup = slot.data.setup;
|
||||||
Color setupDark = slot.data.darkColor;
|
light.set(setup.color);
|
||||||
|
Color setupDark = setup.darkColor;
|
||||||
dark.r = setupDark.r;
|
dark.r = setupDark.r;
|
||||||
dark.g = setupDark.g;
|
dark.g = setupDark.g;
|
||||||
dark.b = setupDark.b;
|
dark.b = setupDark.b;
|
||||||
@ -1432,7 +1434,8 @@ public class Animation {
|
|||||||
float[] frames = this.frames;
|
float[] frames = this.frames;
|
||||||
Color light = pose.color, dark = pose.darkColor;
|
Color light = pose.color, dark = pose.darkColor;
|
||||||
if (time < frames[0]) {
|
if (time < frames[0]) {
|
||||||
Color setupLight = slot.data.color, setupDark = slot.data.darkColor;
|
SlotPose setup = slot.data.setup;
|
||||||
|
Color setupLight = setup.color, setupDark = setup.darkColor;
|
||||||
switch (blend) {
|
switch (blend) {
|
||||||
case setup:
|
case setup:
|
||||||
light.r = setupLight.r;
|
light.r = setupLight.r;
|
||||||
@ -1498,7 +1501,8 @@ public class Animation {
|
|||||||
dark.b = b2;
|
dark.b = b2;
|
||||||
} else {
|
} else {
|
||||||
if (blend == setup) {
|
if (blend == setup) {
|
||||||
Color setupLight = slot.data.color, setupDark = slot.data.darkColor;
|
SlotPose setup = slot.data.setup;
|
||||||
|
Color setupLight = setup.color, setupDark = setup.darkColor;
|
||||||
light.r = setupLight.r;
|
light.r = setupLight.r;
|
||||||
light.g = setupLight.g;
|
light.g = setupLight.g;
|
||||||
light.b = setupLight.b;
|
light.b = setupLight.b;
|
||||||
@ -1958,8 +1962,9 @@ public class Animation {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Changes an IK constraint's {@link IkConstraint#getMix()}, {@link IkConstraint#getSoftness()},
|
/** Changes an IK constraint's {@link IkConstraintPose#getMix()}, {@link IkConstraintPose#getSoftness()},
|
||||||
* {@link IkConstraint#getBendDirection()}, {@link IkConstraint#getStretch()}, and {@link IkConstraint#getCompress()}. */
|
* {@link IkConstraintPose#getBendDirection()}, {@link IkConstraintPose#getStretch()}, and
|
||||||
|
* {@link IkConstraintPose#getCompress()}. */
|
||||||
static public class IkConstraintTimeline extends CurveTimeline {
|
static public class IkConstraintTimeline extends CurveTimeline {
|
||||||
static public final int ENTRIES = 6;
|
static public final int ENTRIES = 6;
|
||||||
static private final int MIX = 1, SOFTNESS = 2, BEND_DIRECTION = 3, COMPRESS = 4, STRETCH = 5;
|
static private final int MIX = 1, SOFTNESS = 2, BEND_DIRECTION = 3, COMPRESS = 4, STRETCH = 5;
|
||||||
@ -2001,24 +2006,24 @@ public class Animation {
|
|||||||
|
|
||||||
IkConstraint constraint = skeleton.ikConstraints.get(constraintIndex);
|
IkConstraint constraint = skeleton.ikConstraints.get(constraintIndex);
|
||||||
if (!constraint.active) return;
|
if (!constraint.active) return;
|
||||||
if (appliedPose) constraint = constraint.applied;
|
IkConstraintPose pose = appliedPose ? constraint.applied : constraint.pose, setup = constraint.data.setup;
|
||||||
|
|
||||||
float[] frames = this.frames;
|
float[] frames = this.frames;
|
||||||
if (time < frames[0]) {
|
if (time < frames[0]) {
|
||||||
switch (blend) {
|
switch (blend) {
|
||||||
case setup:
|
case setup:
|
||||||
constraint.mix = constraint.data.mix;
|
pose.mix = setup.mix;
|
||||||
constraint.softness = constraint.data.softness;
|
pose.softness = setup.softness;
|
||||||
constraint.bendDirection = constraint.data.bendDirection;
|
pose.bendDirection = setup.bendDirection;
|
||||||
constraint.compress = constraint.data.compress;
|
pose.compress = setup.compress;
|
||||||
constraint.stretch = constraint.data.stretch;
|
pose.stretch = setup.stretch;
|
||||||
return;
|
return;
|
||||||
case first:
|
case first:
|
||||||
constraint.mix += (constraint.data.mix - constraint.mix) * alpha;
|
pose.mix += (setup.mix - pose.mix) * alpha;
|
||||||
constraint.softness += (constraint.data.softness - constraint.softness) * alpha;
|
pose.softness += (setup.softness - pose.softness) * alpha;
|
||||||
constraint.bendDirection = constraint.data.bendDirection;
|
pose.bendDirection = setup.bendDirection;
|
||||||
constraint.compress = constraint.data.compress;
|
pose.compress = setup.compress;
|
||||||
constraint.stretch = constraint.data.stretch;
|
pose.stretch = setup.stretch;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -2043,25 +2048,25 @@ public class Animation {
|
|||||||
softness = getBezierValue(time, i, SOFTNESS, curveType + BEZIER_SIZE - BEZIER);
|
softness = getBezierValue(time, i, SOFTNESS, curveType + BEZIER_SIZE - BEZIER);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (blend == setup) {
|
if (blend == MixBlend.setup) {
|
||||||
constraint.mix = constraint.data.mix + (mix - constraint.data.mix) * alpha;
|
pose.mix = setup.mix + (mix - setup.mix) * alpha;
|
||||||
constraint.softness = constraint.data.softness + (softness - constraint.data.softness) * alpha;
|
pose.softness = setup.softness + (softness - setup.softness) * alpha;
|
||||||
if (direction == out) {
|
if (direction == out) {
|
||||||
constraint.bendDirection = constraint.data.bendDirection;
|
pose.bendDirection = setup.bendDirection;
|
||||||
constraint.compress = constraint.data.compress;
|
pose.compress = setup.compress;
|
||||||
constraint.stretch = constraint.data.stretch;
|
pose.stretch = setup.stretch;
|
||||||
} else {
|
} else {
|
||||||
constraint.bendDirection = (int)frames[i + BEND_DIRECTION];
|
pose.bendDirection = (int)frames[i + BEND_DIRECTION];
|
||||||
constraint.compress = frames[i + COMPRESS] != 0;
|
pose.compress = frames[i + COMPRESS] != 0;
|
||||||
constraint.stretch = frames[i + STRETCH] != 0;
|
pose.stretch = frames[i + STRETCH] != 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
constraint.mix += (mix - constraint.mix) * alpha;
|
pose.mix += (mix - pose.mix) * alpha;
|
||||||
constraint.softness += (softness - constraint.softness) * alpha;
|
pose.softness += (softness - pose.softness) * alpha;
|
||||||
if (direction == in) {
|
if (direction == in) {
|
||||||
constraint.bendDirection = (int)frames[i + BEND_DIRECTION];
|
pose.bendDirection = (int)frames[i + BEND_DIRECTION];
|
||||||
constraint.compress = frames[i + COMPRESS] != 0;
|
pose.compress = frames[i + COMPRESS] != 0;
|
||||||
constraint.stretch = frames[i + STRETCH] != 0;
|
pose.stretch = frames[i + STRETCH] != 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -417,23 +417,23 @@ public class AnimationState {
|
|||||||
|
|
||||||
Bone bone = skeleton.bones.get(timeline.boneIndex);
|
Bone bone = skeleton.bones.get(timeline.boneIndex);
|
||||||
if (!bone.active) return;
|
if (!bone.active) return;
|
||||||
BonePose pose = bone.getPose();
|
BonePose pose = bone.getPose(), setup = bone.data.setup;
|
||||||
float[] frames = timeline.frames;
|
float[] frames = timeline.frames;
|
||||||
float r1, r2;
|
float r1, r2;
|
||||||
if (time < frames[0]) { // Time is before first frame.
|
if (time < frames[0]) { // Time is before first frame.
|
||||||
switch (blend) {
|
switch (blend) {
|
||||||
case setup:
|
case setup:
|
||||||
pose.rotation = bone.data.rotation;
|
pose.rotation = setup.rotation;
|
||||||
// Fall through.
|
// Fall through.
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
case first:
|
case first:
|
||||||
r1 = pose.rotation;
|
r1 = pose.rotation;
|
||||||
r2 = bone.data.rotation;
|
r2 = setup.rotation;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
r1 = blend == MixBlend.setup ? bone.data.rotation : pose.rotation;
|
r1 = blend == MixBlend.setup ? setup.rotation : pose.rotation;
|
||||||
r2 = bone.data.rotation + timeline.getCurveValue(time);
|
r2 = setup.rotation + timeline.getCurveValue(time);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mix between rotations using the direction of the shortest route on the first frame.
|
// Mix between rotations using the direction of the shortest route on the first frame.
|
||||||
|
|||||||
@ -66,7 +66,7 @@ public class Bone {
|
|||||||
|
|
||||||
/** Sets this bone's local transform to the setup pose. */
|
/** Sets this bone's local transform to the setup pose. */
|
||||||
public void setupPose () {
|
public void setupPose () {
|
||||||
pose.set(data);
|
pose.set(data.setup);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The bone's setup pose data. */
|
/** The bone's setup pose data. */
|
||||||
|
|||||||
@ -33,10 +33,11 @@ import com.badlogic.gdx.graphics.Color;
|
|||||||
import com.badlogic.gdx.utils.Null;
|
import com.badlogic.gdx.utils.Null;
|
||||||
|
|
||||||
/** The setup pose for a bone. */
|
/** The setup pose for a bone. */
|
||||||
public class BoneData extends BonePose {
|
public class BoneData {
|
||||||
final int index;
|
final int index;
|
||||||
final String name;
|
final String name;
|
||||||
@Null final BoneData parent;
|
@Null final BoneData parent;
|
||||||
|
final BonePose setup = new BonePose();
|
||||||
float length;
|
float length;
|
||||||
boolean skinRequired;
|
boolean skinRequired;
|
||||||
|
|
||||||
@ -54,12 +55,12 @@ public class BoneData extends BonePose {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Copy constructor. */
|
/** Copy constructor. */
|
||||||
public BoneData (BoneData bone, @Null BoneData parent) {
|
public BoneData (BoneData data, @Null BoneData parent) {
|
||||||
index = bone.index;
|
index = data.index;
|
||||||
name = bone.name;
|
name = data.name;
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
length = bone.length;
|
length = data.length;
|
||||||
set(bone);
|
setup.set(data.setup);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The index of the bone in {@link Skeleton#getBones()}. */
|
/** The index of the bone in {@link Skeleton#getBones()}. */
|
||||||
@ -76,6 +77,10 @@ public class BoneData extends BonePose {
|
|||||||
return parent;
|
return parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BonePose getSetupPose () {
|
||||||
|
return setup;
|
||||||
|
}
|
||||||
|
|
||||||
/** The bone's length. */
|
/** The bone's length. */
|
||||||
public float getLength () {
|
public float getLength () {
|
||||||
return length;
|
return length;
|
||||||
|
|||||||
@ -39,16 +39,16 @@ public class BonePose {
|
|||||||
BonePose () {
|
BonePose () {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void set (BonePose bone) {
|
public void set (BonePose pose) {
|
||||||
if (bone == null) throw new IllegalArgumentException("bone cannot be null.");
|
if (pose == null) throw new IllegalArgumentException("pose cannot be null.");
|
||||||
x = bone.x;
|
x = pose.x;
|
||||||
y = bone.y;
|
y = pose.y;
|
||||||
rotation = bone.rotation;
|
rotation = pose.rotation;
|
||||||
scaleX = bone.scaleX;
|
scaleX = pose.scaleX;
|
||||||
scaleY = bone.scaleY;
|
scaleY = pose.scaleY;
|
||||||
shearX = bone.shearX;
|
shearX = pose.shearX;
|
||||||
shearY = bone.shearY;
|
shearY = pose.shearY;
|
||||||
inherit = bone.inherit;
|
inherit = pose.inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The local x translation. */
|
/** The local x translation. */
|
||||||
|
|||||||
@ -43,19 +43,9 @@ public class IkConstraint implements Updatable {
|
|||||||
final IkConstraintData data;
|
final IkConstraintData data;
|
||||||
final Array<BoneApplied> bones;
|
final Array<BoneApplied> bones;
|
||||||
BoneApplied target;
|
BoneApplied target;
|
||||||
IkConstraint applied;
|
final IkConstraintPose pose = new IkConstraintPose(), applied = new IkConstraintPose();
|
||||||
boolean active;
|
boolean active;
|
||||||
|
|
||||||
int bendDirection;
|
|
||||||
boolean compress, stretch;
|
|
||||||
float mix = 1, softness;
|
|
||||||
|
|
||||||
private IkConstraint (IkConstraintData data, Array<BoneApplied> bones, BoneApplied target) {
|
|
||||||
this.data = data;
|
|
||||||
this.bones = bones;
|
|
||||||
this.target = target;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IkConstraint (IkConstraintData data, Skeleton skeleton) {
|
public IkConstraint (IkConstraintData data, Skeleton skeleton) {
|
||||||
if (data == null) throw new IllegalArgumentException("data cannot be null.");
|
if (data == null) throw new IllegalArgumentException("data cannot be null.");
|
||||||
if (skeleton == null) throw new IllegalArgumentException("skeleton cannot be null.");
|
if (skeleton == null) throw new IllegalArgumentException("skeleton cannot be null.");
|
||||||
@ -67,8 +57,6 @@ public class IkConstraint implements Updatable {
|
|||||||
|
|
||||||
target = skeleton.bones.get(data.target.index).applied;
|
target = skeleton.bones.get(data.target.index).applied;
|
||||||
|
|
||||||
applied = new IkConstraint(data, bones, target);
|
|
||||||
|
|
||||||
setupPose();
|
setupPose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,24 +67,20 @@ public class IkConstraint implements Updatable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setupPose () {
|
public void setupPose () {
|
||||||
IkConstraintData data = this.data;
|
pose.set(data.setup);
|
||||||
mix = data.mix;
|
|
||||||
softness = data.softness;
|
|
||||||
bendDirection = data.bendDirection;
|
|
||||||
compress = data.compress;
|
|
||||||
stretch = data.stretch;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Applies the constraint to the constrained bones. */
|
/** Applies the constraint to the constrained bones. */
|
||||||
public void update (Physics physics) {
|
public void update (Physics physics) {
|
||||||
if (mix == 0) return;
|
IkConstraintPose pose = applied;
|
||||||
|
if (pose.mix == 0) return;
|
||||||
BoneApplied target = this.target;
|
BoneApplied target = this.target;
|
||||||
Object[] bones = this.bones.items;
|
Object[] bones = this.bones.items;
|
||||||
switch (this.bones.size) {
|
switch (this.bones.size) {
|
||||||
case 1 -> apply((BoneApplied)bones[0], target.worldX, target.worldY, compress, stretch, data.uniform, mix);
|
case 1 -> apply((BoneApplied)bones[0], target.worldX, target.worldY, pose.compress, pose.stretch, data.uniform, pose.mix);
|
||||||
case 2 -> //
|
case 2 -> //
|
||||||
apply((BoneApplied)bones[0], (BoneApplied)bones[1], target.worldX, target.worldY, bendDirection, stretch, data.uniform,
|
apply((BoneApplied)bones[0], (BoneApplied)bones[1], target.worldX, target.worldY, pose.bendDirection, pose.stretch,
|
||||||
softness, mix);
|
data.uniform, pose.softness, pose.mix);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,55 +99,12 @@ public class IkConstraint implements Updatable {
|
|||||||
this.target = target;
|
this.target = target;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A percentage (0-1) that controls the mix between the constrained and unconstrained rotation.
|
public IkConstraintPose getPose () {
|
||||||
* <p>
|
return pose;
|
||||||
* For two bone IK: if the parent bone has local nonuniform scale, the child bone's local Y translation is set to 0. */
|
|
||||||
public float getMix () {
|
|
||||||
return mix;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setMix (float mix) {
|
public IkConstraintPose getAppliedPose () {
|
||||||
this.mix = mix;
|
return applied;
|
||||||
}
|
|
||||||
|
|
||||||
/** For two bone IK, the target bone's distance from the maximum reach of the bones where rotation begins to slow. The bones
|
|
||||||
* will not straighten completely until the target is this far out of range. */
|
|
||||||
public float getSoftness () {
|
|
||||||
return softness;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSoftness (float softness) {
|
|
||||||
this.softness = softness;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** For two bone IK, controls the bend direction of the IK bones, either 1 or -1. */
|
|
||||||
public int getBendDirection () {
|
|
||||||
return bendDirection;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setBendDirection (int bendDirection) {
|
|
||||||
this.bendDirection = bendDirection;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** For one bone IK, when true and the target is too close, the bone is scaled to reach it. */
|
|
||||||
public boolean getCompress () {
|
|
||||||
return compress;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCompress (boolean compress) {
|
|
||||||
this.compress = compress;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** When true and the target is out of range, the parent bone is scaled to reach it.
|
|
||||||
* <p>
|
|
||||||
* For two bone IK: 1) the child bone's local Y translation is set to 0, 2) stretch is not applied if {@link #getSoftness()} is
|
|
||||||
* > 0, and 3) if the parent bone has local nonuniform scale, stretch is not applied. */
|
|
||||||
public boolean getStretch () {
|
|
||||||
return stretch;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setStretch (boolean stretch) {
|
|
||||||
this.stretch = stretch;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns false when this constraint won't be updated by
|
/** Returns false when this constraint won't be updated by
|
||||||
|
|||||||
@ -37,9 +37,8 @@ import com.badlogic.gdx.utils.Array;
|
|||||||
public class IkConstraintData extends ConstraintData {
|
public class IkConstraintData extends ConstraintData {
|
||||||
final Array<BoneData> bones = new Array();
|
final Array<BoneData> bones = new Array();
|
||||||
BoneData target;
|
BoneData target;
|
||||||
int bendDirection;
|
final IkConstraintPose setup = new IkConstraintPose();
|
||||||
boolean compress, stretch, uniform;
|
boolean uniform;
|
||||||
float mix, softness;
|
|
||||||
|
|
||||||
public IkConstraintData (String name) {
|
public IkConstraintData (String name) {
|
||||||
super(name);
|
super(name);
|
||||||
@ -60,58 +59,12 @@ public class IkConstraintData extends ConstraintData {
|
|||||||
this.target = target;
|
this.target = target;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A percentage (0-1) that controls the mix between the constrained and unconstrained rotation.
|
public IkConstraintPose getSetupPose () {
|
||||||
* <p>
|
return setup;
|
||||||
* For two bone IK: if the parent bone has local nonuniform scale, the child bone's local Y translation is set to 0. */
|
|
||||||
public float getMix () {
|
|
||||||
return mix;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setMix (float mix) {
|
/** When true and {@link IkConstraintPose#getCompress()} or {@link IkConstraintPose#getStretch()} is used, the bone is scaled
|
||||||
this.mix = mix;
|
* on both the X and Y axes. */
|
||||||
}
|
|
||||||
|
|
||||||
/** For two bone IK, the target bone's distance from the maximum reach of the bones where rotation begins to slow. The bones
|
|
||||||
* will not straighten completely until the target is this far out of range. */
|
|
||||||
public float getSoftness () {
|
|
||||||
return softness;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSoftness (float softness) {
|
|
||||||
this.softness = softness;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** For two bone IK, controls the bend direction of the IK bones, either 1 or -1. */
|
|
||||||
public int getBendDirection () {
|
|
||||||
return bendDirection;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setBendDirection (int bendDirection) {
|
|
||||||
this.bendDirection = bendDirection;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** For one bone IK, when true and the target is too close, the bone is scaled to reach it. */
|
|
||||||
public boolean getCompress () {
|
|
||||||
return compress;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCompress (boolean compress) {
|
|
||||||
this.compress = compress;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** When true and the target is out of range, the parent bone is scaled to reach it.
|
|
||||||
* <p>
|
|
||||||
* For two bone IK: 1) the child bone's local Y translation is set to 0, 2) stretch is not applied if {@link #getSoftness()} is
|
|
||||||
* > 0, and 3) if the parent bone has local nonuniform scale, stretch is not applied. */
|
|
||||||
public boolean getStretch () {
|
|
||||||
return stretch;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setStretch (boolean stretch) {
|
|
||||||
this.stretch = stretch;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** When true and {@link #getCompress()} or {@link #getStretch()} is used, the bone is scaled on both the X and Y axes. */
|
|
||||||
public boolean getUniform () {
|
public boolean getUniform () {
|
||||||
return uniform;
|
return uniform;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,96 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* Spine Runtimes License Agreement
|
||||||
|
* Last updated April 5, 2025. Replaces all prior versions.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013-2025, Esoteric Software LLC
|
||||||
|
*
|
||||||
|
* Integration of the Spine Runtimes into software or otherwise creating
|
||||||
|
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||||
|
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||||
|
* http://esotericsoftware.com/spine-editor-license
|
||||||
|
*
|
||||||
|
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||||
|
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||||
|
* "Products"), provided that each user of the Products must obtain their own
|
||||||
|
* Spine Editor license and redistribution of the Products in any form must
|
||||||
|
* include this license and copyright notice.
|
||||||
|
*
|
||||||
|
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||||
|
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
package com.esotericsoftware.spine;
|
||||||
|
|
||||||
|
/** Stores the current pose for an IK constraint. */
|
||||||
|
public class IkConstraintPose {
|
||||||
|
int bendDirection;
|
||||||
|
boolean compress, stretch;
|
||||||
|
float mix, softness;
|
||||||
|
|
||||||
|
public void set (IkConstraintPose pose) {
|
||||||
|
mix = pose.mix;
|
||||||
|
softness = pose.softness;
|
||||||
|
bendDirection = pose.bendDirection;
|
||||||
|
compress = pose.compress;
|
||||||
|
stretch = pose.stretch;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A percentage (0-1) that controls the mix between the constrained and unconstrained rotation.
|
||||||
|
* <p>
|
||||||
|
* For two bone IK: if the parent bone has local nonuniform scale, the child bone's local Y translation is set to 0. */
|
||||||
|
public float getMix () {
|
||||||
|
return mix;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMix (float mix) {
|
||||||
|
this.mix = mix;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** For two bone IK, the target bone's distance from the maximum reach of the bones where rotation begins to slow. The bones
|
||||||
|
* will not straighten completely until the target is this far out of range. */
|
||||||
|
public float getSoftness () {
|
||||||
|
return softness;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSoftness (float softness) {
|
||||||
|
this.softness = softness;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** For two bone IK, controls the bend direction of the IK bones, either 1 or -1. */
|
||||||
|
public int getBendDirection () {
|
||||||
|
return bendDirection;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBendDirection (int bendDirection) {
|
||||||
|
this.bendDirection = bendDirection;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** For one bone IK, when true and the target is too close, the bone is scaled to reach it. */
|
||||||
|
public boolean getCompress () {
|
||||||
|
return compress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCompress (boolean compress) {
|
||||||
|
this.compress = compress;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** When true and the target is out of range, the parent bone is scaled to reach it.
|
||||||
|
* <p>
|
||||||
|
* For two bone IK: 1) the child bone's local Y translation is set to 0, 2) stretch is not applied if {@link #getSoftness()} is
|
||||||
|
* > 0, and 3) if the parent bone has local nonuniform scale, stretch is not applied. */
|
||||||
|
public boolean getStretch () {
|
||||||
|
return stretch;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStretch (boolean stretch) {
|
||||||
|
this.stretch = stretch;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -53,6 +53,7 @@ import com.esotericsoftware.spine.utils.SkeletonClipping;
|
|||||||
* Runtimes Guide. */
|
* Runtimes Guide. */
|
||||||
public class Skeleton {
|
public class Skeleton {
|
||||||
static private final short[] quadTriangles = {0, 1, 2, 2, 3, 0};
|
static private final short[] quadTriangles = {0, 1, 2, 2, 3, 0};
|
||||||
|
private static final Object IkConstraint = null;
|
||||||
final SkeletonData data;
|
final SkeletonData data;
|
||||||
final Array<Bone> bones;
|
final Array<Bone> bones;
|
||||||
final Array<Slot> slots;
|
final Array<Slot> slots;
|
||||||
@ -412,16 +413,22 @@ public class Skeleton {
|
|||||||
* See <a href="https://esotericsoftware.com/spine-runtime-skeletons#World-transforms">World transforms</a> in the Spine
|
* See <a href="https://esotericsoftware.com/spine-runtime-skeletons#World-transforms">World transforms</a> in the Spine
|
||||||
* Runtimes Guide. */
|
* Runtimes Guide. */
|
||||||
public void updateWorldTransform (Physics physics) {
|
public void updateWorldTransform (Physics physics) {
|
||||||
Object[] bones = this.bones.items;
|
Object[] objects = this.bones.items;
|
||||||
for (int i = 0, n = this.bones.size; i < n; i++) {
|
for (int i = 0, n = this.bones.size; i < n; i++) {
|
||||||
var bone = (Bone)bones[i];
|
var bone = (Bone)objects[i];
|
||||||
if (bone.active) bone.applied.set(bone.pose);
|
if (bone.active) bone.applied.set(bone.pose);
|
||||||
}
|
}
|
||||||
Object[] slots = this.slots.items;
|
objects = this.slots.items;
|
||||||
for (int i = 0, n = this.slots.size; i < n; i++) {
|
for (int i = 0, n = this.slots.size; i < n; i++) {
|
||||||
var slot = (Slot)slots[i];
|
var slot = (Slot)objects[i];
|
||||||
if (slot.bone.active) slot.applied.set(slot.pose);
|
if (slot.bone.active) slot.applied.set(slot.pose);
|
||||||
}
|
}
|
||||||
|
objects = ikConstraints.items;
|
||||||
|
for (int i = 0, n = ikConstraints.size; i < n; i++) {
|
||||||
|
var constraint = (IkConstraint)objects[i];
|
||||||
|
if (constraint.active) constraint.applied.set(constraint.pose);
|
||||||
|
}
|
||||||
|
|
||||||
// BOZO! - Reset the rest.
|
// BOZO! - Reset the rest.
|
||||||
|
|
||||||
Object[] updateCache = this.updateCache.items;
|
Object[] updateCache = this.updateCache.items;
|
||||||
|
|||||||
@ -217,15 +217,16 @@ public class SkeletonBinary extends SkeletonLoader {
|
|||||||
String name = input.readString();
|
String name = input.readString();
|
||||||
BoneData parent = i == 0 ? null : (BoneData)bones[input.readInt(true)];
|
BoneData parent = i == 0 ? null : (BoneData)bones[input.readInt(true)];
|
||||||
var data = new BoneData(i, name, parent);
|
var data = new BoneData(i, name, parent);
|
||||||
data.rotation = input.readFloat();
|
BonePose setup = data.setup;
|
||||||
data.x = input.readFloat() * scale;
|
setup.rotation = input.readFloat();
|
||||||
data.y = input.readFloat() * scale;
|
setup.x = input.readFloat() * scale;
|
||||||
data.scaleX = input.readFloat();
|
setup.y = input.readFloat() * scale;
|
||||||
data.scaleY = input.readFloat();
|
setup.scaleX = input.readFloat();
|
||||||
data.shearX = input.readFloat();
|
setup.scaleY = input.readFloat();
|
||||||
data.shearY = input.readFloat();
|
setup.shearX = input.readFloat();
|
||||||
|
setup.shearY = input.readFloat();
|
||||||
|
setup.inherit = Inherit.values[input.readByte()];
|
||||||
data.length = input.readFloat() * scale;
|
data.length = input.readFloat() * scale;
|
||||||
data.inherit = Inherit.values[input.readByte()];
|
|
||||||
data.skinRequired = input.readBoolean();
|
data.skinRequired = input.readBoolean();
|
||||||
if (nonessential) {
|
if (nonessential) {
|
||||||
Color.rgba8888ToColor(data.color, input.readInt());
|
Color.rgba8888ToColor(data.color, input.readInt());
|
||||||
@ -241,10 +242,10 @@ public class SkeletonBinary extends SkeletonLoader {
|
|||||||
String slotName = input.readString();
|
String slotName = input.readString();
|
||||||
var boneData = (BoneData)bones[input.readInt(true)];
|
var boneData = (BoneData)bones[input.readInt(true)];
|
||||||
var data = new SlotData(i, slotName, boneData);
|
var data = new SlotData(i, slotName, boneData);
|
||||||
Color.rgba8888ToColor(data.color, input.readInt());
|
Color.rgba8888ToColor(data.setup.color, input.readInt());
|
||||||
|
|
||||||
int darkColor = input.readInt();
|
int darkColor = input.readInt();
|
||||||
if (darkColor != -1) Color.rgb888ToColor(data.darkColor = new Color(), darkColor);
|
if (darkColor != -1) Color.rgb888ToColor(data.setup.darkColor = new Color(), darkColor);
|
||||||
|
|
||||||
data.attachmentName = input.readStringRef();
|
data.attachmentName = input.readStringRef();
|
||||||
data.blendMode = BlendMode.values[input.readInt(true)];
|
data.blendMode = BlendMode.values[input.readInt(true)];
|
||||||
@ -263,12 +264,13 @@ public class SkeletonBinary extends SkeletonLoader {
|
|||||||
data.target = (BoneData)bones[input.readInt(true)];
|
data.target = (BoneData)bones[input.readInt(true)];
|
||||||
int flags = input.read();
|
int flags = input.read();
|
||||||
data.skinRequired = (flags & 1) != 0;
|
data.skinRequired = (flags & 1) != 0;
|
||||||
data.bendDirection = (flags & 2) != 0 ? 1 : -1;
|
data.uniform = (flags & 2) != 0;
|
||||||
data.compress = (flags & 4) != 0;
|
IkConstraintPose setup = data.setup;
|
||||||
data.stretch = (flags & 8) != 0;
|
setup.bendDirection = (flags & 4) != 0 ? 1 : -1;
|
||||||
data.uniform = (flags & 16) != 0;
|
setup.compress = (flags & 8) != 0;
|
||||||
if ((flags & 32) != 0) data.mix = (flags & 64) != 0 ? input.readFloat() : 1;
|
setup.stretch = (flags & 16) != 0;
|
||||||
if ((flags & 128) != 0) data.softness = input.readFloat() * scale;
|
if ((flags & 32) != 0) setup.mix = (flags & 64) != 0 ? input.readFloat() : 1;
|
||||||
|
if ((flags & 128) != 0) setup.softness = input.readFloat() * scale;
|
||||||
o[i] = data;
|
o[i] = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -174,14 +174,15 @@ public class SkeletonJson extends SkeletonLoader {
|
|||||||
}
|
}
|
||||||
var data = new BoneData(skeletonData.bones.size, boneMap.getString("name"), parent);
|
var data = new BoneData(skeletonData.bones.size, boneMap.getString("name"), parent);
|
||||||
data.length = boneMap.getFloat("length", 0) * scale;
|
data.length = boneMap.getFloat("length", 0) * scale;
|
||||||
data.x = boneMap.getFloat("x", 0) * scale;
|
BonePose setup = data.setup;
|
||||||
data.y = boneMap.getFloat("y", 0) * scale;
|
setup.x = boneMap.getFloat("x", 0) * scale;
|
||||||
data.rotation = boneMap.getFloat("rotation", 0);
|
setup.y = boneMap.getFloat("y", 0) * scale;
|
||||||
data.scaleX = boneMap.getFloat("scaleX", 1);
|
setup.rotation = boneMap.getFloat("rotation", 0);
|
||||||
data.scaleY = boneMap.getFloat("scaleY", 1);
|
setup.scaleX = boneMap.getFloat("scaleX", 1);
|
||||||
data.shearX = boneMap.getFloat("shearX", 0);
|
setup.scaleY = boneMap.getFloat("scaleY", 1);
|
||||||
data.shearY = boneMap.getFloat("shearY", 0);
|
setup.shearX = boneMap.getFloat("shearX", 0);
|
||||||
data.inherit = Inherit.valueOf(boneMap.getString("inherit", Inherit.normal.name()));
|
setup.shearY = boneMap.getFloat("shearY", 0);
|
||||||
|
setup.inherit = Inherit.valueOf(boneMap.getString("inherit", Inherit.normal.name()));
|
||||||
data.skinRequired = boneMap.getBoolean("skin", false);
|
data.skinRequired = boneMap.getBoolean("skin", false);
|
||||||
|
|
||||||
String color = boneMap.getString("color", null);
|
String color = boneMap.getString("color", null);
|
||||||
@ -203,10 +204,10 @@ public class SkeletonJson extends SkeletonLoader {
|
|||||||
var data = new SlotData(skeletonData.slots.size, slotName, boneData);
|
var data = new SlotData(skeletonData.slots.size, slotName, boneData);
|
||||||
|
|
||||||
String color = slotMap.getString("color", null);
|
String color = slotMap.getString("color", null);
|
||||||
if (color != null) Color.valueOf(color, data.getColor());
|
if (color != null) Color.valueOf(color, data.getSetupPose().getColor());
|
||||||
|
|
||||||
String dark = slotMap.getString("dark", null);
|
String dark = slotMap.getString("dark", null);
|
||||||
if (dark != null) data.setDarkColor(Color.valueOf(dark));
|
if (dark != null) Color.valueOf(dark, data.getSetupPose().getDarkColor());
|
||||||
|
|
||||||
data.attachmentName = slotMap.getString("attachment", null);
|
data.attachmentName = slotMap.getString("attachment", null);
|
||||||
data.blendMode = BlendMode.valueOf(slotMap.getString("blend", BlendMode.normal.name()));
|
data.blendMode = BlendMode.valueOf(slotMap.getString("blend", BlendMode.normal.name()));
|
||||||
@ -230,12 +231,13 @@ public class SkeletonJson extends SkeletonLoader {
|
|||||||
data.target = skeletonData.findBone(targetName);
|
data.target = skeletonData.findBone(targetName);
|
||||||
if (data.target == null) throw new SerializationException("IK target bone not found: " + targetName);
|
if (data.target == null) throw new SerializationException("IK target bone not found: " + targetName);
|
||||||
|
|
||||||
data.mix = constraintMap.getFloat("mix", 1);
|
|
||||||
data.softness = constraintMap.getFloat("softness", 0) * scale;
|
|
||||||
data.bendDirection = constraintMap.getBoolean("bendPositive", true) ? 1 : -1;
|
|
||||||
data.compress = constraintMap.getBoolean("compress", false);
|
|
||||||
data.stretch = constraintMap.getBoolean("stretch", false);
|
|
||||||
data.uniform = constraintMap.getBoolean("uniform", false);
|
data.uniform = constraintMap.getBoolean("uniform", false);
|
||||||
|
IkConstraintPose setup = data.setup;
|
||||||
|
setup.mix = constraintMap.getFloat("mix", 1);
|
||||||
|
setup.softness = constraintMap.getFloat("softness", 0) * scale;
|
||||||
|
setup.bendDirection = constraintMap.getBoolean("bendPositive", true) ? 1 : -1;
|
||||||
|
setup.compress = constraintMap.getBoolean("compress", false);
|
||||||
|
setup.stretch = constraintMap.getBoolean("stretch", false);
|
||||||
|
|
||||||
skeletonData.ikConstraints.add(data);
|
skeletonData.ikConstraints.add(data);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -45,7 +45,7 @@ public class Slot {
|
|||||||
if (skeleton == null) throw new IllegalArgumentException("skeleton cannot be null.");
|
if (skeleton == null) throw new IllegalArgumentException("skeleton cannot be null.");
|
||||||
this.data = data;
|
this.data = data;
|
||||||
bone = skeleton.bones.get(data.boneData.index);
|
bone = skeleton.bones.get(data.boneData.index);
|
||||||
if (data.darkColor != null) {
|
if (data.setup.darkColor != null) {
|
||||||
pose.darkColor = new Color();
|
pose.darkColor = new Color();
|
||||||
applied.darkColor = new Color();
|
applied.darkColor = new Color();
|
||||||
}
|
}
|
||||||
@ -58,7 +58,7 @@ public class Slot {
|
|||||||
if (bone == null) throw new IllegalArgumentException("bone cannot be null.");
|
if (bone == null) throw new IllegalArgumentException("bone cannot be null.");
|
||||||
data = slot.data;
|
data = slot.data;
|
||||||
this.bone = bone;
|
this.bone = bone;
|
||||||
if (data.darkColor != null) {
|
if (data.setup.darkColor != null) {
|
||||||
pose.darkColor = new Color();
|
pose.darkColor = new Color();
|
||||||
applied.darkColor = new Color();
|
applied.darkColor = new Color();
|
||||||
}
|
}
|
||||||
@ -67,7 +67,7 @@ public class Slot {
|
|||||||
|
|
||||||
/** Sets this slot to the setup pose. */
|
/** Sets this slot to the setup pose. */
|
||||||
public void setupPose () {
|
public void setupPose () {
|
||||||
pose.set(data);
|
pose.set(data.setup);
|
||||||
if (data.attachmentName != null) pose.setAttachment(bone.skeleton.getAttachment(data.index, data.attachmentName));
|
if (data.attachmentName != null) pose.setAttachment(bone.skeleton.getAttachment(data.index, data.attachmentName));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -29,14 +29,14 @@
|
|||||||
|
|
||||||
package com.esotericsoftware.spine;
|
package com.esotericsoftware.spine;
|
||||||
|
|
||||||
import com.badlogic.gdx.graphics.Color;
|
|
||||||
import com.badlogic.gdx.utils.Null;
|
import com.badlogic.gdx.utils.Null;
|
||||||
|
|
||||||
/** Stores the setup pose for a {@link Slot}. */
|
/** Stores the setup pose for a {@link Slot}. */
|
||||||
public class SlotData extends SlotPose {
|
public class SlotData {
|
||||||
final int index;
|
final int index;
|
||||||
final String name;
|
final String name;
|
||||||
final BoneData boneData;
|
final BoneData boneData;
|
||||||
|
final SlotPose setup = new SlotPose();
|
||||||
@Null String attachmentName;
|
@Null String attachmentName;
|
||||||
BlendMode blendMode;
|
BlendMode blendMode;
|
||||||
|
|
||||||
@ -67,20 +67,8 @@ public class SlotData extends SlotPose {
|
|||||||
return boneData;
|
return boneData;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The color used to tint the slot's attachment. If {@link #getDarkColor()} is set, this is used as the light color for two
|
public SlotPose getSetupPose () {
|
||||||
* color tinting. */
|
return setup;
|
||||||
public Color getColor () {
|
|
||||||
return color;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** The dark color used to tint the slot's attachment for two color tinting, or null if two color tinting is not used. The dark
|
|
||||||
* color's alpha is not used. */
|
|
||||||
public @Null Color getDarkColor () {
|
|
||||||
return darkColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDarkColor (@Null Color darkColor) {
|
|
||||||
this.darkColor = darkColor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAttachmentName (@Null String attachmentName) {
|
public void setAttachmentName (@Null String attachmentName) {
|
||||||
|
|||||||
@ -44,21 +44,21 @@ import com.esotericsoftware.spine.attachments.VertexAttachment;
|
|||||||
public class SlotPose {
|
public class SlotPose {
|
||||||
final Color color = new Color();
|
final Color color = new Color();
|
||||||
@Null Color darkColor;
|
@Null Color darkColor;
|
||||||
@Null Attachment attachment;
|
@Null Attachment attachment; // Not used in setup pose.
|
||||||
int sequenceIndex;
|
int sequenceIndex;
|
||||||
final FloatArray deform = new FloatArray(0);
|
final FloatArray deform = new FloatArray(0);
|
||||||
|
|
||||||
SlotPose () {
|
SlotPose () {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void set (SlotPose slot) {
|
public void set (SlotPose pose) {
|
||||||
if (slot == null) throw new IllegalArgumentException("slot cannot be null.");
|
if (pose == null) throw new IllegalArgumentException("pose cannot be null.");
|
||||||
color.set(slot.color);
|
color.set(pose.color);
|
||||||
if (slot.darkColor != null) darkColor.set(slot.darkColor);
|
if (darkColor != null) darkColor.set(pose.darkColor);
|
||||||
attachment = slot.attachment;
|
attachment = pose.attachment;
|
||||||
sequenceIndex = slot.sequenceIndex;
|
sequenceIndex = pose.sequenceIndex;
|
||||||
deform.size = 0;
|
deform.size = 0;
|
||||||
deform.addAll(slot.deform);
|
deform.addAll(pose.deform);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The color used to tint the slot's attachment. If {@link #getDarkColor()} is set, this is used as the light color for two
|
/** The color used to tint the slot's attachment. If {@link #getDarkColor()} is set, this is used as the light color for two
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user