mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-03-26 22:49:01 +08:00
[libgdx] Pose classes for all the remaining constraints.
This commit is contained in:
parent
08af7407b3
commit
c8069fa852
@ -2072,9 +2072,9 @@ public class Animation {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Changes a transform constraint's {@link TransformConstraint#getMixRotate()}, {@link TransformConstraint#getMixX()},
|
/** Changes a transform constraint's {@link TransformConstraintPose#getMixRotate()}, {@link TransformConstraintPose#getMixX()},
|
||||||
* {@link TransformConstraint#getMixY()}, {@link TransformConstraint#getMixScaleX()},
|
* {@link TransformConstraintPose#getMixY()}, {@link TransformConstraintPose#getMixScaleX()},
|
||||||
* {@link TransformConstraint#getMixScaleY()}, and {@link TransformConstraint#getMixShearY()}. */
|
* {@link TransformConstraintPose#getMixScaleY()}, and {@link TransformConstraintPose#getMixShearY()}. */
|
||||||
static public class TransformConstraintTimeline extends CurveTimeline {
|
static public class TransformConstraintTimeline extends CurveTimeline {
|
||||||
static public final int ENTRIES = 7;
|
static public final int ENTRIES = 7;
|
||||||
static private final int ROTATE = 1, X = 2, Y = 3, SCALEX = 4, SCALEY = 5, SHEARY = 6;
|
static private final int ROTATE = 1, X = 2, Y = 3, SCALEX = 4, SCALEY = 5, SHEARY = 6;
|
||||||
@ -2116,27 +2116,27 @@ public class Animation {
|
|||||||
|
|
||||||
TransformConstraint constraint = skeleton.transformConstraints.get(constraintIndex);
|
TransformConstraint constraint = skeleton.transformConstraints.get(constraintIndex);
|
||||||
if (!constraint.active) return;
|
if (!constraint.active) return;
|
||||||
if (appliedPose) constraint = constraint.applied;
|
TransformConstraintPose pose = appliedPose ? constraint.applied : constraint.pose;
|
||||||
|
|
||||||
float[] frames = this.frames;
|
float[] frames = this.frames;
|
||||||
if (time < frames[0]) {
|
if (time < frames[0]) {
|
||||||
TransformConstraintData data = constraint.data;
|
TransformConstraintPose setup = constraint.data.setup;
|
||||||
switch (blend) {
|
switch (blend) {
|
||||||
case setup:
|
case setup:
|
||||||
constraint.mixRotate = data.mixRotate;
|
pose.mixRotate = setup.mixRotate;
|
||||||
constraint.mixX = data.mixX;
|
pose.mixX = setup.mixX;
|
||||||
constraint.mixY = data.mixY;
|
pose.mixY = setup.mixY;
|
||||||
constraint.mixScaleX = data.mixScaleX;
|
pose.mixScaleX = setup.mixScaleX;
|
||||||
constraint.mixScaleY = data.mixScaleY;
|
pose.mixScaleY = setup.mixScaleY;
|
||||||
constraint.mixShearY = data.mixShearY;
|
pose.mixShearY = setup.mixShearY;
|
||||||
return;
|
return;
|
||||||
case first:
|
case first:
|
||||||
constraint.mixRotate += (data.mixRotate - constraint.mixRotate) * alpha;
|
pose.mixRotate += (setup.mixRotate - pose.mixRotate) * alpha;
|
||||||
constraint.mixX += (data.mixX - constraint.mixX) * alpha;
|
pose.mixX += (setup.mixX - pose.mixX) * alpha;
|
||||||
constraint.mixY += (data.mixY - constraint.mixY) * alpha;
|
pose.mixY += (setup.mixY - pose.mixY) * alpha;
|
||||||
constraint.mixScaleX += (data.mixScaleX - constraint.mixScaleX) * alpha;
|
pose.mixScaleX += (setup.mixScaleX - pose.mixScaleX) * alpha;
|
||||||
constraint.mixScaleY += (data.mixScaleY - constraint.mixScaleY) * alpha;
|
pose.mixScaleY += (setup.mixScaleY - pose.mixScaleY) * alpha;
|
||||||
constraint.mixShearY += (data.mixShearY - constraint.mixShearY) * alpha;
|
pose.mixShearY += (setup.mixShearY - pose.mixShearY) * alpha;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -2178,25 +2178,25 @@ public class Animation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (blend == setup) {
|
if (blend == setup) {
|
||||||
TransformConstraintData data = constraint.data;
|
TransformConstraintPose setup = constraint.data.setup;
|
||||||
constraint.mixRotate = data.mixRotate + (rotate - data.mixRotate) * alpha;
|
pose.mixRotate = setup.mixRotate + (rotate - setup.mixRotate) * alpha;
|
||||||
constraint.mixX = data.mixX + (x - data.mixX) * alpha;
|
pose.mixX = setup.mixX + (x - setup.mixX) * alpha;
|
||||||
constraint.mixY = data.mixY + (y - data.mixY) * alpha;
|
pose.mixY = setup.mixY + (y - setup.mixY) * alpha;
|
||||||
constraint.mixScaleX = data.mixScaleX + (scaleX - data.mixScaleX) * alpha;
|
pose.mixScaleX = setup.mixScaleX + (scaleX - setup.mixScaleX) * alpha;
|
||||||
constraint.mixScaleY = data.mixScaleY + (scaleY - data.mixScaleY) * alpha;
|
pose.mixScaleY = setup.mixScaleY + (scaleY - setup.mixScaleY) * alpha;
|
||||||
constraint.mixShearY = data.mixShearY + (shearY - data.mixShearY) * alpha;
|
pose.mixShearY = setup.mixShearY + (shearY - setup.mixShearY) * alpha;
|
||||||
} else {
|
} else {
|
||||||
constraint.mixRotate += (rotate - constraint.mixRotate) * alpha;
|
pose.mixRotate += (rotate - pose.mixRotate) * alpha;
|
||||||
constraint.mixX += (x - constraint.mixX) * alpha;
|
pose.mixX += (x - pose.mixX) * alpha;
|
||||||
constraint.mixY += (y - constraint.mixY) * alpha;
|
pose.mixY += (y - pose.mixY) * alpha;
|
||||||
constraint.mixScaleX += (scaleX - constraint.mixScaleX) * alpha;
|
pose.mixScaleX += (scaleX - pose.mixScaleX) * alpha;
|
||||||
constraint.mixScaleY += (scaleY - constraint.mixScaleY) * alpha;
|
pose.mixScaleY += (scaleY - pose.mixScaleY) * alpha;
|
||||||
constraint.mixShearY += (shearY - constraint.mixShearY) * alpha;
|
pose.mixShearY += (shearY - pose.mixShearY) * alpha;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Changes a path constraint's {@link PathConstraint#getPosition()}. */
|
/** Changes a path constraint's {@link PathConstraintPose#getPosition()}. */
|
||||||
static public class PathConstraintPositionTimeline extends CurveTimeline1 {
|
static public class PathConstraintPositionTimeline extends CurveTimeline1 {
|
||||||
final int constraintIndex;
|
final int constraintIndex;
|
||||||
|
|
||||||
@ -2216,13 +2216,13 @@ public class Animation {
|
|||||||
|
|
||||||
PathConstraint constraint = skeleton.pathConstraints.get(constraintIndex);
|
PathConstraint constraint = skeleton.pathConstraints.get(constraintIndex);
|
||||||
if (constraint.active) {
|
if (constraint.active) {
|
||||||
if (appliedPose) constraint = constraint.applied;
|
PathConstraintPose pose = appliedPose ? constraint.applied : constraint.pose;
|
||||||
constraint.position = getAbsoluteValue(time, alpha, blend, constraint.position, constraint.data.position);
|
pose.position = getAbsoluteValue(time, alpha, blend, pose.position, constraint.data.setup.position);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Changes a path constraint's {@link PathConstraint#getSpacing()}. */
|
/** Changes a path constraint's {@link PathConstraintPose#getSpacing()}. */
|
||||||
static public class PathConstraintSpacingTimeline extends CurveTimeline1 {
|
static public class PathConstraintSpacingTimeline extends CurveTimeline1 {
|
||||||
final int constraintIndex;
|
final int constraintIndex;
|
||||||
|
|
||||||
@ -2242,14 +2242,14 @@ public class Animation {
|
|||||||
|
|
||||||
PathConstraint constraint = skeleton.pathConstraints.get(constraintIndex);
|
PathConstraint constraint = skeleton.pathConstraints.get(constraintIndex);
|
||||||
if (constraint.active) {
|
if (constraint.active) {
|
||||||
if (appliedPose) constraint = constraint.applied;
|
PathConstraintPose pose = appliedPose ? constraint.applied : constraint.pose;
|
||||||
constraint.spacing = getAbsoluteValue(time, alpha, blend, constraint.spacing, constraint.data.spacing);
|
pose.spacing = getAbsoluteValue(time, alpha, blend, pose.spacing, constraint.data.setup.spacing);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Changes a path constraint's {@link PathConstraint#getMixRotate()}, {@link PathConstraint#getMixX()}, and
|
/** Changes a path constraint's {@link PathConstraintPose#getMixRotate()}, {@link PathConstraintPose#getMixX()}, and
|
||||||
* {@link PathConstraint#getMixY()}. */
|
* {@link PathConstraintPose#getMixY()}. */
|
||||||
static public class PathConstraintMixTimeline extends CurveTimeline {
|
static public class PathConstraintMixTimeline extends CurveTimeline {
|
||||||
static public final int ENTRIES = 4;
|
static public final int ENTRIES = 4;
|
||||||
static private final int ROTATE = 1, X = 2, Y = 3;
|
static private final int ROTATE = 1, X = 2, Y = 3;
|
||||||
@ -2287,21 +2287,21 @@ public class Animation {
|
|||||||
|
|
||||||
PathConstraint constraint = skeleton.pathConstraints.get(constraintIndex);
|
PathConstraint constraint = skeleton.pathConstraints.get(constraintIndex);
|
||||||
if (!constraint.active) return;
|
if (!constraint.active) return;
|
||||||
if (appliedPose) constraint = constraint.applied;
|
PathConstraintPose pose = appliedPose ? constraint.applied : constraint.pose;
|
||||||
|
|
||||||
float[] frames = this.frames;
|
float[] frames = this.frames;
|
||||||
if (time < frames[0]) {
|
if (time < frames[0]) {
|
||||||
PathConstraintData data = constraint.data;
|
PathConstraintPose setup = constraint.data.setup;
|
||||||
switch (blend) {
|
switch (blend) {
|
||||||
case setup:
|
case setup:
|
||||||
constraint.mixRotate = data.mixRotate;
|
pose.mixRotate = setup.mixRotate;
|
||||||
constraint.mixX = data.mixX;
|
pose.mixX = setup.mixX;
|
||||||
constraint.mixY = data.mixY;
|
pose.mixY = setup.mixY;
|
||||||
return;
|
return;
|
||||||
case first:
|
case first:
|
||||||
constraint.mixRotate += (data.mixRotate - constraint.mixRotate) * alpha;
|
pose.mixRotate += (setup.mixRotate - pose.mixRotate) * alpha;
|
||||||
constraint.mixX += (data.mixX - constraint.mixX) * alpha;
|
pose.mixX += (setup.mixX - pose.mixX) * alpha;
|
||||||
constraint.mixY += (data.mixY - constraint.mixY) * alpha;
|
pose.mixY += (setup.mixY - pose.mixY) * alpha;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -2331,14 +2331,14 @@ public class Animation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (blend == setup) {
|
if (blend == setup) {
|
||||||
PathConstraintData data = constraint.data;
|
PathConstraintPose setup = constraint.data.setup;
|
||||||
constraint.mixRotate = data.mixRotate + (rotate - data.mixRotate) * alpha;
|
pose.mixRotate = setup.mixRotate + (rotate - setup.mixRotate) * alpha;
|
||||||
constraint.mixX = data.mixX + (x - data.mixX) * alpha;
|
pose.mixX = setup.mixX + (x - setup.mixX) * alpha;
|
||||||
constraint.mixY = data.mixY + (y - data.mixY) * alpha;
|
pose.mixY = setup.mixY + (y - setup.mixY) * alpha;
|
||||||
} else {
|
} else {
|
||||||
constraint.mixRotate += (rotate - constraint.mixRotate) * alpha;
|
pose.mixRotate += (rotate - pose.mixRotate) * alpha;
|
||||||
constraint.mixX += (x - constraint.mixX) * alpha;
|
pose.mixX += (x - pose.mixX) * alpha;
|
||||||
constraint.mixY += (y - constraint.mixY) * alpha;
|
pose.mixY += (y - pose.mixY) * alpha;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2370,44 +2370,38 @@ public class Animation {
|
|||||||
for (int i = 0, n = skeleton.physicsConstraints.size; i < n; i++) {
|
for (int i = 0, n = skeleton.physicsConstraints.size; i < n; i++) {
|
||||||
constraint = (PhysicsConstraint)constraints[i];
|
constraint = (PhysicsConstraint)constraints[i];
|
||||||
if (constraint.active && global(constraint.data)) {
|
if (constraint.active && global(constraint.data)) {
|
||||||
if (appliedPose) constraint = constraint.applied;
|
PhysicsConstraintPose pose = appliedPose ? constraint.applied : constraint.pose;
|
||||||
set(constraint, getAbsoluteValue(time, alpha, blend, get(constraint), setup(constraint), value));
|
set(pose, getAbsoluteValue(time, alpha, blend, get(pose), get(constraint.data.setup), value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
constraint = skeleton.physicsConstraints.get(constraintIndex);
|
constraint = skeleton.physicsConstraints.get(constraintIndex);
|
||||||
if (constraint.active) {
|
if (constraint.active) {
|
||||||
if (appliedPose) constraint = constraint.applied;
|
PhysicsConstraintPose pose = appliedPose ? constraint.applied : constraint.pose;
|
||||||
set(constraint, getAbsoluteValue(time, alpha, blend, get(constraint), setup(constraint)));
|
set(pose, getAbsoluteValue(time, alpha, blend, get(pose), get(constraint.data.setup)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract protected float setup (PhysicsConstraint constraint);
|
abstract protected float get (PhysicsConstraintPose pose);
|
||||||
|
|
||||||
abstract protected float get (PhysicsConstraint constraint);
|
abstract protected void set (PhysicsConstraintPose pose, float value);
|
||||||
|
|
||||||
abstract protected void set (PhysicsConstraint constraint, float value);
|
|
||||||
|
|
||||||
abstract protected boolean global (PhysicsConstraintData constraint);
|
abstract protected boolean global (PhysicsConstraintData constraint);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Changes a physics constraint's {@link PhysicsConstraint#getInertia()}. */
|
/** Changes a physics constraint's {@link PhysicsConstraintPose#getInertia()}. */
|
||||||
static public class PhysicsConstraintInertiaTimeline extends PhysicsConstraintTimeline {
|
static public class PhysicsConstraintInertiaTimeline extends PhysicsConstraintTimeline {
|
||||||
public PhysicsConstraintInertiaTimeline (int frameCount, int bezierCount, int physicsConstraintIndex) {
|
public PhysicsConstraintInertiaTimeline (int frameCount, int bezierCount, int physicsConstraintIndex) {
|
||||||
super(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintInertia);
|
super(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintInertia);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected float setup (PhysicsConstraint constraint) {
|
protected float get (PhysicsConstraintPose pose) {
|
||||||
return constraint.data.inertia;
|
return pose.inertia;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected float get (PhysicsConstraint constraint) {
|
protected void set (PhysicsConstraintPose pose, float value) {
|
||||||
return constraint.inertia;
|
pose.inertia = value;
|
||||||
}
|
|
||||||
|
|
||||||
protected void set (PhysicsConstraint constraint, float value) {
|
|
||||||
constraint.inertia = value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean global (PhysicsConstraintData constraint) {
|
protected boolean global (PhysicsConstraintData constraint) {
|
||||||
@ -2415,22 +2409,18 @@ public class Animation {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Changes a physics constraint's {@link PhysicsConstraint#getStrength()}. */
|
/** Changes a physics constraint's {@link PhysicsConstraintPose#getStrength()}. */
|
||||||
static public class PhysicsConstraintStrengthTimeline extends PhysicsConstraintTimeline {
|
static public class PhysicsConstraintStrengthTimeline extends PhysicsConstraintTimeline {
|
||||||
public PhysicsConstraintStrengthTimeline (int frameCount, int bezierCount, int physicsConstraintIndex) {
|
public PhysicsConstraintStrengthTimeline (int frameCount, int bezierCount, int physicsConstraintIndex) {
|
||||||
super(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintStrength);
|
super(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintStrength);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected float setup (PhysicsConstraint constraint) {
|
protected float get (PhysicsConstraintPose pose) {
|
||||||
return constraint.data.strength;
|
return pose.strength;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected float get (PhysicsConstraint constraint) {
|
protected void set (PhysicsConstraintPose pose, float value) {
|
||||||
return constraint.strength;
|
pose.strength = value;
|
||||||
}
|
|
||||||
|
|
||||||
protected void set (PhysicsConstraint constraint, float value) {
|
|
||||||
constraint.strength = value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean global (PhysicsConstraintData constraint) {
|
protected boolean global (PhysicsConstraintData constraint) {
|
||||||
@ -2438,22 +2428,18 @@ public class Animation {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Changes a physics constraint's {@link PhysicsConstraint#getDamping()}. */
|
/** Changes a physics constraint's {@link PhysicsConstraintPose#getDamping()}. */
|
||||||
static public class PhysicsConstraintDampingTimeline extends PhysicsConstraintTimeline {
|
static public class PhysicsConstraintDampingTimeline extends PhysicsConstraintTimeline {
|
||||||
public PhysicsConstraintDampingTimeline (int frameCount, int bezierCount, int physicsConstraintIndex) {
|
public PhysicsConstraintDampingTimeline (int frameCount, int bezierCount, int physicsConstraintIndex) {
|
||||||
super(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintDamping);
|
super(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintDamping);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected float setup (PhysicsConstraint constraint) {
|
protected float get (PhysicsConstraintPose pose) {
|
||||||
return constraint.data.damping;
|
return pose.damping;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected float get (PhysicsConstraint constraint) {
|
protected void set (PhysicsConstraintPose pose, float value) {
|
||||||
return constraint.damping;
|
pose.damping = value;
|
||||||
}
|
|
||||||
|
|
||||||
protected void set (PhysicsConstraint constraint, float value) {
|
|
||||||
constraint.damping = value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean global (PhysicsConstraintData constraint) {
|
protected boolean global (PhysicsConstraintData constraint) {
|
||||||
@ -2461,22 +2447,18 @@ public class Animation {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Changes a physics constraint's {@link PhysicsConstraint#getMassInverse()}. The timeline values are not inverted. */
|
/** Changes a physics constraint's {@link PhysicsConstraintPose#getMassInverse()}. The timeline values are not inverted. */
|
||||||
static public class PhysicsConstraintMassTimeline extends PhysicsConstraintTimeline {
|
static public class PhysicsConstraintMassTimeline extends PhysicsConstraintTimeline {
|
||||||
public PhysicsConstraintMassTimeline (int frameCount, int bezierCount, int physicsConstraintIndex) {
|
public PhysicsConstraintMassTimeline (int frameCount, int bezierCount, int physicsConstraintIndex) {
|
||||||
super(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintMass);
|
super(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintMass);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected float setup (PhysicsConstraint constraint) {
|
protected float get (PhysicsConstraintPose pose) {
|
||||||
return 1 / constraint.data.massInverse;
|
return 1 / pose.massInverse;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected float get (PhysicsConstraint constraint) {
|
protected void set (PhysicsConstraintPose pose, float value) {
|
||||||
return 1 / constraint.massInverse;
|
pose.massInverse = 1 / value;
|
||||||
}
|
|
||||||
|
|
||||||
protected void set (PhysicsConstraint constraint, float value) {
|
|
||||||
constraint.massInverse = 1 / value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean global (PhysicsConstraintData constraint) {
|
protected boolean global (PhysicsConstraintData constraint) {
|
||||||
@ -2484,22 +2466,18 @@ public class Animation {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Changes a physics constraint's {@link PhysicsConstraint#getWind()}. */
|
/** Changes a physics constraint's {@link PhysicsConstraintPose#getWind()}. */
|
||||||
static public class PhysicsConstraintWindTimeline extends PhysicsConstraintTimeline {
|
static public class PhysicsConstraintWindTimeline extends PhysicsConstraintTimeline {
|
||||||
public PhysicsConstraintWindTimeline (int frameCount, int bezierCount, int physicsConstraintIndex) {
|
public PhysicsConstraintWindTimeline (int frameCount, int bezierCount, int physicsConstraintIndex) {
|
||||||
super(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintWind);
|
super(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintWind);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected float setup (PhysicsConstraint constraint) {
|
protected float get (PhysicsConstraintPose pose) {
|
||||||
return constraint.data.wind;
|
return pose.wind;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected float get (PhysicsConstraint constraint) {
|
protected void set (PhysicsConstraintPose pose, float value) {
|
||||||
return constraint.wind;
|
pose.wind = value;
|
||||||
}
|
|
||||||
|
|
||||||
protected void set (PhysicsConstraint constraint, float value) {
|
|
||||||
constraint.wind = value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean global (PhysicsConstraintData constraint) {
|
protected boolean global (PhysicsConstraintData constraint) {
|
||||||
@ -2507,22 +2485,18 @@ public class Animation {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Changes a physics constraint's {@link PhysicsConstraint#getGravity()}. */
|
/** Changes a physics constraint's {@link PhysicsConstraintPose#getGravity()}. */
|
||||||
static public class PhysicsConstraintGravityTimeline extends PhysicsConstraintTimeline {
|
static public class PhysicsConstraintGravityTimeline extends PhysicsConstraintTimeline {
|
||||||
public PhysicsConstraintGravityTimeline (int frameCount, int bezierCount, int physicsConstraintIndex) {
|
public PhysicsConstraintGravityTimeline (int frameCount, int bezierCount, int physicsConstraintIndex) {
|
||||||
super(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintGravity);
|
super(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintGravity);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected float setup (PhysicsConstraint constraint) {
|
protected float get (PhysicsConstraintPose pose) {
|
||||||
return constraint.data.gravity;
|
return pose.gravity;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected float get (PhysicsConstraint constraint) {
|
protected void set (PhysicsConstraintPose pose, float value) {
|
||||||
return constraint.gravity;
|
pose.gravity = value;
|
||||||
}
|
|
||||||
|
|
||||||
protected void set (PhysicsConstraint constraint, float value) {
|
|
||||||
constraint.gravity = value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean global (PhysicsConstraintData constraint) {
|
protected boolean global (PhysicsConstraintData constraint) {
|
||||||
@ -2530,22 +2504,18 @@ public class Animation {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Changes a physics constraint's {@link PhysicsConstraint#getMix()}. */
|
/** Changes a physics constraint's {@link PhysicsConstraintPose#getMix()}. */
|
||||||
static public class PhysicsConstraintMixTimeline extends PhysicsConstraintTimeline {
|
static public class PhysicsConstraintMixTimeline extends PhysicsConstraintTimeline {
|
||||||
public PhysicsConstraintMixTimeline (int frameCount, int bezierCount, int physicsConstraintIndex) {
|
public PhysicsConstraintMixTimeline (int frameCount, int bezierCount, int physicsConstraintIndex) {
|
||||||
super(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintMix);
|
super(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintMix);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected float setup (PhysicsConstraint constraint) {
|
protected float get (PhysicsConstraintPose pose) {
|
||||||
return constraint.data.mix;
|
return pose.mix;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected float get (PhysicsConstraint constraint) {
|
protected void set (PhysicsConstraintPose pose, float value) {
|
||||||
return constraint.mix;
|
pose.mix = value;
|
||||||
}
|
|
||||||
|
|
||||||
protected void set (PhysicsConstraint constraint, float value) {
|
|
||||||
constraint.mix = value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean global (PhysicsConstraintData constraint) {
|
protected boolean global (PhysicsConstraintData constraint) {
|
||||||
@ -2601,17 +2571,13 @@ public class Animation {
|
|||||||
if (time < frames[0]) return;
|
if (time < frames[0]) return;
|
||||||
|
|
||||||
if (lastTime < frames[0] || time >= frames[search(frames, lastTime) + 1]) {
|
if (lastTime < frames[0] || time >= frames[search(frames, lastTime) + 1]) {
|
||||||
if (constraint != null) {
|
if (constraint != null)
|
||||||
if (appliedPose) constraint = constraint.applied;
|
|
||||||
constraint.reset();
|
constraint.reset();
|
||||||
} else {
|
else {
|
||||||
Object[] constraints = skeleton.physicsConstraints.items;
|
Object[] constraints = skeleton.physicsConstraints.items;
|
||||||
for (int i = 0, n = skeleton.physicsConstraints.size; i < n; i++) {
|
for (int i = 0, n = skeleton.physicsConstraints.size; i < n; i++) {
|
||||||
constraint = (PhysicsConstraint)constraints[i];
|
constraint = (PhysicsConstraint)constraints[i];
|
||||||
if (constraint.active) {
|
if (constraint.active) constraint.reset();
|
||||||
if (appliedPose) constraint = constraint.applied;
|
|
||||||
constraint.reset();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -63,7 +63,7 @@ public class IkConstraint implements Updatable {
|
|||||||
/** Copy constructor. */
|
/** Copy constructor. */
|
||||||
public IkConstraint (IkConstraint constraint, Skeleton skeleton) {
|
public IkConstraint (IkConstraint constraint, Skeleton skeleton) {
|
||||||
this(constraint.data, skeleton);
|
this(constraint.data, skeleton);
|
||||||
setupPose();
|
pose.set(constraint.pose);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setupPose () {
|
public void setupPose () {
|
||||||
@ -72,15 +72,15 @@ public class IkConstraint implements Updatable {
|
|||||||
|
|
||||||
/** Applies the constraint to the constrained bones. */
|
/** Applies the constraint to the constrained bones. */
|
||||||
public void update (Physics physics) {
|
public void update (Physics physics) {
|
||||||
IkConstraintPose pose = applied;
|
IkConstraintPose a = applied;
|
||||||
if (pose.mix == 0) return;
|
if (a.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, pose.compress, pose.stretch, data.uniform, pose.mix);
|
case 1 -> apply((BoneApplied)bones[0], target.worldX, target.worldY, a.compress, a.stretch, data.uniform, a.mix);
|
||||||
case 2 -> //
|
case 2 -> //
|
||||||
apply((BoneApplied)bones[0], (BoneApplied)bones[1], target.worldX, target.worldY, pose.bendDirection, pose.stretch,
|
apply((BoneApplied)bones[0], (BoneApplied)bones[1], target.worldX, target.worldY, a.bendDirection, a.stretch,
|
||||||
data.uniform, pose.softness, pose.mix);
|
data.uniform, a.softness, a.mix);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -35,15 +35,19 @@ import com.badlogic.gdx.utils.Array;
|
|||||||
* <p>
|
* <p>
|
||||||
* See <a href="https://esotericsoftware.com/spine-ik-constraints">IK constraints</a> in the Spine User Guide. */
|
* See <a href="https://esotericsoftware.com/spine-ik-constraints">IK constraints</a> in the Spine User Guide. */
|
||||||
public class IkConstraintData extends ConstraintData {
|
public class IkConstraintData extends ConstraintData {
|
||||||
|
final IkConstraintPose setup = new IkConstraintPose();
|
||||||
final Array<BoneData> bones = new Array();
|
final Array<BoneData> bones = new Array();
|
||||||
BoneData target;
|
BoneData target;
|
||||||
final IkConstraintPose setup = new IkConstraintPose();
|
|
||||||
boolean uniform;
|
boolean uniform;
|
||||||
|
|
||||||
public IkConstraintData (String name) {
|
public IkConstraintData (String name) {
|
||||||
super(name);
|
super(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IkConstraintPose getSetupPose () {
|
||||||
|
return setup;
|
||||||
|
}
|
||||||
|
|
||||||
/** The bones that are constrained by this IK constraint. */
|
/** The bones that are constrained by this IK constraint. */
|
||||||
public Array<BoneData> getBones () {
|
public Array<BoneData> getBones () {
|
||||||
return bones;
|
return bones;
|
||||||
@ -59,10 +63,6 @@ public class IkConstraintData extends ConstraintData {
|
|||||||
this.target = target;
|
this.target = target;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IkConstraintPose getSetupPose () {
|
|
||||||
return setup;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** When true and {@link IkConstraintPose#getCompress()} or {@link IkConstraintPose#getStretch()} is used, the bone is scaled
|
/** When true and {@link IkConstraintPose#getCompress()} or {@link IkConstraintPose#getStretch()} is used, the bone is scaled
|
||||||
* on both the X and Y axes. */
|
* on both the X and Y axes. */
|
||||||
public boolean getUniform () {
|
public boolean getUniform () {
|
||||||
|
|||||||
@ -52,11 +52,9 @@ public class PathConstraint implements Updatable {
|
|||||||
final PathConstraintData data;
|
final PathConstraintData data;
|
||||||
final Array<BoneApplied> bones;
|
final Array<BoneApplied> bones;
|
||||||
Slot slot;
|
Slot slot;
|
||||||
PathConstraint applied;
|
final PathConstraintPose pose = new PathConstraintPose(), applied = new PathConstraintPose();
|
||||||
boolean active;
|
boolean active;
|
||||||
|
|
||||||
float position, spacing, mixRotate, mixX, mixY;
|
|
||||||
|
|
||||||
private final FloatArray spaces = new FloatArray(), positions = new FloatArray();
|
private final FloatArray spaces = new FloatArray(), positions = new FloatArray();
|
||||||
private final FloatArray world = new FloatArray(), curves = new FloatArray(), lengths = new FloatArray();
|
private final FloatArray world = new FloatArray(), curves = new FloatArray(), lengths = new FloatArray();
|
||||||
private final float[] segments = new float[10];
|
private final float[] segments = new float[10];
|
||||||
@ -78,31 +76,25 @@ public class PathConstraint implements Updatable {
|
|||||||
|
|
||||||
slot = skeleton.slots.get(data.slot.index);
|
slot = skeleton.slots.get(data.slot.index);
|
||||||
|
|
||||||
applied = new PathConstraint(data, bones, slot);
|
|
||||||
|
|
||||||
setupPose();
|
setupPose();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Copy constructor. */
|
/** Copy constructor. */
|
||||||
public PathConstraint (PathConstraint constraint, Skeleton skeleton) {
|
public PathConstraint (PathConstraint constraint, Skeleton skeleton) {
|
||||||
this(constraint.data, skeleton);
|
this(constraint.data, skeleton);
|
||||||
setupPose();
|
pose.set(constraint.pose);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setupPose () {
|
public void setupPose () {
|
||||||
PathConstraintData data = this.data;
|
pose.set(data.setup);
|
||||||
position = data.position;
|
|
||||||
spacing = data.spacing;
|
|
||||||
mixRotate = data.mixRotate;
|
|
||||||
mixX = data.mixX;
|
|
||||||
mixY = data.mixY;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 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 (!(slot.applied.attachment instanceof PathAttachment pathAttachment)) return;
|
if (!(slot.applied.attachment instanceof PathAttachment pathAttachment)) return;
|
||||||
|
|
||||||
float mixRotate = this.mixRotate, mixX = this.mixX, mixY = this.mixY;
|
PathConstraintPose pose = applied;
|
||||||
|
float mixRotate = pose.mixRotate, mixX = pose.mixX, mixY = pose.mixY;
|
||||||
if (mixRotate == 0 && mixX == 0 && mixY == 0) return;
|
if (mixRotate == 0 && mixX == 0 && mixY == 0) return;
|
||||||
|
|
||||||
PathConstraintData data = this.data;
|
PathConstraintData data = this.data;
|
||||||
@ -110,7 +102,7 @@ public class PathConstraint implements Updatable {
|
|||||||
int boneCount = this.bones.size, spacesCount = tangents ? boneCount : boneCount + 1;
|
int boneCount = this.bones.size, spacesCount = tangents ? boneCount : boneCount + 1;
|
||||||
Object[] bones = this.bones.items;
|
Object[] bones = this.bones.items;
|
||||||
float[] spaces = this.spaces.setSize(spacesCount), lengths = scale ? this.lengths.setSize(boneCount) : null;
|
float[] spaces = this.spaces.setSize(spacesCount), lengths = scale ? this.lengths.setSize(boneCount) : null;
|
||||||
float spacing = this.spacing;
|
float spacing = pose.spacing;
|
||||||
|
|
||||||
switch (data.spacingMode) {
|
switch (data.spacingMode) {
|
||||||
case percent -> {
|
case percent -> {
|
||||||
@ -224,7 +216,7 @@ public class PathConstraint implements Updatable {
|
|||||||
|
|
||||||
float[] computeWorldPositions (PathAttachment path, int spacesCount, boolean tangents) {
|
float[] computeWorldPositions (PathAttachment path, int spacesCount, boolean tangents) {
|
||||||
Slot slot = this.slot;
|
Slot slot = this.slot;
|
||||||
float position = this.position;
|
float position = applied.position;
|
||||||
float[] spaces = this.spaces.items, out = this.positions.setSize(spacesCount * 3 + 2), world;
|
float[] spaces = this.spaces.items, out = this.positions.setSize(spacesCount * 3 + 2), world;
|
||||||
boolean closed = path.getClosed();
|
boolean closed = path.getClosed();
|
||||||
int verticesLength = path.getWorldVerticesLength(), curveCount = verticesLength / 6, prevCurve = NONE;
|
int verticesLength = path.getWorldVerticesLength(), curveCount = verticesLength / 6, prevCurve = NONE;
|
||||||
@ -480,51 +472,6 @@ public class PathConstraint implements Updatable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The position along the path. */
|
|
||||||
public float getPosition () {
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPosition (float position) {
|
|
||||||
this.position = position;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** The spacing between bones. */
|
|
||||||
public float getSpacing () {
|
|
||||||
return spacing;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSpacing (float spacing) {
|
|
||||||
this.spacing = spacing;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A percentage (0-1) that controls the mix between the constrained and unconstrained rotation. */
|
|
||||||
public float getMixRotate () {
|
|
||||||
return mixRotate;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMixRotate (float mixRotate) {
|
|
||||||
this.mixRotate = mixRotate;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A percentage (0-1) that controls the mix between the constrained and unconstrained translation X. */
|
|
||||||
public float getMixX () {
|
|
||||||
return mixX;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMixX (float mixX) {
|
|
||||||
this.mixX = mixX;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A percentage (0-1) that controls the mix between the constrained and unconstrained translation Y. */
|
|
||||||
public float getMixY () {
|
|
||||||
return mixY;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMixY (float mixY) {
|
|
||||||
this.mixY = mixY;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** The bones that will be modified by this path constraint. */
|
/** The bones that will be modified by this path constraint. */
|
||||||
public Array<BoneApplied> getBones () {
|
public Array<BoneApplied> getBones () {
|
||||||
return bones;
|
return bones;
|
||||||
@ -540,6 +487,14 @@ public class PathConstraint implements Updatable {
|
|||||||
this.slot = slot;
|
this.slot = slot;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public PathConstraintPose getPose () {
|
||||||
|
return pose;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PathConstraintPose getAppliedPose () {
|
||||||
|
return applied;
|
||||||
|
}
|
||||||
|
|
||||||
/** Returns false when this constraint won't be updated by
|
/** Returns false when this constraint won't be updated by
|
||||||
* {@link Skeleton#updateWorldTransform(com.esotericsoftware.spine.Physics)} because a skin is required and the
|
* {@link Skeleton#updateWorldTransform(com.esotericsoftware.spine.Physics)} because a skin is required and the
|
||||||
* {@link Skeleton#getSkin() active skin} does not contain this item.
|
* {@link Skeleton#getSkin() active skin} does not contain this item.
|
||||||
|
|||||||
@ -35,18 +35,22 @@ import com.badlogic.gdx.utils.Array;
|
|||||||
* <p>
|
* <p>
|
||||||
* See <a href="https://esotericsoftware.com/spine-path-constraints">Path constraints</a> in the Spine User Guide. */
|
* See <a href="https://esotericsoftware.com/spine-path-constraints">Path constraints</a> in the Spine User Guide. */
|
||||||
public class PathConstraintData extends ConstraintData {
|
public class PathConstraintData extends ConstraintData {
|
||||||
|
final PathConstraintPose setup = new PathConstraintPose();
|
||||||
final Array<BoneData> bones = new Array();
|
final Array<BoneData> bones = new Array();
|
||||||
SlotData slot;
|
SlotData slot;
|
||||||
PositionMode positionMode;
|
PositionMode positionMode;
|
||||||
SpacingMode spacingMode;
|
SpacingMode spacingMode;
|
||||||
RotateMode rotateMode;
|
RotateMode rotateMode;
|
||||||
float offsetRotation;
|
float offsetRotation;
|
||||||
float position, spacing, mixRotate, mixX, mixY;
|
|
||||||
|
|
||||||
public PathConstraintData (String name) {
|
public PathConstraintData (String name) {
|
||||||
super(name);
|
super(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public PathConstraintPose getSetupPose () {
|
||||||
|
return setup;
|
||||||
|
}
|
||||||
|
|
||||||
/** The bones that will be modified by this path constraint. */
|
/** The bones that will be modified by this path constraint. */
|
||||||
public Array<BoneData> getBones () {
|
public Array<BoneData> getBones () {
|
||||||
return bones;
|
return bones;
|
||||||
@ -101,51 +105,6 @@ public class PathConstraintData extends ConstraintData {
|
|||||||
this.offsetRotation = offsetRotation;
|
this.offsetRotation = offsetRotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The position along the path. */
|
|
||||||
public float getPosition () {
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPosition (float position) {
|
|
||||||
this.position = position;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** The spacing between bones. */
|
|
||||||
public float getSpacing () {
|
|
||||||
return spacing;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSpacing (float spacing) {
|
|
||||||
this.spacing = spacing;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A percentage (0-1) that controls the mix between the constrained and unconstrained rotation. */
|
|
||||||
public float getMixRotate () {
|
|
||||||
return mixRotate;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMixRotate (float mixRotate) {
|
|
||||||
this.mixRotate = mixRotate;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A percentage (0-1) that controls the mix between the constrained and unconstrained translation X. */
|
|
||||||
public float getMixX () {
|
|
||||||
return mixX;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMixX (float mixX) {
|
|
||||||
this.mixX = mixX;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A percentage (0-1) that controls the mix between the constrained and unconstrained translation Y. */
|
|
||||||
public float getMixY () {
|
|
||||||
return mixY;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMixY (float mixY) {
|
|
||||||
this.mixY = mixY;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Controls how the first bone is positioned along the path.
|
/** Controls how the first bone is positioned along the path.
|
||||||
* <p>
|
* <p>
|
||||||
* See <a href="https://esotericsoftware.com/spine-path-constraints#Position-mode">Position mode</a> in the Spine User
|
* See <a href="https://esotericsoftware.com/spine-path-constraints#Position-mode">Position mode</a> in the Spine User
|
||||||
|
|||||||
@ -0,0 +1,88 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* 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 a pose for a path constraint. */
|
||||||
|
public class PathConstraintPose {
|
||||||
|
float position, spacing, mixRotate, mixX, mixY;
|
||||||
|
|
||||||
|
public void set (PathConstraintPose pose) {
|
||||||
|
position = pose.position;
|
||||||
|
spacing = pose.spacing;
|
||||||
|
mixRotate = pose.mixRotate;
|
||||||
|
mixX = pose.mixX;
|
||||||
|
mixY = pose.mixY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The position along the path. */
|
||||||
|
public float getPosition () {
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPosition (float position) {
|
||||||
|
this.position = position;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The spacing between bones. */
|
||||||
|
public float getSpacing () {
|
||||||
|
return spacing;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSpacing (float spacing) {
|
||||||
|
this.spacing = spacing;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A percentage (0-1) that controls the mix between the constrained and unconstrained rotation. */
|
||||||
|
public float getMixRotate () {
|
||||||
|
return mixRotate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMixRotate (float mixRotate) {
|
||||||
|
this.mixRotate = mixRotate;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A percentage (0-1) that controls the mix between the constrained and unconstrained translation X. */
|
||||||
|
public float getMixX () {
|
||||||
|
return mixX;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMixX (float mixX) {
|
||||||
|
this.mixX = mixX;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A percentage (0-1) that controls the mix between the constrained and unconstrained translation Y. */
|
||||||
|
public float getMixY () {
|
||||||
|
return mixY;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMixY (float mixY) {
|
||||||
|
this.mixY = mixY;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -38,11 +38,9 @@ public class PhysicsConstraint implements Updatable {
|
|||||||
final PhysicsConstraintData data;
|
final PhysicsConstraintData data;
|
||||||
final Skeleton skeleton;
|
final Skeleton skeleton;
|
||||||
BoneApplied bone;
|
BoneApplied bone;
|
||||||
PhysicsConstraint applied;
|
final PhysicsConstraintPose pose = new PhysicsConstraintPose(), applied = new PhysicsConstraintPose();
|
||||||
boolean active;
|
boolean active;
|
||||||
|
|
||||||
float inertia, strength, damping, massInverse, wind, gravity, mix;
|
|
||||||
|
|
||||||
boolean reset = true;
|
boolean reset = true;
|
||||||
float ux, uy, cx, cy, tx, ty;
|
float ux, uy, cx, cy, tx, ty;
|
||||||
float xOffset, xVelocity;
|
float xOffset, xVelocity;
|
||||||
@ -65,15 +63,13 @@ public class PhysicsConstraint implements Updatable {
|
|||||||
|
|
||||||
bone = skeleton.bones.get(data.bone.index).applied;
|
bone = skeleton.bones.get(data.bone.index).applied;
|
||||||
|
|
||||||
applied = new PhysicsConstraint(data, skeleton, bone);
|
|
||||||
|
|
||||||
setupPose();
|
setupPose();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Copy constructor. */
|
/** Copy constructor. */
|
||||||
public PhysicsConstraint (PhysicsConstraint constraint, Skeleton skeleton) {
|
public PhysicsConstraint (PhysicsConstraint constraint, Skeleton skeleton) {
|
||||||
this(constraint.data, skeleton);
|
this(constraint.data, skeleton);
|
||||||
setupPose();
|
pose.set(constraint.pose);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void reset () {
|
public void reset () {
|
||||||
@ -91,14 +87,7 @@ public class PhysicsConstraint implements Updatable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setupPose () {
|
public void setupPose () {
|
||||||
PhysicsConstraintData data = this.data;
|
pose.set(data.setup);
|
||||||
inertia = data.inertia;
|
|
||||||
strength = data.strength;
|
|
||||||
damping = data.damping;
|
|
||||||
massInverse = data.massInverse;
|
|
||||||
wind = data.wind;
|
|
||||||
gravity = data.gravity;
|
|
||||||
mix = data.mix;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Translates the physics constraint so next {@link #update(Physics)} forces are applied as if the bone moved an additional
|
/** Translates the physics constraint so next {@link #update(Physics)} forces are applied as if the bone moved an additional
|
||||||
@ -120,7 +109,8 @@ public class PhysicsConstraint implements Updatable {
|
|||||||
|
|
||||||
/** Applies the constraint to the constrained bones. */
|
/** Applies the constraint to the constrained bones. */
|
||||||
public void update (Physics physics) {
|
public void update (Physics physics) {
|
||||||
float mix = this.mix;
|
PhysicsConstraintPose pose = applied;
|
||||||
|
float mix = pose.mix;
|
||||||
if (mix == 0) return;
|
if (mix == 0) return;
|
||||||
|
|
||||||
boolean x = data.x > 0, y = data.y > 0, rotateOrShearX = data.rotate > 0 || data.shearX > 0, scaleX = data.scaleX > 0;
|
boolean x = data.x > 0, y = data.y > 0, rotateOrShearX = data.rotate > 0 || data.shearX > 0, scaleX = data.scaleX > 0;
|
||||||
@ -145,7 +135,7 @@ public class PhysicsConstraint implements Updatable {
|
|||||||
ux = bx;
|
ux = bx;
|
||||||
uy = by;
|
uy = by;
|
||||||
} else {
|
} else {
|
||||||
float a = remaining, i = inertia, t = data.step, f = skeleton.data.referenceScale, d = -1;
|
float a = remaining, i = pose.inertia, t = data.step, f = skeleton.data.referenceScale, d = -1;
|
||||||
float qx = data.limit * delta, qy = qx * Math.abs(skeleton.scaleY);
|
float qx = data.limit * delta, qy = qx * Math.abs(skeleton.scaleY);
|
||||||
qx *= Math.abs(skeleton.scaleX);
|
qx *= Math.abs(skeleton.scaleX);
|
||||||
if (x || y) {
|
if (x || y) {
|
||||||
@ -160,8 +150,9 @@ public class PhysicsConstraint implements Updatable {
|
|||||||
uy = by;
|
uy = by;
|
||||||
}
|
}
|
||||||
if (a >= t) {
|
if (a >= t) {
|
||||||
d = (float)Math.pow(damping, 60 * t);
|
d = (float)Math.pow(pose.damping, 60 * t);
|
||||||
float m = massInverse * t, e = strength, w = wind * f * skeleton.scaleX, g = gravity * f * skeleton.scaleY;
|
float m = pose.massInverse * t, e = pose.strength, w = pose.wind * f * skeleton.scaleX,
|
||||||
|
g = pose.gravity * f * skeleton.scaleY;
|
||||||
do {
|
do {
|
||||||
if (x) {
|
if (x) {
|
||||||
xVelocity += (w - xOffset * e) * m;
|
xVelocity += (w - xOffset * e) * m;
|
||||||
@ -209,8 +200,8 @@ public class PhysicsConstraint implements Updatable {
|
|||||||
}
|
}
|
||||||
a = remaining;
|
a = remaining;
|
||||||
if (a >= t) {
|
if (a >= t) {
|
||||||
if (d == -1) d = (float)Math.pow(damping, 60 * t);
|
if (d == -1) d = (float)Math.pow(pose.damping, 60 * t);
|
||||||
float m = massInverse * t, e = strength, w = wind, g = gravity, h = l / f;
|
float m = pose.massInverse * t, e = pose.strength, w = pose.wind, g = pose.gravity, h = l / f;
|
||||||
while (true) {
|
while (true) {
|
||||||
a -= t;
|
a -= t;
|
||||||
if (scaleX) {
|
if (scaleX) {
|
||||||
@ -283,6 +274,15 @@ public class PhysicsConstraint implements Updatable {
|
|||||||
bone.updateLocalTransform();
|
bone.updateLocalTransform();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** The physics constraint's setup pose data. */
|
||||||
|
public PhysicsConstraintData getData () {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Skeleton getSkeleton () {
|
||||||
|
return skeleton;
|
||||||
|
}
|
||||||
|
|
||||||
/** The bone constrained by this physics constraint. */
|
/** The bone constrained by this physics constraint. */
|
||||||
public BoneApplied getBone () {
|
public BoneApplied getBone () {
|
||||||
return bone;
|
return bone;
|
||||||
@ -292,61 +292,12 @@ public class PhysicsConstraint implements Updatable {
|
|||||||
this.bone = bone;
|
this.bone = bone;
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getInertia () {
|
public PhysicsConstraintPose getPose () {
|
||||||
return inertia;
|
return pose;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setInertia (float inertia) {
|
public PhysicsConstraintPose getAppliedPose () {
|
||||||
this.inertia = inertia;
|
return applied;
|
||||||
}
|
|
||||||
|
|
||||||
public float getStrength () {
|
|
||||||
return strength;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setStrength (float strength) {
|
|
||||||
this.strength = strength;
|
|
||||||
}
|
|
||||||
|
|
||||||
public float getDamping () {
|
|
||||||
return damping;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDamping (float damping) {
|
|
||||||
this.damping = damping;
|
|
||||||
}
|
|
||||||
|
|
||||||
public float getMassInverse () {
|
|
||||||
return massInverse;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMassInverse (float massInverse) {
|
|
||||||
this.massInverse = massInverse;
|
|
||||||
}
|
|
||||||
|
|
||||||
public float getWind () {
|
|
||||||
return wind;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setWind (float wind) {
|
|
||||||
this.wind = wind;
|
|
||||||
}
|
|
||||||
|
|
||||||
public float getGravity () {
|
|
||||||
return gravity;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setGravity (float gravity) {
|
|
||||||
this.gravity = gravity;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A percentage (0-1) that controls the mix between the constrained and unconstrained poses. */
|
|
||||||
public float getMix () {
|
|
||||||
return mix;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMix (float mix) {
|
|
||||||
this.mix = mix;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns false when this constraint won't be updated by
|
/** Returns false when this constraint won't be updated by
|
||||||
@ -360,11 +311,6 @@ public class PhysicsConstraint implements Updatable {
|
|||||||
return active;
|
return active;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The physics constraint's setup pose data. */
|
|
||||||
public PhysicsConstraintData getData () {
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString () {
|
public String toString () {
|
||||||
return data.name;
|
return data.name;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -33,15 +33,19 @@ package com.esotericsoftware.spine;
|
|||||||
* <p>
|
* <p>
|
||||||
* See <a href="https://esotericsoftware.com/spine-physics-constraints">Physics constraints</a> in the Spine User Guide. */
|
* See <a href="https://esotericsoftware.com/spine-physics-constraints">Physics constraints</a> in the Spine User Guide. */
|
||||||
public class PhysicsConstraintData extends ConstraintData {
|
public class PhysicsConstraintData extends ConstraintData {
|
||||||
|
final PhysicsConstraintPose setup = new PhysicsConstraintPose();
|
||||||
BoneData bone;
|
BoneData bone;
|
||||||
float x, y, rotate, scaleX, shearX, limit;
|
float x, y, rotate, scaleX, shearX, limit, step;
|
||||||
float step, inertia, strength, damping, massInverse, wind, gravity, mix;
|
|
||||||
boolean inertiaGlobal, strengthGlobal, dampingGlobal, massGlobal, windGlobal, gravityGlobal, mixGlobal;
|
boolean inertiaGlobal, strengthGlobal, dampingGlobal, massGlobal, windGlobal, gravityGlobal, mixGlobal;
|
||||||
|
|
||||||
public PhysicsConstraintData (String name) {
|
public PhysicsConstraintData (String name) {
|
||||||
super(name);
|
super(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public PhysicsConstraintPose getSetupPose () {
|
||||||
|
return setup;
|
||||||
|
}
|
||||||
|
|
||||||
/** The bone constrained by this physics constraint. */
|
/** The bone constrained by this physics constraint. */
|
||||||
public BoneData getBone () {
|
public BoneData getBone () {
|
||||||
return bone;
|
return bone;
|
||||||
@ -107,63 +111,6 @@ public class PhysicsConstraintData extends ConstraintData {
|
|||||||
this.limit = limit;
|
this.limit = limit;
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getInertia () {
|
|
||||||
return inertia;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setInertia (float inertia) {
|
|
||||||
this.inertia = inertia;
|
|
||||||
}
|
|
||||||
|
|
||||||
public float getStrength () {
|
|
||||||
return strength;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setStrength (float strength) {
|
|
||||||
this.strength = strength;
|
|
||||||
}
|
|
||||||
|
|
||||||
public float getDamping () {
|
|
||||||
return damping;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDamping (float damping) {
|
|
||||||
this.damping = damping;
|
|
||||||
}
|
|
||||||
|
|
||||||
public float getMassInverse () {
|
|
||||||
return massInverse;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMassInverse (float massInverse) {
|
|
||||||
this.massInverse = massInverse;
|
|
||||||
}
|
|
||||||
|
|
||||||
public float getWind () {
|
|
||||||
return wind;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setWind (float wind) {
|
|
||||||
this.wind = wind;
|
|
||||||
}
|
|
||||||
|
|
||||||
public float getGravity () {
|
|
||||||
return gravity;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setGravity (float gravity) {
|
|
||||||
this.gravity = gravity;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A percentage (0-1) that controls the mix between the constrained and unconstrained poses. */
|
|
||||||
public float getMix () {
|
|
||||||
return mix;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMix (float mix) {
|
|
||||||
this.mix = mix;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean getInertiaGlobal () {
|
public boolean getInertiaGlobal () {
|
||||||
return inertiaGlobal;
|
return inertiaGlobal;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,102 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* 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 a pose for a physics constraint. */
|
||||||
|
public class PhysicsConstraintPose {
|
||||||
|
float inertia, strength, damping, massInverse, wind, gravity, mix;
|
||||||
|
|
||||||
|
public void set (PhysicsConstraintPose pose) {
|
||||||
|
inertia = pose.inertia;
|
||||||
|
strength = pose.strength;
|
||||||
|
damping = pose.damping;
|
||||||
|
massInverse = pose.massInverse;
|
||||||
|
wind = pose.wind;
|
||||||
|
gravity = pose.gravity;
|
||||||
|
mix = pose.mix;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getInertia () {
|
||||||
|
return inertia;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInertia (float inertia) {
|
||||||
|
this.inertia = inertia;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getStrength () {
|
||||||
|
return strength;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStrength (float strength) {
|
||||||
|
this.strength = strength;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getDamping () {
|
||||||
|
return damping;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDamping (float damping) {
|
||||||
|
this.damping = damping;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getMassInverse () {
|
||||||
|
return massInverse;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMassInverse (float massInverse) {
|
||||||
|
this.massInverse = massInverse;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getWind () {
|
||||||
|
return wind;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setWind (float wind) {
|
||||||
|
this.wind = wind;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getGravity () {
|
||||||
|
return gravity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGravity (float gravity) {
|
||||||
|
this.gravity = gravity;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A percentage (0-1) that controls the mix between the constrained and unconstrained poses. */
|
||||||
|
public float getMix () {
|
||||||
|
return mix;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMix (float mix) {
|
||||||
|
this.mix = mix;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -38,7 +38,6 @@ import com.badlogic.gdx.utils.FloatArray;
|
|||||||
import com.badlogic.gdx.utils.Null;
|
import com.badlogic.gdx.utils.Null;
|
||||||
|
|
||||||
import com.esotericsoftware.spine.Animation.BoneTimeline;
|
import com.esotericsoftware.spine.Animation.BoneTimeline;
|
||||||
import com.esotericsoftware.spine.Animation.Timeline;
|
|
||||||
import com.esotericsoftware.spine.Skin.SkinEntry;
|
import com.esotericsoftware.spine.Skin.SkinEntry;
|
||||||
import com.esotericsoftware.spine.attachments.Attachment;
|
import com.esotericsoftware.spine.attachments.Attachment;
|
||||||
import com.esotericsoftware.spine.attachments.ClippingAttachment;
|
import com.esotericsoftware.spine.attachments.ClippingAttachment;
|
||||||
@ -256,21 +255,24 @@ public class Skeleton {
|
|||||||
constraint.active = !constraint.data.skinRequired || (skin != null && skin.constraints.contains(constraint.data, true));
|
constraint.active = !constraint.data.skinRequired || (skin != null && skin.constraints.contains(constraint.data, true));
|
||||||
if (!constraint.active) return;
|
if (!constraint.active) return;
|
||||||
|
|
||||||
|
Object[] timelines = constraint.data.animation.timelines.items;
|
||||||
|
int timelineCount = constraint.data.animation.timelines.size;
|
||||||
|
|
||||||
Object[] bones = this.bones.items;
|
Object[] bones = this.bones.items;
|
||||||
for (Timeline timeline : constraint.animation.timelines)
|
for (int i = 0; i < timelineCount; i++)
|
||||||
if (timeline instanceof BoneTimeline boneTimeline) sortBone((Bone)bones[boneTimeline.getBoneIndex()]);
|
if (timelines[i] instanceof BoneTimeline boneTimeline) sortBone((Bone)bones[boneTimeline.getBoneIndex()]);
|
||||||
|
|
||||||
updateCache.add(constraint);
|
updateCache.add(constraint);
|
||||||
|
|
||||||
for (Timeline timeline : constraint.animation.timelines) {
|
for (int i = 0; i < timelineCount; i++) {
|
||||||
if (timeline instanceof BoneTimeline boneTimeline) {
|
if (timelines[i] instanceof BoneTimeline boneTimeline) {
|
||||||
var bone = (Bone)bones[boneTimeline.getBoneIndex()];
|
var bone = (Bone)bones[boneTimeline.getBoneIndex()];
|
||||||
sortReset(bone.children);
|
sortReset(bone.children);
|
||||||
bone.sorted = false;
|
bone.sorted = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (Timeline timeline : constraint.animation.timelines)
|
for (int i = 0; i < timelineCount; i++)
|
||||||
if (timeline instanceof BoneTimeline boneTimeline) sortBone((Bone)bones[boneTimeline.getBoneIndex()]);
|
if (timelines[i] instanceof BoneTimeline boneTimeline) sortBone((Bone)bones[boneTimeline.getBoneIndex()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sortIkConstraint (IkConstraint constraint) {
|
private void sortIkConstraint (IkConstraint constraint) {
|
||||||
@ -347,9 +349,9 @@ public class Skeleton {
|
|||||||
updateCache.add(constraint);
|
updateCache.add(constraint);
|
||||||
|
|
||||||
for (int i = 0; i < boneCount; i++)
|
for (int i = 0; i < boneCount; i++)
|
||||||
sortReset(((Bone)constrained[i]).children);
|
sortReset(((BoneApplied)constrained[i]).bone.children);
|
||||||
for (int i = 0; i < boneCount; i++)
|
for (int i = 0; i < boneCount; i++)
|
||||||
((Bone)constrained[i]).sorted = true;
|
((BoneApplied)constrained[i]).bone.sorted = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sortPathConstraintAttachment (Skin skin, int slotIndex, Bone slotBone) {
|
private void sortPathConstraintAttachment (Skin skin, int slotIndex, Bone slotBone) {
|
||||||
@ -371,7 +373,7 @@ public class Skeleton {
|
|||||||
int nn = pathBones[i++];
|
int nn = pathBones[i++];
|
||||||
nn += i;
|
nn += i;
|
||||||
while (i < nn)
|
while (i < nn)
|
||||||
sortBone(((BoneApplied)bones[pathBones[i++]]).bone);
|
sortBone((Bone)bones[pathBones[i++]]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -428,8 +430,26 @@ public class Skeleton {
|
|||||||
var constraint = (IkConstraint)objects[i];
|
var constraint = (IkConstraint)objects[i];
|
||||||
if (constraint.active) constraint.applied.set(constraint.pose);
|
if (constraint.active) constraint.applied.set(constraint.pose);
|
||||||
}
|
}
|
||||||
|
objects = pathConstraints.items;
|
||||||
// BOZO! - Reset the rest.
|
for (int i = 0, n = pathConstraints.size; i < n; i++) {
|
||||||
|
var constraint = (PathConstraint)objects[i];
|
||||||
|
if (constraint.active) constraint.applied.set(constraint.pose);
|
||||||
|
}
|
||||||
|
objects = transformConstraints.items;
|
||||||
|
for (int i = 0, n = transformConstraints.size; i < n; i++) {
|
||||||
|
var constraint = (TransformConstraint)objects[i];
|
||||||
|
if (constraint.active) constraint.applied.set(constraint.pose);
|
||||||
|
}
|
||||||
|
objects = physicsConstraints.items;
|
||||||
|
for (int i = 0, n = physicsConstraints.size; i < n; i++) {
|
||||||
|
var constraint = (PhysicsConstraint)objects[i];
|
||||||
|
if (constraint.active) constraint.applied.set(constraint.pose);
|
||||||
|
}
|
||||||
|
objects = sliders.items;
|
||||||
|
for (int i = 0, n = sliders.size; i < n; i++) {
|
||||||
|
var constraint = (Slider)objects[i];
|
||||||
|
if (constraint.active) constraint.applied.set(constraint.pose);
|
||||||
|
}
|
||||||
|
|
||||||
Object[] updateCache = this.updateCache.items;
|
Object[] updateCache = this.updateCache.items;
|
||||||
for (int i = 0, n = this.updateCache.size; i < n; i++)
|
for (int i = 0, n = this.updateCache.size; i < n; i++)
|
||||||
@ -444,12 +464,41 @@ public class Skeleton {
|
|||||||
public void updateWorldTransform (Physics physics, BoneApplied parent) {
|
public void updateWorldTransform (Physics physics, BoneApplied parent) {
|
||||||
if (parent == null) throw new IllegalArgumentException("parent cannot be null.");
|
if (parent == null) throw new IllegalArgumentException("parent cannot be null.");
|
||||||
|
|
||||||
Object[] bones = this.bones.items;
|
Object[] objects = this.bones.items;
|
||||||
for (int i = 1, n = this.bones.size; i < n; i++) { // Skip root bone.
|
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);
|
||||||
}
|
}
|
||||||
// BOZO! - Reset the rest.
|
objects = this.slots.items;
|
||||||
|
for (int i = 0, n = this.slots.size; i < n; i++) {
|
||||||
|
var slot = (Slot)objects[i];
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
objects = pathConstraints.items;
|
||||||
|
for (int i = 0, n = pathConstraints.size; i < n; i++) {
|
||||||
|
var constraint = (PathConstraint)objects[i];
|
||||||
|
if (constraint.active) constraint.applied.set(constraint.pose);
|
||||||
|
}
|
||||||
|
objects = transformConstraints.items;
|
||||||
|
for (int i = 0, n = transformConstraints.size; i < n; i++) {
|
||||||
|
var constraint = (TransformConstraint)objects[i];
|
||||||
|
if (constraint.active) constraint.applied.set(constraint.pose);
|
||||||
|
}
|
||||||
|
objects = physicsConstraints.items;
|
||||||
|
for (int i = 0, n = physicsConstraints.size; i < n; i++) {
|
||||||
|
var constraint = (PhysicsConstraint)objects[i];
|
||||||
|
if (constraint.active) constraint.applied.set(constraint.pose);
|
||||||
|
}
|
||||||
|
objects = sliders.items;
|
||||||
|
for (int i = 0, n = sliders.size; i < n; i++) {
|
||||||
|
var constraint = (Slider)objects[i];
|
||||||
|
if (constraint.active) constraint.applied.set(constraint.pose);
|
||||||
|
}
|
||||||
|
|
||||||
// Apply the parent bone transform to the root bone. The root bone always inherits scale, rotation and reflection.
|
// Apply the parent bone transform to the root bone. The root bone always inherits scale, rotation and reflection.
|
||||||
BoneApplied rootBone = getRootBone().applied;
|
BoneApplied rootBone = getRootBone().applied;
|
||||||
|
|||||||
@ -343,12 +343,13 @@ public class SkeletonBinary extends SkeletonLoader {
|
|||||||
if ((flags & 16) != 0) data.offsetScaleY = input.readFloat();
|
if ((flags & 16) != 0) data.offsetScaleY = input.readFloat();
|
||||||
if ((flags & 32) != 0) data.offsetShearY = input.readFloat();
|
if ((flags & 32) != 0) data.offsetShearY = input.readFloat();
|
||||||
flags = input.read();
|
flags = input.read();
|
||||||
if ((flags & 1) != 0) data.mixRotate = input.readFloat();
|
TransformConstraintPose setup = data.getSetupPose();
|
||||||
if ((flags & 2) != 0) data.mixX = input.readFloat();
|
if ((flags & 1) != 0) setup.mixRotate = input.readFloat();
|
||||||
if ((flags & 4) != 0) data.mixY = input.readFloat();
|
if ((flags & 2) != 0) setup.mixX = input.readFloat();
|
||||||
if ((flags & 8) != 0) data.mixScaleX = input.readFloat();
|
if ((flags & 4) != 0) setup.mixY = input.readFloat();
|
||||||
if ((flags & 16) != 0) data.mixScaleY = input.readFloat();
|
if ((flags & 8) != 0) setup.mixScaleX = input.readFloat();
|
||||||
if ((flags & 32) != 0) data.mixShearY = input.readFloat();
|
if ((flags & 16) != 0) setup.mixScaleY = input.readFloat();
|
||||||
|
if ((flags & 32) != 0) setup.mixShearY = input.readFloat();
|
||||||
o[i] = data;
|
o[i] = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -367,13 +368,14 @@ public class SkeletonBinary extends SkeletonLoader {
|
|||||||
data.spacingMode = SpacingMode.values[(flags >> 1) & 3];
|
data.spacingMode = SpacingMode.values[(flags >> 1) & 3];
|
||||||
data.rotateMode = RotateMode.values[(flags >> 3) & 3];
|
data.rotateMode = RotateMode.values[(flags >> 3) & 3];
|
||||||
if ((flags & 128) != 0) data.offsetRotation = input.readFloat();
|
if ((flags & 128) != 0) data.offsetRotation = input.readFloat();
|
||||||
data.position = input.readFloat();
|
PathConstraintPose setup = data.setup;
|
||||||
if (data.positionMode == PositionMode.fixed) data.position *= scale;
|
setup.position = input.readFloat();
|
||||||
data.spacing = input.readFloat();
|
if (data.positionMode == PositionMode.fixed) setup.position *= scale;
|
||||||
if (data.spacingMode == SpacingMode.length || data.spacingMode == SpacingMode.fixed) data.spacing *= scale;
|
setup.spacing = input.readFloat();
|
||||||
data.mixRotate = input.readFloat();
|
if (data.spacingMode == SpacingMode.length || data.spacingMode == SpacingMode.fixed) setup.spacing *= scale;
|
||||||
data.mixX = input.readFloat();
|
setup.mixRotate = input.readFloat();
|
||||||
data.mixY = input.readFloat();
|
setup.mixX = input.readFloat();
|
||||||
|
setup.mixY = input.readFloat();
|
||||||
o[i] = data;
|
o[i] = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -392,12 +394,13 @@ public class SkeletonBinary extends SkeletonLoader {
|
|||||||
if ((flags & 32) != 0) data.shearX = input.readFloat();
|
if ((flags & 32) != 0) data.shearX = input.readFloat();
|
||||||
data.limit = ((flags & 64) != 0 ? input.readFloat() : 5000) * scale;
|
data.limit = ((flags & 64) != 0 ? input.readFloat() : 5000) * scale;
|
||||||
data.step = 1f / input.readUnsignedByte();
|
data.step = 1f / input.readUnsignedByte();
|
||||||
data.inertia = input.readFloat();
|
PhysicsConstraintPose setup = data.getSetupPose();
|
||||||
data.strength = input.readFloat();
|
setup.inertia = input.readFloat();
|
||||||
data.damping = input.readFloat();
|
setup.strength = input.readFloat();
|
||||||
data.massInverse = (flags & 128) != 0 ? input.readFloat() : 1;
|
setup.damping = input.readFloat();
|
||||||
data.wind = input.readFloat();
|
setup.massInverse = (flags & 128) != 0 ? input.readFloat() : 1;
|
||||||
data.gravity = input.readFloat();
|
setup.wind = input.readFloat();
|
||||||
|
setup.gravity = input.readFloat();
|
||||||
flags = input.read();
|
flags = input.read();
|
||||||
if ((flags & 1) != 0) data.inertiaGlobal = true;
|
if ((flags & 1) != 0) data.inertiaGlobal = true;
|
||||||
if ((flags & 2) != 0) data.strengthGlobal = true;
|
if ((flags & 2) != 0) data.strengthGlobal = true;
|
||||||
@ -406,7 +409,7 @@ public class SkeletonBinary extends SkeletonLoader {
|
|||||||
if ((flags & 16) != 0) data.windGlobal = true;
|
if ((flags & 16) != 0) data.windGlobal = true;
|
||||||
if ((flags & 32) != 0) data.gravityGlobal = true;
|
if ((flags & 32) != 0) data.gravityGlobal = true;
|
||||||
if ((flags & 64) != 0) data.mixGlobal = true;
|
if ((flags & 64) != 0) data.mixGlobal = true;
|
||||||
data.mix = (flags & 128) != 0 ? input.readFloat() : 1;
|
setup.mix = (flags & 128) != 0 ? input.readFloat() : 1;
|
||||||
o[i] = data;
|
o[i] = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -330,12 +330,13 @@ public class SkeletonJson extends SkeletonLoader {
|
|||||||
data.offsetScaleY = constraintMap.getFloat("scaleY", 0);
|
data.offsetScaleY = constraintMap.getFloat("scaleY", 0);
|
||||||
data.offsetShearY = constraintMap.getFloat("shearY", 0);
|
data.offsetShearY = constraintMap.getFloat("shearY", 0);
|
||||||
|
|
||||||
if (rotate) data.mixRotate = constraintMap.getFloat("mixRotate", 1);
|
TransformConstraintPose setup = data.setup;
|
||||||
if (x) data.mixX = constraintMap.getFloat("mixX", 1);
|
if (rotate) setup.mixRotate = constraintMap.getFloat("mixRotate", 1);
|
||||||
if (y) data.mixY = constraintMap.getFloat("mixY", data.mixX);
|
if (x) setup.mixX = constraintMap.getFloat("mixX", 1);
|
||||||
if (scaleX) data.mixScaleX = constraintMap.getFloat("mixScaleX", 1);
|
if (y) setup.mixY = constraintMap.getFloat("mixY", setup.mixX);
|
||||||
if (scaleY) data.mixScaleY = constraintMap.getFloat("mixScaleY", data.mixScaleX);
|
if (scaleX) setup.mixScaleX = constraintMap.getFloat("mixScaleX", 1);
|
||||||
if (shearY) data.mixShearY = constraintMap.getFloat("mixShearY", 1);
|
if (scaleY) setup.mixScaleY = constraintMap.getFloat("mixScaleY", setup.mixScaleX);
|
||||||
|
if (shearY) setup.mixShearY = constraintMap.getFloat("mixShearY", 1);
|
||||||
|
|
||||||
skeletonData.transformConstraints.add(data);
|
skeletonData.transformConstraints.add(data);
|
||||||
}
|
}
|
||||||
@ -360,13 +361,14 @@ public class SkeletonJson extends SkeletonLoader {
|
|||||||
data.spacingMode = SpacingMode.valueOf(constraintMap.getString("spacingMode", "length"));
|
data.spacingMode = SpacingMode.valueOf(constraintMap.getString("spacingMode", "length"));
|
||||||
data.rotateMode = RotateMode.valueOf(constraintMap.getString("rotateMode", "tangent"));
|
data.rotateMode = RotateMode.valueOf(constraintMap.getString("rotateMode", "tangent"));
|
||||||
data.offsetRotation = constraintMap.getFloat("rotation", 0);
|
data.offsetRotation = constraintMap.getFloat("rotation", 0);
|
||||||
data.position = constraintMap.getFloat("position", 0);
|
PathConstraintPose setup = data.setup;
|
||||||
if (data.positionMode == PositionMode.fixed) data.position *= scale;
|
setup.position = constraintMap.getFloat("position", 0);
|
||||||
data.spacing = constraintMap.getFloat("spacing", 0);
|
if (data.positionMode == PositionMode.fixed) setup.position *= scale;
|
||||||
if (data.spacingMode == SpacingMode.length || data.spacingMode == SpacingMode.fixed) data.spacing *= scale;
|
setup.spacing = constraintMap.getFloat("spacing", 0);
|
||||||
data.mixRotate = constraintMap.getFloat("mixRotate", 1);
|
if (data.spacingMode == SpacingMode.length || data.spacingMode == SpacingMode.fixed) setup.spacing *= scale;
|
||||||
data.mixX = constraintMap.getFloat("mixX", 1);
|
setup.mixRotate = constraintMap.getFloat("mixRotate", 1);
|
||||||
data.mixY = constraintMap.getFloat("mixY", 1);
|
setup.mixX = constraintMap.getFloat("mixX", 1);
|
||||||
|
setup.mixY = constraintMap.getFloat("mixY", 1);
|
||||||
|
|
||||||
skeletonData.pathConstraints.add(data);
|
skeletonData.pathConstraints.add(data);
|
||||||
}
|
}
|
||||||
@ -388,13 +390,14 @@ public class SkeletonJson extends SkeletonLoader {
|
|||||||
data.shearX = constraintMap.getFloat("shearX", 0);
|
data.shearX = constraintMap.getFloat("shearX", 0);
|
||||||
data.limit = constraintMap.getFloat("limit", 5000) * scale;
|
data.limit = constraintMap.getFloat("limit", 5000) * scale;
|
||||||
data.step = 1f / constraintMap.getInt("fps", 60);
|
data.step = 1f / constraintMap.getInt("fps", 60);
|
||||||
data.inertia = constraintMap.getFloat("inertia", 1);
|
PhysicsConstraintPose setup = data.getSetupPose();
|
||||||
data.strength = constraintMap.getFloat("strength", 100);
|
setup.inertia = constraintMap.getFloat("inertia", 1);
|
||||||
data.damping = constraintMap.getFloat("damping", 1);
|
setup.strength = constraintMap.getFloat("strength", 100);
|
||||||
data.massInverse = 1 / constraintMap.getFloat("mass", 1);
|
setup.damping = constraintMap.getFloat("damping", 1);
|
||||||
data.wind = constraintMap.getFloat("wind", 0);
|
setup.massInverse = 1 / constraintMap.getFloat("mass", 1);
|
||||||
data.gravity = constraintMap.getFloat("gravity", 0);
|
setup.wind = constraintMap.getFloat("wind", 0);
|
||||||
data.mix = constraintMap.getFloat("mix", 1);
|
setup.gravity = constraintMap.getFloat("gravity", 0);
|
||||||
|
setup.mix = constraintMap.getFloat("mix", 1);
|
||||||
data.inertiaGlobal = constraintMap.getBoolean("inertiaGlobal", false);
|
data.inertiaGlobal = constraintMap.getBoolean("inertiaGlobal", false);
|
||||||
data.strengthGlobal = constraintMap.getBoolean("strengthGlobal", false);
|
data.strengthGlobal = constraintMap.getBoolean("strengthGlobal", false);
|
||||||
data.dampingGlobal = constraintMap.getBoolean("dampingGlobal", false);
|
data.dampingGlobal = constraintMap.getBoolean("dampingGlobal", false);
|
||||||
|
|||||||
@ -38,8 +38,7 @@ import com.esotericsoftware.spine.Animation.MixDirection;
|
|||||||
public class Slider implements Updatable {
|
public class Slider implements Updatable {
|
||||||
final SliderData data;
|
final SliderData data;
|
||||||
final Skeleton skeleton;
|
final Skeleton skeleton;
|
||||||
Animation animation;
|
final SliderPose pose = new SliderPose(), applied = new SliderPose();
|
||||||
float time, mix;
|
|
||||||
|
|
||||||
boolean active;
|
boolean active;
|
||||||
|
|
||||||
@ -59,14 +58,20 @@ public class Slider implements Updatable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void update (Physics physics) {
|
public void update (Physics physics) {
|
||||||
animation.apply(skeleton, time, time, false, null, mix, MixBlend.replace, MixDirection.in, true);
|
SliderPose pose = applied;
|
||||||
|
data.animation.apply(skeleton, pose.time, pose.time, false, null, pose.mix, MixBlend.replace, MixDirection.in, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setupPose () {
|
public void setupPose () {
|
||||||
SliderData data = this.data;
|
pose.set(data.setup);
|
||||||
animation = data.animation;
|
}
|
||||||
time = data.time;
|
|
||||||
mix = data.mix;
|
public SliderPose getPose () {
|
||||||
|
return pose;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SliderPose getAppliedPose () {
|
||||||
|
return applied;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns false when this constraint won't be updated by
|
/** Returns false when this constraint won't be updated by
|
||||||
@ -80,27 +85,7 @@ public class Slider implements Updatable {
|
|||||||
return active;
|
return active;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Animation getAnimation () {
|
public String toString () {
|
||||||
return animation;
|
return data.name;
|
||||||
}
|
|
||||||
|
|
||||||
public void setAnimation (Animation animation) {
|
|
||||||
this.animation = animation;
|
|
||||||
}
|
|
||||||
|
|
||||||
public float getTime () {
|
|
||||||
return time;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTime (float time) {
|
|
||||||
this.time = time;
|
|
||||||
}
|
|
||||||
|
|
||||||
public float getMix () {
|
|
||||||
return mix;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMix (float mix) {
|
|
||||||
this.mix = mix;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -33,13 +33,17 @@ package com.esotericsoftware.spine;
|
|||||||
* <p>
|
* <p>
|
||||||
* See <a href="https://esotericsoftware.com/spine-physics-constraints">Physics constraints</a> in the Spine User Guide. */
|
* See <a href="https://esotericsoftware.com/spine-physics-constraints">Physics constraints</a> in the Spine User Guide. */
|
||||||
public class SliderData extends ConstraintData {
|
public class SliderData extends ConstraintData {
|
||||||
|
final SliderPose setup = new SliderPose();
|
||||||
Animation animation;
|
Animation animation;
|
||||||
float time, mix;
|
|
||||||
|
|
||||||
public SliderData (String name) {
|
public SliderData (String name) {
|
||||||
super(name);
|
super(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SliderPose getSetupPose () {
|
||||||
|
return setup;
|
||||||
|
}
|
||||||
|
|
||||||
public Animation getAnimation () {
|
public Animation getAnimation () {
|
||||||
return animation;
|
return animation;
|
||||||
}
|
}
|
||||||
@ -47,20 +51,4 @@ public class SliderData extends ConstraintData {
|
|||||||
public void setAnimation (Animation animation) {
|
public void setAnimation (Animation animation) {
|
||||||
this.animation = animation;
|
this.animation = animation;
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getTime () {
|
|
||||||
return time;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTime (float time) {
|
|
||||||
this.time = time;
|
|
||||||
}
|
|
||||||
|
|
||||||
public float getMix () {
|
|
||||||
return mix;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMix (float mix) {
|
|
||||||
this.mix = mix;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,57 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* 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 a pose for a slider. */
|
||||||
|
public class SliderPose {
|
||||||
|
float time, mix;
|
||||||
|
|
||||||
|
public void set (SliderPose pose) {
|
||||||
|
time = pose.time;
|
||||||
|
mix = pose.mix;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public float getTime () {
|
||||||
|
return time;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTime (float time) {
|
||||||
|
this.time = time;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getMix () {
|
||||||
|
return mix;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMix (float mix) {
|
||||||
|
this.mix = mix;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -44,11 +44,9 @@ public class TransformConstraint implements Updatable {
|
|||||||
final TransformConstraintData data;
|
final TransformConstraintData data;
|
||||||
final Array<BoneApplied> bones;
|
final Array<BoneApplied> bones;
|
||||||
BoneApplied source;
|
BoneApplied source;
|
||||||
TransformConstraint applied;
|
final TransformConstraintPose pose = new TransformConstraintPose(), applied = new TransformConstraintPose();
|
||||||
boolean active;
|
boolean active;
|
||||||
|
|
||||||
float mixRotate, mixX, mixY, mixScaleX, mixScaleY, mixShearY;
|
|
||||||
|
|
||||||
public TransformConstraint (TransformConstraintData data, Array<BoneApplied> bones, BoneApplied source) {
|
public TransformConstraint (TransformConstraintData data, Array<BoneApplied> bones, BoneApplied source) {
|
||||||
this.data = data;
|
this.data = data;
|
||||||
this.bones = bones;
|
this.bones = bones;
|
||||||
@ -66,30 +64,24 @@ public class TransformConstraint implements Updatable {
|
|||||||
|
|
||||||
source = skeleton.bones.get(data.source.index).applied;
|
source = skeleton.bones.get(data.source.index).applied;
|
||||||
|
|
||||||
applied = new TransformConstraint(data, bones, source);
|
|
||||||
|
|
||||||
setupPose();
|
setupPose();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Copy constructor. */
|
/** Copy constructor. */
|
||||||
public TransformConstraint (TransformConstraint constraint, Skeleton skeleton) {
|
public TransformConstraint (TransformConstraint constraint, Skeleton skeleton) {
|
||||||
this(constraint.data, skeleton);
|
this(constraint.data, skeleton);
|
||||||
setupPose();
|
pose.set(constraint.pose);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setupPose () {
|
public void setupPose () {
|
||||||
TransformConstraintData data = this.data;
|
pose.set(data.setup);
|
||||||
mixRotate = data.mixRotate;
|
|
||||||
mixX = data.mixX;
|
|
||||||
mixY = data.mixY;
|
|
||||||
mixScaleX = data.mixScaleX;
|
|
||||||
mixScaleY = data.mixScaleY;
|
|
||||||
mixShearY = data.mixShearY;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 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 (mixRotate == 0 && mixX == 0 && mixY == 0 && mixScaleX == 0 && mixScaleY == 0 && mixShearY == 0) return;
|
TransformConstraintPose pose = applied;
|
||||||
|
if (pose.mixRotate == 0 && pose.mixX == 0 && pose.mixY == 0 && pose.mixScaleX == 0 && pose.mixScaleY == 0
|
||||||
|
&& pose.mixShearY == 0) return;
|
||||||
|
|
||||||
TransformConstraintData data = this.data;
|
TransformConstraintData data = this.data;
|
||||||
boolean localFrom = data.localSource, localTarget = data.localTarget, additive = data.additive, clamp = data.clamp;
|
boolean localFrom = data.localSource, localTarget = data.localTarget, additive = data.additive, clamp = data.clamp;
|
||||||
@ -105,7 +97,7 @@ public class TransformConstraint implements Updatable {
|
|||||||
Object[] toItems = from.to.items;
|
Object[] toItems = from.to.items;
|
||||||
for (int t = 0, tn = from.to.size; t < tn; t++) {
|
for (int t = 0, tn = from.to.size; t < tn; t++) {
|
||||||
var to = (ToProperty)toItems[t];
|
var to = (ToProperty)toItems[t];
|
||||||
if (to.mix(this) != 0) {
|
if (to.mix(pose) != 0) {
|
||||||
float clamped = to.offset + value * to.scale;
|
float clamped = to.offset + value * to.scale;
|
||||||
if (clamp) {
|
if (clamp) {
|
||||||
if (to.offset < to.max)
|
if (to.offset < to.max)
|
||||||
@ -113,7 +105,7 @@ public class TransformConstraint implements Updatable {
|
|||||||
else
|
else
|
||||||
clamped = clamp(clamped, to.max, to.offset);
|
clamped = clamp(clamped, to.max, to.offset);
|
||||||
}
|
}
|
||||||
to.apply(this, bone, clamped, localTarget, additive);
|
to.apply(pose, bone, clamped, localTarget, additive);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -139,58 +131,12 @@ public class TransformConstraint implements Updatable {
|
|||||||
this.source = source;
|
this.source = source;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A percentage (0-1) that controls the mix between the constrained and unconstrained rotation. */
|
public TransformConstraintPose getPose () {
|
||||||
public float getMixRotate () {
|
return pose;
|
||||||
return mixRotate;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setMixRotate (float mixRotate) {
|
public TransformConstraintPose getAppliedPose () {
|
||||||
this.mixRotate = mixRotate;
|
return applied;
|
||||||
}
|
|
||||||
|
|
||||||
/** A percentage (0-1) that controls the mix between the constrained and unconstrained translation X. */
|
|
||||||
public float getMixX () {
|
|
||||||
return mixX;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMixX (float mixX) {
|
|
||||||
this.mixX = mixX;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A percentage (0-1) that controls the mix between the constrained and unconstrained translation Y. */
|
|
||||||
public float getMixY () {
|
|
||||||
return mixY;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMixY (float mixY) {
|
|
||||||
this.mixY = mixY;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A percentage (0-1) that controls the mix between the constrained and unconstrained scale X. */
|
|
||||||
public float getMixScaleX () {
|
|
||||||
return mixScaleX;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMixScaleX (float mixScaleX) {
|
|
||||||
this.mixScaleX = mixScaleX;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A percentage (0-1) that controls the mix between the constrained and unconstrained scale X. */
|
|
||||||
public float getMixScaleY () {
|
|
||||||
return mixScaleY;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMixScaleY (float mixScaleY) {
|
|
||||||
this.mixScaleY = mixScaleY;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A percentage (0-1) that controls the mix between the constrained and unconstrained shear Y. */
|
|
||||||
public float getMixShearY () {
|
|
||||||
return mixShearY;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMixShearY (float mixShearY) {
|
|
||||||
this.mixShearY = mixShearY;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns false when this constraint won't be updated by
|
/** Returns false when this constraint won't be updated by
|
||||||
|
|||||||
@ -37,9 +37,9 @@ import com.badlogic.gdx.utils.Array;
|
|||||||
* <p>
|
* <p>
|
||||||
* See <a href="https://esotericsoftware.com/spine-transform-constraints">Transform constraints</a> in the Spine User Guide. */
|
* See <a href="https://esotericsoftware.com/spine-transform-constraints">Transform constraints</a> in the Spine User Guide. */
|
||||||
public class TransformConstraintData extends ConstraintData {
|
public class TransformConstraintData extends ConstraintData {
|
||||||
|
final TransformConstraintPose setup = new TransformConstraintPose();
|
||||||
final Array<BoneData> bones = new Array();
|
final Array<BoneData> bones = new Array();
|
||||||
BoneData source;
|
BoneData source;
|
||||||
float mixRotate, mixX, mixY, mixScaleX, mixScaleY, mixShearY;
|
|
||||||
float offsetRotation, offsetX, offsetY, offsetScaleX, offsetScaleY, offsetShearY;
|
float offsetRotation, offsetX, offsetY, offsetScaleX, offsetScaleY, offsetShearY;
|
||||||
boolean localSource, localTarget, additive, clamp;
|
boolean localSource, localTarget, additive, clamp;
|
||||||
final Array<FromProperty> properties = new Array();
|
final Array<FromProperty> properties = new Array();
|
||||||
@ -48,6 +48,10 @@ public class TransformConstraintData extends ConstraintData {
|
|||||||
super(name);
|
super(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TransformConstraintPose getSetupPose () {
|
||||||
|
return setup;
|
||||||
|
}
|
||||||
|
|
||||||
/** The bones that will be modified by this transform constraint. */
|
/** The bones that will be modified by this transform constraint. */
|
||||||
public Array<BoneData> getBones () {
|
public Array<BoneData> getBones () {
|
||||||
return bones;
|
return bones;
|
||||||
@ -63,65 +67,6 @@ public class TransformConstraintData extends ConstraintData {
|
|||||||
this.source = source;
|
this.source = source;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The mapping of transform properties to other transform properties. */
|
|
||||||
public Array<FromProperty> getProperties () {
|
|
||||||
return properties;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A percentage (0-1) that controls the mix between the constrained and unconstrained rotation. */
|
|
||||||
public float getMixRotate () {
|
|
||||||
return mixRotate;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMixRotate (float mixRotate) {
|
|
||||||
this.mixRotate = mixRotate;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A percentage (0-1) that controls the mix between the constrained and unconstrained translation X. */
|
|
||||||
public float getMixX () {
|
|
||||||
return mixX;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMixX (float mixX) {
|
|
||||||
this.mixX = mixX;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A percentage (0-1) that controls the mix between the constrained and unconstrained translation Y. */
|
|
||||||
public float getMixY () {
|
|
||||||
return mixY;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMixY (float mixY) {
|
|
||||||
this.mixY = mixY;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A percentage (0-1) that controls the mix between the constrained and unconstrained scale X. */
|
|
||||||
public float getMixScaleX () {
|
|
||||||
return mixScaleX;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMixScaleX (float mixScaleX) {
|
|
||||||
this.mixScaleX = mixScaleX;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A percentage (0-1) that controls the mix between the constrained and unconstrained scale Y. */
|
|
||||||
public float getMixScaleY () {
|
|
||||||
return mixScaleY;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMixScaleY (float mixScaleY) {
|
|
||||||
this.mixScaleY = mixScaleY;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A percentage (0-1) that controls the mix between the constrained and unconstrained shear Y. */
|
|
||||||
public float getMixShearY () {
|
|
||||||
return mixShearY;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMixShearY (float mixShearY) {
|
|
||||||
this.mixShearY = mixShearY;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** An offset added to the constrained bone rotation. */
|
/** An offset added to the constrained bone rotation. */
|
||||||
public float getOffsetRotation () {
|
public float getOffsetRotation () {
|
||||||
return offsetRotation;
|
return offsetRotation;
|
||||||
@ -212,6 +157,11 @@ public class TransformConstraintData extends ConstraintData {
|
|||||||
this.clamp = clamp;
|
this.clamp = clamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** The mapping of transform properties to other transform properties. */
|
||||||
|
public Array<FromProperty> getProperties () {
|
||||||
|
return properties;
|
||||||
|
}
|
||||||
|
|
||||||
/** Source property for a {@link TransformConstraint}. */
|
/** Source property for a {@link TransformConstraint}. */
|
||||||
static abstract public class FromProperty {
|
static abstract public class FromProperty {
|
||||||
/** The value of this property that corresponds to {@link ToProperty#offset}. */
|
/** The value of this property that corresponds to {@link ToProperty#offset}. */
|
||||||
@ -235,11 +185,11 @@ public class TransformConstraintData extends ConstraintData {
|
|||||||
/** The scale of the {@link FromProperty} value in relation to this property. */
|
/** The scale of the {@link FromProperty} value in relation to this property. */
|
||||||
public float scale;
|
public float scale;
|
||||||
|
|
||||||
/** Reads the mix for this property from the specified constraint. */
|
/** Reads the mix for this property from the specified pose. */
|
||||||
abstract public float mix (TransformConstraint constraint);
|
abstract public float mix (TransformConstraintPose pose);
|
||||||
|
|
||||||
/** Applies the value to this property. */
|
/** Applies the value to this property. */
|
||||||
abstract public void apply (TransformConstraint constraint, BoneApplied bone, float value, boolean local, boolean additive);
|
abstract public void apply (TransformConstraintPose pose, BoneApplied bone, float value, boolean local, boolean additive);
|
||||||
}
|
}
|
||||||
|
|
||||||
static public class FromRotate extends FromProperty {
|
static public class FromRotate extends FromProperty {
|
||||||
@ -253,14 +203,14 @@ public class TransformConstraintData extends ConstraintData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static public class ToRotate extends ToProperty {
|
static public class ToRotate extends ToProperty {
|
||||||
public float mix (TransformConstraint constraint) {
|
public float mix (TransformConstraintPose pose) {
|
||||||
return constraint.mixRotate;
|
return pose.mixRotate;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void apply (TransformConstraint constraint, BoneApplied bone, float value, boolean local, boolean additive) {
|
public void apply (TransformConstraintPose pose, BoneApplied bone, float value, boolean local, boolean additive) {
|
||||||
if (local) {
|
if (local) {
|
||||||
if (!additive) value -= bone.rotation;
|
if (!additive) value -= bone.rotation;
|
||||||
bone.rotation += value * constraint.mixRotate;
|
bone.rotation += value * pose.mixRotate;
|
||||||
} else {
|
} else {
|
||||||
float a = bone.a, b = bone.b, c = bone.c, d = bone.d;
|
float a = bone.a, b = bone.b, c = bone.c, d = bone.d;
|
||||||
value *= degRad;
|
value *= degRad;
|
||||||
@ -269,7 +219,7 @@ public class TransformConstraintData extends ConstraintData {
|
|||||||
value -= PI2;
|
value -= PI2;
|
||||||
else if (value < -PI) //
|
else if (value < -PI) //
|
||||||
value += PI2;
|
value += PI2;
|
||||||
value *= constraint.mixRotate;
|
value *= pose.mixRotate;
|
||||||
float cos = cos(value), sin = sin(value);
|
float cos = cos(value), sin = sin(value);
|
||||||
bone.a = cos * a - sin * c;
|
bone.a = cos * a - sin * c;
|
||||||
bone.b = cos * b - sin * d;
|
bone.b = cos * b - sin * d;
|
||||||
@ -286,17 +236,17 @@ public class TransformConstraintData extends ConstraintData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static public class ToX extends ToProperty {
|
static public class ToX extends ToProperty {
|
||||||
public float mix (TransformConstraint constraint) {
|
public float mix (TransformConstraintPose pose) {
|
||||||
return constraint.mixX;
|
return pose.mixX;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void apply (TransformConstraint constraint, BoneApplied bone, float value, boolean local, boolean additive) {
|
public void apply (TransformConstraintPose pose, BoneApplied bone, float value, boolean local, boolean additive) {
|
||||||
if (local) {
|
if (local) {
|
||||||
if (!additive) value -= bone.x;
|
if (!additive) value -= bone.x;
|
||||||
bone.x += value * constraint.mixX;
|
bone.x += value * pose.mixX;
|
||||||
} else {
|
} else {
|
||||||
if (!additive) value -= bone.worldX;
|
if (!additive) value -= bone.worldX;
|
||||||
bone.worldX += value * constraint.mixX;
|
bone.worldX += value * pose.mixX;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -308,17 +258,17 @@ public class TransformConstraintData extends ConstraintData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static public class ToY extends ToProperty {
|
static public class ToY extends ToProperty {
|
||||||
public float mix (TransformConstraint constraint) {
|
public float mix (TransformConstraintPose pose) {
|
||||||
return constraint.mixY;
|
return pose.mixY;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void apply (TransformConstraint constraint, BoneApplied bone, float value, boolean local, boolean additive) {
|
public void apply (TransformConstraintPose pose, BoneApplied bone, float value, boolean local, boolean additive) {
|
||||||
if (local) {
|
if (local) {
|
||||||
if (!additive) value -= bone.y;
|
if (!additive) value -= bone.y;
|
||||||
bone.y += value * constraint.mixY;
|
bone.y += value * pose.mixY;
|
||||||
} else {
|
} else {
|
||||||
if (!additive) value -= bone.worldY;
|
if (!additive) value -= bone.worldY;
|
||||||
bone.worldY += value * constraint.mixY;
|
bone.worldY += value * pose.mixY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -330,23 +280,23 @@ public class TransformConstraintData extends ConstraintData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static public class ToScaleX extends ToProperty {
|
static public class ToScaleX extends ToProperty {
|
||||||
public float mix (TransformConstraint constraint) {
|
public float mix (TransformConstraintPose pose) {
|
||||||
return constraint.mixScaleX;
|
return pose.mixScaleX;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void apply (TransformConstraint constraint, BoneApplied bone, float value, boolean local, boolean additive) {
|
public void apply (TransformConstraintPose pose, BoneApplied bone, float value, boolean local, boolean additive) {
|
||||||
if (local) {
|
if (local) {
|
||||||
if (additive)
|
if (additive)
|
||||||
bone.scaleX *= 1 + ((value - 1) * constraint.mixScaleX);
|
bone.scaleX *= 1 + ((value - 1) * pose.mixScaleX);
|
||||||
else if (bone.scaleX != 0) //
|
else if (bone.scaleX != 0) //
|
||||||
bone.scaleX = 1 + (value / bone.scaleX - 1) * constraint.mixScaleX;
|
bone.scaleX = 1 + (value / bone.scaleX - 1) * pose.mixScaleX;
|
||||||
} else {
|
} else {
|
||||||
float s;
|
float s;
|
||||||
if (additive)
|
if (additive)
|
||||||
s = 1 + (value - 1) * constraint.mixScaleX;
|
s = 1 + (value - 1) * pose.mixScaleX;
|
||||||
else {
|
else {
|
||||||
s = (float)Math.sqrt(bone.a * bone.a + bone.c * bone.c);
|
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) * pose.mixScaleX;
|
||||||
}
|
}
|
||||||
bone.a *= s;
|
bone.a *= s;
|
||||||
bone.c *= s;
|
bone.c *= s;
|
||||||
@ -361,23 +311,23 @@ public class TransformConstraintData extends ConstraintData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static public class ToScaleY extends ToProperty {
|
static public class ToScaleY extends ToProperty {
|
||||||
public float mix (TransformConstraint constraint) {
|
public float mix (TransformConstraintPose pose) {
|
||||||
return constraint.mixScaleY;
|
return pose.mixScaleY;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void apply (TransformConstraint constraint, BoneApplied bone, float value, boolean local, boolean additive) {
|
public void apply (TransformConstraintPose pose, BoneApplied bone, float value, boolean local, boolean additive) {
|
||||||
if (local) {
|
if (local) {
|
||||||
if (additive)
|
if (additive)
|
||||||
bone.scaleY *= 1 + ((value - 1) * constraint.mixScaleY);
|
bone.scaleY *= 1 + ((value - 1) * pose.mixScaleY);
|
||||||
else if (bone.scaleY != 0) //
|
else if (bone.scaleY != 0) //
|
||||||
bone.scaleY = 1 + (value / bone.scaleY - 1) * constraint.mixScaleY;
|
bone.scaleY = 1 + (value / bone.scaleY - 1) * pose.mixScaleY;
|
||||||
} else {
|
} else {
|
||||||
float s;
|
float s;
|
||||||
if (additive)
|
if (additive)
|
||||||
s = 1 + (value - 1) * constraint.mixScaleY;
|
s = 1 + (value - 1) * pose.mixScaleY;
|
||||||
else {
|
else {
|
||||||
s = (float)Math.sqrt(bone.b * bone.b + bone.d * bone.d);
|
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) * pose.mixScaleY;
|
||||||
}
|
}
|
||||||
bone.b *= s;
|
bone.b *= s;
|
||||||
bone.d *= s;
|
bone.d *= s;
|
||||||
@ -393,14 +343,14 @@ public class TransformConstraintData extends ConstraintData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static public class ToShearY extends ToProperty {
|
static public class ToShearY extends ToProperty {
|
||||||
public float mix (TransformConstraint constraint) {
|
public float mix (TransformConstraintPose pose) {
|
||||||
return constraint.mixShearY;
|
return pose.mixShearY;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void apply (TransformConstraint constraint, BoneApplied bone, float value, boolean local, boolean additive) {
|
public void apply (TransformConstraintPose pose, BoneApplied bone, float value, boolean local, boolean additive) {
|
||||||
if (local) {
|
if (local) {
|
||||||
if (!additive) value -= bone.shearY;
|
if (!additive) value -= bone.shearY;
|
||||||
bone.shearY += value * constraint.mixShearY;
|
bone.shearY += value * pose.mixShearY;
|
||||||
} else {
|
} else {
|
||||||
float b = bone.b, d = bone.d, by = atan2(d, b);
|
float b = bone.b, d = bone.d, by = atan2(d, b);
|
||||||
value = (value + 90) * degRad;
|
value = (value + 90) * degRad;
|
||||||
@ -413,7 +363,7 @@ public class TransformConstraintData extends ConstraintData {
|
|||||||
else if (value < -PI) //
|
else if (value < -PI) //
|
||||||
value += PI2;
|
value += PI2;
|
||||||
}
|
}
|
||||||
value = by + value * constraint.mixShearY;
|
value = by + value * pose.mixShearY;
|
||||||
float s = (float)Math.sqrt(b * b + d * d);
|
float s = (float)Math.sqrt(b * b + d * d);
|
||||||
bone.b = cos(value) * s;
|
bone.b = cos(value) * s;
|
||||||
bone.d = sin(value) * s;
|
bone.d = sin(value) * s;
|
||||||
|
|||||||
@ -0,0 +1,98 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* 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 a pose for a transform constraint. */
|
||||||
|
public class TransformConstraintPose {
|
||||||
|
float mixRotate, mixX, mixY, mixScaleX, mixScaleY, mixShearY;
|
||||||
|
|
||||||
|
public void set (TransformConstraintPose pose) {
|
||||||
|
mixRotate = pose.mixRotate;
|
||||||
|
mixX = pose.mixX;
|
||||||
|
mixY = pose.mixY;
|
||||||
|
mixScaleX = pose.mixScaleX;
|
||||||
|
mixScaleY = pose.mixScaleY;
|
||||||
|
mixShearY = pose.mixShearY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A percentage (0-1) that controls the mix between the constrained and unconstrained rotation. */
|
||||||
|
public float getMixRotate () {
|
||||||
|
return mixRotate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMixRotate (float mixRotate) {
|
||||||
|
this.mixRotate = mixRotate;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A percentage (0-1) that controls the mix between the constrained and unconstrained translation X. */
|
||||||
|
public float getMixX () {
|
||||||
|
return mixX;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMixX (float mixX) {
|
||||||
|
this.mixX = mixX;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A percentage (0-1) that controls the mix between the constrained and unconstrained translation Y. */
|
||||||
|
public float getMixY () {
|
||||||
|
return mixY;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMixY (float mixY) {
|
||||||
|
this.mixY = mixY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A percentage (0-1) that controls the mix between the constrained and unconstrained scale X. */
|
||||||
|
public float getMixScaleX () {
|
||||||
|
return mixScaleX;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMixScaleX (float mixScaleX) {
|
||||||
|
this.mixScaleX = mixScaleX;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A percentage (0-1) that controls the mix between the constrained and unconstrained scale X. */
|
||||||
|
public float getMixScaleY () {
|
||||||
|
return mixScaleY;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMixScaleY (float mixScaleY) {
|
||||||
|
this.mixScaleY = mixScaleY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A percentage (0-1) that controls the mix between the constrained and unconstrained shear Y. */
|
||||||
|
public float getMixShearY () {
|
||||||
|
return mixShearY;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMixShearY (float mixShearY) {
|
||||||
|
this.mixShearY = mixShearY;
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user