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.VertexAttachment;
/** A simple container for a list of timelines and a name. */
public class Animation {
final String name;
final Array<Timeline> timelines;
@ -54,7 +55,7 @@ public class Animation {
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 () {
return duration;
}
@ -64,7 +65,8 @@ public class Animation {
}
/** 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,
boolean setupPose, boolean mixingOut) {
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);
}
/** The animation's name, which is unique within the skeleton. */
public String getName () {
return name;
}
@ -127,17 +130,32 @@ public class Animation {
return -1;
}
/** The interface for all timelines. */
static public interface Timeline {
/** Sets the value(s) for the specified time.
* @param events May be null to not collect fired events.
* @param setupPose True when the timeline is mixed with the setup pose, false when it is mixed with the current pose.
* Passing true when alpha is 1 is slightly more efficient for most timelines.
* @param mixingOut True when changing alpha over time toward 0 (the setup or current pose), false when changing alpha
* toward 1 (the timeline's pose). Used for timelines with instant transitions, eg draw order, attachment
* visibility, scale sign. */
/** Applies this timeline to the skeleton.
* @param skeleton The skeleton the timeline is being applied to. This provides access to the bones, slots, and other
* skeleton components the timeline may change.
* @param lastTime The time this timeline was last applied. Timelines such as {@link EventTimeline} trigger only at specific
* times rather than every frame. In that case, the timeline triggers everything between <code>lastTime</code>
* (exclusive) and <code>time</code> (inclusive).
* @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,
boolean mixingOut);
/** Uniquely encodes both the type of this timeline and the skeleton property that it affects. */
public int getPropertyId ();
}
@ -149,7 +167,7 @@ public class Animation {
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 {
static public final float LINEAR = 0, STEPPED = 1, BEZIER = 2;
static private final int BEZIER_SIZE = 10 * 2 - 1;
@ -161,18 +179,23 @@ public class Animation {
curves = new float[(frameCount - 1) * BEZIER_SIZE];
}
/** The number of key frames for this timeline. */
public int getFrameCount () {
return curves.length / BEZIER_SIZE + 1;
}
/** Sets the specified key frame to linear interpolation. */
public void setLinear (int frameIndex) {
curves[frameIndex * BEZIER_SIZE] = LINEAR;
}
/** Sets the specified key frame to stepped interpolation. */
public void setStepped (int frameIndex) {
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) {
int index = frameIndex * BEZIER_SIZE;
if (index == curves.length) return LINEAR;
@ -182,9 +205,9 @@ public class Animation {
return BEZIER;
}
/** Sets the control handle positions for an interpolation bezier curve used to transition from this keyframe to the next.
* cx1 and cx2 are from 0 to 1, representing the percent of time between the two keyframes. cy1 and cy2 are the percent of
* the difference between the keyframe's values. */
/** Sets the specified key frame to Bezier interpolation. <code>cx1</code> and <code>cx2</code> are from 0 to 1,
* representing the percent of time between the two key frames. <code>cy1</code> and <code>cy2</code> are the percent of the
* difference between the key frame's values. */
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 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) {
percent = MathUtils.clamp(percent, 0, 1);
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 final int ENTRIES = 2;
static final int PREV_TIME = -2, PREV_ROTATION = -1;
@ -258,15 +283,17 @@ public class Animation {
this.boneIndex = index;
}
/** The index of the bone in {@link Skeleton#getBones()} that will be changed. */
public int getBoneIndex () {
return boneIndex;
}
/** The time in seconds and rotation in degrees for each key frame. */
public float[] getFrames () {
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) {
frameIndex <<= 1;
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 final int ENTRIES = 3;
static final int PREV_TIME = -3, PREV_X = -2, PREV_Y = -1;
@ -333,15 +361,17 @@ public class Animation {
this.boneIndex = index;
}
/** The index of the bone in {@link Skeleton#getBones()} that will be changed. */
public int getBoneIndex () {
return boneIndex;
}
/** The time in seconds, x, and y values for each key frame. */
public float[] getFrames () {
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) {
frameIndex *= ENTRIES;
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 {
public ScaleTimeline (int 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 {
public ShearTimeline (int 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 final int ENTRIES = 5;
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;
}
/** The index of the slot in {@link Skeleton#getSlots()} that will be changed. */
public int getSlotIndex () {
return slotIndex;
}
/** The time in seconds, red, green, blue, and alpha values for each key frame. */
public float[] getFrames () {
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) {
frameIndex *= ENTRIES;
frames[frameIndex] = time;
@ -561,6 +596,7 @@ public class Animation {
}
}
/** Changes a slot's {@link Slot#getAttachment()}. */
static public class AttachmentTimeline implements Timeline {
int slotIndex;
final float[] frames; // time, ...
@ -575,6 +611,7 @@ public class Animation {
return (TimelineType.attachment.ordinal() << 24) + slotIndex;
}
/** The number of key frames for this timeline. */
public int getFrameCount () {
return frames.length;
}
@ -584,19 +621,22 @@ public class Animation {
this.slotIndex = index;
}
/** The index of the slot in {@link Skeleton#getSlots()} that will be changed. */
public int getSlotIndex () {
return slotIndex;
}
/** The time in seconds for each key frame. */
public float[] getFrames () {
return frames;
}
/** The attachment name for each key frame. May contain null values to clear the attachment. */
public String[] getAttachmentNames () {
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) {
frames[frameIndex] = time;
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 {
int slotIndex;
VertexAttachment attachment;
@ -647,6 +688,7 @@ public class Animation {
this.slotIndex = index;
}
/** The index of the slot in {@link Skeleton#getSlots()} that will be changed. */
public int getSlotIndex () {
return slotIndex;
}
@ -655,19 +697,23 @@ public class Animation {
this.attachment = attachment;
}
/** The attachment that will be deformed. */
public VertexAttachment getAttachment () {
return attachment;
}
/** The time in seconds for each key frame. */
public float[] getFrames () {
return frames;
}
/** The vertices for each key frame. */
public float[][] getVertices () {
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) {
frames[frameIndex] = time;
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 {
private final float[] frames; // time, ...
private final Event[] events;
@ -768,25 +815,28 @@ public class Animation {
return TimelineType.event.ordinal() << 24;
}
/** The number of key frames for this timeline. */
public int getFrameCount () {
return frames.length;
}
/** The time in seconds for each key frame. */
public float[] getFrames () {
return frames;
}
/** The event for each key frame. */
public Event[] getEvents () {
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) {
frames[frameIndex] = event.time;
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,
boolean mixingOut) {
if (firedEvents == null) return;
@ -816,6 +866,7 @@ public class Animation {
}
}
/** Changes a skeleton's {@link Skeleton#getDrawOrder()}. */
static public class DrawOrderTimeline implements Timeline {
private final float[] frames; // time, ...
private final int[][] drawOrders;
@ -829,20 +880,24 @@ public class Animation {
return TimelineType.drawOrder.ordinal() << 24;
}
/** The number of key frames for this timeline. */
public int getFrameCount () {
return frames.length;
}
/** The time in seconds for each key frame. */
public float[] getFrames () {
return frames;
}
/** The draw order for each key frame. See {@link #setFrame(int, float, int[])}. */
public int[][] getDrawOrders () {
return drawOrders;
}
/** Sets the time of the specified keyframe.
* @param drawOrder May be null to use bind pose draw order. */
/** Sets the time in seconds and the draw order for the specified key frame.
* @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) {
frames[frameIndex] = time;
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 final int ENTRIES = 3;
static private final int PREV_TIME = -3, PREV_MIX = -2, PREV_BEND_DIRECTION = -1;
@ -898,15 +954,17 @@ public class Animation {
this.ikConstraintIndex = index;
}
/** The index of the IK constraint slot in {@link Skeleton#getIkConstraints()} that will be changed. */
public int getIkConstraintIndex () {
return ikConstraintIndex;
}
/** The time in seconds, mix, and bend direction for each key frame. */
public float[] getFrames () {
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) {
frameIndex *= ENTRIES;
frames[frameIndex] = time;
@ -949,6 +1007,7 @@ public class Animation {
}
}
/** Changes a transform constraint's mixes. */
static public class TransformConstraintTimeline extends CurveTimeline {
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;
@ -971,15 +1030,17 @@ public class Animation {
this.transformConstraintIndex = index;
}
/** The index of the transform constraint slot in {@link Skeleton#getTransformConstraints()} that will be changed. */
public int getTransformConstraintIndex () {
return transformConstraintIndex;
}
/** The time in seconds, rotate mix, translate mix, scale mix, and shear mix for each key frame. */
public float[] getFrames () {
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) {
frameIndex *= ENTRIES;
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 final int ENTRIES = 2;
static final int PREV_TIME = -2, PREV_VALUE = -1;
@ -1057,19 +1119,21 @@ public class Animation {
this.pathConstraintIndex = index;
}
/** The index of the path constraint slot in {@link Skeleton#getPathConstraints()} that will be changed. */
public int getPathConstraintIndex () {
return pathConstraintIndex;
}
/** The time in seconds and path constraint position for each key frame. */
public float[] getFrames () {
return frames;
}
/** Sets the time and value of the specified keyframe. */
public void setFrame (int frameIndex, float time, float value) {
/** Sets the time in seconds and path constraint position for the specified key frame. */
public void setFrame (int frameIndex, float time, float position) {
frameIndex *= ENTRIES;
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,
@ -1099,6 +1163,7 @@ public class Animation {
}
}
/** Changes a path constraint's {@link PathConstraint#getSpacing()}. */
static public class PathConstraintSpacingTimeline extends PathConstraintPositionTimeline {
public PathConstraintSpacingTimeline (int frameCount) {
super(frameCount);
@ -1136,6 +1201,7 @@ public class Animation {
}
}
/** Changes a path constraint's mixes. */
static public class PathConstraintMixTimeline extends CurveTimeline {
static public final int ENTRIES = 3;
static private final int PREV_TIME = -3, PREV_ROTATE = -2, PREV_TRANSLATE = -1;
@ -1159,15 +1225,17 @@ public class Animation {
this.pathConstraintIndex = index;
}
/** The index of the path constraint slot in {@link Skeleton#getPathConstraints()} that will be changed. */
public int getPathConstraintIndex () {
return pathConstraintIndex;
}
/** The time in seconds, rotate mix, and translate mix for each key frame. */
public float[] getFrames () {
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) {
frameIndex *= ENTRIES;
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.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>
* Animations on different tracks are applied sequentially each frame, from lowest to highest track index. This enables animations
* 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. */
* See <a href='http://esotericsoftware.com/spine-applying-animations/'>Applying Animations</a> in the Spine Runtimes Guide. */
public class AnimationState {
static private final Animation emptyAnimation = new Animation("<empty>", new Array(0), 0);
@ -75,7 +74,7 @@ public class AnimationState {
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) {
delta *= timeScale;
for (int i = 0, n = tracks.size; i < n; i++) {
@ -337,10 +336,10 @@ public class AnimationState {
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>
* 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 () {
queue.drainDisabled = true;
for (int i = 0, n = tracks.size; i < n; i++)
@ -350,10 +349,10 @@ public class AnimationState {
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>
* 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) {
if (trackIndex >= tracks.size) return;
TrackEntry current = tracks.get(trackIndex);
@ -395,7 +394,9 @@ public class AnimationState {
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) {
Animation animation = data.skeletonData.findAnimation(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.
* @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
* after {@link AnimationStateListener#dispose(TrackEntry)}. */
* after the {@link AnimationStateListener#dispose(TrackEntry)} event occurs. */
public TrackEntry setAnimation (int trackIndex, Animation animation, boolean loop) {
if (animation == null) throw new IllegalArgumentException("animation cannot be null.");
TrackEntry current = expandToIndex(trackIndex);
@ -425,18 +428,21 @@ public class AnimationState {
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) {
Animation animation = data.skeletonData.findAnimation(animationName);
if (animation == null) throw new IllegalArgumentException("Animation not found: " + animationName);
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
* 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
* after {@link AnimationStateListener#dispose(TrackEntry)}. */
* after the {@link AnimationStateListener#dispose(TrackEntry)} event occurs. */
public TrackEntry addAnimation (int trackIndex, Animation animation, boolean loop, float delay) {
if (animation == null) throw new IllegalArgumentException("animation cannot be null.");
@ -466,7 +472,13 @@ public class AnimationState {
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) {
TrackEntry entry = setAnimation(trackIndex, emptyAnimation, false);
entry.mixDuration = mixDuration;
@ -474,12 +486,13 @@ public class AnimationState {
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
* specified mix duration.
/** Adds an empty animation to be played after the current or last queued animation for a track, and sets the track entry's
* {@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
* 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
* after {@link AnimationStateListener#dispose(TrackEntry)}. */
* after the {@link AnimationStateListener#dispose(TrackEntry)} event occurs. */
public TrackEntry addEmptyAnimation (int trackIndex, float mixDuration, float delay) {
if (delay <= 0) delay -= mixDuration;
TrackEntry entry = addAnimation(trackIndex, emptyAnimation, false, delay);
@ -598,7 +611,7 @@ public class AnimationState {
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) {
if (trackIndex >= tracks.size) return null;
return tracks.get(trackIndex);
@ -615,19 +628,22 @@ public class AnimationState {
listeners.removeValue(listener, true);
}
/** Removes all listeners added with {@link #addListener(AnimationStateListener)}. */
public void clearListeners () {
listeners.clear();
}
/** Discards all {@link #addListener(AnimationStateListener) listener} notifications that have not yet been delivered. This can
* be useful to call from an {@link AnimationStateListener} when it is known that further notifications that may have been
* already queued for delivery are not wanted because new animations are being set. */
/** Discards all listener notifications that have not yet been delivered. This can be useful to call from an
* {@link AnimationStateListener} when it is known that further notifications that may have been already queued for delivery
* are not wanted because new animations are being set. */
public void clearListenerNotifications () {
queue.clear();
}
/** 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 () {
return timeScale;
}
@ -636,6 +652,7 @@ public class AnimationState {
this.timeScale = timeScale;
}
/** The AnimationStateData to look up mix durations. */
public AnimationStateData getData () {
return data;
}
@ -645,7 +662,7 @@ public class AnimationState {
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 () {
return tracks;
}
@ -662,7 +679,9 @@ public class AnimationState {
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 {
Animation animation;
TrackEntry next, mixingFrom;
@ -685,10 +704,14 @@ public class AnimationState {
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 () {
return trackIndex;
}
/** The animation to apply for this track entry. */
public Animation getAnimation () {
return animation;
}
@ -697,6 +720,8 @@ public class AnimationState {
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 () {
return loop;
}
@ -705,9 +730,9 @@ public class AnimationState {
this.loop = loop;
}
/** Seconds to postpone playing the animation. When a track entry is the current track entry, delay postpones incrementing
* the track time. When a track entry is queued, delay is the time from the start of the previous animation to when the
* track entry will become the current track entry. */
/** Seconds to postpone playing the animation. When a track entry is the current track entry, <code>delay</code> postpones
* incrementing the {@link #getTrackTime()}. When a track entry is queued, <code>delay</code> is the time from the start of
* the previous animation to when the track entry will become the current track entry. */
public float getDelay () {
return delay;
}
@ -727,13 +752,13 @@ public class AnimationState {
this.trackTime = trackTime;
}
/** The track time in seconds when this animation will be removed from the track. Defaults to the animation duration for
* non-looping animations and to {@link Integer#MAX_VALUE} for looping animations. If the track end time is reached, no
* other animations are queued for playback, and mixing from any previous animations is complete, then the track is cleared,
* leaving skeletons in their last pose.
/** The track time in seconds when this animation will be removed from the track. Defaults to the animation
* {@link Animation#duration} for non-looping animations and the highest float possible for looping animations. If the track
* end time is reached, no other animations are queued for playback, and mixing from any previous animations is complete,
* then the track is cleared, leaving skeletons in their previous pose.
* <p>
* 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 () {
return trackEnd;
}
@ -744,8 +769,8 @@ public class AnimationState {
/** Seconds when this animation starts, both initially and after looping. Defaults to 0.
* <p>
* When changing the animation start time, it often makes sense to set {@link #getAnimationLast()} to the same value to
* prevent timeline keys before the start time from triggering. */
* When changing the <code>animationStart</code> time, it often makes sense to set {@link #getAnimationLast()} to the same
* value to prevent timeline keys before the start time from triggering. */
public float getAnimationStart () {
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
* 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 () {
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
* animation is applied, event timelines will fire all events between the animation last time (exclusive) and animation time
* (inclusive). Defaults to -1 to ensure triggers on frame 0 happen the first time this animation is applied. */
* animation is applied, event timelines will fire all events between the <code>animationLast</code> time (exclusive) and
* <code>animationTime</code> (inclusive). Defaults to -1 to ensure triggers on frame 0 happen the first time this animation
* is applied. */
public float getAnimationLast () {
return animationLast;
}
@ -776,8 +802,9 @@ public class AnimationState {
nextAnimationLast = animationLast;
}
/** Uses {@link #getTrackTime()} to compute the animation time between {@link #getAnimationStart()} and
* {@link #getAnimationEnd()}. When the track time is 0, the animation time is equal to the animation start time. */
/** Uses {@link #getTrackTime()} to compute the <code>animationTime</code>, which is between {@link #getAnimationStart()}
* 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 () {
if (loop) {
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
* faster. Defaults to 1. */
* faster. Defaults to 1.
* <p>
* See AnimationState {@link AnimationState#getTimeScale()} for affecting all animations. */
public float getTimeScale () {
return timeScale;
}
@ -807,8 +836,8 @@ public class AnimationState {
this.listener = listener;
}
/** Values < 1 mix this animation with the setup pose or the skeleton's last pose. Defaults to 1, which overwrites the
* skeleton's last pose with this animation.
/** Values < 1 mix this animation with the setup pose or the skeleton's previous pose. Defaults to 1, which overwrites the
* skeleton's previous pose with this animation.
* <p>
* 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. */
@ -820,8 +849,9 @@ public class AnimationState {
this.alpha = alpha;
}
/** When the mix percentage (mix time / mix duration) is less than the event threshold, 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. */
/** When the mix percentage ({@link #getMixTime()} / {@link #getMixDuration()}) is less than the
* <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 () {
return eventThreshold;
}
@ -830,9 +860,9 @@ public class AnimationState {
this.eventThreshold = eventThreshold;
}
/** When the mix percentage (mix time / mix duration) is less than the attachment threshold, attachment timelines for the
* animation being mixed out will be applied. Defaults to 0, so attachment timelines are not applied for an animation being
* mixed out. */
/** When the mix percentage ({@link #getMixTime()} / {@link #getMixDuration()}) is less than the
* <code>attachmentThreshold</code>, attachment timelines for the animation being mixed out will be applied. Defaults to 0,
* so attachment timelines are not applied for an animation being mixed out. */
public float getAttachmentThreshold () {
return attachmentThreshold;
}
@ -841,9 +871,9 @@ public class AnimationState {
this.attachmentThreshold = attachmentThreshold;
}
/** When the mix percentage (mix time / mix duration) is less than the draw order threshold, draw order timelines for the
* animation being mixed out will be applied. Defaults to 0, so draw order timelines are not applied for an animation being
* mixed out. */
/** When the mix percentage ({@link #getMixTime()} / {@link #getMixDuration()}) is less than the
* <code>drawOrderThreshold</code>, draw order timelines for the animation being mixed out will be applied. Defaults to 0,
* so draw order timelines are not applied for an animation being mixed out. */
public float getDrawOrderThreshold () {
return drawOrderThreshold;
}
@ -852,19 +882,21 @@ public class AnimationState {
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 () {
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 () {
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
* {@link #getMixDuration()} when the mix is complete. The mix time can be set manually rather than use the value from
* AnimationStateData. */
/** Seconds from 0 to the {@link #getMixDuration()} when mixing from the previous animation to this animation. May be
* slightly more than <code>mixDuration</code> when the mix is complete. The mix time can be set manually rather than use
* the value from AnimationStateData {@link AnimationStateData#getMix(Animation, Animation)}. */
public float getMixTime () {
return mixTime;
}
@ -873,10 +905,11 @@ public class AnimationState {
this.mixTime = mixTime;
}
/** Seconds for mixing from the previous animation to this animation. Defaults to the value provided by
* {@link AnimationStateData} based on the animation before this animation (if any).
/** Seconds for mixing from the previous animation to this animation. Defaults to the value provided by AnimationStateData
* {@link AnimationStateData#getMix(Animation, Animation)} based on the animation before this animation (if any).
* <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 () {
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
* 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 () {
return mixingFrom;
}
@ -1003,7 +1036,7 @@ public class AnimationState {
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.
* 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);
/** Invoked every time this entry's animation completes a loop. */

View File

@ -31,10 +31,11 @@
package com.esotericsoftware.spine;
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 {
private final SkeletonData skeletonData;
final SkeletonData skeletonData;
final ObjectFloatMap<Key> animationToMixTime = new ObjectFloatMap();
final Key tempKey = new Key();
float defaultMix;
@ -44,10 +45,14 @@ public class AnimationStateData {
this.skeletonData = skeletonData;
}
/** The SkeletonData to look up animations when they are specified by name. */
public SkeletonData getSkeletonData () {
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) {
Animation from = skeletonData.findAnimation(fromName);
if (from == null) throw new IllegalArgumentException("Animation not found: " + fromName);
@ -56,6 +61,9 @@ public class AnimationStateData {
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) {
if (from == null) throw new IllegalArgumentException("from cannot be null.");
if (to == null) throw new IllegalArgumentException("to cannot be null.");
@ -65,6 +73,8 @@ public class AnimationStateData {
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) {
if (from == null) throw new IllegalArgumentException("from 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);
}
/** The mix duration to use when no mix duration has been defined between two animations. */
public float getDefaultMix () {
return defaultMix;
}

View File

@ -32,6 +32,7 @@ package com.esotericsoftware.spine;
import com.badlogic.gdx.graphics.GL20;
/** Determines how images are blended with existing pixels when drawn. */
public enum BlendMode {
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), //

View File

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

View File

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

View File

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

View File

@ -30,6 +30,14 @@
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 {
final private EventData data;
int intValue;
@ -67,10 +75,12 @@ public class Event {
this.stringValue = stringValue;
}
/** The animation time this event was keyed. */
public float getTime () {
return time;
}
/** The events's setup pose data. */
public EventData getData () {
return data;
}

View File

@ -30,6 +30,9 @@
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 {
final String name;
int intValue;
@ -65,6 +68,7 @@ public class EventData {
this.stringValue = stringValue;
}
/** The name of the event, which is unique within the skeleton. */
public String getName () {
return name;
}

View File

@ -34,6 +34,10 @@ import static com.badlogic.gdx.math.MathUtils.*;
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 {
final IkConstraintData data;
final Array<Bone> bones;
@ -67,6 +71,7 @@ public class IkConstraint implements Constraint {
bendDirection = constraint.bendDirection;
}
/** Applies the constraint to the constrained bones. */
public void apply () {
update();
}
@ -88,10 +93,12 @@ public class IkConstraint implements Constraint {
return data.order;
}
/** The bones that will be modified by this IK constraint. */
public Array<Bone> getBones () {
return bones;
}
/** The bone that is the IK target. */
public Bone getTarget () {
return target;
}
@ -100,6 +107,7 @@ public class IkConstraint implements Constraint {
this.target = target;
}
/** A percentage (0-1) that controls the mix between the constrained and unconstrained rotations. */
public float getMix () {
return mix;
}
@ -108,6 +116,7 @@ public class IkConstraint implements Constraint {
this.mix = mix;
}
/** Controls the bend direction of the IK bones, either 1 or -1. */
public int getBendDirection () {
return bendDirection;
}
@ -116,6 +125,7 @@ public class IkConstraint implements Constraint {
this.bendDirection = bendDirection;
}
/** The IK constraint's setup pose data. */
public IkConstraintData getData () {
return data;
}
@ -124,8 +134,7 @@ public class IkConstraint implements Constraint {
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
* coordinate system. */
/** Applies 1 bone IK. The target is specified in the world coordinate system. */
static public void apply (Bone bone, float targetX, float targetY, float alpha) {
if (!bone.appliedValid) bone.updateAppliedTransform();
Bone p = bone.parent;
@ -141,8 +150,7 @@ public class IkConstraint implements Constraint {
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
* target is specified in the world coordinate system.
/** Applies 2 bone IK. The target is specified in the world coordinate system.
* @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) {
if (alpha == 0) {

View File

@ -32,6 +32,9 @@ package com.esotericsoftware.spine;
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 {
final String name;
int order;
@ -45,10 +48,12 @@ public class IkConstraintData {
this.name = name;
}
/** The IK constraint's name, which is unique within the skeleton. */
public String getName () {
return name;
}
/** See {@link Constraint#getOrder()}. */
public int getOrder () {
return order;
}
@ -57,10 +62,12 @@ public class IkConstraintData {
this.order = order;
}
/** The bones that are constrained by this IK constraint. */
public Array<BoneData> getBones () {
return bones;
}
/** The bone that is the IK target. */
public BoneData getTarget () {
return target;
}
@ -70,6 +77,7 @@ public class IkConstraintData {
this.target = target;
}
/** Controls the bend direction of the IK bones, either 1 or -1. */
public int getBendDirection () {
return bendDirection;
}
@ -78,6 +86,7 @@ public class IkConstraintData {
this.bendDirection = bendDirection;
}
/** A percentage (0-1) that controls the mix between the constrained and unconstrained rotations. */
public float getMix () {
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.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 {
static private final int NONE = -1, BEFORE = -2, AFTER = -3;
@ -81,6 +85,7 @@ public class PathConstraint implements Constraint {
translateMix = constraint.translateMix;
}
/** Applies the constraint to the constrained bones. */
public void apply () {
update();
}
@ -414,6 +419,7 @@ public class PathConstraint implements Constraint {
return data.order;
}
/** The position along the path. */
public float getPosition () {
return position;
}
@ -422,6 +428,7 @@ public class PathConstraint implements Constraint {
this.position = position;
}
/** The spacing between bones. */
public float getSpacing () {
return spacing;
}
@ -430,6 +437,7 @@ public class PathConstraint implements Constraint {
this.spacing = spacing;
}
/** A percentage (0-1) that controls the mix between the constrained and unconstrained rotations. */
public float getRotateMix () {
return rotateMix;
}
@ -438,6 +446,7 @@ public class PathConstraint implements Constraint {
this.rotateMix = rotateMix;
}
/** A percentage (0-1) that controls the mix between the constrained and unconstrained translations. */
public float getTranslateMix () {
return translateMix;
}
@ -446,10 +455,12 @@ public class PathConstraint implements Constraint {
this.translateMix = translateMix;
}
/** The bones that will be modified by this path constraint. */
public Array<Bone> getBones () {
return bones;
}
/** The slot whose path attachment will be used to constrained the bones. */
public Slot getTarget () {
return target;
}
@ -458,6 +469,7 @@ public class PathConstraint implements Constraint {
this.target = target;
}
/** The path constraint's setup pose data. */
public PathConstraintData getData () {
return data;
}

View File

@ -32,6 +32,9 @@ package com.esotericsoftware.spine;
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 {
final String name;
int order;
@ -48,10 +51,12 @@ public class PathConstraintData {
this.name = name;
}
/** The path constraint's name, which is unique within the skeleton. */
public String getName () {
return name;
}
/** See {@link Constraint#getOrder()}. */
public int getOrder () {
return order;
}
@ -60,10 +65,12 @@ public class PathConstraintData {
this.order = order;
}
/** The bones that will be modified by this path constraint. */
public Array<BoneData> getBones () {
return bones;
}
/** The slot whose path attachment will be used to constrained the bones. */
public SlotData getTarget () {
return target;
}
@ -72,6 +79,7 @@ public class PathConstraintData {
this.target = target;
}
/** The mode for positioning the first bone on the path. */
public PositionMode getPositionMode () {
return positionMode;
}
@ -80,6 +88,7 @@ public class PathConstraintData {
this.positionMode = positionMode;
}
/** The mode for positioning the bones after the first bone on the path. */
public SpacingMode getSpacingMode () {
return spacingMode;
}
@ -88,6 +97,7 @@ public class PathConstraintData {
this.spacingMode = spacingMode;
}
/** The mode for adjusting the rotation of the bones. */
public RotateMode getRotateMode () {
return rotateMode;
}
@ -96,6 +106,7 @@ public class PathConstraintData {
this.rotateMode = rotateMode;
}
/** An offset added to the constrained bone rotation. */
public float getOffsetRotation () {
return offsetRotation;
}
@ -104,6 +115,7 @@ public class PathConstraintData {
this.offsetRotation = offsetRotation;
}
/** The position along the path. */
public float getPosition () {
return position;
}
@ -112,6 +124,7 @@ public class PathConstraintData {
this.position = position;
}
/** The spacing between bones. */
public float getSpacing () {
return spacing;
}
@ -120,6 +133,7 @@ public class PathConstraintData {
this.spacing = spacing;
}
/** A percentage (0-1) that controls the mix between the constrained and unconstrained rotations. */
public float getRotateMix () {
return rotateMix;
}
@ -128,6 +142,7 @@ public class PathConstraintData {
this.rotateMix = rotateMix;
}
/** A percentage (0-1) that controls the mix between the constrained and unconstrained translations. */
public float getTranslateMix () {
return translateMix;
}
@ -140,18 +155,27 @@ public class PathConstraintData {
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 {
fixed, percent;
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 {
length, fixed, percent;
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 {
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.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 {
final SkeletonData data;
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 () {
// 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
@ -312,7 +319,7 @@ public class Skeleton {
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 () {
setBonesToSetupPose();
setSlotsToSetupPose();
@ -352,6 +359,7 @@ public class Skeleton {
}
}
/** Sets the slots and draw order to their setup pose values. */
public void setSlotsToSetupPose () {
Array<Slot> slots = this.slots;
System.arraycopy(slots.items, 0, drawOrder.items, 0, slots.size);
@ -359,10 +367,12 @@ public class Skeleton {
slots.get(i).setToSetupPose();
}
/** The skeleton's setup pose data. */
public SkeletonData getData () {
return data;
}
/** The skeleton's bones, sorted parent first. The root bone is always the first bone. */
public Array<Bone> getBones () {
return bones;
}
@ -371,13 +381,15 @@ public class Skeleton {
return updateCache;
}
/** @return May return null. */
/** Returns the root bone, or null. */
public Bone getRootBone () {
if (bones.size == 0) return null;
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) {
if (boneName == null) throw new IllegalArgumentException("boneName cannot be null.");
Array<Bone> bones = this.bones;
@ -388,11 +400,14 @@ public class Skeleton {
return null;
}
/** The skeleton's slots. */
public Array<Slot> getSlots () {
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) {
if (slotName == null) throw new IllegalArgumentException("slotName cannot be null.");
Array<Slot> slots = this.slots;
@ -403,24 +418,25 @@ public class Skeleton {
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 () {
return drawOrder;
}
/** Sets the slots and the order they will be drawn. */
public void setDrawOrder (Array<Slot> drawOrder) {
if (drawOrder == null) throw new IllegalArgumentException("drawOrder cannot be null.");
this.drawOrder = drawOrder;
}
/** @return May be null. */
/** The skeleton's current skin.
* @return May be null. */
public Skin getSkin () {
return skin;
}
/** Sets a skin by name.
* @see #setSkin(Skin) */
* <p>
* See {@link #setSkin(Skin)}. */
public void setSkin (String skinName) {
Skin skin = data.findSkin(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}.
* <p>
* 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.
* @param newSkin May be null. */
@ -450,14 +467,22 @@ public class Skeleton {
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) {
SlotData slot = data.findSlot(slotName);
if (slot == null) throw new IllegalArgumentException("Slot not found: " + slotName);
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) {
if (attachmentName == null) throw new IllegalArgumentException("attachmentName cannot be null.");
if (skin != null) {
@ -468,8 +493,8 @@ public class Skeleton {
return null;
}
/** Sets 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}.
/** A convenience method to set an attachment by finding the slot with {@link #findSlot(String)}, finding the attachment with
* {@link #getAttachment(int, String)}, then setting the slot's {@link Slot#attachment}.
* @param attachmentName May be null to clear the slot. */
public void setAttachment (String slotName, String attachmentName) {
if (slotName == null) throw new IllegalArgumentException("slotName cannot be null.");
@ -484,11 +509,14 @@ public class Skeleton {
slot.setAttachment(attachment);
}
/** The skeleton's IK constraints. */
public Array<IkConstraint> getIkConstraints () {
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) {
if (constraintName == null) throw new IllegalArgumentException("constraintName cannot be null.");
Array<IkConstraint> ikConstraints = this.ikConstraints;
@ -499,11 +527,14 @@ public class Skeleton {
return null;
}
/** The skeleton's transform constraints. */
public Array<TransformConstraint> getTransformConstraints () {
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) {
if (constraintName == null) throw new IllegalArgumentException("constraintName cannot be null.");
Array<TransformConstraint> transformConstraints = this.transformConstraints;
@ -514,11 +545,14 @@ public class Skeleton {
return null;
}
/** The skeleton's path constraints. */
public Array<PathConstraint> getPathConstraints () {
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) {
if (constraintName == null) throw new IllegalArgumentException("constraintName cannot be null.");
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.
* @param offset The distance from the skeleton origin to the bottom left corner of the AABB.
* @param size The width and height of the AABB. */
* @param offset An output value, the distance from the skeleton origin to the bottom left corner of the AABB.
* @param size An output value, the width and height of the AABB. */
public void getBounds (Vector2 offset, Vector2 size) {
if (offset == null) throw new IllegalArgumentException("offset 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);
}
/** The color to tint all the skeleton's attachments. */
public Color getColor () {
return color;
}
@ -569,6 +604,8 @@ public class Skeleton {
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 () {
return flipX;
}
@ -577,6 +614,8 @@ public class Skeleton {
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 () {
return flipY;
}
@ -590,6 +629,7 @@ public class Skeleton {
this.flipY = flipY;
}
/** Sets the skeleton X position, which is added to the root bone worldX position. */
public float getX () {
return x;
}
@ -598,6 +638,7 @@ public class Skeleton {
this.x = x;
}
/** Sets the skeleton Y position, which is added to the root bone worldY position. */
public float getY () {
return y;
}
@ -611,6 +652,9 @@ public class Skeleton {
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 () {
return time;
}
@ -619,6 +663,7 @@ public class Skeleton {
this.time = time;
}
/** Increments the skeleton's {@link #time}. */
public void update (float 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.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 {
static public final int BONE_ROTATE = 0;
static public final int BONE_TRANSLATE = 1;
@ -104,11 +109,14 @@ public class SkeletonBinary {
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 () {
return scale;
}
/** Scales the bones, images, and animations as they are loaded. */
public void setScale (float scale) {
this.scale = scale;
}

View File

@ -30,13 +30,14 @@
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.FloatArray;
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 {
private float minX, minY, maxX, maxY;
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) {
if (skeleton == null) throw new IllegalArgumentException("skeleton cannot be null.");
Array<BoundingBoxAttachment> boundingBoxes = this.boundingBoxes;
@ -194,34 +199,42 @@ public class SkeletonBounds {
return false;
}
/** The left edge of the axis aligned bounding box. */
public float getMinX () {
return minX;
}
/** The bottom edge of the axis aligned bounding box. */
public float getMinY () {
return minY;
}
/** The right edge of the axis aligned bounding box. */
public float getMaxX () {
return maxX;
}
/** The top edge of the axis aligned bounding box. */
public float getMaxY () {
return maxY;
}
/** The width of the axis aligned bounding box. */
public float getWidth () {
return maxX - minX;
}
/** The height of the axis aligned bounding box. */
public float getHeight () {
return maxY - minY;
}
/** The visible bounding boxes. */
public Array<BoundingBoxAttachment> getBoundingBoxes () {
return boundingBoxes;
}
/** The world vertices for the bounding box polygons. */
public Array<FloatArray> getPolygons () {
return polygons;
}

View File

@ -32,6 +32,10 @@ package com.esotericsoftware.spine;
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 {
String name;
final Array<BoneData> bones = new Array(); // Ordered parents first.
@ -52,11 +56,14 @@ public class SkeletonData {
// --- Bones.
/** The skeleton's bones, sorted parent first. The root bone is always the first bone. */
public Array<BoneData> getBones () {
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) {
if (boneName == null) throw new IllegalArgumentException("boneName cannot be null.");
Array<BoneData> bones = this.bones;
@ -69,11 +76,14 @@ public class SkeletonData {
// --- Slots.
/** The skeleton's slots. */
public Array<SlotData> getSlots () {
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) {
if (slotName == null) throw new IllegalArgumentException("slotName cannot be null.");
Array<SlotData> slots = this.slots;
@ -86,7 +96,10 @@ public class SkeletonData {
// --- 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 () {
return defaultSkin;
}
@ -96,7 +109,9 @@ public class SkeletonData {
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) {
if (skinName == null) throw new IllegalArgumentException("skinName cannot be null.");
for (Skin skin : skins)
@ -104,14 +119,16 @@ public class SkeletonData {
return null;
}
/** Returns all skins, including the default skin. */
/** All skins, including the default skin. */
public Array<Skin> getSkins () {
return skins;
}
// --- 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) {
if (eventDataName == null) throw new IllegalArgumentException("eventDataName cannot be null.");
for (EventData eventData : events)
@ -119,17 +136,21 @@ public class SkeletonData {
return null;
}
/** The skeleton's events. */
public Array<EventData> getEvents () {
return events;
}
// --- Animations.
/** The skeleton's animations. */
public Array<Animation> getAnimations () {
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) {
if (animationName == null) throw new IllegalArgumentException("animationName cannot be null.");
Array<Animation> animations = this.animations;
@ -142,11 +163,14 @@ public class SkeletonData {
// --- IK constraints
/** The skeleton's IK constraints. */
public Array<IkConstraintData> getIkConstraints () {
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) {
if (constraintName == null) throw new IllegalArgumentException("constraintName cannot be null.");
Array<IkConstraintData> ikConstraints = this.ikConstraints;
@ -159,11 +183,14 @@ public class SkeletonData {
// --- Transform constraints
/** The skeleton's transform constraints. */
public Array<TransformConstraintData> getTransformConstraints () {
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) {
if (constraintName == null) throw new IllegalArgumentException("constraintName cannot be null.");
Array<TransformConstraintData> transformConstraints = this.transformConstraints;
@ -176,11 +203,14 @@ public class SkeletonData {
// --- Path constraints
/** The skeleton's path constraints. */
public Array<PathConstraintData> getPathConstraints () {
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) {
if (constraintName == null) throw new IllegalArgumentException("constraintName cannot be null.");
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 () {
return name;
}
@ -203,6 +234,7 @@ public class SkeletonData {
this.name = name;
}
/** The width of the skeleton's axis aligned bounding box in the setup pose. */
public float getWidth () {
return width;
}
@ -211,6 +243,7 @@ public class SkeletonData {
this.width = width;
}
/** The height of the skeleton's axis aligned bounding box in the setup pose. */
public float getHeight () {
return height;
}
@ -219,7 +252,7 @@ public class SkeletonData {
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 () {
return version;
}
@ -229,7 +262,8 @@ public class SkeletonData {
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 () {
return hash;
}
@ -239,7 +273,8 @@ public class SkeletonData {
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 () {
return imagesPath;
}
@ -249,6 +284,7 @@ public class SkeletonData {
this.imagesPath = imagesPath;
}
/** The dopesheet FPS in Spine. Available only when nonessential data was exported. */
public float getFps () {
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.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 {
private final AttachmentLoader attachmentLoader;
private float scale = 1;
@ -83,11 +88,14 @@ public class SkeletonJson {
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 () {
return scale;
}
/** Scales the bones, images, and animations as they are loaded. */
public void setScale (float 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.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 {
static private final Key lookup = new Key();
@ -53,6 +56,7 @@ public class Skin {
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) {
if (attachment == null) throw new IllegalArgumentException("attachment cannot be null.");
if (slotIndex < 0) throw new IllegalArgumentException("slotIndex must be >= 0.");
@ -61,7 +65,7 @@ public class Skin {
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) {
if (slotIndex < 0) throw new IllegalArgumentException("slotIndex must be >= 0.");
lookup.set(slotIndex, name);
@ -88,6 +92,7 @@ public class Skin {
attachments.clear();
}
/** The skin's name, which is unique within the skeleton. */
public String getName () {
return name;
}

View File

@ -32,8 +32,13 @@ package com.esotericsoftware.spine;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.utils.FloatArray;
import com.esotericsoftware.spine.Animation.DeformTimeline;
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 {
final SlotData data;
final Bone bone;
@ -62,28 +67,33 @@ public class Slot {
attachmentTime = slot.attachmentTime;
}
/** The slot's setup pose data. */
public SlotData getData () {
return data;
}
/** The bone this slot belongs to. */
public Bone getBone () {
return bone;
}
/** The skeleton this slot belongs to. */
public Skeleton getSkeleton () {
return bone.skeleton;
}
/** The color used to tint the slot's attachment. */
public Color getColor () {
return color;
}
/** @return May be null. */
/** The current attachment for the slot, or null if the slot has no attachment. */
public Attachment getAttachment () {
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. */
public void setAttachment (Attachment attachment) {
if (this.attachment == attachment) return;
@ -92,13 +102,21 @@ public class Slot {
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) {
attachmentTime = bone.skeleton.time - time;
}
/** Returns the time since the attachment was set. */
public float getAttachmentTime () {
return bone.skeleton.time - attachmentTime;
/** Vertices to deform the slot's attachment.
* <p>
* See {@link VertexAttachment#computeWorldVertices(Slot, int, int, float[], int)} and {@link DeformTimeline}. */
public FloatArray getAttachmentVertices () {
return attachmentVertices;
}
public void setAttachmentVertices (FloatArray attachmentVertices) {
@ -106,10 +124,7 @@ public class Slot {
this.attachmentVertices = attachmentVertices;
}
public FloatArray getAttachmentVertices () {
return attachmentVertices;
}
/** Sets this slot to the setup pose. */
public void setToSetupPose () {
color.set(data.color);
if (data.attachmentName == null)

View File

@ -32,6 +32,7 @@ package com.esotericsoftware.spine;
import com.badlogic.gdx.graphics.Color;
/** Stores the setup pose for a {@link Slot}. */
public class SlotData {
final int index;
final String name;
@ -49,18 +50,22 @@ public class SlotData {
this.boneData = boneData;
}
/** The index of the slot in {@link Skeleton#getSlots()}. */
public int getIndex () {
return index;
}
/** The name of the slot, which is unique within the skeleton. */
public String getName () {
return name;
}
/** The bone this slot belongs to. */
public BoneData getBoneData () {
return boneData;
}
/** The color used to tint the slot's attachment. */
public Color getColor () {
return color;
}
@ -70,11 +75,12 @@ public class SlotData {
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 () {
return attachmentName;
}
/** The blend mode for drawing the slot's attachment. */
public BlendMode getBlendMode () {
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.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 {
final TransformConstraintData data;
final Array<Bone> bones;
@ -71,6 +75,7 @@ public class TransformConstraint implements Constraint {
shearMix = constraint.shearMix;
}
/** Applies the constraint to the constrained bones. */
public void apply () {
update();
}
@ -143,10 +148,12 @@ public class TransformConstraint implements Constraint {
return data.order;
}
/** The bones that will be modified by this transform constraint. */
public Array<Bone> getBones () {
return bones;
}
/** The target bone whose world transform will be copied to the constrained bones. */
public Bone getTarget () {
return target;
}
@ -155,6 +162,7 @@ public class TransformConstraint implements Constraint {
this.target = target;
}
/** A percentage (0-1) that controls the mix between the constrained and unconstrained rotations. */
public float getRotateMix () {
return rotateMix;
}
@ -163,6 +171,7 @@ public class TransformConstraint implements Constraint {
this.rotateMix = rotateMix;
}
/** A percentage (0-1) that controls the mix between the constrained and unconstrained translations. */
public float getTranslateMix () {
return translateMix;
}
@ -171,6 +180,7 @@ public class TransformConstraint implements Constraint {
this.translateMix = translateMix;
}
/** A percentage (0-1) that controls the mix between the constrained and unconstrained scales. */
public float getScaleMix () {
return scaleMix;
}
@ -179,6 +189,7 @@ public class TransformConstraint implements Constraint {
this.scaleMix = scaleMix;
}
/** A percentage (0-1) that controls the mix between the constrained and unconstrained scales. */
public float getShearMix () {
return shearMix;
}
@ -187,6 +198,7 @@ public class TransformConstraint implements Constraint {
this.shearMix = shearMix;
}
/** The transform constraint's setup pose data. */
public TransformConstraintData getData () {
return data;
}

View File

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

View File

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

View File

@ -32,16 +32,20 @@ package com.esotericsoftware.spine.attachments;
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 {
/** @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);
/** @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);
/** @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);
/** @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);
}

View File

@ -31,8 +31,13 @@
package com.esotericsoftware.spine.attachments;
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 {
// Nonessential.
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.utils.FloatArray;
import com.badlogic.gdx.utils.NumberUtils;
import com.esotericsoftware.spine.Animation.DeformTimeline;
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 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 {
private TextureRegion region;
private String path;
@ -68,6 +72,8 @@ public class MeshAttachment extends VertexAttachment {
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 () {
float[] regionUVs = this.regionUVs;
int verticesLength = regionUVs.length;
@ -160,6 +166,8 @@ public class MeshAttachment extends VertexAttachment {
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) {
return this == sourceAttachment || (inheritDeform && parentMesh == sourceAttachment);
}
@ -168,11 +176,11 @@ public class MeshAttachment extends VertexAttachment {
return worldVertices;
}
/** Triplets of vertex indices which describe the mesh's triangulation. */
public short[] getTriangles () {
return triangles;
}
/** Vertex number triplets which describe the mesh's triangulation. */
public void setTriangles (short[] triangles) {
this.triangles = triangles;
}
@ -186,10 +194,12 @@ public class MeshAttachment extends VertexAttachment {
this.regionUVs = regionUVs;
}
/** The color to tint the mesh. */
public Color getColor () {
return color;
}
/** The name of the texture region for this attachment. */
public String getPath () {
return path;
}
@ -198,6 +208,7 @@ public class MeshAttachment extends VertexAttachment {
this.path = path;
}
/** The number of entries at the beginning of {@link #vertices} that make up the mesh hull. */
public int getHullLength () {
return hullLength;
}
@ -210,10 +221,13 @@ public class MeshAttachment extends VertexAttachment {
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 () {
return edges;
}
/** The width of the mesh's image. Available only when nonessential data was exported. */
public float getWidth () {
return width;
}
@ -222,6 +236,7 @@ public class MeshAttachment extends VertexAttachment {
this.width = width;
}
/** The height of the mesh's image. Available only when nonessential data was exported. */
public float getHeight () {
return height;
}
@ -230,7 +245,9 @@ public class MeshAttachment extends VertexAttachment {
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 () {
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 () {
return inheritDeform;
}

View File

@ -31,8 +31,11 @@
package com.esotericsoftware.spine.attachments;
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 {
float[] lengths;
boolean closed, constantSpeed;
@ -53,6 +56,8 @@ public class PathAttachment extends VertexAttachment {
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 () {
return constantSpeed;
}
@ -61,7 +66,7 @@ public class PathAttachment extends VertexAttachment {
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 () {
return lengths;
}
@ -70,6 +75,8 @@ public class PathAttachment extends VertexAttachment {
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 () {
return color;
}

View File

@ -30,10 +30,6 @@
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 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.math.MathUtils;
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 {
static public final int BLX = 0;
static public final int BLY = 1;
@ -64,6 +65,7 @@ public class RegionAttachment extends Attachment {
super(name);
}
/** Calculates the {@link #offset} using the region settings. Must be called after changing region settings. */
public void updateOffset () {
float width = getWidth();
float height = getHeight();
@ -196,10 +198,14 @@ public class RegionAttachment extends Attachment {
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 () {
return offset;
}
/** The local x translation. */
public float getX () {
return x;
}
@ -208,6 +214,7 @@ public class RegionAttachment extends Attachment {
this.x = x;
}
/** The local y translation. */
public float getY () {
return y;
}
@ -216,6 +223,7 @@ public class RegionAttachment extends Attachment {
this.y = y;
}
/** The local scaleX. */
public float getScaleX () {
return scaleX;
}
@ -224,6 +232,7 @@ public class RegionAttachment extends Attachment {
this.scaleX = scaleX;
}
/** The local scaleY. */
public float getScaleY () {
return scaleY;
}
@ -232,6 +241,7 @@ public class RegionAttachment extends Attachment {
this.scaleY = scaleY;
}
/** The local rotation. */
public float getRotation () {
return rotation;
}
@ -240,6 +250,7 @@ public class RegionAttachment extends Attachment {
this.rotation = rotation;
}
/** The width of the region attachment in Spine. */
public float getWidth () {
return width;
}
@ -248,6 +259,7 @@ public class RegionAttachment extends Attachment {
this.width = width;
}
/** The height of the region attachment in Spine. */
public float getHeight () {
return height;
}
@ -256,10 +268,12 @@ public class RegionAttachment extends Attachment {
this.height = height;
}
/** The color to tint the region attachment. */
public Color getColor () {
return color;
}
/** The name of the texture region for this attachment. */
public String getPath () {
return path;
}

View File

@ -35,7 +35,8 @@ import com.esotericsoftware.spine.Bone;
import com.esotericsoftware.spine.Skeleton;
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 {
int[] bones;
float[] vertices;
@ -45,11 +46,18 @@ public class VertexAttachment extends Attachment {
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);
}
/** 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 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>.
@ -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) {
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 () {
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) {
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 () {
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) {
this.vertices = vertices;
}
/** The maximum length required of the <code>worldVertices</code> passed to
* {@link #computeWorldVertices(Slot, int, int, float[], int)}. */
public int getWorldVerticesLength () {
return worldVerticesLength;
}