Major API documentation update.

Used to generate this fancy stuff!
http://esotericsoftware.com/spine-api-reference
This commit is contained in:
NathanSweet 2016-10-29 00:51:25 +02:00
parent e14a783c38
commit 8fe76a8dd9
31 changed files with 637 additions and 174 deletions

View File

@ -37,6 +37,7 @@ import com.badlogic.gdx.utils.FloatArray;
import com.esotericsoftware.spine.attachments.Attachment; import com.esotericsoftware.spine.attachments.Attachment;
import com.esotericsoftware.spine.attachments.VertexAttachment; import com.esotericsoftware.spine.attachments.VertexAttachment;
/** A simple container for a list of timelines and a name. */
public class Animation { public class Animation {
final String name; final String name;
final Array<Timeline> timelines; final Array<Timeline> timelines;
@ -54,7 +55,7 @@ public class Animation {
return timelines; return timelines;
} }
/** Returns the duration of the animation in seconds. */ /** The duration of the animation in seconds, which is the highest time of all keys in the timeline. */
public float getDuration () { public float getDuration () {
return duration; return duration;
} }
@ -64,7 +65,8 @@ public class Animation {
} }
/** Applies all the animation's timelines to the specified skeleton. /** Applies all the animation's timelines to the specified skeleton.
* @see Timeline#apply(Skeleton, float, float, Array, float, boolean, boolean) */ * <p>
* See Timeline {@link Timeline#apply(Skeleton, float, float, Array, float, boolean, boolean)}. */
public void apply (Skeleton skeleton, float lastTime, float time, boolean loop, Array<Event> events, float alpha, public void apply (Skeleton skeleton, float lastTime, float time, boolean loop, Array<Event> events, float alpha,
boolean setupPose, boolean mixingOut) { boolean setupPose, boolean mixingOut) {
if (skeleton == null) throw new IllegalArgumentException("skeleton cannot be null."); if (skeleton == null) throw new IllegalArgumentException("skeleton cannot be null.");
@ -79,6 +81,7 @@ public class Animation {
timelines.get(i).apply(skeleton, lastTime, time, events, alpha, setupPose, false); timelines.get(i).apply(skeleton, lastTime, time, events, alpha, setupPose, false);
} }
/** The animation's name, which is unique within the skeleton. */
public String getName () { public String getName () {
return name; return name;
} }
@ -127,17 +130,32 @@ public class Animation {
return -1; return -1;
} }
/** The interface for all timelines. */
static public interface Timeline { static public interface Timeline {
/** Sets the value(s) for the specified time. /** Applies this timeline to the skeleton.
* @param events May be null to not collect fired events. * @param skeleton The skeleton the timeline is being applied to. This provides access to the bones, slots, and other
* @param setupPose True when the timeline is mixed with the setup pose, false when it is mixed with the current pose. * skeleton components the timeline may change.
* Passing true when alpha is 1 is slightly more efficient for most timelines. * @param lastTime The time this timeline was last applied. Timelines such as {@link EventTimeline} trigger only at specific
* @param mixingOut True when changing alpha over time toward 0 (the setup or current pose), false when changing alpha * times rather than every frame. In that case, the timeline triggers everything between <code>lastTime</code>
* toward 1 (the timeline's pose). Used for timelines with instant transitions, eg draw order, attachment * (exclusive) and <code>time</code> (inclusive).
* visibility, scale sign. */ * @param time The time within the animation. Most timelines find the key before and the key after this time so they can
* interpolate between the keys.
* @param events If any events are fired, they are added to this list. Can be null to ignore firing events or if the
* timeline does not fire events.
* @param alpha 0 results in the value of the current or setup pose (depending on <code>setupPose</code>). 1 results in the
* value from the timeline. Between 0 and 1 results in a value mixed between the current or setup pose and the
* value from the timeline. By adjusting <code>alpha</code> over time, an animation can be mixed in or out.
* <code>alpha</code> can also be useful to apply animations on top of each other.
* @param setupPose Controls mixing when <code>alpha</code> < 1. When true the value from the timeline is mixed with the
* value from the setup pose. When false the value from the timeline is mixed with the value from the current
* pose. Passing true when <code>alpha</code> is 1 is slightly more efficient for most timelines.
* @param mixingOut True when changing <code>alpha</code> over time toward 0 (the setup or current pose), false when
* changing <code>alpha</code> toward 1 (the timeline's pose). Used for timelines which perform instant
* transitions, such as {@link DrawOrderTimeline} or {@link AttachmentTimeline}. */
public void apply (Skeleton skeleton, float lastTime, float time, Array<Event> events, float alpha, boolean setupPose, public void apply (Skeleton skeleton, float lastTime, float time, Array<Event> events, float alpha, boolean setupPose,
boolean mixingOut); boolean mixingOut);
/** Uniquely encodes both the type of this timeline and the skeleton property that it affects. */
public int getPropertyId (); public int getPropertyId ();
} }
@ -149,7 +167,7 @@ public class Animation {
pathConstraintPosition, pathConstraintSpacing, pathConstraintMix pathConstraintPosition, pathConstraintSpacing, pathConstraintMix
} }
/** Base class for frames that use an interpolation bezier curve. */ /** The base class for timelines that use interpolation between key frame values. */
abstract static public class CurveTimeline implements Timeline { abstract static public class CurveTimeline implements Timeline {
static public final float LINEAR = 0, STEPPED = 1, BEZIER = 2; static public final float LINEAR = 0, STEPPED = 1, BEZIER = 2;
static private final int BEZIER_SIZE = 10 * 2 - 1; static private final int BEZIER_SIZE = 10 * 2 - 1;
@ -161,18 +179,23 @@ public class Animation {
curves = new float[(frameCount - 1) * BEZIER_SIZE]; curves = new float[(frameCount - 1) * BEZIER_SIZE];
} }
/** The number of key frames for this timeline. */
public int getFrameCount () { public int getFrameCount () {
return curves.length / BEZIER_SIZE + 1; return curves.length / BEZIER_SIZE + 1;
} }
/** Sets the specified key frame to linear interpolation. */
public void setLinear (int frameIndex) { public void setLinear (int frameIndex) {
curves[frameIndex * BEZIER_SIZE] = LINEAR; curves[frameIndex * BEZIER_SIZE] = LINEAR;
} }
/** Sets the specified key frame to stepped interpolation. */
public void setStepped (int frameIndex) { public void setStepped (int frameIndex) {
curves[frameIndex * BEZIER_SIZE] = STEPPED; curves[frameIndex * BEZIER_SIZE] = STEPPED;
} }
/** Returns the interpolation type for the specified key frame.
* @return Linear is 0, stepped is 1, Bezier is 2. */
public float getCurveType (int frameIndex) { public float getCurveType (int frameIndex) {
int index = frameIndex * BEZIER_SIZE; int index = frameIndex * BEZIER_SIZE;
if (index == curves.length) return LINEAR; if (index == curves.length) return LINEAR;
@ -182,9 +205,9 @@ public class Animation {
return BEZIER; return BEZIER;
} }
/** Sets the control handle positions for an interpolation bezier curve used to transition from this keyframe to the next. /** Sets the specified key frame to Bezier interpolation. <code>cx1</code> and <code>cx2</code> are from 0 to 1,
* cx1 and cx2 are from 0 to 1, representing the percent of time between the two keyframes. cy1 and cy2 are the percent of * representing the percent of time between the two key frames. <code>cy1</code> and <code>cy2</code> are the percent of the
* the difference between the keyframe's values. */ * difference between the key frame's values. */
public void setCurve (int frameIndex, float cx1, float cy1, float cx2, float cy2) { public void setCurve (int frameIndex, float cx1, float cy1, float cx2, float cy2) {
float tmpx = (-cx1 * 2 + cx2) * 0.03f, tmpy = (-cy1 * 2 + cy2) * 0.03f; float tmpx = (-cx1 * 2 + cx2) * 0.03f, tmpy = (-cy1 * 2 + cy2) * 0.03f;
float dddfx = ((cx1 - cx2) * 3 + 1) * 0.006f, dddfy = ((cy1 - cy2) * 3 + 1) * 0.006f; float dddfx = ((cx1 - cx2) * 3 + 1) * 0.006f, dddfy = ((cy1 - cy2) * 3 + 1) * 0.006f;
@ -208,6 +231,7 @@ public class Animation {
} }
} }
/** Returns the interpolated percentage for the specified key frame and linear percentage. */
public float getCurvePercent (int frameIndex, float percent) { public float getCurvePercent (int frameIndex, float percent) {
percent = MathUtils.clamp(percent, 0, 1); percent = MathUtils.clamp(percent, 0, 1);
float[] curves = this.curves; float[] curves = this.curves;
@ -236,6 +260,7 @@ public class Animation {
} }
} }
/** Changes a bone's local {@link Bone#getRotation()}. */
static public class RotateTimeline extends CurveTimeline { static public class RotateTimeline extends CurveTimeline {
static public final int ENTRIES = 2; static public final int ENTRIES = 2;
static final int PREV_TIME = -2, PREV_ROTATION = -1; static final int PREV_TIME = -2, PREV_ROTATION = -1;
@ -258,15 +283,17 @@ public class Animation {
this.boneIndex = index; this.boneIndex = index;
} }
/** The index of the bone in {@link Skeleton#getBones()} that will be changed. */
public int getBoneIndex () { public int getBoneIndex () {
return boneIndex; return boneIndex;
} }
/** The time in seconds and rotation in degrees for each key frame. */
public float[] getFrames () { public float[] getFrames () {
return frames; return frames;
} }
/** Sets the time and angle of the specified keyframe. */ /** Sets the time in seconds and the rotation in degrees for the specified key frame. */
public void setFrame (int frameIndex, float time, float degrees) { public void setFrame (int frameIndex, float time, float degrees) {
frameIndex <<= 1; frameIndex <<= 1;
frames[frameIndex] = time; frames[frameIndex] = time;
@ -311,6 +338,7 @@ public class Animation {
} }
} }
/** Changes a bone's local {@link Bone#getX()} and {@link Bone#getY()}. */
static public class TranslateTimeline extends CurveTimeline { static public class TranslateTimeline extends CurveTimeline {
static public final int ENTRIES = 3; static public final int ENTRIES = 3;
static final int PREV_TIME = -3, PREV_X = -2, PREV_Y = -1; static final int PREV_TIME = -3, PREV_X = -2, PREV_Y = -1;
@ -333,15 +361,17 @@ public class Animation {
this.boneIndex = index; this.boneIndex = index;
} }
/** The index of the bone in {@link Skeleton#getBones()} that will be changed. */
public int getBoneIndex () { public int getBoneIndex () {
return boneIndex; return boneIndex;
} }
/** The time in seconds, x, and y values for each key frame. */
public float[] getFrames () { public float[] getFrames () {
return frames; return frames;
} }
/** Sets the time and value of the specified keyframe. */ /** Sets the time in seconds, x, and y values for the specified key frame. */
public void setFrame (int frameIndex, float time, float x, float y) { public void setFrame (int frameIndex, float time, float x, float y) {
frameIndex *= ENTRIES; frameIndex *= ENTRIES;
frames[frameIndex] = time; frames[frameIndex] = time;
@ -382,6 +412,7 @@ public class Animation {
} }
} }
/** Changes a bone's local {@link Bone#getScaleX()} and {@link Bone#getScaleY()}. */
static public class ScaleTimeline extends TranslateTimeline { static public class ScaleTimeline extends TranslateTimeline {
public ScaleTimeline (int frameCount) { public ScaleTimeline (int frameCount) {
super(frameCount); super(frameCount);
@ -440,6 +471,7 @@ public class Animation {
} }
} }
/** Changes a bone's local {@link Bone#getShearX()} and {@link Bone#getShearY()}. */
static public class ShearTimeline extends TranslateTimeline { static public class ShearTimeline extends TranslateTimeline {
public ShearTimeline (int frameCount) { public ShearTimeline (int frameCount) {
super(frameCount); super(frameCount);
@ -482,6 +514,7 @@ public class Animation {
} }
} }
/** Changes a slot's {@link Slot#getColor()}. */
static public class ColorTimeline extends CurveTimeline { static public class ColorTimeline extends CurveTimeline {
static public final int ENTRIES = 5; static public final int ENTRIES = 5;
static private final int PREV_TIME = -5, PREV_R = -4, PREV_G = -3, PREV_B = -2, PREV_A = -1; static private final int PREV_TIME = -5, PREV_R = -4, PREV_G = -3, PREV_B = -2, PREV_A = -1;
@ -504,15 +537,17 @@ public class Animation {
this.slotIndex = index; this.slotIndex = index;
} }
/** The index of the slot in {@link Skeleton#getSlots()} that will be changed. */
public int getSlotIndex () { public int getSlotIndex () {
return slotIndex; return slotIndex;
} }
/** The time in seconds, red, green, blue, and alpha values for each key frame. */
public float[] getFrames () { public float[] getFrames () {
return frames; return frames;
} }
/** Sets the time and value of the specified keyframe. */ /** Sets the time in seconds, red, green, blue, and alpha for the specified key frame. */
public void setFrame (int frameIndex, float time, float r, float g, float b, float a) { public void setFrame (int frameIndex, float time, float r, float g, float b, float a) {
frameIndex *= ENTRIES; frameIndex *= ENTRIES;
frames[frameIndex] = time; frames[frameIndex] = time;
@ -561,6 +596,7 @@ public class Animation {
} }
} }
/** Changes a slot's {@link Slot#getAttachment()}. */
static public class AttachmentTimeline implements Timeline { static public class AttachmentTimeline implements Timeline {
int slotIndex; int slotIndex;
final float[] frames; // time, ... final float[] frames; // time, ...
@ -575,6 +611,7 @@ public class Animation {
return (TimelineType.attachment.ordinal() << 24) + slotIndex; return (TimelineType.attachment.ordinal() << 24) + slotIndex;
} }
/** The number of key frames for this timeline. */
public int getFrameCount () { public int getFrameCount () {
return frames.length; return frames.length;
} }
@ -584,19 +621,22 @@ public class Animation {
this.slotIndex = index; this.slotIndex = index;
} }
/** The index of the slot in {@link Skeleton#getSlots()} that will be changed. */
public int getSlotIndex () { public int getSlotIndex () {
return slotIndex; return slotIndex;
} }
/** The time in seconds for each key frame. */
public float[] getFrames () { public float[] getFrames () {
return frames; return frames;
} }
/** The attachment name for each key frame. May contain null values to clear the attachment. */
public String[] getAttachmentNames () { public String[] getAttachmentNames () {
return attachmentNames; return attachmentNames;
} }
/** Sets the time and value of the specified keyframe. */ /** Sets the time in seconds and the attachment name for the specified key frame. */
public void setFrame (int frameIndex, float time, String attachmentName) { public void setFrame (int frameIndex, float time, String attachmentName) {
frames[frameIndex] = time; frames[frameIndex] = time;
attachmentNames[frameIndex] = attachmentName; attachmentNames[frameIndex] = attachmentName;
@ -626,6 +666,7 @@ public class Animation {
} }
} }
/** Changes a slot's {@link Slot#getAttachmentVertices()} to deform a {@link VertexAttachment}. */
static public class DeformTimeline extends CurveTimeline { static public class DeformTimeline extends CurveTimeline {
int slotIndex; int slotIndex;
VertexAttachment attachment; VertexAttachment attachment;
@ -647,6 +688,7 @@ public class Animation {
this.slotIndex = index; this.slotIndex = index;
} }
/** The index of the slot in {@link Skeleton#getSlots()} that will be changed. */
public int getSlotIndex () { public int getSlotIndex () {
return slotIndex; return slotIndex;
} }
@ -655,19 +697,23 @@ public class Animation {
this.attachment = attachment; this.attachment = attachment;
} }
/** The attachment that will be deformed. */
public VertexAttachment getAttachment () { public VertexAttachment getAttachment () {
return attachment; return attachment;
} }
/** The time in seconds for each key frame. */
public float[] getFrames () { public float[] getFrames () {
return frames; return frames;
} }
/** The vertices for each key frame. */
public float[][] getVertices () { public float[][] getVertices () {
return frameVertices; return frameVertices;
} }
/** Sets the time of the specified keyframe. */ /** Sets the time in seconds and the vertices for the specified key frame.
* @param vertices Vertex positions for an unweighted VertexAttachment, or deform offsets if it has weights. */
public void setFrame (int frameIndex, float time, float[] vertices) { public void setFrame (int frameIndex, float time, float[] vertices) {
frames[frameIndex] = time; frames[frameIndex] = time;
frameVertices[frameIndex] = vertices; frameVertices[frameIndex] = vertices;
@ -755,6 +801,7 @@ public class Animation {
} }
} }
/** Fires an {@link Event} when specific animation times are reached. */
static public class EventTimeline implements Timeline { static public class EventTimeline implements Timeline {
private final float[] frames; // time, ... private final float[] frames; // time, ...
private final Event[] events; private final Event[] events;
@ -768,25 +815,28 @@ public class Animation {
return TimelineType.event.ordinal() << 24; return TimelineType.event.ordinal() << 24;
} }
/** The number of key frames for this timeline. */
public int getFrameCount () { public int getFrameCount () {
return frames.length; return frames.length;
} }
/** The time in seconds for each key frame. */
public float[] getFrames () { public float[] getFrames () {
return frames; return frames;
} }
/** The event for each key frame. */
public Event[] getEvents () { public Event[] getEvents () {
return events; return events;
} }
/** Sets the time of the specified keyframe. */ /** Sets the time in seconds and the event for the specified key frame. */
public void setFrame (int frameIndex, Event event) { public void setFrame (int frameIndex, Event event) {
frames[frameIndex] = event.time; frames[frameIndex] = event.time;
events[frameIndex] = event; events[frameIndex] = event;
} }
/** Fires events for frames > lastTime and <= time. */ /** Fires events for frames > <code>lastTime</code> and <= <code>time</code>. */
public void apply (Skeleton skeleton, float lastTime, float time, Array<Event> firedEvents, float alpha, boolean setupPose, public void apply (Skeleton skeleton, float lastTime, float time, Array<Event> firedEvents, float alpha, boolean setupPose,
boolean mixingOut) { boolean mixingOut) {
if (firedEvents == null) return; if (firedEvents == null) return;
@ -816,6 +866,7 @@ public class Animation {
} }
} }
/** Changes a skeleton's {@link Skeleton#getDrawOrder()}. */
static public class DrawOrderTimeline implements Timeline { static public class DrawOrderTimeline implements Timeline {
private final float[] frames; // time, ... private final float[] frames; // time, ...
private final int[][] drawOrders; private final int[][] drawOrders;
@ -829,20 +880,24 @@ public class Animation {
return TimelineType.drawOrder.ordinal() << 24; return TimelineType.drawOrder.ordinal() << 24;
} }
/** The number of key frames for this timeline. */
public int getFrameCount () { public int getFrameCount () {
return frames.length; return frames.length;
} }
/** The time in seconds for each key frame. */
public float[] getFrames () { public float[] getFrames () {
return frames; return frames;
} }
/** The draw order for each key frame. See {@link #setFrame(int, float, int[])}. */
public int[][] getDrawOrders () { public int[][] getDrawOrders () {
return drawOrders; return drawOrders;
} }
/** Sets the time of the specified keyframe. /** Sets the time in seconds and the draw order for the specified key frame.
* @param drawOrder May be null to use bind pose draw order. */ * @param drawOrder For each slot in {@link Skeleton#slots}, the index of the new draw order. May be null to use setup pose
* draw order. */
public void setFrame (int frameIndex, float time, int[] drawOrder) { public void setFrame (int frameIndex, float time, int[] drawOrder) {
frames[frameIndex] = time; frames[frameIndex] = time;
drawOrders[frameIndex] = drawOrder; drawOrders[frameIndex] = drawOrder;
@ -876,6 +931,7 @@ public class Animation {
} }
} }
/** Changes an IK constraint's {@link IkConstraint#getMix()} and {@link IkConstraint#getBendDirection()}. */
static public class IkConstraintTimeline extends CurveTimeline { static public class IkConstraintTimeline extends CurveTimeline {
static public final int ENTRIES = 3; static public final int ENTRIES = 3;
static private final int PREV_TIME = -3, PREV_MIX = -2, PREV_BEND_DIRECTION = -1; static private final int PREV_TIME = -3, PREV_MIX = -2, PREV_BEND_DIRECTION = -1;
@ -898,15 +954,17 @@ public class Animation {
this.ikConstraintIndex = index; this.ikConstraintIndex = index;
} }
/** The index of the IK constraint slot in {@link Skeleton#getIkConstraints()} that will be changed. */
public int getIkConstraintIndex () { public int getIkConstraintIndex () {
return ikConstraintIndex; return ikConstraintIndex;
} }
/** The time in seconds, mix, and bend direction for each key frame. */
public float[] getFrames () { public float[] getFrames () {
return frames; return frames;
} }
/** Sets the time, mix and bend direction of the specified keyframe. */ /** Sets the time in seconds, mix, and bend direction for the specified key frame. */
public void setFrame (int frameIndex, float time, float mix, int bendDirection) { public void setFrame (int frameIndex, float time, float mix, int bendDirection) {
frameIndex *= ENTRIES; frameIndex *= ENTRIES;
frames[frameIndex] = time; frames[frameIndex] = time;
@ -949,6 +1007,7 @@ public class Animation {
} }
} }
/** Changes a transform constraint's mixes. */
static public class TransformConstraintTimeline extends CurveTimeline { static public class TransformConstraintTimeline extends CurveTimeline {
static public final int ENTRIES = 5; static public final int ENTRIES = 5;
static private final int PREV_TIME = -5, PREV_ROTATE = -4, PREV_TRANSLATE = -3, PREV_SCALE = -2, PREV_SHEAR = -1; static private final int PREV_TIME = -5, PREV_ROTATE = -4, PREV_TRANSLATE = -3, PREV_SCALE = -2, PREV_SHEAR = -1;
@ -971,15 +1030,17 @@ public class Animation {
this.transformConstraintIndex = index; this.transformConstraintIndex = index;
} }
/** The index of the transform constraint slot in {@link Skeleton#getTransformConstraints()} that will be changed. */
public int getTransformConstraintIndex () { public int getTransformConstraintIndex () {
return transformConstraintIndex; return transformConstraintIndex;
} }
/** The time in seconds, rotate mix, translate mix, scale mix, and shear mix for each key frame. */
public float[] getFrames () { public float[] getFrames () {
return frames; return frames;
} }
/** Sets the time and mixes of the specified keyframe. */ /** The time in seconds, rotate mix, translate mix, scale mix, and shear mix for the specified key frame. */
public void setFrame (int frameIndex, float time, float rotateMix, float translateMix, float scaleMix, float shearMix) { public void setFrame (int frameIndex, float time, float rotateMix, float translateMix, float scaleMix, float shearMix) {
frameIndex *= ENTRIES; frameIndex *= ENTRIES;
frames[frameIndex] = time; frames[frameIndex] = time;
@ -1034,6 +1095,7 @@ public class Animation {
} }
} }
/** Changes a path constraint's {@link PathConstraint#getPosition()}. */
static public class PathConstraintPositionTimeline extends CurveTimeline { static public class PathConstraintPositionTimeline extends CurveTimeline {
static public final int ENTRIES = 2; static public final int ENTRIES = 2;
static final int PREV_TIME = -2, PREV_VALUE = -1; static final int PREV_TIME = -2, PREV_VALUE = -1;
@ -1057,19 +1119,21 @@ public class Animation {
this.pathConstraintIndex = index; this.pathConstraintIndex = index;
} }
/** The index of the path constraint slot in {@link Skeleton#getPathConstraints()} that will be changed. */
public int getPathConstraintIndex () { public int getPathConstraintIndex () {
return pathConstraintIndex; return pathConstraintIndex;
} }
/** The time in seconds and path constraint position for each key frame. */
public float[] getFrames () { public float[] getFrames () {
return frames; return frames;
} }
/** Sets the time and value of the specified keyframe. */ /** Sets the time in seconds and path constraint position for the specified key frame. */
public void setFrame (int frameIndex, float time, float value) { public void setFrame (int frameIndex, float time, float position) {
frameIndex *= ENTRIES; frameIndex *= ENTRIES;
frames[frameIndex] = time; frames[frameIndex] = time;
frames[frameIndex + VALUE] = value; frames[frameIndex + VALUE] = position;
} }
public void apply (Skeleton skeleton, float lastTime, float time, Array<Event> events, float alpha, boolean setupPose, public void apply (Skeleton skeleton, float lastTime, float time, Array<Event> events, float alpha, boolean setupPose,
@ -1099,6 +1163,7 @@ public class Animation {
} }
} }
/** Changes a path constraint's {@link PathConstraint#getSpacing()}. */
static public class PathConstraintSpacingTimeline extends PathConstraintPositionTimeline { static public class PathConstraintSpacingTimeline extends PathConstraintPositionTimeline {
public PathConstraintSpacingTimeline (int frameCount) { public PathConstraintSpacingTimeline (int frameCount) {
super(frameCount); super(frameCount);
@ -1136,6 +1201,7 @@ public class Animation {
} }
} }
/** Changes a path constraint's mixes. */
static public class PathConstraintMixTimeline extends CurveTimeline { static public class PathConstraintMixTimeline extends CurveTimeline {
static public final int ENTRIES = 3; static public final int ENTRIES = 3;
static private final int PREV_TIME = -3, PREV_ROTATE = -2, PREV_TRANSLATE = -1; static private final int PREV_TIME = -3, PREV_ROTATE = -2, PREV_TRANSLATE = -1;
@ -1159,15 +1225,17 @@ public class Animation {
this.pathConstraintIndex = index; this.pathConstraintIndex = index;
} }
/** The index of the path constraint slot in {@link Skeleton#getPathConstraints()} that will be changed. */
public int getPathConstraintIndex () { public int getPathConstraintIndex () {
return pathConstraintIndex; return pathConstraintIndex;
} }
/** The time in seconds, rotate mix, and translate mix for each key frame. */
public float[] getFrames () { public float[] getFrames () {
return frames; return frames;
} }
/** Sets the time and mixes of the specified keyframe. */ /** The time in seconds, rotate mix, and translate mix for the specified key frame. */
public void setFrame (int frameIndex, float time, float rotateMix, float translateMix) { public void setFrame (int frameIndex, float time, float rotateMix, float translateMix) {
frameIndex *= ENTRIES; frameIndex *= ENTRIES;
frames[frameIndex] = time; frames[frameIndex] = time;

View File

@ -43,11 +43,10 @@ import com.esotericsoftware.spine.Animation.DrawOrderTimeline;
import com.esotericsoftware.spine.Animation.RotateTimeline; import com.esotericsoftware.spine.Animation.RotateTimeline;
import com.esotericsoftware.spine.Animation.Timeline; import com.esotericsoftware.spine.Animation.Timeline;
/** Stores state for applying one or more animations over time and mixing (crossfading) between animations. /** Applies animations over time, queues animations for later playback, mixes (crossfading) between animations, and applies
* multiple animations on top of each other (layering).
* <p> * <p>
* Animations on different tracks are applied sequentially each frame, from lowest to highest track index. This enables animations * See <a href='http://esotericsoftware.com/spine-applying-animations/'>Applying Animations</a> in the Spine Runtimes Guide. */
* to be layered, where higher tracks either key only a subset of the skeleton pose or use alpha < 1 to mix with the pose on the
* lower track. */
public class AnimationState { public class AnimationState {
static private final Animation emptyAnimation = new Animation("<empty>", new Array(0), 0); static private final Animation emptyAnimation = new Animation("<empty>", new Array(0), 0);
@ -75,7 +74,7 @@ public class AnimationState {
this.data = data; this.data = data;
} }
/** Increments the track entry times, setting queued animations as current if needed. */ /** Increments each track entry {@link TrackEntry#getTrackTime()}, setting queued animations as current if needed. */
public void update (float delta) { public void update (float delta) {
delta *= timeScale; delta *= timeScale;
for (int i = 0, n = tracks.size; i < n; i++) { for (int i = 0, n = tracks.size; i < n; i++) {
@ -337,10 +336,10 @@ public class AnimationState {
events.clear(); events.clear();
} }
/** Removes all animations from all tracks, leaving skeletons in their last pose. /** Removes all animations from all tracks, leaving skeletons in their previous pose.
* <p> * <p>
* It may be desired to use {@link AnimationState#setEmptyAnimations(float)} to mix the skeletons back to the setup pose, * It may be desired to use {@link AnimationState#setEmptyAnimations(float)} to mix the skeletons back to the setup pose,
* rather than leaving them in their last pose. */ * rather than leaving them in their previous pose. */
public void clearTracks () { public void clearTracks () {
queue.drainDisabled = true; queue.drainDisabled = true;
for (int i = 0, n = tracks.size; i < n; i++) for (int i = 0, n = tracks.size; i < n; i++)
@ -350,10 +349,10 @@ public class AnimationState {
queue.drain(); queue.drain();
} }
/** Removes all animations from the track, leaving skeletons in their last pose. /** Removes all animations from the track, leaving skeletons in their previous pose.
* <p> * <p>
* It may be desired to use {@link AnimationState#setEmptyAnimation(int, float)} to mix the skeletons back to the setup pose, * It may be desired to use {@link AnimationState#setEmptyAnimation(int, float)} to mix the skeletons back to the setup pose,
* rather than leaving them in their last pose. */ * rather than leaving them in their previous pose. */
public void clearTrack (int trackIndex) { public void clearTrack (int trackIndex) {
if (trackIndex >= tracks.size) return; if (trackIndex >= tracks.size) return;
TrackEntry current = tracks.get(trackIndex); TrackEntry current = tracks.get(trackIndex);
@ -395,7 +394,9 @@ public class AnimationState {
queue.start(current); queue.start(current);
} }
/** @see #setAnimation(int, Animation, boolean) */ /** Sets an animation by name.
* <p>
* {@link #setAnimation(int, Animation, boolean)}. */
public TrackEntry setAnimation (int trackIndex, String animationName, boolean loop) { public TrackEntry setAnimation (int trackIndex, String animationName, boolean loop) {
Animation animation = data.skeletonData.findAnimation(animationName); Animation animation = data.skeletonData.findAnimation(animationName);
if (animation == null) throw new IllegalArgumentException("Animation not found: " + animationName); if (animation == null) throw new IllegalArgumentException("Animation not found: " + animationName);
@ -403,8 +404,10 @@ public class AnimationState {
} }
/** Sets the current animation for a track, discarding any queued animations. /** Sets the current animation for a track, discarding any queued animations.
* @param loop If true, the animation will repeat. If false it will not, instead its last frame is applied if played beyond its
* duration. In either case {@link TrackEntry#getTrackEnd()} determines when the track is cleared.
* @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 {@link AnimationStateListener#dispose(TrackEntry)}. */ * after the {@link AnimationStateListener#dispose(TrackEntry)} event occurs. */
public TrackEntry setAnimation (int trackIndex, Animation animation, boolean loop) { public TrackEntry setAnimation (int trackIndex, Animation animation, boolean loop) {
if (animation == null) throw new IllegalArgumentException("animation cannot be null."); if (animation == null) throw new IllegalArgumentException("animation cannot be null.");
TrackEntry current = expandToIndex(trackIndex); TrackEntry current = expandToIndex(trackIndex);
@ -425,18 +428,21 @@ public class AnimationState {
return entry; return entry;
} }
/** {@link #addAnimation(int, Animation, boolean, float)} */ /** Queues an animation by name.
* <p>
* See {@link #addAnimation(int, Animation, boolean, float)}. */
public TrackEntry addAnimation (int trackIndex, String animationName, boolean loop, float delay) { public TrackEntry addAnimation (int trackIndex, String animationName, boolean loop, float delay) {
Animation animation = data.skeletonData.findAnimation(animationName); Animation animation = data.skeletonData.findAnimation(animationName);
if (animation == null) throw new IllegalArgumentException("Animation not found: " + animationName); if (animation == null) throw new IllegalArgumentException("Animation not found: " + animationName);
return addAnimation(trackIndex, animation, loop, delay); return addAnimation(trackIndex, animation, loop, delay);
} }
/** Adds an animation to be played after the current or last queued animation for a track. /** Adds an animation to be played after the current or last queued animation for a track. If the track is empty, it is
* equivalent to calling {@link #setAnimation(int, Animation, boolean)}.
* @param delay Seconds to begin this animation after the start of the previous animation. May be <= 0 to use the animation * @param delay Seconds to begin this animation after the start of the previous animation. May be <= 0 to use the animation
* duration of the previous track minus any mix duration plus the negative delay. * duration of the previous track minus any mix duration plus the <code>delay</code>.
* @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 {@link AnimationStateListener#dispose(TrackEntry)}. */ * after the {@link AnimationStateListener#dispose(TrackEntry)} event occurs. */
public TrackEntry addAnimation (int trackIndex, Animation animation, boolean loop, float delay) { public TrackEntry addAnimation (int trackIndex, Animation animation, boolean loop, float delay) {
if (animation == null) throw new IllegalArgumentException("animation cannot be null."); if (animation == null) throw new IllegalArgumentException("animation cannot be null.");
@ -466,7 +472,13 @@ public class AnimationState {
return entry; return entry;
} }
/** Sets an empty animation for a track, discarding any queued animations, and mixes to it over the specified mix duration. */ /** Sets an empty animation for a track, discarding any queued animations, and sets the track entry's
* {@link TrackEntry#getMixDuration()}.
* <p>
* Mixing out is done by setting an empty animation. A mix duration of 0 still mixes out over one frame.
* <p>
* To mix in, first set an empty animation and add an animation using {@link #addAnimation(int, Animation, boolean, float)},
* then set the {@link TrackEntry#setMixDuration(float)} on the returned track entry. */
public TrackEntry setEmptyAnimation (int trackIndex, float mixDuration) { public TrackEntry setEmptyAnimation (int trackIndex, float mixDuration) {
TrackEntry entry = setAnimation(trackIndex, emptyAnimation, false); TrackEntry entry = setAnimation(trackIndex, emptyAnimation, false);
entry.mixDuration = mixDuration; entry.mixDuration = mixDuration;
@ -474,12 +486,13 @@ public class AnimationState {
return entry; return entry;
} }
/** Adds an empty animation to be played after the current or last queued animation for a track, and mixes to it over the /** Adds an empty animation to be played after the current or last queued animation for a track, and sets the track entry's
* specified mix duration. * {@link TrackEntry#getMixDuration()}. If the track is empty, it is equivalent to calling
* {@link #setEmptyAnimation(int, float)}.
* @param delay Seconds to begin this animation after the start of the previous animation. May be <= 0 to use the animation * @param delay Seconds to begin this animation after the start of the previous animation. May be <= 0 to use the animation
* duration of the previous track minus any mix duration plus the negative delay. * duration of the previous track minus any mix duration plus <code>delay</code>.
* @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 {@link AnimationStateListener#dispose(TrackEntry)}. */ * 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) {
if (delay <= 0) delay -= mixDuration; if (delay <= 0) delay -= mixDuration;
TrackEntry entry = addAnimation(trackIndex, emptyAnimation, false, delay); TrackEntry entry = addAnimation(trackIndex, emptyAnimation, false, delay);
@ -598,7 +611,7 @@ public class AnimationState {
usage[i] = propertyIDs.add(timelines.get(i).getPropertyId()); usage[i] = propertyIDs.add(timelines.get(i).getPropertyId());
} }
/** Returns the track entry for the animation currently playing on the track, or null. */ /** Returns the track entry for the animation currently playing on the track, or null if no animation is currently playing. */
public TrackEntry getCurrent (int trackIndex) { public TrackEntry getCurrent (int trackIndex) {
if (trackIndex >= tracks.size) return null; if (trackIndex >= tracks.size) return null;
return tracks.get(trackIndex); return tracks.get(trackIndex);
@ -615,19 +628,22 @@ public class AnimationState {
listeners.removeValue(listener, true); listeners.removeValue(listener, true);
} }
/** Removes all listeners added with {@link #addListener(AnimationStateListener)}. */
public void clearListeners () { public void clearListeners () {
listeners.clear(); listeners.clear();
} }
/** Discards all {@link #addListener(AnimationStateListener) listener} notifications that have not yet been delivered. This can /** Discards all listener notifications that have not yet been delivered. This can be useful to call from an
* be useful to call from an {@link AnimationStateListener} when it is known that further notifications that may have been * {@link AnimationStateListener} when it is known that further notifications that may have been already queued for delivery
* already queued for delivery are not wanted because new animations are being set. */ * are not wanted because new animations are being set. */
public void clearListenerNotifications () { public void clearListenerNotifications () {
queue.clear(); queue.clear();
} }
/** Multiplier for the delta time when the animation state is updated, causing time for all animations to play slower or /** Multiplier for the delta time when the animation state is updated, causing time for all animations to play slower or
* faster. Defaults to 1. */ * faster. Defaults to 1.
* <p>
* See TrackEntry {@link TrackEntry#getTimeScale()} for affecting a single animation. */
public float getTimeScale () { public float getTimeScale () {
return timeScale; return timeScale;
} }
@ -636,6 +652,7 @@ public class AnimationState {
this.timeScale = timeScale; this.timeScale = timeScale;
} }
/** The AnimationStateData to look up mix durations. */
public AnimationStateData getData () { public AnimationStateData getData () {
return data; return data;
} }
@ -645,7 +662,7 @@ public class AnimationState {
this.data = data; this.data = data;
} }
/** Returns the list of tracks that have animations, which may contain null entries. */ /** The list of tracks that currently have animations, which may contain null entries. */
public Array<TrackEntry> getTracks () { public Array<TrackEntry> getTracks () {
return tracks; return tracks;
} }
@ -662,7 +679,9 @@ public class AnimationState {
return buffer.toString(); return buffer.toString();
} }
/** State for the playback of an animation. */ /** Stores settings and other state for the playback of an animation on an {@link AnimationState} track.
* <p>
* References to a track entry must not be kept after the {@link AnimationStateListener#dispose(TrackEntry)} event occurs. */
static public class TrackEntry implements Poolable { static public class TrackEntry implements Poolable {
Animation animation; Animation animation;
TrackEntry next, mixingFrom; TrackEntry next, mixingFrom;
@ -685,10 +704,14 @@ public class AnimationState {
timelinesRotation.clear(); timelinesRotation.clear();
} }
/** The index of the track where this track entry is either current or queued.
* <p>
* See {@link AnimationState#getCurrent(int)}. */
public int getTrackIndex () { public int getTrackIndex () {
return trackIndex; return trackIndex;
} }
/** The animation to apply for this track entry. */
public Animation getAnimation () { public Animation getAnimation () {
return animation; return animation;
} }
@ -697,6 +720,8 @@ public class AnimationState {
this.animation = animation; this.animation = animation;
} }
/** If true, the animation will repeat. If false it will not, instead its last frame is applied if played beyond its
* duration. */
public boolean getLoop () { public boolean getLoop () {
return loop; return loop;
} }
@ -705,9 +730,9 @@ public class AnimationState {
this.loop = loop; this.loop = loop;
} }
/** Seconds to postpone playing the animation. When a track entry is the current track entry, delay postpones incrementing /** Seconds to postpone playing the animation. When a track entry is the current track entry, <code>delay</code> postpones
* the track time. When a track entry is queued, delay is the time from the start of the previous animation to when the * incrementing the {@link #getTrackTime()}. When a track entry is queued, <code>delay</code> is the time from the start of
* track entry will become the current track entry. */ * the previous animation to when the track entry will become the current track entry. */
public float getDelay () { public float getDelay () {
return delay; return delay;
} }
@ -727,13 +752,13 @@ public class AnimationState {
this.trackTime = trackTime; this.trackTime = trackTime;
} }
/** The track time in seconds when this animation will be removed from the track. Defaults to the animation duration for /** The track time in seconds when this animation will be removed from the track. Defaults to the animation
* non-looping animations and to {@link Integer#MAX_VALUE} for looping animations. If the track end time is reached, no * {@link Animation#duration} for non-looping animations and the highest float possible for looping animations. If the track
* other animations are queued for playback, and mixing from any previous animations is complete, then the track is cleared, * end time is reached, no other animations are queued for playback, and mixing from any previous animations is complete,
* leaving skeletons in their last pose. * then the track is cleared, leaving skeletons in their previous pose.
* <p> * <p>
* It may be desired to use {@link AnimationState#addEmptyAnimation(int, float, float)} to mix the skeletons back to the * It may be desired to use {@link AnimationState#addEmptyAnimation(int, float, float)} to mix the skeletons back to the
* setup pose, rather than leaving them in their last pose. */ * setup pose, rather than leaving them in their previous pose. */
public float getTrackEnd () { public float getTrackEnd () {
return trackEnd; return trackEnd;
} }
@ -744,8 +769,8 @@ public class AnimationState {
/** Seconds when this animation starts, both initially and after looping. Defaults to 0. /** Seconds when this animation starts, both initially and after looping. Defaults to 0.
* <p> * <p>
* When changing the animation start time, it often makes sense to set {@link #getAnimationLast()} to the same value to * When changing the <code>animationStart</code> time, it often makes sense to set {@link #getAnimationLast()} to the same
* prevent timeline keys before the start time from triggering. */ * value to prevent timeline keys before the start time from triggering. */
public float getAnimationStart () { public float getAnimationStart () {
return animationStart; return animationStart;
} }
@ -755,7 +780,7 @@ public class AnimationState {
} }
/** Seconds for the last frame of this animation. Non-looping animations won't play past this time. Looping animations will /** Seconds for the last frame of this animation. Non-looping animations won't play past this time. Looping animations will
* loop back to {@link #getAnimationStart()} at this time. Defaults to the animation duration. */ * loop back to {@link #getAnimationStart()} at this time. Defaults to the animation {@link Animation#duration}. */
public float getAnimationEnd () { public float getAnimationEnd () {
return animationEnd; return animationEnd;
} }
@ -765,8 +790,9 @@ public class AnimationState {
} }
/** The time in seconds this animation was last applied. Some timelines use this for one-time triggers. Eg, when this /** The time in seconds this animation was last applied. Some timelines use this for one-time triggers. Eg, when this
* animation is applied, event timelines will fire all events between the animation last time (exclusive) and animation time * animation is applied, event timelines will fire all events between the <code>animationLast</code> time (exclusive) and
* (inclusive). Defaults to -1 to ensure triggers on frame 0 happen the first time this animation is applied. */ * <code>animationTime</code> (inclusive). Defaults to -1 to ensure triggers on frame 0 happen the first time this animation
* is applied. */
public float getAnimationLast () { public float getAnimationLast () {
return animationLast; return animationLast;
} }
@ -776,8 +802,9 @@ public class AnimationState {
nextAnimationLast = animationLast; nextAnimationLast = animationLast;
} }
/** Uses {@link #getTrackTime()} to compute the animation time between {@link #getAnimationStart()} and /** Uses {@link #getTrackTime()} to compute the <code>animationTime</code>, which is between {@link #getAnimationStart()}
* {@link #getAnimationEnd()}. When the track time is 0, the animation time is equal to the animation start time. */ * and {@link #getAnimationEnd()}. When the <code>trackTime</code> is 0, the <code>animationTime</code> is equal to the
* <code>animationStart</code> time. */
public float getAnimationTime () { public float getAnimationTime () {
if (loop) { if (loop) {
float duration = animationEnd - animationStart; float duration = animationEnd - animationStart;
@ -788,7 +815,9 @@ public class AnimationState {
} }
/** Multiplier for the delta time when the animation state is updated, causing time for this animation to pass slower or /** Multiplier for the delta time when the animation state is updated, causing time for this animation to pass slower or
* faster. Defaults to 1. */ * faster. Defaults to 1.
* <p>
* See AnimationState {@link AnimationState#getTimeScale()} for affecting all animations. */
public float getTimeScale () { public float getTimeScale () {
return timeScale; return timeScale;
} }
@ -807,8 +836,8 @@ public class AnimationState {
this.listener = listener; this.listener = listener;
} }
/** Values < 1 mix this animation with the setup pose or the skeleton's last pose. Defaults to 1, which overwrites the /** Values < 1 mix this animation with the setup pose or the skeleton's previous pose. Defaults to 1, which overwrites the
* skeleton's last pose with this animation. * skeleton's previous pose with this animation.
* <p> * <p>
* Typically track 0 is used to completely pose the skeleton, then alpha can be used on higher tracks. It doesn't make sense * Typically track 0 is used to completely pose the skeleton, then alpha can be used on higher tracks. It doesn't make sense
* to use alpha on track 0 if the skeleton pose is from the last frame render. */ * to use alpha on track 0 if the skeleton pose is from the last frame render. */
@ -820,8 +849,9 @@ public class AnimationState {
this.alpha = alpha; this.alpha = alpha;
} }
/** When the mix percentage (mix time / mix duration) is less than the event threshold, event timelines for the animation /** When the mix percentage ({@link #getMixTime()} / {@link #getMixDuration()}) is less than the
* being mixed out will be applied. Defaults to 0, so event timelines are not applied for an animation being mixed out. */ * <code>eventThreshold</code>, event timelines for the animation being mixed out will be applied. Defaults to 0, so event
* timelines are not applied for an animation being mixed out. */
public float getEventThreshold () { public float getEventThreshold () {
return eventThreshold; return eventThreshold;
} }
@ -830,9 +860,9 @@ public class AnimationState {
this.eventThreshold = eventThreshold; this.eventThreshold = eventThreshold;
} }
/** When the mix percentage (mix time / mix duration) is less than the attachment threshold, attachment timelines for the /** When the mix percentage ({@link #getMixTime()} / {@link #getMixDuration()}) is less than the
* animation being mixed out will be applied. Defaults to 0, so attachment timelines are not applied for an animation being * <code>attachmentThreshold</code>, attachment timelines for the animation being mixed out will be applied. Defaults to 0,
* mixed out. */ * so attachment timelines are not applied for an animation being mixed out. */
public float getAttachmentThreshold () { public float getAttachmentThreshold () {
return attachmentThreshold; return attachmentThreshold;
} }
@ -841,9 +871,9 @@ public class AnimationState {
this.attachmentThreshold = attachmentThreshold; this.attachmentThreshold = attachmentThreshold;
} }
/** When the mix percentage (mix time / mix duration) is less than the draw order threshold, draw order timelines for the /** When the mix percentage ({@link #getMixTime()} / {@link #getMixDuration()}) is less than the
* animation being mixed out will be applied. Defaults to 0, so draw order timelines are not applied for an animation being * <code>drawOrderThreshold</code>, draw order timelines for the animation being mixed out will be applied. Defaults to 0,
* mixed out. */ * so draw order timelines are not applied for an animation being mixed out. */
public float getDrawOrderThreshold () { public float getDrawOrderThreshold () {
return drawOrderThreshold; return drawOrderThreshold;
} }
@ -852,19 +882,21 @@ public class AnimationState {
this.drawOrderThreshold = drawOrderThreshold; this.drawOrderThreshold = drawOrderThreshold;
} }
/** The animation queued to start after this animation, or null. */ /** The animation queued to start after this animation, or null. <code>next</code> makes up a linked list. */
public TrackEntry getNext () { public TrackEntry getNext () {
return next; return next;
} }
/** Returns true if at least one loop has been completed. */ /** Returns true if at least one loop has been completed.
* <p>
* See {@link AnimationStateListener#complete(TrackEntry)}. */
public boolean isComplete () { public boolean isComplete () {
return trackTime >= animationEnd - animationStart; return trackTime >= animationEnd - animationStart;
} }
/** Seconds from 0 to the mix duration when mixing from the previous animation to this animation. May be slightly more than /** Seconds from 0 to the {@link #getMixDuration()} when mixing from the previous animation to this animation. May be
* {@link #getMixDuration()} when the mix is complete. The mix time can be set manually rather than use the value from * slightly more than <code>mixDuration</code> when the mix is complete. The mix time can be set manually rather than use
* AnimationStateData. */ * the value from AnimationStateData {@link AnimationStateData#getMix(Animation, Animation)}. */
public float getMixTime () { public float getMixTime () {
return mixTime; return mixTime;
} }
@ -873,10 +905,11 @@ 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 /** Seconds for mixing from the previous animation to this animation. Defaults to the value provided by AnimationStateData
* {@link AnimationStateData} 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>
* The mix duration must be set before {@link AnimationState#update(float)} is next called. */ * The <code>mixDuration</code> must be set for a new track entry before {@link AnimationState#update(float)} is next
* called. */
public float getMixDuration () { public float getMixDuration () {
return mixDuration; return mixDuration;
} }
@ -886,7 +919,7 @@ public class AnimationState {
} }
/** 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 from the previous animation to this animation, or null if no
* mixing is currently occuring. If mixing from multiple animations, mixing from makes up a linked list. */ * mixing is currently occuring. If mixing from multiple animations, <code>mixingFrom</code> makes up a linked list. */
public TrackEntry getMixingFrom () { public TrackEntry getMixingFrom () {
return mixingFrom; return mixingFrom;
} }
@ -1003,7 +1036,7 @@ public class AnimationState {
public void end (TrackEntry entry); public void end (TrackEntry entry);
/** Invoked when this entry will be disposed. This may occur without the entry ever being set as the current entry. /** Invoked when this entry will be disposed. This may occur without the entry ever being set as the current entry.
* References to the entry should not be kept after dispose is called, as it may be destroyed or reused. */ * References to the entry should not be kept after <code>dispose</code> is called, as it may be destroyed or reused. */
public void dispose (TrackEntry entry); public void dispose (TrackEntry entry);
/** Invoked every time this entry's animation completes a loop. */ /** Invoked every time this entry's animation completes a loop. */

View File

@ -31,10 +31,11 @@
package com.esotericsoftware.spine; package com.esotericsoftware.spine;
import com.badlogic.gdx.utils.ObjectFloatMap; import com.badlogic.gdx.utils.ObjectFloatMap;
import com.esotericsoftware.spine.AnimationState.TrackEntry;
/** Stores mixing times between animations. */ /** Stores mix (crossfade) durations to be applied when {@link AnimationState} animations are changed. */
public class AnimationStateData { public class AnimationStateData {
private final SkeletonData skeletonData; final SkeletonData skeletonData;
final ObjectFloatMap<Key> animationToMixTime = new ObjectFloatMap(); final ObjectFloatMap<Key> animationToMixTime = new ObjectFloatMap();
final Key tempKey = new Key(); final Key tempKey = new Key();
float defaultMix; float defaultMix;
@ -44,10 +45,14 @@ public class AnimationStateData {
this.skeletonData = skeletonData; this.skeletonData = skeletonData;
} }
/** The SkeletonData to look up animations when they are specified by name. */
public SkeletonData getSkeletonData () { public SkeletonData getSkeletonData () {
return skeletonData; return skeletonData;
} }
/** Sets a mix duration by animation name.
* <p>
* See {@link #setMix(Animation, Animation, float)}. */
public void setMix (String fromName, String toName, float duration) { public void setMix (String fromName, String toName, float duration) {
Animation from = skeletonData.findAnimation(fromName); Animation from = skeletonData.findAnimation(fromName);
if (from == null) throw new IllegalArgumentException("Animation not found: " + fromName); if (from == null) throw new IllegalArgumentException("Animation not found: " + fromName);
@ -56,6 +61,9 @@ public class AnimationStateData {
setMix(from, to, duration); setMix(from, to, duration);
} }
/** Sets the mix duration when changing from the specified animation to the other.
* <p>
* See {@link TrackEntry#mixDuration}. */
public void setMix (Animation from, Animation to, float duration) { public void setMix (Animation from, Animation to, float duration) {
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.");
@ -65,6 +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
* 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.");
@ -73,6 +83,7 @@ public class AnimationStateData {
return animationToMixTime.get(tempKey, defaultMix); return animationToMixTime.get(tempKey, defaultMix);
} }
/** The mix duration to use when no mix duration has been defined between two animations. */
public float getDefaultMix () { public float getDefaultMix () {
return defaultMix; return defaultMix;
} }

View File

@ -32,6 +32,7 @@ package com.esotericsoftware.spine;
import com.badlogic.gdx.graphics.GL20; import com.badlogic.gdx.graphics.GL20;
/** Determines how images are blended with existing pixels when drawn. */
public enum BlendMode { public enum BlendMode {
normal(GL20.GL_SRC_ALPHA, GL20.GL_ONE, GL20.GL_ONE_MINUS_SRC_ALPHA), // normal(GL20.GL_SRC_ALPHA, GL20.GL_ONE, GL20.GL_ONE_MINUS_SRC_ALPHA), //
additive(GL20.GL_SRC_ALPHA, GL20.GL_ONE, GL20.GL_ONE), // additive(GL20.GL_SRC_ALPHA, GL20.GL_ONE, GL20.GL_ONE), //

View File

@ -38,6 +38,7 @@ import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.Array;
import com.esotericsoftware.spine.BoneData.TransformMode; import com.esotericsoftware.spine.BoneData.TransformMode;
/** Stores a bone's current pose. */
public class Bone implements Updatable { public class Bone implements Updatable {
final BoneData data; final BoneData data;
final Skeleton skeleton; final Skeleton skeleton;
@ -84,12 +85,17 @@ public class Bone implements Updatable {
updateWorldTransform(x, y, rotation, scaleX, scaleY, shearX, shearY); updateWorldTransform(x, y, rotation, scaleX, scaleY, shearX, shearY);
} }
/** Computes the world transform using the parent bone and this bone's local transform. */ /** Computes the world transform using the parent bone and this bone's local transform.
* <p>
* See {@link #updateWorldTransform(float, float, float, float, float, float, float)}. */
public void updateWorldTransform () { public void updateWorldTransform () {
updateWorldTransform(x, y, rotation, scaleX, scaleY, shearX, shearY); updateWorldTransform(x, y, rotation, scaleX, scaleY, shearX, shearY);
} }
/** Computes the world transform using the parent bone and the specified local transform. */ /** Computes the world transform using the parent bone and the specified local transform. Child bones are not updated.
* <p>
* See <a href="http://esotericsoftware.com/spine-skeleton-manipulation#World-transforms">World transforms</a> in the Spine
* Runtimes Guide. */
public void updateWorldTransform (float x, float y, float rotation, float scaleX, float scaleY, float shearX, float shearY) { public void updateWorldTransform (float x, float y, float rotation, float scaleX, float scaleY, float shearX, float shearY) {
ax = x; ax = x;
ay = y; ay = y;
@ -214,6 +220,7 @@ public class Bone implements Updatable {
} }
} }
/** Sets this bone's local transform to the setup pose. */
public void setToSetupPose () { public void setToSetupPose () {
BoneData data = this.data; BoneData data = this.data;
x = data.x; x = data.x;
@ -225,22 +232,27 @@ public class Bone implements Updatable {
shearY = data.shearY; shearY = data.shearY;
} }
/** The bone's setup pose data. */
public BoneData getData () { public BoneData getData () {
return data; return data;
} }
/** The skeleton this bone belongs to. */
public Skeleton getSkeleton () { public Skeleton getSkeleton () {
return skeleton; return skeleton;
} }
/** The parent bone, or null if this is the root bone. */
public Bone getParent () { public Bone getParent () {
return parent; return parent;
} }
/** The immediate children of this bone. */
public Array<Bone> getChildren () { public Array<Bone> getChildren () {
return children; return children;
} }
/** The local x translation. */
public float getX () { public float getX () {
return x; return x;
} }
@ -249,6 +261,7 @@ public class Bone implements Updatable {
this.x = x; this.x = x;
} }
/** The local y translation. */
public float getY () { public float getY () {
return y; return y;
} }
@ -262,6 +275,7 @@ public class Bone implements Updatable {
this.y = y; this.y = y;
} }
/** The local rotation. */
public float getRotation () { public float getRotation () {
return rotation; return rotation;
} }
@ -270,6 +284,7 @@ public class Bone implements Updatable {
this.rotation = rotation; this.rotation = rotation;
} }
/** The local scaleX. */
public float getScaleX () { public float getScaleX () {
return scaleX; return scaleX;
} }
@ -278,6 +293,7 @@ public class Bone implements Updatable {
this.scaleX = scaleX; this.scaleX = scaleX;
} }
/** The local scaleY. */
public float getScaleY () { public float getScaleY () {
return scaleY; return scaleY;
} }
@ -296,6 +312,7 @@ public class Bone implements Updatable {
scaleY = scale; scaleY = scale;
} }
/** The local shearX. */
public float getShearX () { public float getShearX () {
return shearX; return shearX;
} }
@ -304,6 +321,7 @@ public class Bone implements Updatable {
this.shearX = shearX; this.shearX = shearX;
} }
/** The local shearY. */
public float getShearY () { public float getShearY () {
return shearY; return shearY;
} }
@ -312,44 +330,52 @@ public class Bone implements Updatable {
this.shearY = shearY; this.shearY = shearY;
} }
/** Part of the world transform matrix for the X axis. */
public float getA () { public float getA () {
return a; return a;
} }
/** Part of the world transform matrix for the Y axis. */
public float getB () { public float getB () {
return b; return b;
} }
/** Part of the world transform matrix for the X axis. */
public float getC () { public float getC () {
return c; return c;
} }
/** Part of the world transform matrix for the Y axis. */
public float getD () { public float getD () {
return d; return d;
} }
/** The world X position. */
public float getWorldX () { public float getWorldX () {
return worldX; return worldX;
} }
/** The world Y position. */
public float getWorldY () { public float getWorldY () {
return worldY; return worldY;
} }
/** The world rotation for the X axis, calculated using {@link #a} and {@link #c}. */
public float getWorldRotationX () { public float getWorldRotationX () {
return atan2(c, a) * radDeg; return atan2(c, a) * radDeg;
} }
/** The world rotation for the Y axis, calculated using {@link #b} and {@link #d}. */
public float getWorldRotationY () { public float getWorldRotationY () {
return atan2(d, b) * radDeg; return atan2(d, b) * radDeg;
} }
/** Returns the magnitude (always positive) of the world scale X. */ /** The magnitude (always positive) of the world scale X, calculated using {@link #a} and {@link #c}. */
public float getWorldScaleX () { public float getWorldScaleX () {
return (float)Math.sqrt(a * a + c * c); return (float)Math.sqrt(a * a + c * c);
} }
/** Returns the magnitude (always positive) of the world scale Y. */ /** The magnitude (always positive) of the world scale Y, calculated using {@link #b} and {@link #d}. */
public float getWorldScaleY () { public float getWorldScaleY () {
return (float)Math.sqrt(b * b + d * d); return (float)Math.sqrt(b * b + d * d);
} }
@ -366,6 +392,8 @@ public class Bone implements Updatable {
return atan2(parent.a * d - parent.c * b, parent.d * b - parent.b * d) * radDeg; return atan2(parent.a * d - parent.c * b, parent.d * b - parent.b * d) * radDeg;
} }
/** Rotates the world transform the specified amount. {@link #updateWorldTransform()} will need to be called on any child
* bones, recursively. */
public void rotateWorld (float degrees) { public void rotateWorld (float degrees) {
float cos = cosDeg(degrees), sin = sinDeg(degrees); float cos = cosDeg(degrees), sin = sinDeg(degrees);
a = cos * a - sin * c; a = cos * a - sin * c;
@ -435,6 +463,7 @@ public class Bone implements Updatable {
return worldTransform; return worldTransform;
} }
/** Transforms a point from world coordinates to the bone's local coordinates. */
public Vector2 worldToLocal (Vector2 world) { public Vector2 worldToLocal (Vector2 world) {
float invDet = 1 / (a * d - b * c); float invDet = 1 / (a * d - b * c);
float x = world.x - worldX, y = world.y - worldY; float x = world.x - worldX, y = world.y - worldY;
@ -443,6 +472,7 @@ public class Bone implements Updatable {
return world; return world;
} }
/** Transforms a point from the bone's local coordinates to world coordinates. */
public Vector2 localToWorld (Vector2 local) { public Vector2 localToWorld (Vector2 local) {
float x = local.x, y = local.y; float x = local.x, y = local.y;
local.x = x * a + y * b + worldX; local.x = x * a + y * b + worldX;

View File

@ -32,6 +32,7 @@ package com.esotericsoftware.spine;
import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.Color;
/** Stores the setup pose for a {@link Bone}. */
public class BoneData { public class BoneData {
final int index; final int index;
final String name; final String name;
@ -69,10 +70,12 @@ public class BoneData {
shearY = bone.shearY; shearY = bone.shearY;
} }
/** The index of the bone in {@link Skeleton#getBones()}. */
public int getIndex () { public int getIndex () {
return index; return index;
} }
/** The name of the bone, which is unique within the skeleton. */
public String getName () { public String getName () {
return name; return name;
} }
@ -82,6 +85,7 @@ public class BoneData {
return parent; return parent;
} }
/** The bone's length. */
public float getLength () { public float getLength () {
return length; return length;
} }
@ -90,6 +94,7 @@ public class BoneData {
this.length = length; this.length = length;
} }
/** The local x translation. */
public float getX () { public float getX () {
return x; return x;
} }
@ -98,6 +103,7 @@ public class BoneData {
this.x = x; this.x = x;
} }
/** The local y translation. */
public float getY () { public float getY () {
return y; return y;
} }
@ -111,6 +117,7 @@ public class BoneData {
this.y = y; this.y = y;
} }
/** The local rotation. */
public float getRotation () { public float getRotation () {
return rotation; return rotation;
} }
@ -119,6 +126,7 @@ public class BoneData {
this.rotation = rotation; this.rotation = rotation;
} }
/** The local scaleX. */
public float getScaleX () { public float getScaleX () {
return scaleX; return scaleX;
} }
@ -127,6 +135,7 @@ public class BoneData {
this.scaleX = scaleX; this.scaleX = scaleX;
} }
/** The local scaleY. */
public float getScaleY () { public float getScaleY () {
return scaleY; return scaleY;
} }
@ -140,6 +149,7 @@ public class BoneData {
this.scaleY = scaleY; this.scaleY = scaleY;
} }
/** The local shearX. */
public float getShearX () { public float getShearX () {
return shearX; return shearX;
} }
@ -148,6 +158,7 @@ public class BoneData {
this.shearX = shearX; this.shearX = shearX;
} }
/** The local shearX. */
public float getShearY () { public float getShearY () {
return shearY; return shearY;
} }
@ -156,6 +167,7 @@ public class BoneData {
this.shearY = shearY; this.shearY = shearY;
} }
/** The transform mode for how parent world transforms affect this bone. */
public TransformMode getTransformMode () { public TransformMode getTransformMode () {
return transformMode; return transformMode;
} }
@ -164,6 +176,8 @@ public class BoneData {
this.transformMode = transformMode; this.transformMode = transformMode;
} }
/** The color of the bone as it was in Spine. Available only when nonessential data was exported. Bones are not usually
* rendered at runtime. */
public Color getColor () { public Color getColor () {
return color; return color;
} }
@ -172,6 +186,7 @@ public class BoneData {
return name; return name;
} }
/** Determines how a bone inherits world transforms from parent bones. */
static public enum TransformMode { static public enum TransformMode {
normal, onlyTranslation, noRotationOrReflection, noScale, noScaleOrReflection; normal, onlyTranslation, noRotationOrReflection, noScale, noScaleOrReflection;

View File

@ -30,6 +30,8 @@
package com.esotericsoftware.spine; package com.esotericsoftware.spine;
/** The interface for all constraints. */
public interface Constraint extends Updatable { public interface Constraint extends Updatable {
/** The ordinal for the order a skeleton's constraints will be applied. */
public int getOrder (); public int getOrder ();
} }

View File

@ -30,6 +30,14 @@
package com.esotericsoftware.spine; package com.esotericsoftware.spine;
import com.esotericsoftware.spine.Animation.Timeline;
import com.esotericsoftware.spine.AnimationState.AnimationStateListener;
/** Stores the current pose values for an {@link Event}.
* <p>
* See Timeline {@link Timeline#apply(Skeleton, float, float, com.badlogic.gdx.utils.Array, float, boolean, boolean)},
* AnimationStateListener {@link AnimationStateListener#event(com.esotericsoftware.spine.AnimationState.TrackEntry, Event)}, and
* <a href="http://esotericsoftware.com/spine-events">Events</a> in the Spine User Guide. */
public class Event { public class Event {
final private EventData data; final private EventData data;
int intValue; int intValue;
@ -67,10 +75,12 @@ public class Event {
this.stringValue = stringValue; this.stringValue = stringValue;
} }
/** The animation time this event was keyed. */
public float getTime () { public float getTime () {
return time; return time;
} }
/** The events's setup pose data. */
public EventData getData () { public EventData getData () {
return data; return data;
} }

View File

@ -30,6 +30,9 @@
package com.esotericsoftware.spine; package com.esotericsoftware.spine;
/** Stores the setup pose values for an {@link Event}.
* <p>
* See <a href="http://esotericsoftware.com/spine-events">Events</a> in the Spine User Guide. */
public class EventData { public class EventData {
final String name; final String name;
int intValue; int intValue;
@ -65,6 +68,7 @@ public class EventData {
this.stringValue = stringValue; this.stringValue = stringValue;
} }
/** The name of the event, which is unique within the skeleton. */
public String getName () { public String getName () {
return name; return name;
} }

View File

@ -34,6 +34,10 @@ import static com.badlogic.gdx.math.MathUtils.*;
import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.Array;
/** Stores the current pose for an IK constraint. An IK constraint adjusts the rotation of 1 or 2 constrained bones so the tip of
* the last bone is as close to the target bone as possible.
* <p>
* See <a href="http://esotericsoftware.com/spine-ik-constraints">IK constraints</a> in the Spine User Guide. */
public class IkConstraint implements Constraint { public class IkConstraint implements Constraint {
final IkConstraintData data; final IkConstraintData data;
final Array<Bone> bones; final Array<Bone> bones;
@ -67,6 +71,7 @@ public class IkConstraint implements Constraint {
bendDirection = constraint.bendDirection; bendDirection = constraint.bendDirection;
} }
/** Applies the constraint to the constrained bones. */
public void apply () { public void apply () {
update(); update();
} }
@ -88,10 +93,12 @@ public class IkConstraint implements Constraint {
return data.order; return data.order;
} }
/** The bones that will be modified by this IK constraint. */
public Array<Bone> getBones () { public Array<Bone> getBones () {
return bones; return bones;
} }
/** The bone that is the IK target. */
public Bone getTarget () { public Bone getTarget () {
return target; return target;
} }
@ -100,6 +107,7 @@ public class IkConstraint implements Constraint {
this.target = target; this.target = target;
} }
/** A percentage (0-1) that controls the mix between the constrained and unconstrained rotations. */
public float getMix () { public float getMix () {
return mix; return mix;
} }
@ -108,6 +116,7 @@ public class IkConstraint implements Constraint {
this.mix = mix; this.mix = mix;
} }
/** Controls the bend direction of the IK bones, either 1 or -1. */
public int getBendDirection () { public int getBendDirection () {
return bendDirection; return bendDirection;
} }
@ -116,6 +125,7 @@ public class IkConstraint implements Constraint {
this.bendDirection = bendDirection; this.bendDirection = bendDirection;
} }
/** The IK constraint's setup pose data. */
public IkConstraintData getData () { public IkConstraintData getData () {
return data; return data;
} }
@ -124,8 +134,7 @@ public class IkConstraint implements Constraint {
return data.name; return data.name;
} }
/** Adjusts the bone rotation so the tip is as close to the target position as possible. The target is specified in the world /** Applies 1 bone IK. The target is specified in the world coordinate system. */
* coordinate system. */
static public void apply (Bone bone, float targetX, float targetY, float alpha) { static public void apply (Bone bone, float targetX, float targetY, float alpha) {
if (!bone.appliedValid) bone.updateAppliedTransform(); if (!bone.appliedValid) bone.updateAppliedTransform();
Bone p = bone.parent; Bone p = bone.parent;
@ -141,8 +150,7 @@ public class IkConstraint implements Constraint {
bone.ashearY); bone.ashearY);
} }
/** Adjusts the parent and child bone rotations so the tip of the child is as close to the target position as possible. The /** Applies 2 bone IK. The target is specified in the world coordinate system.
* target is specified in the world coordinate system.
* @param child A direct descendant of the parent bone. */ * @param child A direct descendant of the parent bone. */
static public void apply (Bone parent, Bone child, float targetX, float targetY, int bendDir, float alpha) { static public void apply (Bone parent, Bone child, float targetX, float targetY, int bendDir, float alpha) {
if (alpha == 0) { if (alpha == 0) {

View File

@ -32,6 +32,9 @@ package com.esotericsoftware.spine;
import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.Array;
/** Stores the setup pose for an {@link IkConstraint}.
* <p>
* See <a href="http://esotericsoftware.com/spine-ik-constraints">IK constraints</a> in the Spine User Guide. */
public class IkConstraintData { public class IkConstraintData {
final String name; final String name;
int order; int order;
@ -45,10 +48,12 @@ public class IkConstraintData {
this.name = name; this.name = name;
} }
/** The IK constraint's name, which is unique within the skeleton. */
public String getName () { public String getName () {
return name; return name;
} }
/** See {@link Constraint#getOrder()}. */
public int getOrder () { public int getOrder () {
return order; return order;
} }
@ -57,10 +62,12 @@ public class IkConstraintData {
this.order = order; this.order = order;
} }
/** The bones that are constrained by this IK constraint. */
public Array<BoneData> getBones () { public Array<BoneData> getBones () {
return bones; return bones;
} }
/** The bone that is the IK target. */
public BoneData getTarget () { public BoneData getTarget () {
return target; return target;
} }
@ -70,6 +77,7 @@ public class IkConstraintData {
this.target = target; this.target = target;
} }
/** Controls the bend direction of the IK bones, either 1 or -1. */
public int getBendDirection () { public int getBendDirection () {
return bendDirection; return bendDirection;
} }
@ -78,6 +86,7 @@ public class IkConstraintData {
this.bendDirection = bendDirection; this.bendDirection = bendDirection;
} }
/** A percentage (0-1) that controls the mix between the constrained and unconstrained rotations. */
public float getMix () { public float getMix () {
return mix; return mix;
} }

View File

@ -40,6 +40,10 @@ import com.esotericsoftware.spine.PathConstraintData.SpacingMode;
import com.esotericsoftware.spine.attachments.Attachment; import com.esotericsoftware.spine.attachments.Attachment;
import com.esotericsoftware.spine.attachments.PathAttachment; import com.esotericsoftware.spine.attachments.PathAttachment;
/** Stores the current pose for a path constraint. A path constraint adjusts the rotation, translation, and scale of the
* constrained bones so they follow a {@link PathAttachment}.
* <p>
* See <a href="http://esotericsoftware.com/spine-path-constraints">Path constraints</a> in the Spine User Guide. */
public class PathConstraint implements Constraint { public class PathConstraint implements Constraint {
static private final int NONE = -1, BEFORE = -2, AFTER = -3; static private final int NONE = -1, BEFORE = -2, AFTER = -3;
@ -81,6 +85,7 @@ public class PathConstraint implements Constraint {
translateMix = constraint.translateMix; translateMix = constraint.translateMix;
} }
/** Applies the constraint to the constrained bones. */
public void apply () { public void apply () {
update(); update();
} }
@ -414,6 +419,7 @@ public class PathConstraint implements Constraint {
return data.order; return data.order;
} }
/** The position along the path. */
public float getPosition () { public float getPosition () {
return position; return position;
} }
@ -422,6 +428,7 @@ public class PathConstraint implements Constraint {
this.position = position; this.position = position;
} }
/** The spacing between bones. */
public float getSpacing () { public float getSpacing () {
return spacing; return spacing;
} }
@ -430,6 +437,7 @@ public class PathConstraint implements Constraint {
this.spacing = spacing; this.spacing = spacing;
} }
/** A percentage (0-1) that controls the mix between the constrained and unconstrained rotations. */
public float getRotateMix () { public float getRotateMix () {
return rotateMix; return rotateMix;
} }
@ -438,6 +446,7 @@ public class PathConstraint implements Constraint {
this.rotateMix = rotateMix; this.rotateMix = rotateMix;
} }
/** A percentage (0-1) that controls the mix between the constrained and unconstrained translations. */
public float getTranslateMix () { public float getTranslateMix () {
return translateMix; return translateMix;
} }
@ -446,10 +455,12 @@ public class PathConstraint implements Constraint {
this.translateMix = translateMix; this.translateMix = translateMix;
} }
/** The bones that will be modified by this path constraint. */
public Array<Bone> getBones () { public Array<Bone> getBones () {
return bones; return bones;
} }
/** The slot whose path attachment will be used to constrained the bones. */
public Slot getTarget () { public Slot getTarget () {
return target; return target;
} }
@ -458,6 +469,7 @@ public class PathConstraint implements Constraint {
this.target = target; this.target = target;
} }
/** The path constraint's setup pose data. */
public PathConstraintData getData () { public PathConstraintData getData () {
return data; return data;
} }

View File

@ -32,6 +32,9 @@ package com.esotericsoftware.spine;
import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.Array;
/** Stores the setup pose for a {@link PathConstraint}.
* <p>
* See <a href="http://esotericsoftware.com/spine-path-constraints">Path constraints</a> in the Spine User Guide. */
public class PathConstraintData { public class PathConstraintData {
final String name; final String name;
int order; int order;
@ -48,10 +51,12 @@ public class PathConstraintData {
this.name = name; this.name = name;
} }
/** The path constraint's name, which is unique within the skeleton. */
public String getName () { public String getName () {
return name; return name;
} }
/** See {@link Constraint#getOrder()}. */
public int getOrder () { public int getOrder () {
return order; return order;
} }
@ -60,10 +65,12 @@ public class PathConstraintData {
this.order = order; this.order = order;
} }
/** The bones that will be modified by this path constraint. */
public Array<BoneData> getBones () { public Array<BoneData> getBones () {
return bones; return bones;
} }
/** The slot whose path attachment will be used to constrained the bones. */
public SlotData getTarget () { public SlotData getTarget () {
return target; return target;
} }
@ -72,6 +79,7 @@ public class PathConstraintData {
this.target = target; this.target = target;
} }
/** The mode for positioning the first bone on the path. */
public PositionMode getPositionMode () { public PositionMode getPositionMode () {
return positionMode; return positionMode;
} }
@ -80,6 +88,7 @@ public class PathConstraintData {
this.positionMode = positionMode; this.positionMode = positionMode;
} }
/** The mode for positioning the bones after the first bone on the path. */
public SpacingMode getSpacingMode () { public SpacingMode getSpacingMode () {
return spacingMode; return spacingMode;
} }
@ -88,6 +97,7 @@ public class PathConstraintData {
this.spacingMode = spacingMode; this.spacingMode = spacingMode;
} }
/** The mode for adjusting the rotation of the bones. */
public RotateMode getRotateMode () { public RotateMode getRotateMode () {
return rotateMode; return rotateMode;
} }
@ -96,6 +106,7 @@ public class PathConstraintData {
this.rotateMode = rotateMode; this.rotateMode = rotateMode;
} }
/** An offset added to the constrained bone rotation. */
public float getOffsetRotation () { public float getOffsetRotation () {
return offsetRotation; return offsetRotation;
} }
@ -104,6 +115,7 @@ public class PathConstraintData {
this.offsetRotation = offsetRotation; this.offsetRotation = offsetRotation;
} }
/** The position along the path. */
public float getPosition () { public float getPosition () {
return position; return position;
} }
@ -112,6 +124,7 @@ public class PathConstraintData {
this.position = position; this.position = position;
} }
/** The spacing between bones. */
public float getSpacing () { public float getSpacing () {
return spacing; return spacing;
} }
@ -120,6 +133,7 @@ public class PathConstraintData {
this.spacing = spacing; this.spacing = spacing;
} }
/** A percentage (0-1) that controls the mix between the constrained and unconstrained rotations. */
public float getRotateMix () { public float getRotateMix () {
return rotateMix; return rotateMix;
} }
@ -128,6 +142,7 @@ public class PathConstraintData {
this.rotateMix = rotateMix; this.rotateMix = rotateMix;
} }
/** A percentage (0-1) that controls the mix between the constrained and unconstrained translations. */
public float getTranslateMix () { public float getTranslateMix () {
return translateMix; return translateMix;
} }
@ -140,18 +155,27 @@ public class PathConstraintData {
return name; return name;
} }
/** Controls how the first bone is positioned along the path.
* <p>
* See <a href="http://esotericsoftware.com/spine-path-constraints#Position-mode">Position mode</a> in the Spine User Guide. */
static public enum PositionMode { static public enum PositionMode {
fixed, percent; fixed, percent;
static public final PositionMode[] values = PositionMode.values(); static public final PositionMode[] values = PositionMode.values();
} }
/** Controls how bones after the first bone are positioned along the path.
* <p>
* See <a href="http://esotericsoftware.com/spine-path-constraints#Spacing-mode">Spacing mode</a> in the Spine User Guide. */
static public enum SpacingMode { static public enum SpacingMode {
length, fixed, percent; length, fixed, percent;
static public final SpacingMode[] values = SpacingMode.values(); static public final SpacingMode[] values = SpacingMode.values();
} }
/** Controls how bones are rotated, translated, and scaled to match the path.
* <p>
* See <a href="http://esotericsoftware.com/spine-path-constraints#Rotate-mode">Rotate mode</a> in the Spine User Guide. */
static public enum RotateMode { static public enum RotateMode {
tangent, chain, chainScale; tangent, chain, chainScale;

View File

@ -40,6 +40,10 @@ import com.esotericsoftware.spine.attachments.MeshAttachment;
import com.esotericsoftware.spine.attachments.PathAttachment; import com.esotericsoftware.spine.attachments.PathAttachment;
import com.esotericsoftware.spine.attachments.RegionAttachment; import com.esotericsoftware.spine.attachments.RegionAttachment;
/** Stores the current pose for a skeleton.
* <p>
* See <a href="http://esotericsoftware.com/spine-runtime-architecture#Instance-objects">Instance objects</a> in the Spine
* Runtimes Guide. */
public class Skeleton { public class Skeleton {
final SkeletonData data; final SkeletonData data;
final Array<Bone> bones; final Array<Bone> bones;
@ -290,7 +294,10 @@ public class Skeleton {
} }
} }
/** Updates the world transform for each bone and applies constraints. */ /** Updates the world transform for each bone and applies all constraints.
* <p>
* See <a href="http://esotericsoftware.com/spine-skeleton-manipulation#World-transforms">World transforms</a> in the Spine
* Runtimes Guide. */
public void updateWorldTransform () { public void updateWorldTransform () {
// This partial update avoids computing the world transform for constrained bones when 1) the bone is not updated // This partial update avoids computing the world transform for constrained bones when 1) the bone is not updated
// before the constraint, 2) the constraint only needs to access the applied local transform, and 3) the constraint calls // before the constraint, 2) the constraint only needs to access the applied local transform, and 3) the constraint calls
@ -312,7 +319,7 @@ public class Skeleton {
updateCache.get(i).update(); updateCache.get(i).update();
} }
/** Sets the bones, constraints, and slots to their setup pose values. */ /** Sets the bones, constraints, slots, and draw order to their setup pose values. */
public void setToSetupPose () { public void setToSetupPose () {
setBonesToSetupPose(); setBonesToSetupPose();
setSlotsToSetupPose(); setSlotsToSetupPose();
@ -352,6 +359,7 @@ public class Skeleton {
} }
} }
/** Sets the slots and draw order to their setup pose values. */
public void setSlotsToSetupPose () { public void setSlotsToSetupPose () {
Array<Slot> slots = this.slots; Array<Slot> slots = this.slots;
System.arraycopy(slots.items, 0, drawOrder.items, 0, slots.size); System.arraycopy(slots.items, 0, drawOrder.items, 0, slots.size);
@ -359,10 +367,12 @@ public class Skeleton {
slots.get(i).setToSetupPose(); slots.get(i).setToSetupPose();
} }
/** The skeleton's setup pose data. */
public SkeletonData getData () { public SkeletonData getData () {
return data; return data;
} }
/** The skeleton's bones, sorted parent first. The root bone is always the first bone. */
public Array<Bone> getBones () { public Array<Bone> getBones () {
return bones; return bones;
} }
@ -371,13 +381,15 @@ public class Skeleton {
return updateCache; return updateCache;
} }
/** @return May return null. */ /** Returns the root bone, or null. */
public Bone getRootBone () { public Bone getRootBone () {
if (bones.size == 0) return null; if (bones.size == 0) return null;
return bones.first(); return bones.first();
} }
/** @return May be null. */ /** Finds a bone by comparing each bone's name. It is more efficient to cache the results of this method than to call it
* multiple times.
* @return May be null. */
public Bone findBone (String boneName) { public Bone findBone (String boneName) {
if (boneName == null) throw new IllegalArgumentException("boneName cannot be null."); if (boneName == null) throw new IllegalArgumentException("boneName cannot be null.");
Array<Bone> bones = this.bones; Array<Bone> bones = this.bones;
@ -388,11 +400,14 @@ public class Skeleton {
return null; return null;
} }
/** The skeleton's slots. */
public Array<Slot> getSlots () { public Array<Slot> getSlots () {
return slots; return slots;
} }
/** @return May be null. */ /** Finds a slot by comparing each slot's name. It is more efficient to cache the results of this method than to call it
* multiple times.
* @return May be null. */
public Slot findSlot (String slotName) { public Slot findSlot (String slotName) {
if (slotName == null) throw new IllegalArgumentException("slotName cannot be null."); if (slotName == null) throw new IllegalArgumentException("slotName cannot be null.");
Array<Slot> slots = this.slots; Array<Slot> slots = this.slots;
@ -403,24 +418,25 @@ public class Skeleton {
return null; return null;
} }
/** Returns the slots in the order they will 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 array may be modified to change the draw order. */
public Array<Slot> getDrawOrder () { public Array<Slot> getDrawOrder () {
return drawOrder; return drawOrder;
} }
/** Sets the slots and the order they will be drawn. */
public void setDrawOrder (Array<Slot> drawOrder) { public void setDrawOrder (Array<Slot> drawOrder) {
if (drawOrder == null) throw new IllegalArgumentException("drawOrder cannot be null."); if (drawOrder == null) throw new IllegalArgumentException("drawOrder cannot be null.");
this.drawOrder = drawOrder; this.drawOrder = drawOrder;
} }
/** @return May be null. */ /** The skeleton's current skin.
* @return May be null. */
public Skin getSkin () { public Skin getSkin () {
return skin; return skin;
} }
/** Sets a skin by name. /** Sets a skin by name.
* @see #setSkin(Skin) */ * <p>
* See {@link #setSkin(Skin)}. */
public void setSkin (String skinName) { public void setSkin (String skinName) {
Skin skin = data.findSkin(skinName); Skin skin = data.findSkin(skinName);
if (skin == null) throw new IllegalArgumentException("Skin not found: " + skinName); if (skin == null) throw new IllegalArgumentException("Skin not found: " + skinName);
@ -428,6 +444,7 @@ public class Skeleton {
} }
/** Sets the skin used to look up attachments before looking in the {@link SkeletonData#getDefaultSkin() default skin}. /** Sets the skin used to look up attachments before looking in the {@link SkeletonData#getDefaultSkin() default skin}.
* <p>
* Attachments from the new skin are attached if the corresponding attachment from the old skin was attached. If there was no * Attachments from the new skin are attached if the corresponding attachment from the old skin was attached. If there was no
* old skin, each slot's setup mode attachment is attached from the new skin. * old skin, each slot's setup mode attachment is attached from the new skin.
* @param newSkin May be null. */ * @param newSkin May be null. */
@ -450,14 +467,22 @@ public class Skeleton {
skin = newSkin; skin = newSkin;
} }
/** @return May be null. */ /** Finds an attachment by looking in the {@link #skin} and {@link SkeletonData#defaultSkin} using the slot name and attachment
* name.
* <p>
* See {@link #getAttachment(int, String)}.
* @return May be null. */
public Attachment getAttachment (String slotName, String attachmentName) { public Attachment getAttachment (String slotName, String attachmentName) {
SlotData slot = data.findSlot(slotName); SlotData slot = data.findSlot(slotName);
if (slot == null) throw new IllegalArgumentException("Slot not found: " + slotName); if (slot == null) throw new IllegalArgumentException("Slot not found: " + slotName);
return getAttachment(slot.getIndex(), attachmentName); return getAttachment(slot.getIndex(), attachmentName);
} }
/** @return May be null. */ /** Finds an attachment by looking in the {@link #skin} and {@link SkeletonData#defaultSkin} using the slot index and
* attachment name. First the skin is checked and if the attachment was not found, the default skin is checked.
* <p>
* See <a href="http://esotericsoftware.com/spine-runtime-skins">Runtime skins</a> in the Spine Runtimes Guide.
* @return May be null. */
public Attachment getAttachment (int slotIndex, String attachmentName) { public Attachment getAttachment (int slotIndex, String attachmentName) {
if (attachmentName == null) throw new IllegalArgumentException("attachmentName cannot be null."); if (attachmentName == null) throw new IllegalArgumentException("attachmentName cannot be null.");
if (skin != null) { if (skin != null) {
@ -468,8 +493,8 @@ public class Skeleton {
return null; return null;
} }
/** Sets an attachment by finding the slot with {@link #findSlot(String)}, finding the attachment with /** A convenience method to set an attachment by finding the slot with {@link #findSlot(String)}, finding the attachment with
* {@link #getAttachment(int, String)}, then sets the slot's {@link Slot#attachment}. * {@link #getAttachment(int, String)}, then setting the slot's {@link Slot#attachment}.
* @param attachmentName May be null to clear the slot. */ * @param attachmentName May be null to clear the slot. */
public void setAttachment (String slotName, String attachmentName) { public void setAttachment (String slotName, String attachmentName) {
if (slotName == null) throw new IllegalArgumentException("slotName cannot be null."); if (slotName == null) throw new IllegalArgumentException("slotName cannot be null.");
@ -484,11 +509,14 @@ public class Skeleton {
slot.setAttachment(attachment); slot.setAttachment(attachment);
} }
/** The skeleton's IK constraints. */
public Array<IkConstraint> getIkConstraints () { public Array<IkConstraint> getIkConstraints () {
return ikConstraints; return ikConstraints;
} }
/** @return May be null. */ /** Finds an IK constraint by comparing each IK constraint's name. It is more efficient to cache the results of this method
* than to call it multiple times.
* @return May be null. */
public IkConstraint findIkConstraint (String constraintName) { public IkConstraint findIkConstraint (String constraintName) {
if (constraintName == null) throw new IllegalArgumentException("constraintName cannot be null."); if (constraintName == null) throw new IllegalArgumentException("constraintName cannot be null.");
Array<IkConstraint> ikConstraints = this.ikConstraints; Array<IkConstraint> ikConstraints = this.ikConstraints;
@ -499,11 +527,14 @@ public class Skeleton {
return null; return null;
} }
/** The skeleton's transform constraints. */
public Array<TransformConstraint> getTransformConstraints () { public Array<TransformConstraint> getTransformConstraints () {
return transformConstraints; return transformConstraints;
} }
/** @return May be null. */ /** Finds a transform constraint by comparing each transform constraint's name. It is more efficient to cache the results of
* this method than to call it multiple times.
* @return May be null. */
public TransformConstraint findTransformConstraint (String constraintName) { public TransformConstraint findTransformConstraint (String constraintName) {
if (constraintName == null) throw new IllegalArgumentException("constraintName cannot be null."); if (constraintName == null) throw new IllegalArgumentException("constraintName cannot be null.");
Array<TransformConstraint> transformConstraints = this.transformConstraints; Array<TransformConstraint> transformConstraints = this.transformConstraints;
@ -514,11 +545,14 @@ public class Skeleton {
return null; return null;
} }
/** The skeleton's path constraints. */
public Array<PathConstraint> getPathConstraints () { public Array<PathConstraint> getPathConstraints () {
return pathConstraints; return pathConstraints;
} }
/** @return May be null. */ /** Finds a path constraint by comparing each path constraint's name. It is more efficient to cache the results of this method
* than to call it multiple times.
* @return May be null. */
public PathConstraint findPathConstraint (String constraintName) { public PathConstraint findPathConstraint (String constraintName) {
if (constraintName == null) throw new IllegalArgumentException("constraintName cannot be null."); if (constraintName == null) throw new IllegalArgumentException("constraintName cannot be null.");
Array<PathConstraint> pathConstraints = this.pathConstraints; Array<PathConstraint> pathConstraints = this.pathConstraints;
@ -530,8 +564,8 @@ public class Skeleton {
} }
/** Returns the axis aligned bounding box (AABB) of the region and mesh attachments for the current pose. /** Returns the axis aligned bounding box (AABB) of the region and mesh attachments for the current pose.
* @param offset The distance from the skeleton origin to the bottom left corner of the AABB. * @param offset An output value, the distance from the skeleton origin to the bottom left corner of the AABB.
* @param size The width and height of the AABB. */ * @param size An output value, the width and height of the AABB. */
public void getBounds (Vector2 offset, Vector2 size) { public void getBounds (Vector2 offset, Vector2 size) {
if (offset == null) throw new IllegalArgumentException("offset cannot be null."); if (offset == null) throw new IllegalArgumentException("offset cannot be null.");
if (size == null) throw new IllegalArgumentException("size cannot be null."); if (size == null) throw new IllegalArgumentException("size cannot be null.");
@ -559,6 +593,7 @@ public class Skeleton {
size.set(maxX - minX, maxY - minY); size.set(maxX - minX, maxY - minY);
} }
/** The color to tint all the skeleton's attachments. */
public Color getColor () { public Color getColor () {
return color; return color;
} }
@ -569,6 +604,8 @@ public class Skeleton {
this.color.set(color); this.color.set(color);
} }
/** If true, the entire skeleton is flipped over the Y axis. This affects all bones, even if the bone's transform mode
* disallows scale inheritance. */
public boolean getFlipX () { public boolean getFlipX () {
return flipX; return flipX;
} }
@ -577,6 +614,8 @@ public class Skeleton {
this.flipX = flipX; this.flipX = flipX;
} }
/** If true, the entire skeleton is flipped over the X axis. This affects all bones, even if the bone's transform mode
* disallows scale inheritance. */
public boolean getFlipY () { public boolean getFlipY () {
return flipY; return flipY;
} }
@ -590,6 +629,7 @@ public class Skeleton {
this.flipY = flipY; this.flipY = flipY;
} }
/** Sets the skeleton X position, which is added to the root bone worldX position. */
public float getX () { public float getX () {
return x; return x;
} }
@ -598,6 +638,7 @@ public class Skeleton {
this.x = x; this.x = x;
} }
/** Sets the skeleton Y position, which is added to the root bone worldY position. */
public float getY () { public float getY () {
return y; return y;
} }
@ -611,6 +652,9 @@ public class Skeleton {
this.y = y; this.y = y;
} }
/** Returns the skeleton's time. This can be used for tracking, such as with Slot {@link Slot#getAttachmentTime()}.
* <p>
* See {@link #update(float)}. */
public float getTime () { public float getTime () {
return time; return time;
} }
@ -619,6 +663,7 @@ public class Skeleton {
this.time = time; this.time = time;
} }
/** Increments the skeleton's {@link #time}. */
public void update (float delta) { public void update (float delta) {
time += delta; time += delta;
} }

View File

@ -72,6 +72,11 @@ import com.esotericsoftware.spine.attachments.PathAttachment;
import com.esotericsoftware.spine.attachments.RegionAttachment; import com.esotericsoftware.spine.attachments.RegionAttachment;
import com.esotericsoftware.spine.attachments.VertexAttachment; import com.esotericsoftware.spine.attachments.VertexAttachment;
/** Loads skeleton data in the Spine binary format.
* <p>
* See <a href="http://esotericsoftware.com/spine-binary-format">Spine binary format</a> and
* <a href="http://esotericsoftware.com/spine-loading-skeleton-data#JSON-and-binary-data">JSON and binary data</a> in the Spine
* Runtimes Guide. */
public class SkeletonBinary { public class SkeletonBinary {
static public final int BONE_ROTATE = 0; static public final int BONE_ROTATE = 0;
static public final int BONE_TRANSLATE = 1; static public final int BONE_TRANSLATE = 1;
@ -104,11 +109,14 @@ public class SkeletonBinary {
this.attachmentLoader = attachmentLoader; this.attachmentLoader = attachmentLoader;
} }
/** Scales bone positions, image sizes, and translations as they are loaded. This allows different size images to be used at
* runtime than were used in Spine.
* <p>
* See <a href="http://esotericsoftware.com/spine-loading-skeleton-data#Scaling">Scaling</a> in the Spine Runtimes Guide. */
public float getScale () { public float getScale () {
return scale; return scale;
} }
/** Scales the bones, images, and animations as they are loaded. */
public void setScale (float scale) { public void setScale (float scale) {
this.scale = scale; this.scale = scale;
} }

View File

@ -30,13 +30,14 @@
package com.esotericsoftware.spine; package com.esotericsoftware.spine;
import com.esotericsoftware.spine.attachments.Attachment;
import com.esotericsoftware.spine.attachments.BoundingBoxAttachment;
import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.FloatArray; import com.badlogic.gdx.utils.FloatArray;
import com.badlogic.gdx.utils.Pool; import com.badlogic.gdx.utils.Pool;
import com.esotericsoftware.spine.attachments.Attachment;
import com.esotericsoftware.spine.attachments.BoundingBoxAttachment;
/** Collects each {@link BoundingBoxAttachment} that is visible and computes the world vertices for its polygon. The polygon
* vertices are provided along with convenience methods for doing hit detection. */
public class SkeletonBounds { public class SkeletonBounds {
private float minX, minY, maxX, maxY; private float minX, minY, maxX, maxY;
private Array<BoundingBoxAttachment> boundingBoxes = new Array(); private Array<BoundingBoxAttachment> boundingBoxes = new Array();
@ -47,6 +48,10 @@ public class SkeletonBounds {
} }
}; };
/** Clears any previous polygons, finds all visible bounding box attachments, and computes the world vertices for each bounding
* box's polygon.
* @param updateAabb If true, the axis aligned bounding box containing all the polygons is computed. If false, the
* SkeletonBounds AABB methods will always return true. */
public void update (Skeleton skeleton, boolean updateAabb) { public void update (Skeleton skeleton, boolean updateAabb) {
if (skeleton == null) throw new IllegalArgumentException("skeleton cannot be null."); if (skeleton == null) throw new IllegalArgumentException("skeleton cannot be null.");
Array<BoundingBoxAttachment> boundingBoxes = this.boundingBoxes; Array<BoundingBoxAttachment> boundingBoxes = this.boundingBoxes;
@ -194,34 +199,42 @@ public class SkeletonBounds {
return false; return false;
} }
/** The left edge of the axis aligned bounding box. */
public float getMinX () { public float getMinX () {
return minX; return minX;
} }
/** The bottom edge of the axis aligned bounding box. */
public float getMinY () { public float getMinY () {
return minY; return minY;
} }
/** The right edge of the axis aligned bounding box. */
public float getMaxX () { public float getMaxX () {
return maxX; return maxX;
} }
/** The top edge of the axis aligned bounding box. */
public float getMaxY () { public float getMaxY () {
return maxY; return maxY;
} }
/** The width of the axis aligned bounding box. */
public float getWidth () { public float getWidth () {
return maxX - minX; return maxX - minX;
} }
/** The height of the axis aligned bounding box. */
public float getHeight () { public float getHeight () {
return maxY - minY; return maxY - minY;
} }
/** The visible bounding boxes. */
public Array<BoundingBoxAttachment> getBoundingBoxes () { public Array<BoundingBoxAttachment> getBoundingBoxes () {
return boundingBoxes; return boundingBoxes;
} }
/** The world vertices for the bounding box polygons. */
public Array<FloatArray> getPolygons () { public Array<FloatArray> getPolygons () {
return polygons; return polygons;
} }

View File

@ -32,6 +32,10 @@ package com.esotericsoftware.spine;
import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.Array;
/** Stores the setup pose and all of the stateless data for a skeleton.
* <p>
* See <a href="http://esotericsoftware.com/spine-runtime-architecture#Data-objects">Data objects</a> in the Spine Runtimes
* Guide. */
public class SkeletonData { public class SkeletonData {
String name; String name;
final Array<BoneData> bones = new Array(); // Ordered parents first. final Array<BoneData> bones = new Array(); // Ordered parents first.
@ -52,11 +56,14 @@ public class SkeletonData {
// --- Bones. // --- Bones.
/** The skeleton's bones, sorted parent first. The root bone is always the first bone. */
public Array<BoneData> getBones () { public Array<BoneData> getBones () {
return bones; return bones;
} }
/** @return May be null. */ /** Finds a bone by comparing each bone's name. It is more efficient to cache the results of this method than to call it
* multiple times.
* @return May be null. */
public BoneData findBone (String boneName) { public BoneData findBone (String boneName) {
if (boneName == null) throw new IllegalArgumentException("boneName cannot be null."); if (boneName == null) throw new IllegalArgumentException("boneName cannot be null.");
Array<BoneData> bones = this.bones; Array<BoneData> bones = this.bones;
@ -69,11 +76,14 @@ public class SkeletonData {
// --- Slots. // --- Slots.
/** The skeleton's slots. */
public Array<SlotData> getSlots () { public Array<SlotData> getSlots () {
return slots; return slots;
} }
/** @return May be null. */ /** Finds a slot by comparing each slot's name. It is more efficient to cache the results of this method than to call it
* multiple times.
* @return May be null. */
public SlotData findSlot (String slotName) { public SlotData findSlot (String slotName) {
if (slotName == null) throw new IllegalArgumentException("slotName cannot be null."); if (slotName == null) throw new IllegalArgumentException("slotName cannot be null.");
Array<SlotData> slots = this.slots; Array<SlotData> slots = this.slots;
@ -86,7 +96,10 @@ public class SkeletonData {
// --- Skins. // --- Skins.
/** @return May be null. */ /** The skeleton's default skin. By default this skin contains all attachments that were not in a skin in Spine.
* <p>
* See {@link Skeleton#getAttachment(int, String)}.
* @return May be null. */
public Skin getDefaultSkin () { public Skin getDefaultSkin () {
return defaultSkin; return defaultSkin;
} }
@ -96,7 +109,9 @@ public class SkeletonData {
this.defaultSkin = defaultSkin; this.defaultSkin = defaultSkin;
} }
/** @return May be null. */ /** Finds a skin by comparing each skin's name. It is more efficient to cache the results of this method than to call it
* multiple times.
* @return May be null. */
public Skin findSkin (String skinName) { public Skin findSkin (String skinName) {
if (skinName == null) throw new IllegalArgumentException("skinName cannot be null."); if (skinName == null) throw new IllegalArgumentException("skinName cannot be null.");
for (Skin skin : skins) for (Skin skin : skins)
@ -104,14 +119,16 @@ public class SkeletonData {
return null; return null;
} }
/** Returns all skins, including the default skin. */ /** All skins, including the default skin. */
public Array<Skin> getSkins () { public Array<Skin> getSkins () {
return skins; return skins;
} }
// --- Events. // --- Events.
/** @return May be null. */ /** Finds an event by comparing each events's name. It is more efficient to cache the results of this method than to call it
* multiple times.
* @return May be null. */
public EventData findEvent (String eventDataName) { public EventData findEvent (String eventDataName) {
if (eventDataName == null) throw new IllegalArgumentException("eventDataName cannot be null."); if (eventDataName == null) throw new IllegalArgumentException("eventDataName cannot be null.");
for (EventData eventData : events) for (EventData eventData : events)
@ -119,17 +136,21 @@ public class SkeletonData {
return null; return null;
} }
/** The skeleton's events. */
public Array<EventData> getEvents () { public Array<EventData> getEvents () {
return events; return events;
} }
// --- Animations. // --- Animations.
/** The skeleton's animations. */
public Array<Animation> getAnimations () { public Array<Animation> getAnimations () {
return animations; return animations;
} }
/** @return May be null. */ /** Finds an animation by comparing each animation's name. It is more efficient to cache the results of this method than to
* call it multiple times.
* @return May be null. */
public Animation findAnimation (String animationName) { public Animation findAnimation (String animationName) {
if (animationName == null) throw new IllegalArgumentException("animationName cannot be null."); if (animationName == null) throw new IllegalArgumentException("animationName cannot be null.");
Array<Animation> animations = this.animations; Array<Animation> animations = this.animations;
@ -142,11 +163,14 @@ public class SkeletonData {
// --- IK constraints // --- IK constraints
/** The skeleton's IK constraints. */
public Array<IkConstraintData> getIkConstraints () { public Array<IkConstraintData> getIkConstraints () {
return ikConstraints; return ikConstraints;
} }
/** @return May be null. */ /** Finds an IK constraint by comparing each IK constraint's name. It is more efficient to cache the results of this method
* than to call it multiple times.
* @return May be null. */
public IkConstraintData findIkConstraint (String constraintName) { public IkConstraintData findIkConstraint (String constraintName) {
if (constraintName == null) throw new IllegalArgumentException("constraintName cannot be null."); if (constraintName == null) throw new IllegalArgumentException("constraintName cannot be null.");
Array<IkConstraintData> ikConstraints = this.ikConstraints; Array<IkConstraintData> ikConstraints = this.ikConstraints;
@ -159,11 +183,14 @@ public class SkeletonData {
// --- Transform constraints // --- Transform constraints
/** The skeleton's transform constraints. */
public Array<TransformConstraintData> getTransformConstraints () { public Array<TransformConstraintData> getTransformConstraints () {
return transformConstraints; return transformConstraints;
} }
/** @return May be null. */ /** Finds a transform constraint by comparing each transform constraint's name. It is more efficient to cache the results of
* this method than to call it multiple times.
* @return May be null. */
public TransformConstraintData findTransformConstraint (String constraintName) { public TransformConstraintData findTransformConstraint (String constraintName) {
if (constraintName == null) throw new IllegalArgumentException("constraintName cannot be null."); if (constraintName == null) throw new IllegalArgumentException("constraintName cannot be null.");
Array<TransformConstraintData> transformConstraints = this.transformConstraints; Array<TransformConstraintData> transformConstraints = this.transformConstraints;
@ -176,11 +203,14 @@ public class SkeletonData {
// --- Path constraints // --- Path constraints
/** The skeleton's path constraints. */
public Array<PathConstraintData> getPathConstraints () { public Array<PathConstraintData> getPathConstraints () {
return pathConstraints; return pathConstraints;
} }
/** @return May be null. */ /** Finds a path constraint by comparing each path constraint's name. It is more efficient to cache the results of this method
* than to call it multiple times.
* @return May be null. */
public PathConstraintData findPathConstraint (String constraintName) { public PathConstraintData findPathConstraint (String constraintName) {
if (constraintName == null) throw new IllegalArgumentException("constraintName cannot be null."); if (constraintName == null) throw new IllegalArgumentException("constraintName cannot be null.");
Array<PathConstraintData> pathConstraints = this.pathConstraints; Array<PathConstraintData> pathConstraints = this.pathConstraints;
@ -193,7 +223,8 @@ public class SkeletonData {
// --- // ---
/** @return May be null. */ /** The skeleton's name, which by default is the name of the skeleton data file, if possible.
* @return May be null. */
public String getName () { public String getName () {
return name; return name;
} }
@ -203,6 +234,7 @@ public class SkeletonData {
this.name = name; this.name = name;
} }
/** The width of the skeleton's axis aligned bounding box in the setup pose. */
public float getWidth () { public float getWidth () {
return width; return width;
} }
@ -211,6 +243,7 @@ public class SkeletonData {
this.width = width; this.width = width;
} }
/** The height of the skeleton's axis aligned bounding box in the setup pose. */
public float getHeight () { public float getHeight () {
return height; return height;
} }
@ -219,7 +252,7 @@ public class SkeletonData {
this.height = height; this.height = height;
} }
/** Returns the Spine version used to export this data, or null. */ /** The Spine version used to export the skeleton data, or null. */
public String getVersion () { public String getVersion () {
return version; return version;
} }
@ -229,7 +262,8 @@ public class SkeletonData {
this.version = version; this.version = version;
} }
/** @return May be null. */ /** The skeleton data hash. This value will change if any of the skeleton data has changed.
* @return May be null. */
public String getHash () { public String getHash () {
return hash; return hash;
} }
@ -239,7 +273,8 @@ public class SkeletonData {
this.hash = hash; this.hash = hash;
} }
/** @return May be null. */ /** The path to the image directory as defined in Spine. Available only when nonessential data was exported.
* @return May be null. */
public String getImagesPath () { public String getImagesPath () {
return imagesPath; return imagesPath;
} }
@ -249,6 +284,7 @@ public class SkeletonData {
this.imagesPath = imagesPath; this.imagesPath = imagesPath;
} }
/** The dopesheet FPS in Spine. Available only when nonessential data was exported. */
public float getFps () { public float getFps () {
return fps; return fps;
} }

View File

@ -69,6 +69,11 @@ import com.esotericsoftware.spine.attachments.PathAttachment;
import com.esotericsoftware.spine.attachments.RegionAttachment; import com.esotericsoftware.spine.attachments.RegionAttachment;
import com.esotericsoftware.spine.attachments.VertexAttachment; import com.esotericsoftware.spine.attachments.VertexAttachment;
/** Loads skeleton data in the Spine JSON format.
* <p>
* See <a href="http://esotericsoftware.com/spine-json-format">Spine JSON format</a> and
* <a href="http://esotericsoftware.com/spine-loading-skeleton-data#JSON-and-binary-data">JSON and binary data</a> in the Spine
* Runtimes Guide. */
public class SkeletonJson { public class SkeletonJson {
private final AttachmentLoader attachmentLoader; private final AttachmentLoader attachmentLoader;
private float scale = 1; private float scale = 1;
@ -83,11 +88,14 @@ public class SkeletonJson {
this.attachmentLoader = attachmentLoader; this.attachmentLoader = attachmentLoader;
} }
/** Scales bone positions, image sizes, and translations as they are loaded. This allows different size images to be used at
* runtime than were used in Spine.
* <p>
* See <a href="http://esotericsoftware.com/spine-loading-skeleton-data#Scaling">Scaling</a> in the Spine Runtimes Guide. */
public float getScale () { public float getScale () {
return scale; return scale;
} }
/** Scales the bones, images, and animations as they are loaded. */
public void setScale (float scale) { public void setScale (float scale) {
this.scale = scale; this.scale = scale;
} }

View File

@ -36,7 +36,10 @@ import com.badlogic.gdx.utils.ObjectMap.Entry;
import com.badlogic.gdx.utils.Pool; import com.badlogic.gdx.utils.Pool;
import com.esotericsoftware.spine.attachments.Attachment; import com.esotericsoftware.spine.attachments.Attachment;
/** Stores attachments by slot index and attachment name. */ /** Stores attachments by slot index and attachment name.
* <p>
* See SkeletonData {@link SkeletonData#defaultSkin}, Skeleton {@link Skeleton#skin}, and
* <a href="http://esotericsoftware.com/spine-runtime-skins">Runtime skins</a> in the Spine Runtimes Guide. */
public class Skin { public class Skin {
static private final Key lookup = new Key(); static private final Key lookup = new Key();
@ -53,6 +56,7 @@ public class Skin {
this.name = name; this.name = name;
} }
/** Adds an attachment to the skin for the specified slot index and name. */
public void addAttachment (int slotIndex, String name, Attachment attachment) { public void addAttachment (int slotIndex, String name, Attachment attachment) {
if (attachment == null) throw new IllegalArgumentException("attachment cannot be null."); if (attachment == null) throw new IllegalArgumentException("attachment cannot be null.");
if (slotIndex < 0) throw new IllegalArgumentException("slotIndex must be >= 0."); if (slotIndex < 0) throw new IllegalArgumentException("slotIndex must be >= 0.");
@ -61,7 +65,7 @@ public class Skin {
attachments.put(key, attachment); attachments.put(key, attachment);
} }
/** @return May be null. */ /** Returns the attachment for the specified slot index and name, or null. */
public Attachment getAttachment (int slotIndex, String name) { public Attachment getAttachment (int slotIndex, String name) {
if (slotIndex < 0) throw new IllegalArgumentException("slotIndex must be >= 0."); if (slotIndex < 0) throw new IllegalArgumentException("slotIndex must be >= 0.");
lookup.set(slotIndex, name); lookup.set(slotIndex, name);
@ -88,6 +92,7 @@ public class Skin {
attachments.clear(); attachments.clear();
} }
/** The skin's name, which is unique within the skeleton. */
public String getName () { public String getName () {
return name; return name;
} }

View File

@ -32,8 +32,13 @@ package com.esotericsoftware.spine;
import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.utils.FloatArray; import com.badlogic.gdx.utils.FloatArray;
import com.esotericsoftware.spine.Animation.DeformTimeline;
import com.esotericsoftware.spine.attachments.Attachment; import com.esotericsoftware.spine.attachments.Attachment;
import com.esotericsoftware.spine.attachments.VertexAttachment;
/** Stores a slot's current pose. Slots organize attachments for {@link Skeleton#drawOrder} purposes and provide a place to store
* state for an attachment. State cannot be stored in an attachment itself because attachments are stateless and may be shared
* across multiple skeletons. */
public class Slot { public class Slot {
final SlotData data; final SlotData data;
final Bone bone; final Bone bone;
@ -62,28 +67,33 @@ public class Slot {
attachmentTime = slot.attachmentTime; attachmentTime = slot.attachmentTime;
} }
/** The slot's setup pose data. */
public SlotData getData () { public SlotData getData () {
return data; return data;
} }
/** The bone this slot belongs to. */
public Bone getBone () { public Bone getBone () {
return bone; return bone;
} }
/** The skeleton this slot belongs to. */
public Skeleton getSkeleton () { public Skeleton getSkeleton () {
return bone.skeleton; return bone.skeleton;
} }
/** The color used to tint the slot's attachment. */
public Color getColor () { public Color getColor () {
return color; return color;
} }
/** @return May be null. */ /** The current attachment for the slot, or null if the slot has no attachment. */
public Attachment getAttachment () { public Attachment getAttachment () {
return attachment; return attachment;
} }
/** Sets the attachment and if it changed, resets {@link #getAttachmentTime()} and clears {@link #getAttachmentVertices()}. /** Sets the slot's attachment and, if the attachment changed, resets {@link #attachmentTime} and clears
* {@link #attachmentVertices}.
* @param attachment May be null. */ * @param attachment May be null. */
public void setAttachment (Attachment attachment) { public void setAttachment (Attachment attachment) {
if (this.attachment == attachment) return; if (this.attachment == attachment) return;
@ -92,13 +102,21 @@ public class Slot {
attachmentVertices.clear(); attachmentVertices.clear();
} }
/** The time that has elapsed since the last time the attachment was set or cleared. Relies on Skeleton
* {@link Skeleton#time}. */
public float getAttachmentTime () {
return bone.skeleton.time - attachmentTime;
}
public void setAttachmentTime (float time) { public void setAttachmentTime (float time) {
attachmentTime = bone.skeleton.time - time; attachmentTime = bone.skeleton.time - time;
} }
/** Returns the time since the attachment was set. */ /** Vertices to deform the slot's attachment.
public float getAttachmentTime () { * <p>
return bone.skeleton.time - attachmentTime; * See {@link VertexAttachment#computeWorldVertices(Slot, int, int, float[], int)} and {@link DeformTimeline}. */
public FloatArray getAttachmentVertices () {
return attachmentVertices;
} }
public void setAttachmentVertices (FloatArray attachmentVertices) { public void setAttachmentVertices (FloatArray attachmentVertices) {
@ -106,10 +124,7 @@ public class Slot {
this.attachmentVertices = attachmentVertices; this.attachmentVertices = attachmentVertices;
} }
public FloatArray getAttachmentVertices () { /** Sets this slot to the setup pose. */
return attachmentVertices;
}
public void setToSetupPose () { public void setToSetupPose () {
color.set(data.color); color.set(data.color);
if (data.attachmentName == null) if (data.attachmentName == null)

View File

@ -32,6 +32,7 @@ package com.esotericsoftware.spine;
import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.Color;
/** Stores the setup pose for a {@link Slot}. */
public class SlotData { public class SlotData {
final int index; final int index;
final String name; final String name;
@ -49,18 +50,22 @@ public class SlotData {
this.boneData = boneData; this.boneData = boneData;
} }
/** The index of the slot in {@link Skeleton#getSlots()}. */
public int getIndex () { public int getIndex () {
return index; return index;
} }
/** The name of the slot, which is unique within the skeleton. */
public String getName () { public String getName () {
return name; return name;
} }
/** The bone this slot belongs to. */
public BoneData getBoneData () { public BoneData getBoneData () {
return boneData; return boneData;
} }
/** The color used to tint the slot's attachment. */
public Color getColor () { public Color getColor () {
return color; return color;
} }
@ -70,11 +75,12 @@ public class SlotData {
this.attachmentName = attachmentName; this.attachmentName = attachmentName;
} }
/** @return May be null. */ /** The name of the attachment that is visible for this slot in the setup pose, or null if no attachment is visible. */
public String getAttachmentName () { public String getAttachmentName () {
return attachmentName; return attachmentName;
} }
/** The blend mode for drawing the slot's attachment. */
public BlendMode getBlendMode () { public BlendMode getBlendMode () {
return blendMode; return blendMode;
} }

View File

@ -35,6 +35,10 @@ import static com.badlogic.gdx.math.MathUtils.*;
import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.Array;
/** Stores the current pose for a transform constraint. A transform constraint adjusts the world transform of the constrained
* bones to match that of the target bone.
* <p>
* See <a href="http://esotericsoftware.com/spine-transform-constraints">Transform constraints</a> in the Spine User Guide. */
public class TransformConstraint implements Constraint { public class TransformConstraint implements Constraint {
final TransformConstraintData data; final TransformConstraintData data;
final Array<Bone> bones; final Array<Bone> bones;
@ -71,6 +75,7 @@ public class TransformConstraint implements Constraint {
shearMix = constraint.shearMix; shearMix = constraint.shearMix;
} }
/** Applies the constraint to the constrained bones. */
public void apply () { public void apply () {
update(); update();
} }
@ -143,10 +148,12 @@ public class TransformConstraint implements Constraint {
return data.order; return data.order;
} }
/** The bones that will be modified by this transform constraint. */
public Array<Bone> getBones () { public Array<Bone> getBones () {
return bones; return bones;
} }
/** The target bone whose world transform will be copied to the constrained bones. */
public Bone getTarget () { public Bone getTarget () {
return target; return target;
} }
@ -155,6 +162,7 @@ public class TransformConstraint implements Constraint {
this.target = target; this.target = target;
} }
/** A percentage (0-1) that controls the mix between the constrained and unconstrained rotations. */
public float getRotateMix () { public float getRotateMix () {
return rotateMix; return rotateMix;
} }
@ -163,6 +171,7 @@ public class TransformConstraint implements Constraint {
this.rotateMix = rotateMix; this.rotateMix = rotateMix;
} }
/** A percentage (0-1) that controls the mix between the constrained and unconstrained translations. */
public float getTranslateMix () { public float getTranslateMix () {
return translateMix; return translateMix;
} }
@ -171,6 +180,7 @@ public class TransformConstraint implements Constraint {
this.translateMix = translateMix; this.translateMix = translateMix;
} }
/** A percentage (0-1) that controls the mix between the constrained and unconstrained scales. */
public float getScaleMix () { public float getScaleMix () {
return scaleMix; return scaleMix;
} }
@ -179,6 +189,7 @@ public class TransformConstraint implements Constraint {
this.scaleMix = scaleMix; this.scaleMix = scaleMix;
} }
/** A percentage (0-1) that controls the mix between the constrained and unconstrained scales. */
public float getShearMix () { public float getShearMix () {
return shearMix; return shearMix;
} }
@ -187,6 +198,7 @@ public class TransformConstraint implements Constraint {
this.shearMix = shearMix; this.shearMix = shearMix;
} }
/** The transform constraint's setup pose data. */
public TransformConstraintData getData () { public TransformConstraintData getData () {
return data; return data;
} }

View File

@ -32,6 +32,9 @@ package com.esotericsoftware.spine;
import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.Array;
/** Stores the setup pose for a {@link TransformConstraint}.
* <p>
* See <a href="http://esotericsoftware.com/spine-transform-constraints">Transform constraints</a> in the Spine User Guide. */
public class TransformConstraintData { public class TransformConstraintData {
final String name; final String name;
int order; int order;
@ -45,10 +48,12 @@ public class TransformConstraintData {
this.name = name; this.name = name;
} }
/** The transform constraint's name, which is unique within the skeleton. */
public String getName () { public String getName () {
return name; return name;
} }
/** See {@link Constraint#getOrder()}. */
public int getOrder () { public int getOrder () {
return order; return order;
} }
@ -57,10 +62,12 @@ public class TransformConstraintData {
this.order = order; this.order = order;
} }
/** The bones that will be modified by this transform constraint. */
public Array<BoneData> getBones () { public Array<BoneData> getBones () {
return bones; return bones;
} }
/** The target bone whose world transform will be copied to the constrained bones. */
public BoneData getTarget () { public BoneData getTarget () {
return target; return target;
} }
@ -70,6 +77,7 @@ public class TransformConstraintData {
this.target = target; this.target = target;
} }
/** A percentage (0-1) that controls the mix between the constrained and unconstrained rotations. */
public float getRotateMix () { public float getRotateMix () {
return rotateMix; return rotateMix;
} }
@ -78,6 +86,7 @@ public class TransformConstraintData {
this.rotateMix = rotateMix; this.rotateMix = rotateMix;
} }
/** A percentage (0-1) that controls the mix between the constrained and unconstrained translations. */
public float getTranslateMix () { public float getTranslateMix () {
return translateMix; return translateMix;
} }
@ -86,6 +95,7 @@ public class TransformConstraintData {
this.translateMix = translateMix; this.translateMix = translateMix;
} }
/** A percentage (0-1) that controls the mix between the constrained and unconstrained scales. */
public float getScaleMix () { public float getScaleMix () {
return scaleMix; return scaleMix;
} }
@ -94,6 +104,7 @@ public class TransformConstraintData {
this.scaleMix = scaleMix; this.scaleMix = scaleMix;
} }
/** A percentage (0-1) that controls the mix between the constrained and unconstrained shears. */
public float getShearMix () { public float getShearMix () {
return shearMix; return shearMix;
} }
@ -102,6 +113,7 @@ public class TransformConstraintData {
this.shearMix = shearMix; this.shearMix = shearMix;
} }
/** An offset added to the constrained bone rotation. */
public float getOffsetRotation () { public float getOffsetRotation () {
return offsetRotation; return offsetRotation;
} }
@ -110,6 +122,7 @@ public class TransformConstraintData {
this.offsetRotation = offsetRotation; this.offsetRotation = offsetRotation;
} }
/** An offset added to the constrained bone X translation. */
public float getOffsetX () { public float getOffsetX () {
return offsetX; return offsetX;
} }
@ -118,6 +131,7 @@ public class TransformConstraintData {
this.offsetX = offsetX; this.offsetX = offsetX;
} }
/** An offset added to the constrained bone Y translation. */
public float getOffsetY () { public float getOffsetY () {
return offsetY; return offsetY;
} }
@ -126,6 +140,7 @@ public class TransformConstraintData {
this.offsetY = offsetY; this.offsetY = offsetY;
} }
/** An offset added to the constrained bone scaleX. */
public float getOffsetScaleX () { public float getOffsetScaleX () {
return offsetScaleX; return offsetScaleX;
} }
@ -134,6 +149,7 @@ public class TransformConstraintData {
this.offsetScaleX = offsetScaleX; this.offsetScaleX = offsetScaleX;
} }
/** An offset added to the constrained bone scaleY. */
public float getOffsetScaleY () { public float getOffsetScaleY () {
return offsetScaleY; return offsetScaleY;
} }
@ -142,6 +158,7 @@ public class TransformConstraintData {
this.offsetScaleY = offsetScaleY; this.offsetScaleY = offsetScaleY;
} }
/** An offset added to the constrained bone shearY. */
public float getOffsetShearY () { public float getOffsetShearY () {
return offsetShearY; return offsetShearY;
} }

View File

@ -35,6 +35,11 @@ import com.esotericsoftware.spine.Skin;
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;
/** An {@link AttachmentLoader} that configures attachments using texture regions from an {@link Atlas}.
* <p>
* See <a href='http://esotericsoftware.com/spine-loading-skeleton-data#JSON-and-binary-data'>Loading skeleton data</a> in the
* Spine Runtimes Guide. */
@SuppressWarnings("javadoc")
public class AtlasAttachmentLoader implements AttachmentLoader { public class AtlasAttachmentLoader implements AttachmentLoader {
private TextureAtlas atlas; private TextureAtlas atlas;

View File

@ -30,6 +30,7 @@
package com.esotericsoftware.spine.attachments; package com.esotericsoftware.spine.attachments;
/** The base class for all attachments. */
abstract public class Attachment { abstract public class Attachment {
String name; String name;
@ -38,6 +39,7 @@ abstract public class Attachment {
this.name = name; this.name = name;
} }
/** The attachment's name. */
public String getName () { public String getName () {
return name; return name;
} }

View File

@ -32,16 +32,20 @@ package com.esotericsoftware.spine.attachments;
import com.esotericsoftware.spine.Skin; import com.esotericsoftware.spine.Skin;
/** The interface which can be implemented to customize creating and populating attachments.
* <p>
* See <a href='http://esotericsoftware.com/spine-loading-skeleton-data#AttachmentLoader'>Loading skeleton data</a> in the Spine
* Runtimes Guide. */
public interface AttachmentLoader { public interface AttachmentLoader {
/** @return May be null to not load any attachment. */ /** @return May be null to not load the attachment. */
public RegionAttachment newRegionAttachment (Skin skin, String name, String path); public RegionAttachment newRegionAttachment (Skin skin, String name, String path);
/** @return May be null to not load any attachment. */ /** @return May be null to not load the attachment. */
public MeshAttachment newMeshAttachment (Skin skin, String name, String path); public MeshAttachment newMeshAttachment (Skin skin, String name, String path);
/** @return May be null to not load any attachment. */ /** @return May be null to not load the attachment. */
public BoundingBoxAttachment newBoundingBoxAttachment (Skin skin, String name); public BoundingBoxAttachment newBoundingBoxAttachment (Skin skin, String name);
/** @return May be null to not load any attachment. */ /** @return May be null to not load the attachment. */
public PathAttachment newPathAttachment (Skin skin, String name); public PathAttachment newPathAttachment (Skin skin, String name);
} }

View File

@ -31,8 +31,13 @@
package com.esotericsoftware.spine.attachments; package com.esotericsoftware.spine.attachments;
import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.Color;
import com.esotericsoftware.spine.Slot; import com.esotericsoftware.spine.SkeletonBounds;
/** An attachment with vertices that make up a polygon. Can be used for hit detection, creating physics bodies, spawning particle
* effects, and more.
* <p>
* See {@link SkeletonBounds} and <a href="http://esotericsoftware.com/spine-bounding-boxes">Bounding Boxes</a> in the Spine User
* Guide. */
public class BoundingBoxAttachment extends VertexAttachment { public class BoundingBoxAttachment extends VertexAttachment {
// Nonessential. // Nonessential.
final Color color = new Color(0.38f, 0.94f, 0, 1); final Color color = new Color(0.38f, 0.94f, 0, 1);

View File

@ -35,11 +35,15 @@ 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.FloatArray; import com.badlogic.gdx.utils.FloatArray;
import com.badlogic.gdx.utils.NumberUtils; import com.badlogic.gdx.utils.NumberUtils;
import com.esotericsoftware.spine.Animation.DeformTimeline;
import com.esotericsoftware.spine.Bone; import com.esotericsoftware.spine.Bone;
import com.esotericsoftware.spine.Skeleton; import com.esotericsoftware.spine.Skeleton;
import com.esotericsoftware.spine.Slot; import com.esotericsoftware.spine.Slot;
/** Attachment that displays a texture region. */ /** 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.
* <p>
* See <a href="http://esotericsoftware.com/spine-meshes">Mesh attachments</a> in the Spine User Guide. */
public class MeshAttachment extends VertexAttachment { public class MeshAttachment extends VertexAttachment {
private TextureRegion region; private TextureRegion region;
private String path; private String path;
@ -68,6 +72,8 @@ public class MeshAttachment extends VertexAttachment {
return region; return region;
} }
/** Calculates {@link #worldVertices} UVs using {@link #regionUVs} and the {@link #region}. Must be called after changing the
* region UVs or region. */
public void updateUVs () { public void updateUVs () {
float[] regionUVs = this.regionUVs; float[] regionUVs = this.regionUVs;
int verticesLength = regionUVs.length; int verticesLength = regionUVs.length;
@ -160,6 +166,8 @@ public class MeshAttachment extends VertexAttachment {
return worldVertices; return worldVertices;
} }
/** Returns true if the <code>sourceAttachment</code> is this mesh, else returns true if {@link #inheritDeform} is true and the
* the <code>sourceAttachment</code> is the {@link #parentMesh}. */
public boolean applyDeform (VertexAttachment sourceAttachment) { public boolean applyDeform (VertexAttachment sourceAttachment) {
return this == sourceAttachment || (inheritDeform && parentMesh == sourceAttachment); return this == sourceAttachment || (inheritDeform && parentMesh == sourceAttachment);
} }
@ -168,11 +176,11 @@ public class MeshAttachment extends VertexAttachment {
return worldVertices; return worldVertices;
} }
/** Triplets of vertex indices which describe the mesh's triangulation. */
public short[] getTriangles () { public short[] getTriangles () {
return triangles; return triangles;
} }
/** Vertex number triplets which describe the mesh's triangulation. */
public void setTriangles (short[] triangles) { public void setTriangles (short[] triangles) {
this.triangles = triangles; this.triangles = triangles;
} }
@ -186,10 +194,12 @@ public class MeshAttachment extends VertexAttachment {
this.regionUVs = regionUVs; this.regionUVs = regionUVs;
} }
/** The color to tint the mesh. */
public Color getColor () { public Color getColor () {
return color; return color;
} }
/** The name of the texture region for this attachment. */
public String getPath () { public String getPath () {
return path; return path;
} }
@ -198,6 +208,7 @@ public class MeshAttachment extends VertexAttachment {
this.path = path; this.path = path;
} }
/** The number of entries at the beginning of {@link #vertices} that make up the mesh hull. */
public int getHullLength () { public int getHullLength () {
return hullLength; return hullLength;
} }
@ -210,10 +221,13 @@ public class MeshAttachment extends VertexAttachment {
this.edges = edges; this.edges = edges;
} }
/** Vertex index pairs describing edges for controling triangulation. Mesh triangles will never cross edges. Only available if
* nonessential data was exported. Triangulation is not performed at runtime. */
public short[] getEdges () { public short[] getEdges () {
return edges; return edges;
} }
/** The width of the mesh's image. Available only when nonessential data was exported. */
public float getWidth () { public float getWidth () {
return width; return width;
} }
@ -222,6 +236,7 @@ public class MeshAttachment extends VertexAttachment {
this.width = width; this.width = width;
} }
/** The height of the mesh's image. Available only when nonessential data was exported. */
public float getHeight () { public float getHeight () {
return height; return height;
} }
@ -230,7 +245,9 @@ public class MeshAttachment extends VertexAttachment {
this.height = height; this.height = height;
} }
/** Returns the source mesh if this is a linked mesh, else returns null. */ /** 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
* parent mesh, but may have a different {@link #name} or {@link #path} (and therefore a different texture). */
public MeshAttachment getParentMesh () { public MeshAttachment getParentMesh () {
return parentMesh; return parentMesh;
} }
@ -250,6 +267,10 @@ public class MeshAttachment extends VertexAttachment {
} }
} }
/** When this is a linked mesh (see {@link #parentMesh}), if true, any {@link DeformTimeline} for the {@link #parentMesh} is
* also applied to this mesh. If false, this linked mesh may have its own deform timelines.
* <p>
* See {@link #applyDeform(VertexAttachment)}. */
public boolean getInheritDeform () { public boolean getInheritDeform () {
return inheritDeform; return inheritDeform;
} }

View File

@ -31,8 +31,11 @@
package com.esotericsoftware.spine.attachments; package com.esotericsoftware.spine.attachments;
import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.Color;
import com.esotericsoftware.spine.Slot; import com.esotericsoftware.spine.PathConstraint;
/** An attachment whose vertices make up a composite Bezier curve.
* <p>
* See {@link PathConstraint} and <a href="http://esotericsoftware.com/spine-paths">Paths</a> in the Spine User Guide. */
public class PathAttachment extends VertexAttachment { public class PathAttachment extends VertexAttachment {
float[] lengths; float[] lengths;
boolean closed, constantSpeed; boolean closed, constantSpeed;
@ -53,6 +56,8 @@ public class PathAttachment extends VertexAttachment {
this.closed = closed; this.closed = closed;
} }
/** If true, additional calculations are performed to make calculating positions along the path more accurate. If false, fewer
* calculations are performed but calculating positions along the path is less accurate. */
public boolean getConstantSpeed () { public boolean getConstantSpeed () {
return constantSpeed; return constantSpeed;
} }
@ -61,7 +66,7 @@ public class PathAttachment extends VertexAttachment {
this.constantSpeed = constantSpeed; this.constantSpeed = constantSpeed;
} }
/** Returns the length in the setup pose from the start of the path to the end of each curve. */ /** The lengths along the path in the setup pose from the start of the path to the end of each Bezier curve. */
public float[] getLengths () { public float[] getLengths () {
return lengths; return lengths;
} }
@ -70,6 +75,8 @@ public class PathAttachment extends VertexAttachment {
this.lengths = lengths; this.lengths = lengths;
} }
/** The color of the path as it was in Spine. Available only when nonessential data was exported. Paths are not usually
* rendered at runtime. */
public Color getColor () { public Color getColor () {
return color; return color;
} }

View File

@ -30,10 +30,6 @@
package com.esotericsoftware.spine.attachments; package com.esotericsoftware.spine.attachments;
import com.esotericsoftware.spine.Bone;
import com.esotericsoftware.spine.Skeleton;
import com.esotericsoftware.spine.Slot;
import static com.badlogic.gdx.graphics.g2d.Batch.*; import static com.badlogic.gdx.graphics.g2d.Batch.*;
import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.Color;
@ -41,8 +37,13 @@ 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.math.MathUtils; import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.utils.NumberUtils; import com.badlogic.gdx.utils.NumberUtils;
import com.esotericsoftware.spine.Bone;
import com.esotericsoftware.spine.Skeleton;
import com.esotericsoftware.spine.Slot;
/** Attachment that displays a texture region. */ /** An attachment that displays a textured quadrilateral.
* <p>
* See <a href="http://esotericsoftware.com/spine-regions">Region attachments</a> in the Spine User Guide. */
public class RegionAttachment extends Attachment { public class RegionAttachment extends Attachment {
static public final int BLX = 0; static public final int BLX = 0;
static public final int BLY = 1; static public final int BLY = 1;
@ -64,6 +65,7 @@ public class RegionAttachment extends Attachment {
super(name); super(name);
} }
/** Calculates the {@link #offset} using the region settings. Must be called after changing region settings. */
public void updateOffset () { public void updateOffset () {
float width = getWidth(); float width = getWidth();
float height = getHeight(); float height = getHeight();
@ -196,10 +198,14 @@ public class RegionAttachment extends Attachment {
return vertices; return vertices;
} }
/** For each of the 4 vertices, a pair of <code>x,y</code> values that is the local position of the vertex.
* <p>
* See {@link #updateOffset()}. */
public float[] getOffset () { public float[] getOffset () {
return offset; return offset;
} }
/** The local x translation. */
public float getX () { public float getX () {
return x; return x;
} }
@ -208,6 +214,7 @@ public class RegionAttachment extends Attachment {
this.x = x; this.x = x;
} }
/** The local y translation. */
public float getY () { public float getY () {
return y; return y;
} }
@ -216,6 +223,7 @@ public class RegionAttachment extends Attachment {
this.y = y; this.y = y;
} }
/** The local scaleX. */
public float getScaleX () { public float getScaleX () {
return scaleX; return scaleX;
} }
@ -224,6 +232,7 @@ public class RegionAttachment extends Attachment {
this.scaleX = scaleX; this.scaleX = scaleX;
} }
/** The local scaleY. */
public float getScaleY () { public float getScaleY () {
return scaleY; return scaleY;
} }
@ -232,6 +241,7 @@ public class RegionAttachment extends Attachment {
this.scaleY = scaleY; this.scaleY = scaleY;
} }
/** The local rotation. */
public float getRotation () { public float getRotation () {
return rotation; return rotation;
} }
@ -240,6 +250,7 @@ public class RegionAttachment extends Attachment {
this.rotation = rotation; this.rotation = rotation;
} }
/** The width of the region attachment in Spine. */
public float getWidth () { public float getWidth () {
return width; return width;
} }
@ -248,6 +259,7 @@ public class RegionAttachment extends Attachment {
this.width = width; this.width = width;
} }
/** The height of the region attachment in Spine. */
public float getHeight () { public float getHeight () {
return height; return height;
} }
@ -256,10 +268,12 @@ public class RegionAttachment extends Attachment {
this.height = height; this.height = height;
} }
/** The color to tint the region attachment. */
public Color getColor () { public Color getColor () {
return color; return color;
} }
/** The name of the texture region for this attachment. */
public String getPath () { public String getPath () {
return path; return path;
} }

View File

@ -35,7 +35,8 @@ import com.esotericsoftware.spine.Bone;
import com.esotericsoftware.spine.Skeleton; import com.esotericsoftware.spine.Skeleton;
import com.esotericsoftware.spine.Slot; import com.esotericsoftware.spine.Slot;
/** An attachment with vertices that are transformed by one or more bones and can be deformed by a slot's vertices. */ /** Base class for an attachment with vertices that are transformed by one or more bones and can be deformed by a slot's
* {@link Slot#getAttachmentVertices()}. */
public class VertexAttachment extends Attachment { public class VertexAttachment extends Attachment {
int[] bones; int[] bones;
float[] vertices; float[] vertices;
@ -45,11 +46,18 @@ public class VertexAttachment extends Attachment {
super(name); super(name);
} }
protected void computeWorldVertices (Slot slot, float[] worldVertices) { /** Transforms local {@link #getVertices()} to world coordinates, using 0 for <code>start</code> and <code>offset</code>.
* <p>
* See {@link #computeWorldVertices(Slot, int, int, float[], int)}. */
public void computeWorldVertices (Slot slot, float[] worldVertices) {
computeWorldVertices(slot, 0, worldVerticesLength, worldVertices, 0); computeWorldVertices(slot, 0, worldVerticesLength, worldVertices, 0);
} }
/** Transforms local vertices to world coordinates. /** Transforms local {@link #getVertices()} to world coordinates. If the slot has {@link Slot#getAttachmentVertices()}, they
* are used to deform the vertices.
* <p>
* See <a href="http://esotericsoftware.com/spine-skeleton-manipulation#World-transforms">World transforms</a> in the Spine
* Runtimes Guide.
* @param start The index of the first {@link #getVertices()} value to transform. Each vertex has 2 values, x and y. * @param start The index of the first {@link #getVertices()} value to transform. Each vertex has 2 values, x and y.
* @param count The number of world vertex values to output. Must be <= {@link #getWorldVerticesLength()} - <code>start</code>. * @param count The number of world vertex values to output. Must be <= {@link #getWorldVerticesLength()} - <code>start</code>.
* @param worldVertices The output world vertices. Must have a length >= <code>offset</code> + <code>count</code>. * @param worldVertices The output world vertices. Must have a length >= <code>offset</code> + <code>count</code>.
@ -111,32 +119,37 @@ public class VertexAttachment extends Attachment {
} }
} }
/** Returns true if a deform originally applied to the specified attachment should be applied to this attachment. */ /** Returns true if a deform originally applied to the specified attachment should be applied to this attachment. The default
* implementation returns true only when <code>sourceAttachment</code> is this attachment. */
public boolean applyDeform (VertexAttachment sourceAttachment) { public boolean applyDeform (VertexAttachment sourceAttachment) {
return this == sourceAttachment; return this == sourceAttachment;
} }
/** @return May be null if this attachment has no weights. */ /** The bones which affect the {@link #getVertices()}. The array entries are, for each vertex, the number of bones affecting
* the vertex followed by that many bone indices, which is the index of the bone in {@link Skeleton#getBones()}. May be null if
* this attachment has no weights. */
public int[] getBones () { public int[] getBones () {
return bones; return bones;
} }
/** For each vertex, the number of bones affecting the vertex followed by that many bone indices. Ie: count, boneIndex, ... /** @param bones May be null if this attachment has no weights. */
* @param bones May be null if this attachment has no weights. */
public void setBones (int[] bones) { public void setBones (int[] bones) {
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>
* entries for each vertex. For a weighted attachment, the values are <code>x,y,weight</code> entries for each bone affecting
* each vertex. */
public float[] getVertices () { public float[] getVertices () {
return vertices; return vertices;
} }
/** Sets the vertex position in the bone's coordinate system. For a non-weighted attachment, the values are x,y entries for
* each vertex. For a weighted attachment, the values are x,y,weight entries for each bone affecting each vertex. */
public void setVertices (float[] vertices) { public void setVertices (float[] vertices) {
this.vertices = vertices; this.vertices = vertices;
} }
/** The maximum length required of the <code>worldVertices</code> passed to
* {@link #computeWorldVertices(Slot, int, int, float[], int)}. */
public int getWorldVerticesLength () { public int getWorldVerticesLength () {
return worldVerticesLength; return worldVerticesLength;
} }