mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-02-05 06:44:56 +08:00
[libgdx] Transform constraint fixes, javadoc.
This commit is contained in:
parent
3b78925ca8
commit
d459b040d0
@ -38,7 +38,7 @@ import com.esotericsoftware.spine.Skeleton.Physics;
|
||||
* See <a href="https://esotericsoftware.com/spine-physics-constraints">Physics constraints</a> in the Spine User Guide. */
|
||||
public class PhysicsConstraint implements Updatable {
|
||||
final PhysicsConstraintData data;
|
||||
public Bone bone;
|
||||
Bone bone;
|
||||
float inertia, strength, damping, massInverse, wind, gravity, mix;
|
||||
|
||||
boolean reset = true;
|
||||
|
||||
@ -287,7 +287,7 @@ public class SkeletonBinary extends SkeletonLoader {
|
||||
data.localTo = (flags & 4) != 0;
|
||||
data.relative = (flags & 8) != 0;
|
||||
data.clamp = (flags & 16) != 0;
|
||||
nn = flags >> 5;
|
||||
Object[] froms = data.properties.setSize(nn = flags >> 5);
|
||||
for (int ii = 0, tn; ii < nn; ii++) {
|
||||
FromProperty from = switch (input.readByte()) {
|
||||
case 0 -> new FromRotate();
|
||||
@ -299,7 +299,7 @@ public class SkeletonBinary extends SkeletonLoader {
|
||||
default -> null;
|
||||
};
|
||||
from.offset = input.readFloat() * scale;
|
||||
Object[] properties = from.to.setSize(tn = input.readInt(true));
|
||||
Object[] tos = from.to.setSize(tn = input.readByte());
|
||||
for (int t = 0; t < tn; t++) {
|
||||
ToProperty to = switch (input.readByte()) {
|
||||
case 0 -> new ToRotate();
|
||||
@ -313,8 +313,9 @@ public class SkeletonBinary extends SkeletonLoader {
|
||||
to.offset = input.readFloat() * scale;
|
||||
to.max = input.readFloat() * scale;
|
||||
to.scale = input.readFloat();
|
||||
properties[i] = to;
|
||||
tos[i] = to;
|
||||
}
|
||||
froms[ii] = from;
|
||||
}
|
||||
flags = input.read();
|
||||
if ((flags & 1) != 0) data.mixRotate = input.readFloat();
|
||||
|
||||
@ -272,8 +272,8 @@ public class SkeletonJson extends SkeletonLoader {
|
||||
default -> throw new SerializationException("Invalid transform constraint from property: " + fromEntry.name);
|
||||
};
|
||||
from.offset = fromEntry.getFloat("offset", 0) * scale;
|
||||
for (JsonValue toEntry = constraintMap.getChild("to"); toEntry != null; toEntry = toEntry.next) {
|
||||
ToProperty to = switch (fromEntry.name) {
|
||||
for (JsonValue toEntry = fromEntry.getChild("to"); toEntry != null; toEntry = toEntry.next) {
|
||||
ToProperty to = switch (toEntry.name) {
|
||||
case "rotate" -> new ToRotate();
|
||||
case "x" -> new ToX();
|
||||
case "y" -> new ToY();
|
||||
@ -287,6 +287,7 @@ public class SkeletonJson extends SkeletonLoader {
|
||||
to.scale = toEntry.getFloat("scale");
|
||||
from.to.add(to);
|
||||
}
|
||||
if (from.to.notEmpty()) data.properties.add(from);
|
||||
}
|
||||
|
||||
data.mixRotate = constraintMap.getFloat("mixRotate", 1);
|
||||
|
||||
@ -105,14 +105,20 @@ public class TransformConstraint implements Updatable {
|
||||
var bone = (Bone)bones[i];
|
||||
for (int f = 0; f < fn; f++) {
|
||||
var from = (FromProperty)fromItems[f];
|
||||
if (from.mix(this) != 0) {
|
||||
float mix = from.mix(this);
|
||||
if (mix != 0) {
|
||||
float value = from.value(target, localFrom) - from.offset;
|
||||
Object[] toItems = from.to.items;
|
||||
for (int t = 0, tn = from.to.size; t < tn; t++) {
|
||||
var to = (ToProperty)toItems[t];
|
||||
float clamped = to.offset + value * to.scale;
|
||||
if (clamp) clamped = clamp(clamped, to.offset, to.max);
|
||||
to.apply(this, bone, clamped, localTo, relative);
|
||||
if (clamp) {
|
||||
if (to.offset < to.max)
|
||||
clamped = clamp(clamped, to.offset, to.max);
|
||||
else
|
||||
clamped = clamp(clamped, to.max, to.offset);
|
||||
}
|
||||
to.apply(bone, clamped, localTo, relative, mix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -121,6 +121,7 @@ public class TransformConstraintData extends ConstraintData {
|
||||
this.mixShearY = mixShearY;
|
||||
}
|
||||
|
||||
/** Reads the target bone's local transform instead of its world transform. */
|
||||
public boolean getLocalFrom () {
|
||||
return localFrom;
|
||||
}
|
||||
@ -129,6 +130,7 @@ public class TransformConstraintData extends ConstraintData {
|
||||
this.localFrom = localFrom;
|
||||
}
|
||||
|
||||
/** Sets the constrained bones' local transforms instead of their world transforms. */
|
||||
public boolean getLocalTo () {
|
||||
return localTo;
|
||||
}
|
||||
@ -137,6 +139,7 @@ public class TransformConstraintData extends ConstraintData {
|
||||
this.localTo = localTo;
|
||||
}
|
||||
|
||||
/** Adds the target bone transform to the constrained bones instead of setting it absolutely. */
|
||||
public boolean getRelative () {
|
||||
return relative;
|
||||
}
|
||||
@ -145,6 +148,7 @@ public class TransformConstraintData extends ConstraintData {
|
||||
this.relative = relative;
|
||||
}
|
||||
|
||||
/** Prevents constrained bones from exceeding the ranged defined by {@link ToProperty#offset} and {@link ToProperty#max}. */
|
||||
public boolean getClamp () {
|
||||
return clamp;
|
||||
}
|
||||
@ -153,19 +157,34 @@ public class TransformConstraintData extends ConstraintData {
|
||||
this.clamp = clamp;
|
||||
}
|
||||
|
||||
/** Source property for a {@link TransformConstraint}. */
|
||||
static abstract public class FromProperty {
|
||||
/** The value of this property that corresponds to {@link ToProperty#offset}. */
|
||||
public float offset;
|
||||
|
||||
/** Constrained properties. */
|
||||
public final Array<ToProperty> to = new Array();
|
||||
|
||||
/** Reads this property from the specified bone. */
|
||||
abstract public float value (Bone target, boolean local);
|
||||
|
||||
/** Reads the mix for this property from the specified constraint. */
|
||||
abstract public float mix (TransformConstraint constraint);
|
||||
}
|
||||
|
||||
/** Constrained property for a {@link TransformConstraint}. */
|
||||
static abstract public class ToProperty {
|
||||
public float offset, max, scale;
|
||||
/** The value of this property that corresponds to {@link FromProperty#offset}. */
|
||||
public float offset;
|
||||
|
||||
abstract public void apply (TransformConstraint constraint, Bone bone, float value, boolean local, boolean relative);
|
||||
/** The maximum value of this property when {@link TransformConstraintData#clamp clamped}. */
|
||||
public float max;
|
||||
|
||||
/** The scale of the {@link FromProperty} value in relation to this property. */
|
||||
public float scale;
|
||||
|
||||
/** Applies the value to this property. */
|
||||
abstract public void apply (Bone bone, float value, boolean local, boolean relative, float mix);
|
||||
}
|
||||
|
||||
static public class FromRotate extends FromProperty {
|
||||
@ -179,20 +198,20 @@ public class TransformConstraintData extends ConstraintData {
|
||||
}
|
||||
|
||||
static public class ToRotate extends ToProperty {
|
||||
public void apply (TransformConstraint constraint, Bone bone, float value, boolean local, boolean relative) {
|
||||
public void apply (Bone bone, float value, boolean local, boolean relative, float mix) {
|
||||
if (local) {
|
||||
if (!relative) value -= bone.arotation;
|
||||
bone.arotation += value * constraint.mixRotate;
|
||||
bone.arotation += value * mix;
|
||||
} else {
|
||||
float a = bone.a, b = bone.b, c = bone.c, d = bone.d;
|
||||
float r = value * degRad;
|
||||
if (!relative) r -= atan2(c, a);
|
||||
if (r > PI)
|
||||
r -= PI2;
|
||||
else if (r < -PI) //
|
||||
r += PI2;
|
||||
r *= constraint.mixRotate;
|
||||
float cos = cos(r), sin = sin(r);
|
||||
value *= degRad;
|
||||
if (!relative) value -= atan2(c, a);
|
||||
if (value > PI)
|
||||
value -= PI2;
|
||||
else if (value < -PI) //
|
||||
value += PI2;
|
||||
value *= mix;
|
||||
float cos = cos(value), sin = sin(value);
|
||||
bone.a = cos * a - sin * c;
|
||||
bone.b = cos * b - sin * d;
|
||||
bone.c = sin * a + cos * c;
|
||||
@ -212,13 +231,13 @@ public class TransformConstraintData extends ConstraintData {
|
||||
}
|
||||
|
||||
static public class ToX extends ToProperty {
|
||||
public void apply (TransformConstraint constraint, Bone bone, float value, boolean local, boolean relative) {
|
||||
public void apply (Bone bone, float value, boolean local, boolean relative, float mix) {
|
||||
if (local) {
|
||||
if (!relative) value -= bone.ax;
|
||||
bone.ax += value * constraint.mixX;
|
||||
bone.ax += value * mix;
|
||||
} else {
|
||||
if (!relative) value -= bone.worldX;
|
||||
bone.worldX += value * constraint.mixX;
|
||||
bone.worldX += value * mix;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -234,20 +253,20 @@ public class TransformConstraintData extends ConstraintData {
|
||||
}
|
||||
|
||||
static public class ToY extends ToProperty {
|
||||
public void apply (TransformConstraint constraint, Bone bone, float value, boolean local, boolean relative) {
|
||||
public void apply (Bone bone, float value, boolean local, boolean relative, float mix) {
|
||||
if (local) {
|
||||
if (!relative) value -= bone.ay;
|
||||
bone.ay += value * constraint.mixY;
|
||||
bone.ay += value * mix;
|
||||
} else {
|
||||
if (!relative) value -= bone.worldY;
|
||||
bone.worldY += value * constraint.mixY;
|
||||
bone.worldY += value * mix;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static public class FromScaleX extends FromProperty {
|
||||
public float value (Bone target, boolean local) {
|
||||
return local ? target.arotation : (float)Math.sqrt(target.a * target.a + target.c * target.c);
|
||||
return local ? target.ascaleX : (float)Math.sqrt(target.a * target.a + target.c * target.c);
|
||||
}
|
||||
|
||||
public float mix (TransformConstraint constraint) {
|
||||
@ -256,19 +275,19 @@ public class TransformConstraintData extends ConstraintData {
|
||||
}
|
||||
|
||||
static public class ToScaleX extends ToProperty {
|
||||
public void apply (TransformConstraint constraint, Bone bone, float value, boolean local, boolean relative) {
|
||||
public void apply (Bone bone, float value, boolean local, boolean relative, float mix) {
|
||||
if (local) {
|
||||
if (relative)
|
||||
bone.ascaleX *= 1 + ((value - 1) * constraint.mixScaleX);
|
||||
bone.ascaleX *= 1 + ((value - 1) * mix);
|
||||
else if (bone.ascaleX != 0) //
|
||||
bone.ascaleX = 1 + (value / bone.ascaleX - 1) * constraint.mixScaleX;
|
||||
bone.ascaleX = 1 + (value / bone.ascaleX - 1) * mix;
|
||||
} else {
|
||||
float s;
|
||||
if (relative)
|
||||
s = 1 + (value - 1) * constraint.mixScaleX;
|
||||
s = 1 + (value - 1) * mix;
|
||||
else {
|
||||
s = (float)Math.sqrt(bone.a * bone.a + bone.c * bone.c);
|
||||
if (s != 0) s = 1 + (value / s - 1) * constraint.mixScaleX;
|
||||
if (s != 0) s = 1 + (value / s - 1) * mix;
|
||||
}
|
||||
bone.a *= s;
|
||||
bone.c *= s;
|
||||
@ -278,7 +297,7 @@ public class TransformConstraintData extends ConstraintData {
|
||||
|
||||
static public class FromScaleY extends FromProperty {
|
||||
public float value (Bone target, boolean local) {
|
||||
return local ? target.arotation : (float)Math.sqrt(target.b * target.b + target.d * target.d);
|
||||
return local ? target.ascaleY : (float)Math.sqrt(target.b * target.b + target.d * target.d);
|
||||
}
|
||||
|
||||
public float mix (TransformConstraint constraint) {
|
||||
@ -287,19 +306,19 @@ public class TransformConstraintData extends ConstraintData {
|
||||
}
|
||||
|
||||
static public class ToScaleY extends ToProperty {
|
||||
public void apply (TransformConstraint constraint, Bone bone, float value, boolean local, boolean relative) {
|
||||
public void apply (Bone bone, float value, boolean local, boolean relative, float mix) {
|
||||
if (local) {
|
||||
if (relative)
|
||||
bone.ascaleY *= 1 + ((value - 1) * constraint.mixScaleY);
|
||||
bone.ascaleY *= 1 + ((value - 1) * mix);
|
||||
else if (bone.ascaleY != 0) //
|
||||
bone.ascaleY = 1 + (value / bone.ascaleY - 1) * constraint.mixScaleY;
|
||||
bone.ascaleY = 1 + (value / bone.ascaleY - 1) * mix;
|
||||
} else {
|
||||
float s;
|
||||
if (relative)
|
||||
s = 1 + (value - 1) * constraint.mixScaleY;
|
||||
s = 1 + (value - 1) * mix;
|
||||
else {
|
||||
s = (float)Math.sqrt(bone.b * bone.b + bone.d * bone.d);
|
||||
if (s != 0) s = 1 + (value / s - 1) * constraint.mixScaleY;
|
||||
if (s != 0) s = 1 + (value / s - 1) * mix;
|
||||
}
|
||||
bone.b *= s;
|
||||
bone.d *= s;
|
||||
@ -309,13 +328,7 @@ public class TransformConstraintData extends ConstraintData {
|
||||
|
||||
static public class FromShearY extends FromProperty {
|
||||
public float value (Bone target, boolean local) {
|
||||
if (local) return target.ashearY;
|
||||
float r = atan2(target.d, target.b) - atan2(target.c, target.a);
|
||||
if (r > PI)
|
||||
r -= PI2;
|
||||
else if (r < -PI) //
|
||||
r += PI2;
|
||||
return r;
|
||||
return local ? target.ashearY : (atan2(target.d, target.b) - atan2(target.c, target.a)) * radDeg - 90;
|
||||
}
|
||||
|
||||
public float mix (TransformConstraint constraint) {
|
||||
@ -324,12 +337,13 @@ public class TransformConstraintData extends ConstraintData {
|
||||
}
|
||||
|
||||
static public class ToShearY extends ToProperty {
|
||||
public void apply (TransformConstraint constraint, Bone bone, float value, boolean local, boolean relative) {
|
||||
public void apply (Bone bone, float value, boolean local, boolean relative, float mix) {
|
||||
if (local) {
|
||||
if (!relative) value -= bone.ashearY;
|
||||
bone.ashearY += value * constraint.mixShearY;
|
||||
bone.ashearY += value * mix;
|
||||
} else {
|
||||
float b = bone.b, d = bone.d, by = atan2(d, b);
|
||||
value = (value + 90) * degRad;
|
||||
if (relative)
|
||||
value -= PI / 2;
|
||||
else {
|
||||
@ -339,7 +353,7 @@ public class TransformConstraintData extends ConstraintData {
|
||||
else if (value < -PI) //
|
||||
value += PI2;
|
||||
}
|
||||
value = by + value * constraint.mixShearY;
|
||||
value = by + value * mix;
|
||||
float s = (float)Math.sqrt(b * b + d * d);
|
||||
bone.b = cos(value) * s;
|
||||
bone.d = sin(value) * s;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user