[libgdx] Animation/AnimationState clean up, javadocs.

This commit is contained in:
Nathan Sweet 2026-03-23 01:54:09 -04:00
parent 2f12895884
commit 39fe4692db
22 changed files with 278 additions and 180 deletions

View File

@ -64,7 +64,8 @@ public class Animation {
setTimelines(timelines); setTimelines(timelines);
} }
/** If the returned array or the timelines it contains are modified, {@link #setTimelines(Array)} must be called. */ /** If this list or the timelines it contains are modified, the timelines must be set again to recompute the animation's bone
* indices and timeline property IDs. */
public Array<Timeline> getTimelines () { public Array<Timeline> getTimelines () {
return timelines; return timelines;
} }
@ -87,15 +88,17 @@ public class Animation {
bones.shrink(); bones.shrink();
} }
/** Returns true if this animation contains a timeline with any of the specified property IDs. */ /** Returns true if this animation contains a timeline with any of the specified property IDs.
* <p>
* See {@link Timeline#getPropertyIds()}. */
public boolean hasTimeline (String[] propertyIds) { public boolean hasTimeline (String[] propertyIds) {
for (String id : propertyIds) for (String id : propertyIds)
if (timelineIds.contains(id)) return true; if (timelineIds.contains(id)) return true;
return false; return false;
} }
/** The duration of the animation in seconds, which is usually the highest time of all frames in the timeline. The duration is /** The duration of the animation in seconds, which is usually the highest time of all frames in the timelines. The duration is
* used to know when it has completed and when it should loop back to the start. */ * used to know when the animation has completed and, for animations that repeat, when it should loop back to the start. */
public float getDuration () { public float getDuration () {
return duration; return duration;
} }
@ -104,13 +107,16 @@ public class Animation {
this.duration = duration; this.duration = duration;
} }
/** {@link Skeleton#getBones()} indices that this animation's timelines modify.
* <p>
* See {@link BoneTimeline#getBoneIndex()}. */
public IntArray getBones () { public IntArray getBones () {
return bones; return bones;
} }
/** Applies the animation's timelines to the specified skeleton. /** Applies the animation's timelines to the specified skeleton.
* <p> * <p>
* See Timeline {@link Timeline#apply(Skeleton, float, float, Array, float, boolean, boolean, boolean, boolean)}. * See {@link Timeline#apply(Skeleton, float, float, Array, float, boolean, boolean, boolean, boolean)}.
* @param skeleton The skeleton the animation is applied to. This provides access to the bones, slots, and other skeleton * @param skeleton The skeleton the animation is applied to. This provides access to the bones, slots, and other skeleton
* components the timelines may change. * components the timelines may change.
* @param lastTime The last time in seconds this animation was applied. Some timelines trigger only at discrete times, in which * @param lastTime The last time in seconds this animation was applied. Some timelines trigger only at discrete times, in which
@ -130,7 +136,7 @@ public class Animation {
* @param add If true, for timelines that support it, their values are added to the setup or current values (depending on * @param add If true, for timelines that support it, their values are added to the setup or current values (depending on
* <code>fromSetup</code>). * <code>fromSetup</code>).
* @param out True when the animation is mixing out, else it is mixing in. Used by timelines that perform instant transitions. * @param out True when the animation is mixing out, else it is mixing in. Used by timelines that perform instant transitions.
* @param appliedPose True to modify the {@link Posed#getAppliedPose()}, else modify the {@link Posed#getPose()}. */ * @param appliedPose True to modify the {@link Posed#getAppliedPose()}, else the {@link Posed#getPose()} is modified. */
public void apply (Skeleton skeleton, float lastTime, float time, boolean loop, @Null Array<Event> events, float alpha, public void apply (Skeleton skeleton, float lastTime, float time, boolean loop, @Null Array<Event> events, float alpha,
boolean fromSetup, boolean add, boolean out, boolean appliedPose) { boolean fromSetup, boolean add, boolean out, boolean appliedPose) {
if (skeleton == null) throw new IllegalArgumentException("skeleton cannot be null."); if (skeleton == null) throw new IllegalArgumentException("skeleton cannot be null.");
@ -145,7 +151,9 @@ public class Animation {
timelines[i].apply(skeleton, lastTime, time, events, alpha, fromSetup, add, out, appliedPose); timelines[i].apply(skeleton, lastTime, time, events, alpha, fromSetup, add, out, appliedPose);
} }
/** The animation's name, which is unique across all animations in the skeleton. */ /** The animation's name, unique across all animations in the skeleton.
* <p>
* See {@link SkeletonData#findAnimation(String)}. */
public String getName () { public String getName () {
return name; return name;
} }
@ -190,16 +198,17 @@ public class Animation {
return frames; return frames;
} }
/** The number of entries stored per frame. */ /** The number of values stored per frame. */
public int getFrameEntries () { public int getFrameEntries () {
return 1; return 1;
} }
/** The number of frames for this timeline. */ /** The number of frames in this timeline. */
public int getFrameCount () { public int getFrameCount () {
return frames.length / getFrameEntries(); return frames.length / getFrameEntries();
} }
/** The duration of the timeline in seconds, which is usually the highest time of all frames in the timeline. */
public float getDuration () { public float getDuration () {
return frames[frames.length - getFrameEntries()]; return frames[frames.length - getFrameEntries()];
} }
@ -217,7 +226,7 @@ public class Animation {
/** Applies this timeline to the skeleton. /** Applies this timeline to the skeleton.
* @param skeleton The skeleton the timeline is applied to. This provides access to the bones, slots, and other skeleton * @param skeleton The skeleton the timeline is applied to. This provides access to the bones, slots, and other skeleton
* components the timelines may change. * components the timelines may change.
* @param lastTime The last time in seconds this timline was applied. Some timelines trigger only at discrete times, in * @param lastTime The last time in seconds this timeline was applied. Some timelines trigger only at discrete times, in
* which case all keys are triggered between <code>lastTime</code> (exclusive) and <code>time</code> (inclusive). * which case all keys are triggered between <code>lastTime</code> (exclusive) and <code>time</code> (inclusive).
* Pass -1 the first time a timeline is applied to ensure frame 0 is triggered. * Pass -1 the first time a timeline is applied to ensure frame 0 is triggered.
* @param time The time in seconds the skeleton is being posed for. Timelines find the frame before and after this time and * @param time The time in seconds the skeleton is being posed for. Timelines find the frame before and after this time and
@ -232,8 +241,9 @@ public class Animation {
* timeline values, no change is made before the first frame. * timeline values, no change is made before the first frame.
* @param add If true, for timelines that support it, their values are added to the setup or current values (depending on * @param add If true, for timelines that support it, their values are added to the setup or current values (depending on
* <code>fromSetup</code>). * <code>fromSetup</code>).
* @param out True when the animation is mixing out, else it is mixing in. * @param out True when the animation is mixing out, else it is mixing in. Used by timelines that perform instant
* @param appliedPose True to modify the {@link Posed#getAppliedPose()}, else modify the {@link Posed#getPose()}. */ * transitions.
* @param appliedPose True to modify the {@link Posed#getAppliedPose()}, else the {@link Posed#getPose()} is modified. */
abstract public void apply (Skeleton skeleton, float lastTime, float time, @Null Array<Event> events, float alpha, abstract public void apply (Skeleton skeleton, float lastTime, float time, @Null Array<Event> events, float alpha,
boolean fromSetup, boolean add, boolean out, boolean appliedPose); boolean fromSetup, boolean add, boolean out, boolean appliedPose);
@ -258,7 +268,7 @@ public class Animation {
} }
} }
/** An interface for timelines that change the property of a slot. */ /** An interface for timelines that change a slot's properties. */
static public interface SlotTimeline { static public interface SlotTimeline {
/** The index of the slot in {@link Skeleton#getSlots()} that will be changed when this timeline is applied. */ /** The index of the slot in {@link Skeleton#getSlots()} that will be changed when this timeline is applied. */
public int getSlotIndex (); public int getSlotIndex ();
@ -266,7 +276,9 @@ public class Animation {
/** The base class for timelines that interpolate between frame values using stepped, linear, or a Bezier curve. */ /** The base class for timelines that interpolate between frame values using stepped, linear, or a Bezier curve. */
static abstract public class CurveTimeline extends Timeline { static abstract public class CurveTimeline extends Timeline {
static public final int LINEAR = 0, STEPPED = 1, BEZIER = 2, BEZIER_SIZE = 18; static public final int LINEAR = 0, STEPPED = 1, BEZIER = 2;
/** The number of values stored for each 10 segment Bezier curve. */
static public final int BEZIER_SIZE = 18;
float[] curves; float[] curves;
@ -367,7 +379,7 @@ public class Animation {
} }
} }
/** The base class for a {@link CurveTimeline} that sets one property. */ /** The base class for a {@link CurveTimeline} that sets one property with a curve. */
static abstract public class CurveTimeline1 extends CurveTimeline { static abstract public class CurveTimeline1 extends CurveTimeline {
static public final int ENTRIES = 2; static public final int ENTRIES = 2;
static final int VALUE = 1; static final int VALUE = 1;
@ -413,24 +425,48 @@ public class Animation {
}; };
} }
/** Returns the interpolated value for properties relative to the setup value. The timeline value is added to the setup
* value, rather than replacing it.
* <p>
* See {@link Timeline#apply(Skeleton, float, float, Array, float, boolean, boolean, boolean, boolean)}.
* @param current The current value for the property.
* @param setup The setup value for the property. */
public float getRelativeValue (float time, float alpha, boolean fromSetup, boolean add, float current, float setup) { public float getRelativeValue (float time, float alpha, boolean fromSetup, boolean add, float current, float setup) {
if (time < frames[0]) return fromSetup ? setup : current; if (time < frames[0]) return fromSetup ? setup : current;
float value = getCurveValue(time); float value = getCurveValue(time);
return fromSetup ? setup + value * alpha : current + (add ? value : value + setup - current) * alpha; return fromSetup ? setup + value * alpha : current + (add ? value : value + setup - current) * alpha;
} }
/** Returns the interpolated value for properties set as absolute values. The timeline value replaces the setup value,
* rather than being relative to it.
* <p>
* See {@link Timeline#apply(Skeleton, float, float, Array, float, boolean, boolean, boolean, boolean)}.
* @param current The current value for the property.
* @param setup The setup value for the property. */
public float getAbsoluteValue (float time, float alpha, boolean fromSetup, boolean add, float current, float setup) { public float getAbsoluteValue (float time, float alpha, boolean fromSetup, boolean add, float current, float setup) {
if (time < frames[0]) return fromSetup ? setup : current; if (time < frames[0]) return fromSetup ? setup : current;
float value = getCurveValue(time); float value = getCurveValue(time);
return fromSetup ? setup + (value - setup) * alpha : current + (add ? value : value - current) * alpha; return fromSetup ? setup + (value - setup) * alpha : current + (add ? value : value - current) * alpha;
} }
/** Returns the interpolated value for properties set as absolute values, using the specified timeline value rather than
* calling {@link #getCurveValue(float)}.
* <p>
* See {@link Timeline#apply(Skeleton, float, float, Array, float, boolean, boolean, boolean, boolean)}.
* @param current The current value for the property.
* @param setup The setup value for the property.
* @param value The timeline value to apply. */
public float getAbsoluteValue (float time, float alpha, boolean fromSetup, boolean add, float current, float setup, public float getAbsoluteValue (float time, float alpha, boolean fromSetup, boolean add, float current, float setup,
float value) { float value) {
if (time < frames[0]) return fromSetup ? setup : current; if (time < frames[0]) return fromSetup ? setup : current;
return fromSetup ? setup + (value - setup) * alpha : current + (add ? value : value - current) * alpha; return fromSetup ? setup + (value - setup) * alpha : current + (add ? value : value - current) * alpha;
} }
/** Returns the interpolated value for scale properties. The timeline and setup values are multiplied and sign adjusted.
* <p>
* See {@link Timeline#apply(Skeleton, float, float, Array, float, boolean, boolean, boolean, boolean)}.
* @param current The current value for the property.
* @param setup The setup value for the property. */
public float getScaleValue (float time, float alpha, boolean fromSetup, boolean add, boolean out, float current, public float getScaleValue (float time, float alpha, boolean fromSetup, boolean add, boolean out, float current,
float setup) { float setup) {
if (time < frames[0]) return fromSetup ? setup : current; if (time < frames[0]) return fromSetup ? setup : current;
@ -444,12 +480,13 @@ public class Animation {
} }
} }
/** An interface for timelines that change the property of a bone. */ /** An interface for timelines that change a bone's properties. */
static public interface BoneTimeline { static public interface BoneTimeline {
/** The index of the bone in {@link Skeleton#getBones()} that will be changed when this timeline is applied. */ /** The index of the bone in {@link Skeleton#getBones()} that is changed by this timeline. */
public int getBoneIndex (); public int getBoneIndex ();
} }
/** The base class for timelines that change 1 bone property with a curve. */
static abstract public class BoneTimeline1 extends CurveTimeline1 implements BoneTimeline { static abstract public class BoneTimeline1 extends CurveTimeline1 implements BoneTimeline {
final int boneIndex; final int boneIndex;
@ -473,7 +510,7 @@ public class Animation {
boolean out); boolean out);
} }
/** The base class for a {@link CurveTimeline} that is a {@link BoneTimeline} and sets two properties. */ /** The base class for timelines that change two bone properties with a curve. */
static abstract public class BoneTimeline2 extends CurveTimeline implements BoneTimeline { static abstract public class BoneTimeline2 extends CurveTimeline implements BoneTimeline {
static public final int ENTRIES = 3; static public final int ENTRIES = 3;
static final int VALUE1 = 1, VALUE2 = 2; static final int VALUE1 = 1, VALUE2 = 2;
@ -515,7 +552,7 @@ public class Animation {
boolean out); boolean out);
} }
/** Changes a bone's local {@link BoneLocal#getRotation()}. */ /** Changes {@link BoneLocal#getRotation()}. */
static public class RotateTimeline extends BoneTimeline1 { static public class RotateTimeline extends BoneTimeline1 {
public RotateTimeline (int frameCount, int bezierCount, int boneIndex) { public RotateTimeline (int frameCount, int bezierCount, int boneIndex) {
super(frameCount, bezierCount, boneIndex, Property.rotate); super(frameCount, bezierCount, boneIndex, Property.rotate);
@ -527,7 +564,7 @@ public class Animation {
} }
} }
/** Changes a bone's local {@link BoneLocal#getX()} and {@link BoneLocal#getY()}. */ /** Changes {@link BoneLocal#getX()} and {@link BoneLocal#getY()}. */
static public class TranslateTimeline extends BoneTimeline2 { static public class TranslateTimeline extends BoneTimeline2 {
public TranslateTimeline (int frameCount, int bezierCount, int boneIndex) { public TranslateTimeline (int frameCount, int bezierCount, int boneIndex) {
super(frameCount, bezierCount, boneIndex, Property.x, Property.y); super(frameCount, bezierCount, boneIndex, Property.x, Property.y);
@ -578,7 +615,7 @@ public class Animation {
} }
} }
/** Changes a bone's local {@link BoneLocal#getX()}. */ /** Changes {@link BoneLocal#getX()}. */
static public class TranslateXTimeline extends BoneTimeline1 { static public class TranslateXTimeline extends BoneTimeline1 {
public TranslateXTimeline (int frameCount, int bezierCount, int boneIndex) { public TranslateXTimeline (int frameCount, int bezierCount, int boneIndex) {
super(frameCount, bezierCount, boneIndex, Property.x); super(frameCount, bezierCount, boneIndex, Property.x);
@ -590,7 +627,7 @@ public class Animation {
} }
} }
/** Changes a bone's local {@link BoneLocal#getY()}. */ /** Changes {@link BoneLocal#getY()}. */
static public class TranslateYTimeline extends BoneTimeline1 { static public class TranslateYTimeline extends BoneTimeline1 {
public TranslateYTimeline (int frameCount, int bezierCount, int boneIndex) { public TranslateYTimeline (int frameCount, int bezierCount, int boneIndex) {
super(frameCount, bezierCount, boneIndex, Property.y); super(frameCount, bezierCount, boneIndex, Property.y);
@ -602,7 +639,7 @@ public class Animation {
} }
} }
/** Changes a bone's local {@link BoneLocal#getScaleX()} and {@link BoneLocal#getScaleY()}. */ /** Changes {@link BoneLocal#getScaleX()} and {@link BoneLocal#getScaleY()}. */
static public class ScaleTimeline extends BoneTimeline2 { static public class ScaleTimeline extends BoneTimeline2 {
public ScaleTimeline (int frameCount, int bezierCount, int boneIndex) { public ScaleTimeline (int frameCount, int bezierCount, int boneIndex) {
super(frameCount, bezierCount, boneIndex, Property.scaleX, Property.scaleY); super(frameCount, bezierCount, boneIndex, Property.scaleX, Property.scaleY);
@ -670,7 +707,7 @@ public class Animation {
} }
} }
/** Changes a bone's local {@link BoneLocal#getScaleX()}. */ /** Changes {@link BoneLocal#getScaleX()}. */
static public class ScaleXTimeline extends BoneTimeline1 { static public class ScaleXTimeline extends BoneTimeline1 {
public ScaleXTimeline (int frameCount, int bezierCount, int boneIndex) { public ScaleXTimeline (int frameCount, int bezierCount, int boneIndex) {
super(frameCount, bezierCount, boneIndex, Property.scaleX); super(frameCount, bezierCount, boneIndex, Property.scaleX);
@ -682,7 +719,7 @@ public class Animation {
} }
} }
/** Changes a bone's local {@link BoneLocal#getScaleY()}. */ /** Changes {@link BoneLocal#getScaleY()}. */
static public class ScaleYTimeline extends BoneTimeline1 { static public class ScaleYTimeline extends BoneTimeline1 {
public ScaleYTimeline (int frameCount, int bezierCount, int boneIndex) { public ScaleYTimeline (int frameCount, int bezierCount, int boneIndex) {
super(frameCount, bezierCount, boneIndex, Property.scaleY); super(frameCount, bezierCount, boneIndex, Property.scaleY);
@ -694,7 +731,7 @@ public class Animation {
} }
} }
/** Changes a bone's local {@link BoneLocal#getShearX()} and {@link BoneLocal#getShearY()}. */ /** Changes {@link BoneLocal#getShearX()} and {@link BoneLocal#getShearY()}. */
static public class ShearTimeline extends BoneTimeline2 { static public class ShearTimeline extends BoneTimeline2 {
public ShearTimeline (int frameCount, int bezierCount, int boneIndex) { public ShearTimeline (int frameCount, int bezierCount, int boneIndex) {
super(frameCount, bezierCount, boneIndex, Property.shearX, Property.shearY); super(frameCount, bezierCount, boneIndex, Property.shearX, Property.shearY);
@ -745,7 +782,7 @@ public class Animation {
} }
} }
/** Changes a bone's local {@link BoneLocal#getShearX()}. */ /** Changes {@link BoneLocal#getShearX()}. */
static public class ShearXTimeline extends BoneTimeline1 { static public class ShearXTimeline extends BoneTimeline1 {
public ShearXTimeline (int frameCount, int bezierCount, int boneIndex) { public ShearXTimeline (int frameCount, int bezierCount, int boneIndex) {
super(frameCount, bezierCount, boneIndex, Property.shearX); super(frameCount, bezierCount, boneIndex, Property.shearX);
@ -757,7 +794,7 @@ public class Animation {
} }
} }
/** Changes a bone's local {@link BoneLocal#getShearY()}. */ /** Changes {@link BoneLocal#getShearY()}. */
static public class ShearYTimeline extends BoneTimeline1 { static public class ShearYTimeline extends BoneTimeline1 {
public ShearYTimeline (int frameCount, int bezierCount, int boneIndex) { public ShearYTimeline (int frameCount, int bezierCount, int boneIndex) {
super(frameCount, bezierCount, boneIndex, Property.shearY); super(frameCount, bezierCount, boneIndex, Property.shearY);
@ -769,7 +806,7 @@ public class Animation {
} }
} }
/** Changes a bone's {@link BoneLocal#getInherit()}. */ /** Changes {@link BoneLocal#getInherit()}. */
static public class InheritTimeline extends Timeline implements BoneTimeline { static public class InheritTimeline extends Timeline implements BoneTimeline {
static public final int ENTRIES = 2; static public final int ENTRIES = 2;
static private final int INHERIT = 1; static private final int INHERIT = 1;
@ -817,6 +854,7 @@ public class Animation {
} }
} }
/** The base class for timelines that change any number of slot properties with a curve. */
static abstract public class SlotCurveTimeline extends CurveTimeline implements SlotTimeline { static abstract public class SlotCurveTimeline extends CurveTimeline implements SlotTimeline {
final int slotIndex; final int slotIndex;
@ -838,7 +876,7 @@ public class Animation {
abstract protected void apply (Slot slot, SlotPose pose, float time, float alpha, boolean fromSetup, boolean add); abstract protected void apply (Slot slot, SlotPose pose, float time, float alpha, boolean fromSetup, boolean add);
} }
/** Changes a slot's {@link SlotPose#getColor()}. */ /** Changes {@link SlotPose#getColor()}. */
static public class RGBATimeline extends SlotCurveTimeline { static public class RGBATimeline extends SlotCurveTimeline {
static public final int ENTRIES = 5; static public final int ENTRIES = 5;
static private final int R = 1, G = 2, B = 3, A = 4; static private final int R = 1, G = 2, B = 3, A = 4;
@ -915,7 +953,7 @@ public class Animation {
} }
} }
/** Changes the RGB for a slot's {@link SlotPose#getColor()}. */ /** Changes RGB for a slot's {@link SlotPose#getColor()}. */
static public class RGBTimeline extends SlotCurveTimeline { static public class RGBTimeline extends SlotCurveTimeline {
static public final int ENTRIES = 4; static public final int ENTRIES = 4;
static private final int R = 1, G = 2, B = 3; static private final int R = 1, G = 2, B = 3;
@ -995,7 +1033,7 @@ public class Animation {
} }
} }
/** Changes the alpha for a slot's {@link SlotPose#getColor()}. */ /** Changes alpha for a slot's {@link SlotPose#getColor()}. */
static public class AlphaTimeline extends CurveTimeline1 implements SlotTimeline { static public class AlphaTimeline extends CurveTimeline1 implements SlotTimeline {
final int slotIndex; final int slotIndex;
@ -1033,7 +1071,7 @@ public class Animation {
} }
} }
/** Changes a slot's {@link SlotPose#getColor()} and {@link SlotPose#getDarkColor()} for two color tinting. */ /** Changes {@link SlotPose#getColor()} and {@link SlotPose#getDarkColor()} for two color tinting. */
static public class RGBA2Timeline extends SlotCurveTimeline { static public class RGBA2Timeline extends SlotCurveTimeline {
static public final int ENTRIES = 8; static public final int ENTRIES = 8;
static private final int R = 1, G = 2, B = 3, A = 4, R2 = 5, G2 = 6, B2 = 7; static private final int R = 1, G = 2, B = 3, A = 4, R2 = 5, G2 = 6, B2 = 7;
@ -1144,7 +1182,7 @@ public class Animation {
} }
} }
/** Changes the RGB for a slot's {@link SlotPose#getColor()} and {@link SlotPose#getDarkColor()} for two color tinting. */ /** Changes RGB for a slot's {@link SlotPose#getColor()} and {@link SlotPose#getDarkColor()} for two color tinting. */
static public class RGB2Timeline extends SlotCurveTimeline { static public class RGB2Timeline extends SlotCurveTimeline {
static public final int ENTRIES = 7; static public final int ENTRIES = 7;
static private final int R = 1, G = 2, B = 3, R2 = 4, G2 = 5, B2 = 6; static private final int R = 1, G = 2, B = 3, R2 = 4, G2 = 5, B2 = 6;
@ -1256,7 +1294,7 @@ public class Animation {
} }
} }
/** Changes a slot's {@link SlotPose#getAttachment()}. */ /** Changes {@link SlotPose#getAttachment()}. */
static public class AttachmentTimeline extends Timeline implements SlotTimeline { static public class AttachmentTimeline extends Timeline implements SlotTimeline {
final int slotIndex; final int slotIndex;
final String[] attachmentNames; final String[] attachmentNames;
@ -1306,7 +1344,7 @@ public class Animation {
} }
} }
/** Changes a slot's {@link SlotPose#getDeform()} to deform a {@link VertexAttachment}. */ /** Changes {@link SlotPose#getDeform()} to deform a {@link VertexAttachment}. */
static public class DeformTimeline extends SlotCurveTimeline { static public class DeformTimeline extends SlotCurveTimeline {
final VertexAttachment attachment; final VertexAttachment attachment;
private final float[][] vertices; private final float[][] vertices;
@ -1516,7 +1554,7 @@ public class Animation {
} }
} }
/** Changes a slot's {@link SlotPose#getSequenceIndex()} for an attachment's {@link Sequence}. */ /** Changes {@link SlotPose#getSequenceIndex()} for an attachment's {@link Sequence}. */
static public class SequenceTimeline extends Timeline implements SlotTimeline { static public class SequenceTimeline extends Timeline implements SlotTimeline {
static public final int ENTRIES = 3; static public final int ENTRIES = 3;
static private final int MODE = 1, DELAY = 2; static private final int MODE = 1, DELAY = 2;
@ -1665,7 +1703,7 @@ public class Animation {
} }
} }
/** Changes a skeleton's {@link Skeleton#getDrawOrder()}. */ /** Changes {@link Skeleton#getDrawOrder()}. */
static public class DrawOrderTimeline extends Timeline { static public class DrawOrderTimeline extends Timeline {
static final String propertyID = Integer.toString(Property.drawOrder.ordinal()); static final String propertyID = Integer.toString(Property.drawOrder.ordinal());
static private final String[] propertyIds = {propertyID}; static private final String[] propertyIds = {propertyID};
@ -1715,7 +1753,7 @@ public class Animation {
} }
} }
/** Changes a subset of a skeleton's {@link Skeleton#getDrawOrder()}. */ /** Changes a subset of {@link Skeleton#getDrawOrder()}. */
static public class DrawOrderFolderTimeline extends Timeline { static public class DrawOrderFolderTimeline extends Timeline {
private final int[] slots; private final int[] slots;
private final boolean[] inFolder; private final boolean[] inFolder;
@ -1808,7 +1846,7 @@ public class Animation {
public int getConstraintIndex (); public int getConstraintIndex ();
} }
/** Changes an IK constraint's {@link IkConstraintPose#getMix()}, {@link IkConstraintPose#getSoftness()}, /** Changes {@link IkConstraintPose#getMix()}, {@link IkConstraintPose#getSoftness()},
* {@link IkConstraintPose#getBendDirection()}, {@link IkConstraintPose#getStretch()}, and * {@link IkConstraintPose#getBendDirection()}, {@link IkConstraintPose#getStretch()}, and
* {@link IkConstraintPose#getCompress()}. */ * {@link IkConstraintPose#getCompress()}. */
static public class IkConstraintTimeline extends CurveTimeline implements ConstraintTimeline { static public class IkConstraintTimeline extends CurveTimeline implements ConstraintTimeline {
@ -1902,7 +1940,7 @@ public class Animation {
} }
} }
/** Changes a transform constraint's {@link TransformConstraintPose#getMixRotate()}, {@link TransformConstraintPose#getMixX()}, /** Changes {@link TransformConstraintPose#getMixRotate()}, {@link TransformConstraintPose#getMixX()},
* {@link TransformConstraintPose#getMixY()}, {@link TransformConstraintPose#getMixScaleX()}, * {@link TransformConstraintPose#getMixY()}, {@link TransformConstraintPose#getMixScaleX()},
* {@link TransformConstraintPose#getMixScaleY()}, and {@link TransformConstraintPose#getMixShearY()}. */ * {@link TransformConstraintPose#getMixScaleY()}, and {@link TransformConstraintPose#getMixShearY()}. */
static public class TransformConstraintTimeline extends CurveTimeline implements ConstraintTimeline { static public class TransformConstraintTimeline extends CurveTimeline implements ConstraintTimeline {
@ -2016,6 +2054,7 @@ public class Animation {
} }
} }
/** The base class for timelines that change 1 constraint property with a curve. */
static abstract public class ConstraintTimeline1 extends CurveTimeline1 implements ConstraintTimeline { static abstract public class ConstraintTimeline1 extends CurveTimeline1 implements ConstraintTimeline {
final int constraintIndex; final int constraintIndex;
@ -2029,7 +2068,7 @@ public class Animation {
} }
} }
/** Changes a path constraint's {@link PathConstraintPose#getPosition()}. */ /** Changes {@link PathConstraintPose#getPosition()}. */
static public class PathConstraintPositionTimeline extends ConstraintTimeline1 { static public class PathConstraintPositionTimeline extends ConstraintTimeline1 {
public PathConstraintPositionTimeline (int frameCount, int bezierCount, int constraintIndex) { public PathConstraintPositionTimeline (int frameCount, int bezierCount, int constraintIndex) {
super(frameCount, bezierCount, constraintIndex, Property.pathConstraintPosition); super(frameCount, bezierCount, constraintIndex, Property.pathConstraintPosition);
@ -2046,7 +2085,7 @@ public class Animation {
} }
} }
/** Changes a path constraint's {@link PathConstraintPose#getSpacing()}. */ /** Changes {@link PathConstraintPose#getSpacing()}. */
static public class PathConstraintSpacingTimeline extends ConstraintTimeline1 { static public class PathConstraintSpacingTimeline extends ConstraintTimeline1 {
public PathConstraintSpacingTimeline (int frameCount, int bezierCount, int constraintIndex) { public PathConstraintSpacingTimeline (int frameCount, int bezierCount, int constraintIndex) {
super(frameCount, bezierCount, constraintIndex, Property.pathConstraintSpacing); super(frameCount, bezierCount, constraintIndex, Property.pathConstraintSpacing);
@ -2062,7 +2101,7 @@ public class Animation {
} }
} }
/** Changes a path constraint's {@link PathConstraintPose#getMixRotate()}, {@link PathConstraintPose#getMixX()}, and /** Changes {@link PathConstraintPose#getMixRotate()}, {@link PathConstraintPose#getMixX()}, and
* {@link PathConstraintPose#getMixY()}. */ * {@link PathConstraintPose#getMixY()}. */
static public class PathConstraintMixTimeline extends CurveTimeline implements ConstraintTimeline { static public class PathConstraintMixTimeline extends CurveTimeline implements ConstraintTimeline {
static public final int ENTRIES = 4; static public final int ENTRIES = 4;
@ -2186,7 +2225,7 @@ public class Animation {
abstract protected boolean global (PhysicsConstraintData constraint); abstract protected boolean global (PhysicsConstraintData constraint);
} }
/** Changes a physics constraint's {@link PhysicsConstraintPose#getInertia()}. */ /** Changes {@link PhysicsConstraintPose#getInertia()}. */
static public class PhysicsConstraintInertiaTimeline extends PhysicsConstraintTimeline { static public class PhysicsConstraintInertiaTimeline extends PhysicsConstraintTimeline {
public PhysicsConstraintInertiaTimeline (int frameCount, int bezierCount, int constraintIndex) { public PhysicsConstraintInertiaTimeline (int frameCount, int bezierCount, int constraintIndex) {
super(frameCount, bezierCount, constraintIndex, Property.physicsConstraintInertia); super(frameCount, bezierCount, constraintIndex, Property.physicsConstraintInertia);
@ -2205,7 +2244,7 @@ public class Animation {
} }
} }
/** Changes a physics constraint's {@link PhysicsConstraintPose#getStrength()}. */ /** Changes {@link PhysicsConstraintPose#getStrength()}. */
static public class PhysicsConstraintStrengthTimeline extends PhysicsConstraintTimeline { static public class PhysicsConstraintStrengthTimeline extends PhysicsConstraintTimeline {
public PhysicsConstraintStrengthTimeline (int frameCount, int bezierCount, int constraintIndex) { public PhysicsConstraintStrengthTimeline (int frameCount, int bezierCount, int constraintIndex) {
super(frameCount, bezierCount, constraintIndex, Property.physicsConstraintStrength); super(frameCount, bezierCount, constraintIndex, Property.physicsConstraintStrength);
@ -2224,7 +2263,7 @@ public class Animation {
} }
} }
/** Changes a physics constraint's {@link PhysicsConstraintPose#getDamping()}. */ /** Changes {@link PhysicsConstraintPose#getDamping()}. */
static public class PhysicsConstraintDampingTimeline extends PhysicsConstraintTimeline { static public class PhysicsConstraintDampingTimeline extends PhysicsConstraintTimeline {
public PhysicsConstraintDampingTimeline (int frameCount, int bezierCount, int constraintIndex) { public PhysicsConstraintDampingTimeline (int frameCount, int bezierCount, int constraintIndex) {
super(frameCount, bezierCount, constraintIndex, Property.physicsConstraintDamping); super(frameCount, bezierCount, constraintIndex, Property.physicsConstraintDamping);
@ -2243,7 +2282,7 @@ public class Animation {
} }
} }
/** Changes a physics constraint's {@link PhysicsConstraintPose#getMassInverse()}. The timeline values are not inverted. */ /** Changes {@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 constraintIndex) { public PhysicsConstraintMassTimeline (int frameCount, int bezierCount, int constraintIndex) {
super(frameCount, bezierCount, constraintIndex, Property.physicsConstraintMass); super(frameCount, bezierCount, constraintIndex, Property.physicsConstraintMass);
@ -2262,7 +2301,7 @@ public class Animation {
} }
} }
/** Changes a physics constraint's {@link PhysicsConstraintPose#getWind()}. */ /** Changes {@link PhysicsConstraintPose#getWind()}. */
static public class PhysicsConstraintWindTimeline extends PhysicsConstraintTimeline { static public class PhysicsConstraintWindTimeline extends PhysicsConstraintTimeline {
public PhysicsConstraintWindTimeline (int frameCount, int bezierCount, int constraintIndex) { public PhysicsConstraintWindTimeline (int frameCount, int bezierCount, int constraintIndex) {
super(frameCount, bezierCount, constraintIndex, Property.physicsConstraintWind); super(frameCount, bezierCount, constraintIndex, Property.physicsConstraintWind);
@ -2282,7 +2321,7 @@ public class Animation {
} }
} }
/** Changes a physics constraint's {@link PhysicsConstraintPose#getGravity()}. */ /** Changes {@link PhysicsConstraintPose#getGravity()}. */
static public class PhysicsConstraintGravityTimeline extends PhysicsConstraintTimeline { static public class PhysicsConstraintGravityTimeline extends PhysicsConstraintTimeline {
public PhysicsConstraintGravityTimeline (int frameCount, int bezierCount, int constraintIndex) { public PhysicsConstraintGravityTimeline (int frameCount, int bezierCount, int constraintIndex) {
super(frameCount, bezierCount, constraintIndex, Property.physicsConstraintGravity); super(frameCount, bezierCount, constraintIndex, Property.physicsConstraintGravity);
@ -2302,7 +2341,7 @@ public class Animation {
} }
} }
/** Changes a physics constraint's {@link PhysicsConstraintPose#getMix()}. */ /** Changes {@link PhysicsConstraintPose#getMix()}. */
static public class PhysicsConstraintMixTimeline extends PhysicsConstraintTimeline { static public class PhysicsConstraintMixTimeline extends PhysicsConstraintTimeline {
public PhysicsConstraintMixTimeline (int frameCount, int bezierCount, int constraintIndex) { public PhysicsConstraintMixTimeline (int frameCount, int bezierCount, int constraintIndex) {
super(frameCount, bezierCount, constraintIndex, Property.physicsConstraintMix); super(frameCount, bezierCount, constraintIndex, Property.physicsConstraintMix);
@ -2382,7 +2421,7 @@ public class Animation {
} }
} }
/** Changes a slider's {@link SliderPose#getTime()}. */ /** Changes {@link SliderPose#getTime()}. */
static public class SliderTimeline extends ConstraintTimeline1 { static public class SliderTimeline extends ConstraintTimeline1 {
public SliderTimeline (int frameCount, int bezierCount, int constraintIndex) { public SliderTimeline (int frameCount, int bezierCount, int constraintIndex) {
super(frameCount, bezierCount, constraintIndex, Property.sliderTime); super(frameCount, bezierCount, constraintIndex, Property.sliderTime);
@ -2399,7 +2438,7 @@ public class Animation {
} }
} }
/** Changes a slider's {@link SliderPose#getMix()}. */ /** Changes {@link SliderPose#getMix()}. */
static public class SliderMixTimeline extends ConstraintTimeline1 { static public class SliderMixTimeline extends ConstraintTimeline1 {
public SliderMixTimeline (int frameCount, int bezierCount, int constraintIndex) { public SliderMixTimeline (int frameCount, int bezierCount, int constraintIndex) {
super(frameCount, bezierCount, constraintIndex, Property.sliderMix); super(frameCount, bezierCount, constraintIndex, Property.sliderMix);

View File

@ -297,9 +297,8 @@ public class AnimationState {
Array<Event> events = null; Array<Event> events = null;
if (from.reverse) if (from.reverse)
applyTime = from.animation.duration - applyTime; applyTime = from.animation.duration - applyTime;
else { else if (mix < from.eventThreshold) //
if (mix < from.eventThreshold) events = this.events; events = this.events;
}
int[] timelineMode = from.timelineMode.items; int[] timelineMode = from.timelineMode.items;
TrackEntry[] timelineHoldMix = from.timelineHoldMix.items; TrackEntry[] timelineHoldMix = from.timelineHoldMix.items;
boolean add = from.additive, shortestRotation = add || from.shortestRotation; boolean add = from.additive, shortestRotation = add || from.shortestRotation;
@ -472,8 +471,8 @@ public class AnimationState {
/** Removes all animations from all tracks, leaving skeletons in their current pose. /** Removes all animations from all tracks, leaving skeletons in their current pose.
* <p> * <p>
* It may be desired to use {@link AnimationState#setEmptyAnimations(float)} to mix the skeletons back to the setup pose, * Usually you want to use {@link #setEmptyAnimations(float)} to mix the skeletons back to the setup pose, rather than leaving
* rather than leaving them in their current pose. */ * them in their current pose. */
public void clearTracks () { public void clearTracks () {
boolean oldDrainDisabled = queue.drainDisabled; boolean oldDrainDisabled = queue.drainDisabled;
queue.drainDisabled = true; queue.drainDisabled = true;
@ -486,8 +485,8 @@ public class AnimationState {
/** Removes all animations from the track, leaving skeletons in their current pose. /** Removes all animations from the track, leaving skeletons in their current pose.
* <p> * <p>
* It may be desired to use {@link AnimationState#setEmptyAnimation(int, float)} to mix the skeletons back to the setup pose, * Usually you want to use {@link #setEmptyAnimation(int, float)} to mix the skeletons back to the setup pose, rather than
* rather than leaving them in their current pose. */ * leaving them in their current pose. */
public void clearTrack (int trackIndex) { public void clearTrack (int trackIndex) {
if (trackIndex < 0) throw new IllegalArgumentException("trackIndex must be >= 0."); if (trackIndex < 0) throw new IllegalArgumentException("trackIndex must be >= 0.");
if (trackIndex >= tracks.size) return; if (trackIndex >= tracks.size) return;
@ -586,8 +585,8 @@ public class AnimationState {
/** Adds an animation to be played after the current or last queued animation for a track. If the track has no entries, this is /** Adds an animation to be played after the current or last queued animation for a track. If the track has no entries, this is
* equivalent to calling {@link #setAnimation(int, Animation, boolean)}. * equivalent to calling {@link #setAnimation(int, Animation, boolean)}.
* @param delay If > 0, sets {@link TrackEntry#getDelay()}. If <= 0, the delay set is the duration of the previous track entry * @param delay If > 0, sets {@link TrackEntry#getDelay()}. If <= 0, the delay set is the duration of the previous track entry
* minus any mix duration (from the {@link AnimationStateData}) plus the specified <code>delay</code> (ie the mix * minus any mix duration (from {@link #data}) plus the specified <code>delay</code> (ie the mix ends at (when
* ends at (<code>delay</code> = 0) or before (<code>delay</code> < 0) the previous track entry duration). If the * <code>delay</code> = 0) or before (when <code>delay</code> < 0) the previous track entry duration). If the
* previous entry is looping, its next loop completion is used instead of its duration. * previous entry is looping, its next loop completion is used instead of its duration.
* @return A track entry to allow further customization of animation playback. References to the track entry must not be kept * @return A track entry to allow further customization of animation playback. References to the track entry must not be kept
* after the {@link AnimationStateListener#dispose(TrackEntry)} event occurs. */ * after the {@link AnimationStateListener#dispose(TrackEntry)} event occurs. */
@ -624,7 +623,7 @@ public class AnimationState {
* {@link #setEmptyAnimations(float)}, or {@link #addEmptyAnimation(int, float, float)}. Mixing to an empty animation causes * {@link #setEmptyAnimations(float)}, or {@link #addEmptyAnimation(int, float, float)}. Mixing to an empty animation causes
* the previous animation to be applied less and less over the mix duration. Properties keyed in the previous animation * the previous animation to be applied less and less over the mix duration. Properties keyed in the previous animation
* transition to the value from lower tracks or to the setup pose value if no lower tracks key the property. A mix duration of * transition to the value from lower tracks or to the setup pose value if no lower tracks key the property. A mix duration of
* 0 still mixes out over one frame. * 0 still needs to be applied one more time to mix out, so the the properties it was animating are reverted.
* <p> * <p>
* Mixing in is done by first setting an empty animation, then adding an animation using * Mixing in is done by first setting an empty animation, then adding an animation using
* {@link #addAnimation(int, Animation, boolean, float)} with the desired delay (an empty animation has a duration of 0) and on * {@link #addAnimation(int, Animation, boolean, float)} with the desired delay (an empty animation has a duration of 0) and on
@ -649,9 +648,9 @@ public class AnimationState {
* <a href='https://esotericsoftware.com/spine-applying-animations/#Empty-animations'>Empty animations</a> in the Spine * <a href='https://esotericsoftware.com/spine-applying-animations/#Empty-animations'>Empty animations</a> in the Spine
* Runtimes Guide. * Runtimes Guide.
* @param delay If > 0, sets {@link TrackEntry#getDelay()}. If <= 0, the delay set is the duration of the previous track entry * @param delay If > 0, sets {@link TrackEntry#getDelay()}. If <= 0, the delay set is the duration of the previous track entry
* minus any mix duration plus the specified <code>delay</code> (ie the mix ends at (<code>delay</code> = 0) or * minus any mix duration plus the specified <code>delay</code> (ie the mix ends at (when <code>delay</code> = 0) or
* before (<code>delay</code> < 0) the previous track entry duration). If the previous entry is looping, its next * before (when <code>delay</code> < 0) the previous track entry duration). If the previous entry is looping, its
* loop completion is used instead of its duration. * next loop completion is used instead of its duration.
* @return A track entry to allow further customization of animation playback. References to the track entry must not be kept * @return A track entry to allow further customization of animation playback. References to the track entry must not be kept
* after the {@link AnimationStateListener#dispose(TrackEntry)} event occurs. */ * after the {@link AnimationStateListener#dispose(TrackEntry)} event occurs. */
public TrackEntry addEmptyAnimation (int trackIndex, float mixDuration, float delay) { public TrackEntry addEmptyAnimation (int trackIndex, float mixDuration, float delay) {
@ -827,7 +826,7 @@ public class AnimationState {
/** Multiplier for the delta time when the animation state is updated, causing time for all animations and mixes to play slower /** Multiplier for the delta time when the animation state is updated, causing time for all animations and mixes to play slower
* or faster. Defaults to 1. * or faster. Defaults to 1.
* <p> * <p>
* See TrackEntry {@link TrackEntry#getTimeScale()} for affecting a single animation. */ * See {@link TrackEntry#getTimeScale()} to affect a single animation. */
public float getTimeScale () { public float getTimeScale () {
return timeScale; return timeScale;
} }
@ -846,7 +845,7 @@ public class AnimationState {
this.data = data; this.data = data;
} }
/** The list of tracks that have had animations, which may contain null entries for tracks that currently have no animation. */ /** The list of tracks that have had animations. May contain null entries for tracks that currently have no animation. */
public Array<TrackEntry> getTracks () { public Array<TrackEntry> getTracks () {
return tracks; return tracks;
} }
@ -924,8 +923,7 @@ public class AnimationState {
/** Seconds to postpone playing the animation. Must be >= 0. When this track entry is the current track entry, /** Seconds to postpone playing the animation. Must be >= 0. When this track entry is the current track entry,
* <code>delay</code> postpones incrementing the {@link #getTrackTime()}. When this track entry is queued, * <code>delay</code> postpones incrementing the {@link #getTrackTime()}. When this track entry is queued,
* <code>delay</code> is the time from the start of the previous animation to when this track entry will become the current * <code>delay</code> is the time from the start of the previous animation to when this track entry will become the current
* track entry (ie when the previous track entry {@link TrackEntry#getTrackTime()} >= this track entry's * track entry (ie when the previous track entry {@link #getTrackTime()} >= this track entry's <code>delay</code>).
* <code>delay</code>).
* <p> * <p>
* {@link #getTimeScale()} affects the delay. * {@link #getTimeScale()} affects the delay.
* <p> * <p>
@ -957,7 +955,7 @@ public class AnimationState {
* is reached, no other animations are queued for playback, and mixing from any previous animations is complete, then the * is reached, no other animations are queued for playback, and mixing from any previous animations is complete, then the
* properties keyed by the animation are set to the setup pose and the track is cleared. * properties keyed by the animation are set to the setup pose and the track is cleared.
* <p> * <p>
* It may be desired to use {@link AnimationState#addEmptyAnimation(int, float, float)} rather than have the animation * Usually you want to use {@link AnimationState#addEmptyAnimation(int, float, float)} rather than have the animation
* abruptly cease being applied. */ * abruptly cease being applied. */
public float getTrackEnd () { public float getTrackEnd () {
return trackEnd; return trackEnd;
@ -967,9 +965,11 @@ public class AnimationState {
this.trackEnd = trackEnd; this.trackEnd = trackEnd;
} }
/** If this track entry is non-looping, the track time in seconds when {@link #getAnimationEnd()} is reached, or the current /** If this track entry is non-looping, this is the track time in seconds when {@link #getAnimationEnd()} is reached, or the
* {@link #getTrackTime()} if it has already been reached. If this track entry is looping, the track time when this * current {@link #getTrackTime()} if it has already been reached.
* animation will reach its next {@link #getAnimationEnd()} (the next loop completion). */ * <p>
* If this track entry is looping, this is the track time when this animation will reach its next {@link #getAnimationEnd()}
* (the next loop completion). */
public float getTrackComplete () { public float getTrackComplete () {
float duration = animationEnd - animationStart; float duration = animationEnd - animationStart;
if (duration != 0) { if (duration != 0) {
@ -1018,7 +1018,7 @@ public class AnimationState {
* <code>animationTime</code> is equal to the <code>animationStart</code> time. * <code>animationTime</code> is equal to the <code>animationStart</code> time.
* <p> * <p>
* The <code>animationTime</code> is between {@link #getAnimationStart()} and {@link #getAnimationEnd()}, except if this * The <code>animationTime</code> is between {@link #getAnimationStart()} and {@link #getAnimationEnd()}, except if this
* track entry is non-looping and {@link #getAnimationEnd()} is >= to the animation {@link Animation#duration}, then * track entry is non-looping and {@link #getAnimationEnd()} is >= to the {@link Animation#duration}, then
* <code>animationTime</code> continues to increase past {@link #getAnimationEnd()}. */ * <code>animationTime</code> continues to increase past {@link #getAnimationEnd()}. */
public float getAnimationTime () { public float getAnimationTime () {
if (loop) { if (loop) {
@ -1039,10 +1039,10 @@ public class AnimationState {
* match the animation speed. * match the animation speed.
* <p> * <p>
* When using {@link AnimationState#addAnimation(int, Animation, boolean, float)} with a <code>delay</code> <= 0, the * When using {@link AnimationState#addAnimation(int, Animation, boolean, float)} with a <code>delay</code> <= 0, the
* {@link #getDelay()} is set using the mix duration from the {@link AnimationStateData}, assuming time scale to be 1. If * {@link #getDelay()} is set using the mix duration from {@link AnimationState#data}, assuming time scale to be 1. If the
* the time scale is not 1, the delay may need to be adjusted. * time scale is not 1, the delay may need to be adjusted.
* <p> * <p>
* See AnimationState {@link AnimationState#getTimeScale()} for affecting all animations. */ * See {@link AnimationState#getTimeScale()} to affect all animations. */
public float getTimeScale () { public float getTimeScale () {
return timeScale; return timeScale;
} }
@ -1054,7 +1054,7 @@ public class AnimationState {
/** The listener for events generated by this track entry, or null. /** The listener for events generated by this track entry, or null.
* <p> * <p>
* A track entry returned from {@link AnimationState#setAnimation(int, Animation, boolean)} is already the current animation * A track entry returned from {@link AnimationState#setAnimation(int, Animation, boolean)} is already the current animation
* for the track, so the track entry listener {@link AnimationStateListener#start(TrackEntry)} will not be called. */ * for the track, so the callback for {@link AnimationStateListener#start(TrackEntry)} will not be called. */
public @Null AnimationStateListener getListener () { public @Null AnimationStateListener getListener () {
return listener; return listener;
} }
@ -1063,12 +1063,12 @@ public class AnimationState {
this.listener = listener; this.listener = listener;
} }
/** Values < 1 mix this animation with the skeleton's current pose (usually the pose resulting from lower tracks). Defaults /** Values < 1 mix this animation with the skeleton's current pose (either the setup pose or the pose from lower tracks).
* to 1, which overwrites the skeleton's current pose with this animation. * Defaults to 1, which overwrites the skeleton's current pose with this animation.
* <p> * <p>
* Typically track 0 is used to completely pose the skeleton, then alpha is used on higher tracks. It doesn't make sense to * Alpha should be 1 on track 0.
* use alpha on track 0 if the skeleton pose is from the last frame render. * <p>
* @see #getAlphaAttachmentThreshold() */ * See {@link #getAlphaAttachmentThreshold()}. */
public float getAlpha () { public float getAlpha () {
return alpha; return alpha;
} }
@ -1088,8 +1088,9 @@ public class AnimationState {
this.eventThreshold = eventThreshold; this.eventThreshold = eventThreshold;
} }
/** When {@link #getAlpha()} is greater than <code>alphaAttachmentThreshold</code>, attachment timelines are applied. /** When the computed alpha is greater than <code>alphaAttachmentThreshold</code>, attachment timelines are applied. The
* Defaults to 0, so attachment timelines are always applied. */ * computed alpha includes {@link #getAlpha()} and the mix percentage. Defaults to 0, so attachment timelines are always
* applied. */
public float getAlphaAttachmentThreshold () { public float getAlphaAttachmentThreshold () {
return alphaAttachmentThreshold; return alphaAttachmentThreshold;
} }
@ -1153,8 +1154,8 @@ public class AnimationState {
return trackTime >= animationEnd - animationStart; return trackTime >= animationEnd - animationStart;
} }
/** Seconds from 0 to the {@link #getMixDuration()} when mixing from the previous animation to this animation. May be /** Seconds elapsed from 0 to the {@link #getMixDuration()} when mixing from the previous animation to this animation. May
* slightly more than <code>mixDuration</code> when the mix is complete. */ * be slightly more than <code>mixDuration</code> when the mix is complete. */
public float getMixTime () { public float getMixTime () {
return mixTime; return mixTime;
} }
@ -1163,23 +1164,32 @@ public class AnimationState {
this.mixTime = mixTime; this.mixTime = mixTime;
} }
/** Seconds for mixing from the previous animation to this animation. Defaults to the value provided by AnimationStateData /** Seconds for mixing from the previous animation to this animation. Defaults to the value provided by
* {@link AnimationStateData#getMix(Animation, Animation)} based on the animation before this animation (if any). * {@link AnimationStateData#getMix(Animation, Animation)} based on the animation before this animation (if any).
* <p> * <p>
* A mix duration of 0 still mixes out over one frame to provide the track entry being mixed out a chance to revert the * A mix duration of 0 still needs to be applied one more time to mix out, so the the properties it was animating are
* properties it was animating. A mix duration of 0 can be set at any time to end the mix on the next * reverted. A mix duration of 0 can be set at any time to end the mix on the next {@link AnimationState#update(float)
* {@link AnimationState#update(float) update}. * update}.
* <p> * <p>
* The <code>mixDuration</code> can be set manually rather than use the value from * The <code>mixDuration</code> can be set manually rather than use the value from
* {@link AnimationStateData#getMix(Animation, Animation)}. In that case, the <code>mixDuration</code> can be set for a new * {@link AnimationStateData#getMix(Animation, Animation)}. In that case, the <code>mixDuration</code> can be set for a new
* track entry only before {@link AnimationState#update(float)} is next called. * track entry only before {@link AnimationState#update(float)} is next called.
* <p> * <p>
* When using {@link AnimationState#addAnimation(int, Animation, boolean, float)} with a <code>delay</code> <= 0, the * When using {@link AnimationState#addAnimation(int, Animation, boolean, float)} with a <code>delay</code> <= 0, the
* {@link #getDelay()} is set using the mix duration from the {@link AnimationStateData}. If <code>mixDuration</code> is set * {@link #getDelay()} is set using the mix duration from {@link AnimationState#data}. If <code>mixDuration</code> is set
* afterward, the delay may need to be adjusted. For example:<br> * afterward, the delay needs to be adjusted:
* <code>entry.delay = entry.previous.getTrackComplete() - entry.mixDuration;</code><br> *
* Alternatively, {@link #setMixDuration(float, float)} can be used to recompute the delay:<br> * <pre>
* <code>entry.setMixDuration(0.25f, 0);</code> */ * entry.mixDuration = 0.25;<br>
* entry.delay = entry.previous.getTrackComplete() - entry.mixDuration + 0;
* </pre>
*
* Alternatively, use {@link #setMixDuration(float, float)} to set both the mix duration and recompute the delay:<br>
*
* <pre>
* entry.setMixDuration(0.25f, 0); // mixDuration, delay
* </pre>
*/
public float getMixDuration () { public float getMixDuration () {
return mixDuration; return mixDuration;
} }
@ -1189,18 +1199,19 @@ public class AnimationState {
} }
/** Sets both {@link #getMixDuration()} and {@link #getDelay()}. /** Sets both {@link #getMixDuration()} and {@link #getDelay()}.
* @param delay If > 0, sets {@link TrackEntry#getDelay()}. If <= 0, the delay set is the duration of the previous track * @param delay If > 0, sets {@link #getDelay()}. If <= 0, the delay set is the duration of the previous track entry minus
* entry minus the specified mix duration plus the specified <code>delay</code> (ie the mix ends at * the specified mix duration plus the specified <code>delay</code> (ie the mix ends at (when <code>delay</code> =
* (<code>delay</code> = 0) or before (<code>delay</code> < 0) the previous track entry duration). If the previous * 0) or before (when <code>delay</code> < 0) the previous track entry duration). If the previous entry is
* entry is looping, its next loop completion is used instead of its duration. */ * looping, its next loop completion is used instead of its duration. */
public void setMixDuration (float mixDuration, float delay) { public void setMixDuration (float mixDuration, float delay) {
this.mixDuration = mixDuration; this.mixDuration = mixDuration;
if (delay <= 0) delay = previous == null ? 0 : Math.max(delay + previous.getTrackComplete() - mixDuration, 0); if (delay <= 0) delay = previous == null ? 0 : Math.max(delay + previous.getTrackComplete() - mixDuration, 0);
this.delay = delay; this.delay = delay;
} }
/** When true, timelines in this animation that support additive are added to the setup or current pose. Additive can be set /** When true, timelines in this animation that support additive have their values added to the setup or current pose values
* for a new track entry only before {@link AnimationState#apply(Skeleton)} is next called. */ * instead of replacing them. Additive can be set for a new track entry only before {@link AnimationState#apply(Skeleton)}
* is next called. */
public boolean getAdditive () { public boolean getAdditive () {
return additive; return additive;
} }
@ -1209,14 +1220,14 @@ public class AnimationState {
this.additive = additive; this.additive = additive;
} }
/** The track entry for the previous animation when mixing from the previous animation to this animation, or null if no /** The track entry for the previous animation when mixing to this animation, or null if no mixing is currently occurring.
* mixing is currently occurring. When mixing from multiple animations, <code>mixingFrom</code> makes up a linked list. */ * When mixing from multiple animations, <code>mixingFrom</code> makes up a doubly linked list. */
public @Null TrackEntry getMixingFrom () { public @Null TrackEntry getMixingFrom () {
return mixingFrom; return mixingFrom;
} }
/** The track entry for the next animation when mixing from this animation to the next animation, or null if no mixing is /** The track entry for the next animation when mixing from this animation, or null if no mixing is currently occurring.
* currently occurring. When mixing to multiple animations, <code>mixingTo</code> makes up a linked list. */ * When mixing to multiple animations, <code>mixingTo</code> makes up a doubly linked list. */
public @Null TrackEntry getMixingTo () { public @Null TrackEntry getMixingTo () {
return mixingTo; return mixingTo;
} }
@ -1248,18 +1259,21 @@ public class AnimationState {
* shortest rotation direction may change during the mix. * shortest rotation direction may change during the mix.
* <p> * <p>
* If false, the shortest rotation direction is remembered when the mix starts and the same direction is used for the rest * If false, the shortest rotation direction is remembered when the mix starts and the same direction is used for the rest
* of the mix. Defaults to false. */ * of the mix. Defaults to false.
* <p>
* See {@link #resetRotationDirections()}. */
public boolean getShortestRotation () { public boolean getShortestRotation () {
return shortestRotation; return shortestRotation;
} }
/** Resets the rotation directions for mixing this entry's rotate timelines. This can be useful to avoid bones rotating the /** When {@link #shortestRotation} is false, this clears the directions for mixing this entry's rotation. This can be useful
* long way around when using {@link #getAlpha()} and starting animations on other tracks. * to avoid bones rotating the long way around when using {@link #getAlpha()} and starting animations on other tracks.
* <p> * <p>
* Mixing involves finding a rotation between two others, which has two possible solutions: the short way or the long way * Mixing involves finding a rotation between two others. There are two possible solutions: the short or the long way
* around. The two rotations likely change over time, so which direction is the short or long way also changes. If the short * around. When the two rotations change over time, which direction is the short or long way can also change. If the short
* way was always chosen, bones would flip to the other side when that direction became the long way. TrackEntry chooses the * way was always chosen, bones flip to the other side when that direction became the long way. TrackEntry chooses the short
* short way the first time it is applied and remembers that direction. */ * way the first time it is applied and remembers that direction. Resetting that direction makes it choose a new short way
* on the next apply. */
public void resetRotationDirections () { public void resetRotationDirections () {
timelinesRotation.clear(); timelinesRotation.clear();
} }
@ -1268,7 +1282,7 @@ public class AnimationState {
this.reverse = reverse; this.reverse = reverse;
} }
/** If true, the animation will be applied in reverse. Events are not fired when an animation is applied in reverse. */ /** If true, the animation will be applied in reverse and events will not be fired. */
public boolean getReverse () { public boolean getReverse () {
return reverse; return reverse;
} }
@ -1388,7 +1402,7 @@ public class AnimationState {
* TrackEntry events are collected during {@link AnimationState#update(float)} and {@link AnimationState#apply(Skeleton)} and * TrackEntry events are collected during {@link AnimationState#update(float)} and {@link AnimationState#apply(Skeleton)} and
* fired only after those methods are finished. * fired only after those methods are finished.
* <p> * <p>
* See TrackEntry {@link TrackEntry#setListener(AnimationStateListener)} and AnimationState * See {@link TrackEntry#setListener(AnimationStateListener)} and
* {@link AnimationState#addListener(AnimationStateListener)}. */ * {@link AnimationState#addListener(AnimationStateListener)}. */
static public interface AnimationStateListener { static public interface AnimationStateListener {
/** Invoked when this entry has been set as the current entry. {@link #end(TrackEntry)} will occur when this entry will no /** Invoked when this entry has been set as the current entry. {@link #end(TrackEntry)} will occur when this entry will no

View File

@ -33,7 +33,7 @@ import com.badlogic.gdx.utils.ObjectFloatMap;
import com.esotericsoftware.spine.AnimationState.TrackEntry; import com.esotericsoftware.spine.AnimationState.TrackEntry;
/** Stores mix (crossfade) durations to be applied when {@link AnimationState} animations are changed. */ /** Stores mix (crossfade) durations to be applied when {@link AnimationState} animations are changed on the same track. */
public class AnimationStateData { public class AnimationStateData {
final SkeletonData skeletonData; final SkeletonData skeletonData;
final ObjectFloatMap<Key> animationToMixTime = new ObjectFloatMap(51, 0.8f); final ObjectFloatMap<Key> animationToMixTime = new ObjectFloatMap(51, 0.8f);
@ -73,8 +73,8 @@ public class AnimationStateData {
animationToMixTime.put(key, duration); animationToMixTime.put(key, duration);
} }
/** Returns the mix duration to use when changing from the specified animation to the other, or the {@link #getDefaultMix()} if /** Returns the mix duration to use when changing from the specified animation to the other on the same track, or the
* no mix duration has been set. */ * {@link #getDefaultMix()} if no mix duration has been set. */
public float getMix (Animation from, Animation to) { public float getMix (Animation from, Animation to) {
if (from == null) throw new IllegalArgumentException("from cannot be null."); if (from == null) throw new IllegalArgumentException("from cannot be null.");
if (to == null) throw new IllegalArgumentException("to cannot be null."); if (to == null) throw new IllegalArgumentException("to cannot be null.");

View File

@ -32,12 +32,15 @@ package com.esotericsoftware.spine;
import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.Null; import com.badlogic.gdx.utils.Null;
// BOZO - Update javadocs. /** A bone has a number of poses:
/** The current pose for a bone, before constraints are applied. * <ul>
* <p> * <li>{@link BoneData#getSetupPose()}: The setup pose.
* A bone has a local transform which is used to compute its world transform. A bone also has an applied transform, which is a * <li>{@link #getPose()}: The local pose. Set by animations and app code.
* local transform that can be applied to compute the world transform. The local transform and applied transform may differ if a * <li>{@link #getAppliedPose()}: The applied local pose. This is the local pose modified by constraints and app code.
* constraint or application code modifies the world transform after it was computed from the local transform. */ * <li>The world transform on the applied pose, computed by {@link Skeleton#updateWorldTransform(Physics)} and
* {@link BonePose#updateWorldTransform(Skeleton)}.
* </ul>
*/
public class Bone extends PosedActive<BoneData, BoneLocal, BonePose> { public class Bone extends PosedActive<BoneData, BoneLocal, BonePose> {
@Null final Bone parent; @Null final Bone parent;
final Array<Bone> children = new Array(true, 4, Bone[]::new); final Array<Bone> children = new Array(true, 4, Bone[]::new);

View File

@ -58,11 +58,19 @@ public class BoneData extends PosedData<BoneLocal> {
setup.set(data.setup); setup.set(data.setup);
} }
/** The index of the bone in {@link Skeleton#getBones()}. */ /** The bone's name, unique across all bones in the skeleton.
* <p>
* See {@link SkeletonData#findBone(String)} and {@link Skeleton#findBone(String)}. */
public String getName () { // Do not port.
return super.getName();
}
/** The {@link Skeleton#getBones()} index. */
public int getIndex () { public int getIndex () {
return index; return index;
} }
/** The parent bone, or null if this bone is the root. */
public @Null BoneData getParent () { public @Null BoneData getParent () {
return parent; return parent;
} }
@ -82,7 +90,7 @@ public class BoneData extends PosedData<BoneLocal> {
return color; return color;
} }
/** The bone icon as it was in Spine, or null if nonessential data was not exported. */ /** The bone icon name as it was in Spine, or null if nonessential data was not exported. */
public @Null String getIcon () { public @Null String getIcon () {
return icon; return icon;
} }

View File

@ -9,8 +9,15 @@ import com.badlogic.gdx.math.Vector2;
import com.esotericsoftware.spine.BoneData.Inherit; import com.esotericsoftware.spine.BoneData.Inherit;
/** The applied pose for a bone. This is the {@link Bone} pose with constraints applied and the world transform computed by /** The applied local pose and world transform for a bone. This is the {@link Bone#getPose()} with constraints applied and the
* {@link Skeleton#updateWorldTransform(Physics)}. */ * world transform computed by {@link Skeleton#updateWorldTransform(Physics)} and {@link #updateWorldTransform(Skeleton)}.
* <p>
* If the world transform is changed, call {@link #updateLocalTransform(Skeleton)} before using the local transform. The local
* transform may be needed by other code (eg to apply another constraint).
* <p>
* After changing the world transform, call {@link #updateWorldTransform(Skeleton)} on every descendant bone. It may be more
* convenient to modify the local transform instead, then call {@link Skeleton#updateWorldTransform(Physics)} to update the world
* transforms for all bones and apply constraints. */
public class BonePose extends BoneLocal implements Update { public class BonePose extends BoneLocal implements Update {
Bone bone; Bone bone;
float a, b, worldX; float a, b, worldX;
@ -22,7 +29,8 @@ public class BonePose extends BoneLocal implements Update {
if (world != skeleton.update) updateWorldTransform(skeleton); if (world != skeleton.update) updateWorldTransform(skeleton);
} }
/** Computes the world transform using the parent bone's applied pose and this pose. Child bones are not updated. /** Computes the world transform using the parent bone's world transform and this applied local pose. Child bones are not
* updated.
* <p> * <p>
* See <a href="https://esotericsoftware.com/spine-runtime-skeletons#World-transforms">World transforms</a> in the Spine * See <a href="https://esotericsoftware.com/spine-runtime-skeletons#World-transforms">World transforms</a> in the Spine
* Runtimes Guide. */ * Runtimes Guide. */
@ -130,10 +138,6 @@ public class BonePose extends BoneLocal implements Update {
} }
/** Computes the local transform values from the world transform. /** Computes the local transform values from the world transform.
* <p>
* If the world transform is modified (by a constraint, {@link #rotateWorld(float)}, etc) then this method should be called so
* the local transform matches the world transform. The local transform may be needed by other code (eg to apply another
* constraint).
* <p> * <p>
* Some information is ambiguous in the world transform, such as -1,-1 scale versus 180 rotation. The local transform after * Some information is ambiguous in the world transform, such as -1,-1 scale versus 180 rotation. The local transform after
* calling this method is equivalent to the local transform used to compute the world transform, but may not be identical. */ * calling this method is equivalent to the local transform used to compute the world transform, but may not be identical. */
@ -218,8 +222,9 @@ public class BonePose extends BoneLocal implements Update {
} }
} }
/** If the world transform has been modified and the local transform no longer matches, {@link #updateLocalTransform(Skeleton)} /** If the world transform has been modified by constraints and the local transform no longer matches,
* is called. */ * {@link #updateLocalTransform(Skeleton)} is called. Call this after {@link Skeleton#updateWorldTransform(Physics)} before
* using the applied local transform. */
public void validateLocalTransform (Skeleton skeleton) { public void validateLocalTransform (Skeleton skeleton) {
if (local == skeleton.update) updateLocalTransform(skeleton); if (local == skeleton.update) updateLocalTransform(skeleton);
} }
@ -248,7 +253,7 @@ public class BonePose extends BoneLocal implements Update {
} }
} }
/** Part of the world transform matrix for the X axis. If changed, {@link #updateLocalTransform(Skeleton)} should be called. */ /** Part of the world transform matrix for the X axis. */
public float getA () { public float getA () {
return a; return a;
} }
@ -257,7 +262,7 @@ public class BonePose extends BoneLocal implements Update {
this.a = a; this.a = a;
} }
/** Part of the world transform matrix for the Y axis. If changed, {@link #updateLocalTransform(Skeleton)} should be called. */ /** Part of the world transform matrix for the Y axis. */
public float getB () { public float getB () {
return b; return b;
} }
@ -266,7 +271,7 @@ public class BonePose extends BoneLocal implements Update {
this.b = b; this.b = b;
} }
/** Part of the world transform matrix for the X axis. If changed, {@link #updateLocalTransform(Skeleton)} should be called. */ /** Part of the world transform matrix for the X axis. */
public float getC () { public float getC () {
return c; return c;
} }
@ -275,7 +280,7 @@ public class BonePose extends BoneLocal implements Update {
this.c = c; this.c = c;
} }
/** Part of the world transform matrix for the Y axis. If changed, {@link #updateLocalTransform(Skeleton)} should be called. */ /** Part of the world transform matrix for the Y axis. */
public float getD () { public float getD () {
return d; return d;
} }
@ -284,7 +289,7 @@ public class BonePose extends BoneLocal implements Update {
this.d = d; this.d = d;
} }
/** The world X position. If changed, {@link #updateLocalTransform(Skeleton)} should be called. */ /** The world X position. */
public float getWorldX () { public float getWorldX () {
return worldX; return worldX;
} }
@ -293,7 +298,7 @@ public class BonePose extends BoneLocal implements Update {
this.worldX = worldX; this.worldX = worldX;
} }
/** The world Y position. If changed, {@link #updateLocalTransform(Skeleton)} should be called. */ /** The world Y position. */
public float getWorldY () { public float getWorldY () {
return worldY; return worldY;
} }
@ -382,10 +387,7 @@ public class BonePose extends BoneLocal implements Update {
return atan2Deg(cos * c + sin * d, cos * a + sin * b); return atan2Deg(cos * c + sin * d, cos * a + sin * b);
} }
/** Rotates the world transform the specified amount. /** Rotates the world transform the specified amount. */
* <p>
* After changes are made to the world transform, {@link #updateLocalTransform(Skeleton)} should be called on this bone and any
* child bones, recursively. */
public void rotateWorld (float degrees) { public void rotateWorld (float degrees) {
degrees *= degRad; degrees *= degRad;
float sin = sin(degrees), cos = cos(degrees); float sin = sin(degrees), cos = cos(degrees);

View File

@ -10,5 +10,12 @@ abstract public class ConstraintData< //
super(name, setup); super(name, setup);
} }
/** The constraint's name, unique across all constraints in the skeleton.
* <p>
* See {@link SkeletonData#findConstraint(String, Class)} and {@link Skeleton#findConstraint(String, Class)}. */
public String getName () { // Do not port.
return super.getName();
}
abstract public T create (Skeleton skeleton); abstract public T create (Skeleton skeleton);
} }

View File

@ -34,9 +34,8 @@ import com.esotericsoftware.spine.AnimationState.AnimationStateListener;
/** Stores the current pose values for an {@link Event}. /** Stores the current pose values for an {@link Event}.
* <p> * <p>
* See Timeline * See {@link Timeline#apply(Skeleton, float, float, com.badlogic.gdx.utils.Array, float, boolean, boolean, boolean, boolean)},
* {@link Timeline#apply(Skeleton, float, float, com.badlogic.gdx.utils.Array, float, boolean, boolean, boolean, boolean)}, * {@link AnimationStateListener#event(com.esotericsoftware.spine.AnimationState.TrackEntry, Event)}, and
* AnimationStateListener {@link AnimationStateListener#event(com.esotericsoftware.spine.AnimationState.TrackEntry, Event)}, and
* <a href="https://esotericsoftware.com/spine-events">Events</a> in the Spine User Guide. */ * <a href="https://esotericsoftware.com/spine-events">Events</a> in the Spine User Guide. */
public class Event { public class Event {
final EventData data; final EventData data;

View File

@ -94,7 +94,9 @@ public class EventData {
this.balance = balance; this.balance = balance;
} }
/** The name of the event, which is unique across all events in the skeleton. */ /** The name of the event, unique across all events in the skeleton.
* <p>
* See {@link SkeletonData#findEvent(String)}. */
public String getName () { public String getName () {
return name; return name;
} }

View File

@ -16,11 +16,8 @@ abstract public class PosedActive< //
/** 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. See {@link Skin#getBones()},
* @see Skin#getBones() * {@link Skin#getConstraints()}, {@link PosedData#getSkinRequired()}, and {@link Skeleton#updateCache()}. */
* @see Skin#getConstraints()
* @see PosedData#getSkinRequired()
* @see Skeleton#updateCache() */
public boolean isActive () { public boolean isActive () {
return active; return active;
} }

View File

@ -41,7 +41,6 @@ abstract public class PosedData<P extends Pose> {
this.setup = setup; this.setup = setup;
} }
/** The constraint's name, which is unique across all constraints in the skeleton of the same type. */
public String getName () { public String getName () {
return name; return name;
} }

View File

@ -350,7 +350,7 @@ public class Skeleton {
return null; return null;
} }
/** The skeleton's slots in the order they should be drawn. The returned array may be modified to change the draw order. */ /** The skeleton's slots in the order they should be drawn. The returned list may be modified to change the draw order. */
public Array<Slot> getDrawOrder () { public Array<Slot> getDrawOrder () {
return drawOrder; return drawOrder;
} }
@ -650,7 +650,7 @@ public class Skeleton {
constraints[i].rotate(x, y, degrees); constraints[i].rotate(x, y, degrees);
} }
/** Returns the skeleton's time. This is used for time-based manipulations, such as {@link PhysicsConstraint}. /** Returns the skeleton's time, used for time-based manipulations, such as {@link PhysicsConstraint}.
* <p> * <p>
* See {@link #update(float)}. */ * See {@link #update(float)}. */
public float getTime () { public float getTime () {

View File

@ -39,7 +39,7 @@ import com.esotericsoftware.spine.attachments.MeshAttachment;
/** Stores attachments by slot index and placeholder name. /** Stores attachments by slot index and placeholder name.
* <p> * <p>
* See SkeletonData {@link SkeletonData#defaultSkin}, Skeleton {@link Skeleton#skin}, and * See {@link SkeletonData#defaultSkin}, {@link Skeleton#skin}, and
* <a href="https://esotericsoftware.com/spine-runtime-skins">Runtime skins</a> in the Spine Runtimes Guide. */ * <a href="https://esotericsoftware.com/spine-runtime-skins">Runtime skins</a> in the Spine Runtimes Guide. */
public class Skin { public class Skin {
final String name; final String name;
@ -138,7 +138,9 @@ public class Skin {
return constraints; return constraints;
} }
/** The skin's name, which is unique across all skins in the skeleton. */ /** The skin's name, unique across all skins in the skeleton.
* <p>
* See {@link SkeletonData#findSkin(String)}. */
public String getName () { public String getName () {
return name; return name;
} }

View File

@ -49,7 +49,14 @@ public class SlotData extends PosedData<SlotPose> {
this.boneData = boneData; this.boneData = boneData;
} }
/** The index of the slot in {@link Skeleton#getSlots()}. */ /** The slot's name, unique across all slots in the skeleton.
* <p>
* See {@link SkeletonData#findSlot(String)} and {@link Skeleton#findSlot(String)}. */
public String getName () { // Do not port.
return super.getName();
}
/** The {@link Skeleton#getSlots()} index. */
public int getIndex () { public int getIndex () {
return index; return index;
} }

View File

@ -32,16 +32,20 @@ package com.esotericsoftware.spine.attachments;
import com.badlogic.gdx.graphics.g2d.TextureAtlas; import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.graphics.g2d.TextureAtlas.AtlasRegion; import com.badlogic.gdx.graphics.g2d.TextureAtlas.AtlasRegion;
import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.utils.Null;
import com.esotericsoftware.spine.Skin; import com.esotericsoftware.spine.Skin;
/** An {@link AttachmentLoader} that configures attachments using texture regions from an {@link Atlas}. /** An {@link AttachmentLoader} that configures attachments using texture regions from an {@link TextureAtlas}.
* <p> * <p>
* See <a href='https://esotericsoftware.com/spine-loading-skeleton-data#JSON-and-binary-data'>Loading skeleton data</a> in the * See <a href='https://esotericsoftware.com/spine-loading-skeleton-data#JSON-and-binary-data'>Loading skeleton data</a> in the
* Spine Runtimes Guide. */ * Spine Runtimes Guide. */
@SuppressWarnings("javadoc") @SuppressWarnings("javadoc")
public class AtlasAttachmentLoader implements AttachmentLoader { public class AtlasAttachmentLoader implements AttachmentLoader {
private TextureAtlas atlas; private TextureAtlas atlas;
/** If true, {@link #findRegion(String, String)} may return null. If false, an error is raised if the texture region is not
* found. Default is false. */
public boolean allowMissingRegions; public boolean allowMissingRegions;
public AtlasAttachmentLoader (TextureAtlas atlas) { public AtlasAttachmentLoader (TextureAtlas atlas) {
@ -54,13 +58,17 @@ public class AtlasAttachmentLoader implements AttachmentLoader {
this.allowMissingRegions = allowMissingRegions; this.allowMissingRegions = allowMissingRegions;
} }
/** Sets each {@link Sequence#getRegions()} by calling {@link #findRegion(String, String)} for each texture region using
* {@link Sequence#getPath(String, int)}. */
protected void findRegions (String name, String basePath, Sequence sequence) { protected void findRegions (String name, String basePath, Sequence sequence) {
TextureRegion[] regions = sequence.getRegions(); TextureRegion[] regions = sequence.getRegions();
for (int i = 0, n = regions.length; i < n; i++) for (int i = 0, n = regions.length; i < n; i++)
regions[i] = findRegion(name, sequence.getPath(basePath, i)); regions[i] = findRegion(name, sequence.getPath(basePath, i));
} }
protected AtlasRegion findRegion (String name, String path) { /** Looks for the region with the specified path. If not found and {@link #allowMissingRegions} is false, an error is
* raised. */
protected @Null AtlasRegion findRegion (String name, String path) {
AtlasRegion region = atlas.findRegion(path); AtlasRegion region = atlas.findRegion(path);
if (region == null && !allowMissingRegions) if (region == null && !allowMissingRegions)
throw new RuntimeException("Region not found in atlas: " + path + " (attachment: " + name + ")"); throw new RuntimeException("Region not found in atlas: " + path + " (attachment: " + name + ")");

View File

@ -52,7 +52,7 @@ public class ClippingAttachment extends VertexAttachment {
color.set(other.color); color.set(other.color);
} }
/** Clipping is performed between the clipping attachment's slot and the end slot. If null clipping is done until the end of /** Clipping is performed between the clipping attachment's slot and the end slot. If null, clipping is done until the end of
* the skeleton's rendering. */ * the skeleton's rendering. */
public @Null SlotData getEndSlot () { public @Null SlotData getEndSlot () {
return endSlot; return endSlot;

View File

@ -31,15 +31,21 @@ package com.esotericsoftware.spine.attachments;
import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.Color;
import com.esotericsoftware.spine.SlotPose;
/** Interface for an attachment that gets 1 or more texture regions from a {@link Sequence}. */
public interface HasSequence { public interface HasSequence {
/** The base path for the attachment's texture region. */
public String getPath (); public String getPath ();
public void setPath (String path); public void setPath (String path);
/** The color the attachment is tinted, to be combined with {@link SlotPose#getColor()}. */
public Color getColor (); public Color getColor ();
/** Calls {@link Sequence#update(HasSequence)} on this attachment's sequence. */ /** Calls {@link Sequence#update(HasSequence)} on this attachment's sequence. */
public void updateSequence (); public void updateSequence ();
/** The sequence that provides texture regions, UVs, and vertex offsets for rendering this attachment. */
public Sequence getSequence (); public Sequence getSequence ();
} }

View File

@ -37,7 +37,7 @@ import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.utils.Null; import com.badlogic.gdx.utils.Null;
/** An attachment that displays a textured mesh. A mesh has hull vertices and internal vertices within the hull. Holes are not /** An attachment that displays a textured mesh. A mesh has hull vertices and internal vertices within the hull. Holes are not
* supported. Each vertex has UVs (texture coordinates) and triangles are used to map an image on to the mesh. * supported. Each vertex has UVs (texture coordinates) and triangles that are used to map an image on to the mesh.
* <p> * <p>
* See <a href="https://esotericsoftware.com/spine-meshes">Mesh attachments</a> in the Spine User Guide. */ * See <a href="https://esotericsoftware.com/spine-meshes">Mesh attachments</a> in the Spine User Guide. */
public class MeshAttachment extends VertexAttachment implements HasSequence { public class MeshAttachment extends VertexAttachment implements HasSequence {
@ -138,8 +138,8 @@ public class MeshAttachment extends VertexAttachment implements HasSequence {
this.edges = edges; this.edges = edges;
} }
/** Vertex index pairs describing edges for controlling triangulation, or be null if nonessential data was not exported. Mesh /** Vertex index pairs describing edges for controlling triangulation, or null if nonessential data was not exported. Mesh
* triangles never cross edges. Triangulation is not performed at runtime. */ * triangles do not cross edges. Triangulation is not performed at runtime. */
public @Null short[] getEdges () { public @Null short[] getEdges () {
return edges; return edges;
} }
@ -164,7 +164,7 @@ public class MeshAttachment extends VertexAttachment implements HasSequence {
/** The parent mesh if this is a linked mesh, else null. A linked mesh shares the {@link #bones}, {@link #vertices}, /** The parent mesh if this is a linked mesh, else null. A linked mesh shares the {@link #bones}, {@link #vertices},
* {@link #regionUVs}, {@link #triangles}, {@link #hullLength}, {@link #edges}, {@link #width}, and {@link #height} with the * {@link #regionUVs}, {@link #triangles}, {@link #hullLength}, {@link #edges}, {@link #width}, and {@link #height} with the
* parent mesh, but may have a different {@link #name} or {@link #path} (and therefore a different texture). */ * parent mesh, but may have a different {@link #name} or {@link #path}, and therefore a different texture region. */
public @Null MeshAttachment getParentMesh () { public @Null MeshAttachment getParentMesh () {
return parentMesh; return parentMesh;
} }

View File

@ -70,8 +70,8 @@ public class PathAttachment extends VertexAttachment {
this.closed = closed; this.closed = closed;
} }
/** If true, additional calculations are performed to make computing positions along the path more accurate and movement along /** If true, additional calculations are performed to make computing positions along the path more accurate so movement along
* the path have a constant speed. */ * the path has a constant speed. */
public boolean getConstantSpeed () { public boolean getConstantSpeed () {
return constantSpeed; return constantSpeed;
} }

View File

@ -60,6 +60,7 @@ public class PointAttachment extends Attachment {
color.set(other.color); color.set(other.color);
} }
/** The local X position. */
public float getX () { public float getX () {
return x; return x;
} }
@ -68,6 +69,7 @@ public class PointAttachment extends Attachment {
this.x = x; this.x = x;
} }
/** The local Y position. */
public float getY () { public float getY () {
return y; return y;
} }
@ -76,6 +78,7 @@ public class PointAttachment extends Attachment {
this.y = y; this.y = y;
} }
/** The local rotation in degrees, counter clockwise. */
public float getRotation () { public float getRotation () {
return rotation; return rotation;
} }
@ -90,12 +93,14 @@ public class PointAttachment extends Attachment {
return color; return color;
} }
/** Computes the world position from the local position. */
public Vector2 computeWorldPosition (BonePose bone, Vector2 point) { public Vector2 computeWorldPosition (BonePose bone, Vector2 point) {
point.x = x * bone.getA() + y * bone.getB() + bone.getWorldX(); point.x = x * bone.getA() + y * bone.getB() + bone.getWorldX();
point.y = x * bone.getC() + y * bone.getD() + bone.getWorldY(); point.y = x * bone.getC() + y * bone.getD() + bone.getWorldY();
return point; return point;
} }
/** Computes the world rotation from the local rotation. */
public float computeWorldRotation (BonePose bone) { public float computeWorldRotation (BonePose bone) {
float r = rotation * degRad, cos = cos(r), sin = sin(r); float r = rotation * degRad, cos = cos(r), sin = sin(r);
float x = cos * bone.getA() + sin * bone.getB(); float x = cos * bone.getA() + sin * bone.getB();

View File

@ -153,7 +153,7 @@ public class RegionAttachment extends Attachment implements HasSequence {
this.scaleY = scaleY; this.scaleY = scaleY;
} }
/** The local rotation. */ /** The local rotation in degrees, counter clockwise. */
public float getRotation () { public float getRotation () {
return rotation; return rotation;
} }

View File

@ -40,7 +40,7 @@ import com.esotericsoftware.spine.Skeleton;
import com.esotericsoftware.spine.Slot; import com.esotericsoftware.spine.Slot;
import com.esotericsoftware.spine.SlotPose; import com.esotericsoftware.spine.SlotPose;
/** Base class for an attachment with vertices that are transformed by one or more bones and can be deformed by a slot's /** Base class for an attachment with vertices that are transformed by one or more bones and can be deformed by
* {@link SlotPose#getDeform()}. */ * {@link SlotPose#getDeform()}. */
abstract public class VertexAttachment extends Attachment { abstract public class VertexAttachment extends Attachment {
static private int nextID; static private int nextID;
@ -73,8 +73,8 @@ abstract public class VertexAttachment extends Attachment {
worldVerticesLength = other.worldVerticesLength; worldVerticesLength = other.worldVerticesLength;
} }
/** Transforms the attachment's local {@link #getVertices()} to world coordinates. If the slot's {@link SlotPose#getDeform()} /** Transforms the attachment's local {@link #getVertices()} to world coordinates. If the {@link SlotPose#getDeform()} is not
* is not empty, it is used to deform the vertices. * empty, it is used to deform the vertices.
* <p> * <p>
* See <a href="https://esotericsoftware.com/spine-runtime-skeletons#World-transforms">World transforms</a> in the Spine * See <a href="https://esotericsoftware.com/spine-runtime-skeletons#World-transforms">World transforms</a> in the Spine
* Runtimes Guide. * Runtimes Guide.
@ -142,9 +142,9 @@ abstract public class VertexAttachment extends Attachment {
} }
} }
/** The bones which affect the {@link #getVertices()}. The array entries are, for each vertex, the number of bones affecting /** The bones that affect the {@link #getVertices()}. The entries are, for each vertex, the number of bones affecting the
* the vertex followed by that many bone indices, which is the index of the bone in {@link Skeleton#getBones()}. Will be null * vertex followed by that many bone indices, which is the {@link Skeleton#getBones()} index. Null if this attachment has no
* if this attachment has no weights. */ * weights. */
public @Null int[] getBones () { public @Null int[] getBones () {
return bones; return bones;
} }
@ -154,9 +154,9 @@ abstract public class VertexAttachment extends Attachment {
this.bones = bones; this.bones = bones;
} }
/** The vertex positions in the bone's coordinate system. For a non-weighted attachment, the values are <code>x,y</code> /** The vertex positions in the bone's coordinate system. For a non-weighted attachment, the values are <code>x,y</code> pairs
* entries for each vertex. For a weighted attachment, the values are <code>x,y,weight</code> entries for each bone affecting * for each vertex. For a weighted attachment, the values are <code>x,y,weight</code> triplets for each bone affecting each
* each vertex. */ * vertex. */
public float[] getVertices () { public float[] getVertices () {
return vertices; return vertices;
} }