|
@@ -37,33 +37,61 @@ import spine.attachments.MeshAttachment;
|
|
|
import spine.attachments.PathAttachment;
|
|
|
import spine.attachments.RegionAttachment;
|
|
|
|
|
|
+/** Stores the current pose for a skeleton.
|
|
|
+ * <p>
|
|
|
+ * See <a href="https://esotericsoftware.com/spine-runtime-architecture#Instance-objects">Instance objects</a> in the Spine
|
|
|
+ * Runtimes Guide. */
|
|
|
class Skeleton {
|
|
|
private static var quadTriangles:Array<Int> = [0, 1, 2, 2, 3, 0];
|
|
|
private var _data:SkeletonData;
|
|
|
|
|
|
+ /** The skeleton's bones, sorted parent first. The root bone is always the first bone. */
|
|
|
public var bones:Array<Bone>;
|
|
|
+ /** The skeleton's slots. */
|
|
|
public var slots:Array<Slot>; // Setup pose 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 var drawOrder:Array<Slot>;
|
|
|
+ /** The skeleton's IK constraints. */
|
|
|
public var ikConstraints:Array<IkConstraint>;
|
|
|
+ /** The skeleton's transform constraints. */
|
|
|
public var transformConstraints:Array<TransformConstraint>;
|
|
|
+ /** The skeleton's path constraints. */
|
|
|
public var pathConstraints:Array<PathConstraint>;
|
|
|
+ /** The skeleton's physics constraints. */
|
|
|
public var physicsConstraints:Array<PhysicsConstraint>;
|
|
|
|
|
|
private var _updateCache:Array<Updatable> = new Array<Updatable>();
|
|
|
private var _skin:Skin;
|
|
|
|
|
|
+ /** The color to tint all the skeleton's attachments. */
|
|
|
public var color:Color = new Color(1, 1, 1, 1);
|
|
|
+ /** Scales the entire skeleton on the X axis.
|
|
|
+ * <p>
|
|
|
+ * Bones that do not inherit scale are still affected by this property. */
|
|
|
public var scaleX:Float = 1;
|
|
|
|
|
|
+ /** Scales the entire skeleton on the Y axis.
|
|
|
+ * <p>
|
|
|
+ * Bones that do not inherit scale are still affected by this property. */
|
|
|
public var scaleY(get, default):Float = 1;
|
|
|
function get_scaleY() {
|
|
|
return Bone.yDown ? -scaleY : scaleY;
|
|
|
}
|
|
|
|
|
|
+ /** Sets the skeleton X position, which is added to the root bone worldX position.
|
|
|
+ * <p>
|
|
|
+ * Bones that do not inherit translation are still affected by this property. */
|
|
|
public var x:Float = 0;
|
|
|
+ /** Sets the skeleton Y position, which is added to the root bone worldY position.
|
|
|
+ * <p>
|
|
|
+ * Bones that do not inherit translation are still affected by this property. */
|
|
|
public var y:Float = 0;
|
|
|
+ /** Returns the skeleton's time. This is used for time-based manipulations, such as {@link PhysicsConstraint}.
|
|
|
+ * <p>
|
|
|
+ * See {@link #update(float)}. */
|
|
|
public var time:Float = 0;
|
|
|
|
|
|
+ /** Creates a new skeleton with the specified skeleton data. */
|
|
|
public function new(data:SkeletonData) {
|
|
|
if (data == null) {
|
|
|
throw new SpineException("data cannot be null.");
|
|
@@ -115,8 +143,8 @@ class Skeleton {
|
|
|
updateCache();
|
|
|
}
|
|
|
|
|
|
- /** Caches information about bones and constraints. Must be called if bones, constraints, or weighted path attachments are
|
|
|
- * added or removed. */
|
|
|
+ /** Caches information about bones and constraints. Must be called if the {@link #getSkin()} is modified or if bones,
|
|
|
+ * constraints, or weighted path attachments are added or removed. */
|
|
|
public function updateCache():Void {
|
|
|
_updateCache.resize(0);
|
|
|
|
|
@@ -350,7 +378,10 @@ 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="https://esotericsoftware.com/spine-runtime-skeletons#World-transforms">World transforms</a> in the Spine
|
|
|
+ * Runtimes Guide. */
|
|
|
public function updateWorldTransform(physics:Physics):Void {
|
|
|
if (physics == null) throw new SpineException("physics is undefined");
|
|
|
for (bone in bones) {
|
|
@@ -368,6 +399,11 @@ class Skeleton {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /** Temporarily sets the root bone as a child of the specified bone, then updates the world transform for each bone and applies
|
|
|
+ * all constraints.
|
|
|
+ * <p>
|
|
|
+ * See <a href="https://esotericsoftware.com/spine-runtime-skeletons#World-transforms">World transforms</a> in the Spine
|
|
|
+ * Runtimes Guide. */
|
|
|
public function updateWorldTransformWith(physics:Physics, parent:Bone):Void {
|
|
|
// Apply the parent bone transform to the root bone. The root bone always inherits scale, rotation and reflection.
|
|
|
var rootBone:Bone = rootBone;
|
|
@@ -396,7 +432,7 @@ class Skeleton {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- /** 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 function setToSetupPose():Void {
|
|
|
setBonesToSetupPose();
|
|
|
setSlotsToSetupPose();
|
|
@@ -411,6 +447,7 @@ class Skeleton {
|
|
|
for (constraint in this.physicsConstraints) constraint.setToSetupPose();
|
|
|
}
|
|
|
|
|
|
+ /** Sets the slots and draw order to their setup pose values. */
|
|
|
public function setSlotsToSetupPose():Void {
|
|
|
var i:Int = 0;
|
|
|
for (slot in slots) {
|
|
@@ -419,18 +456,21 @@ class Skeleton {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /** The skeleton's setup pose data. */
|
|
|
public var data(get, never):SkeletonData;
|
|
|
|
|
|
private function get_data():SkeletonData {
|
|
|
return _data;
|
|
|
}
|
|
|
|
|
|
- public var getUpdateCache(get, never):Array<Updatable>;
|
|
|
+ /** The list of bones and constraints, sorted in the order they should be updated, as computed by {@link #updateCache()}. */
|
|
|
+ public var updateCache(get, never):Array<Updatable>;
|
|
|
|
|
|
- private function get_getUpdateCache():Array<Updatable> {
|
|
|
+ private function get_updateCache():Array<Updatable> {
|
|
|
return _updateCache;
|
|
|
}
|
|
|
|
|
|
+ /** Returns the root bone, or null if the skeleton has no bones. */
|
|
|
public var rootBone(get, never):Bone;
|
|
|
|
|
|
private function get_rootBone():Bone {
|
|
@@ -439,7 +479,8 @@ class Skeleton {
|
|
|
return bones[0];
|
|
|
}
|
|
|
|
|
|
- /** @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
|
|
|
+ * repeatedly. */
|
|
|
public function findBone(boneName:String):Bone {
|
|
|
if (boneName == null) {
|
|
|
throw new SpineException("boneName cannot be null.");
|
|
@@ -465,7 +506,8 @@ class Skeleton {
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
- /** @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
|
|
|
+ * repeatedly. */
|
|
|
public function findSlot(slotName:String):Slot {
|
|
|
if (slotName == null) {
|
|
|
throw new SpineException("slotName cannot be null.");
|
|
@@ -477,8 +519,12 @@ class Skeleton {
|
|
|
return null;
|
|
|
}
|
|
|
|
|
|
+ /** The skeleton's current skin. */
|
|
|
public var skinName(get, set):String;
|
|
|
|
|
|
+ /** Sets a skin by name.
|
|
|
+ * <p>
|
|
|
+ * See {@link #setSkin(Skin)}. */
|
|
|
private function set_skinName(skinName:String):String {
|
|
|
var skin:Skin = data.findSkin(skinName);
|
|
|
if (skin == null)
|
|
@@ -492,16 +538,23 @@ class Skeleton {
|
|
|
return _skin == null ? null : _skin.name;
|
|
|
}
|
|
|
|
|
|
+ /** The skeleton's current skin. */
|
|
|
public var skin(get, set):Skin;
|
|
|
|
|
|
private function get_skin():Skin {
|
|
|
return _skin;
|
|
|
}
|
|
|
|
|
|
- /** Sets the skin used to look up attachments before looking in the {@link SkeletonData#getDefaultSkin() default skin}.
|
|
|
- * 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. */
|
|
|
+ /** Sets the skin used to look up attachments before looking in the {@link SkeletonData#getDefaultSkin() default skin}. If the
|
|
|
+ * skin is changed, {@link #updateCache()} is called.
|
|
|
+ * <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.
|
|
|
+ * <p>
|
|
|
+ * After changing the skin, the visible attachments can be reset to those attached in the setup pose by calling
|
|
|
+ * {@link #setSlotsToSetupPose()}. Also, often {@link AnimationState#apply(Skeleton)} is called before the next time the
|
|
|
+ * skeleton is rendered to allow any attachment keys in the current animation(s) to hide or show attachments from the new
|
|
|
+ * skin. */
|
|
|
private function set_skin(newSkin:Skin):Skin {
|
|
|
if (newSkin == _skin)
|
|
|
return null;
|
|
@@ -526,12 +579,18 @@ class Skeleton {
|
|
|
return _skin;
|
|
|
}
|
|
|
|
|
|
- /** @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)}. */
|
|
|
public function getAttachmentForSlotName(slotName:String, attachmentName:String):Attachment {
|
|
|
return getAttachmentForSlotIndex(data.findSlot(slotName).index, 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="https://esotericsoftware.com/spine-runtime-skins">Runtime skins</a> in the Spine Runtimes Guide. */
|
|
|
public function getAttachmentForSlotIndex(slotIndex:Int, attachmentName:String):Attachment {
|
|
|
if (attachmentName == null)
|
|
|
throw new SpineException("attachmentName cannot be null.");
|
|
@@ -545,7 +604,9 @@ class Skeleton {
|
|
|
return null;
|
|
|
}
|
|
|
|
|
|
- /** @param attachmentName May be null. */
|
|
|
+ /** 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's attachment. */
|
|
|
public function setAttachment(slotName:String, attachmentName:String):Void {
|
|
|
if (slotName == null)
|
|
|
throw new SpineException("slotName cannot be null.");
|
|
@@ -567,7 +628,8 @@ class Skeleton {
|
|
|
throw new SpineException("Slot not found: " + slotName);
|
|
|
}
|
|
|
|
|
|
- /** @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 repeatedly. */
|
|
|
public function findIkConstraint(constraintName:String):IkConstraint {
|
|
|
if (constraintName == null)
|
|
|
throw new SpineException("constraintName cannot be null.");
|
|
@@ -578,7 +640,8 @@ class Skeleton {
|
|
|
return null;
|
|
|
}
|
|
|
|
|
|
- /** @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 repeatedly. */
|
|
|
public function findTransformConstraint(constraintName:String):TransformConstraint {
|
|
|
if (constraintName == null)
|
|
|
throw new SpineException("constraintName cannot be null.");
|
|
@@ -589,7 +652,8 @@ class Skeleton {
|
|
|
return null;
|
|
|
}
|
|
|
|
|
|
- /** @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 repeatedly. */
|
|
|
public function findPathConstraint(constraintName:String):PathConstraint {
|
|
|
if (constraintName == null)
|
|
|
throw new SpineException("constraintName cannot be null.");
|
|
@@ -600,7 +664,8 @@ class Skeleton {
|
|
|
return null;
|
|
|
}
|
|
|
|
|
|
- /** @return May be null. */
|
|
|
+ /** Finds a physics constraint by comparing each physics constraint's name. It is more efficient to cache the results of this
|
|
|
+ * method than to call it repeatedly. */
|
|
|
public function findPhysicsConstraint(constraintName:String):PhysicsConstraint {
|
|
|
if (constraintName == null)
|
|
|
throw new SpineException("constraintName cannot be null.");
|
|
@@ -618,6 +683,8 @@ class Skeleton {
|
|
|
private var _tempVertices = new Array<Float>();
|
|
|
private var _bounds = new Rectangle();
|
|
|
|
|
|
+ /** Returns the axis aligned bounding box (AABB) of the region and mesh attachments for the current pose.
|
|
|
+ * Optionally applies clipping. */
|
|
|
public function getBounds(clipper: SkeletonClipping = null):Rectangle {
|
|
|
var minX:Float = Math.POSITIVE_INFINITY;
|
|
|
var minY:Float = Math.POSITIVE_INFINITY;
|
|
@@ -674,15 +741,18 @@ class Skeleton {
|
|
|
return _bounds;
|
|
|
}
|
|
|
|
|
|
+ /** Increments the skeleton's {@link #time}. */
|
|
|
public function update (delta:Float):Void {
|
|
|
time += delta;
|
|
|
}
|
|
|
|
|
|
+ /** Calls {@link PhysicsConstraint#translate(float, float)} for each physics constraint. */
|
|
|
public function physicsTranslate (x:Float, y:Float):Void {
|
|
|
for (physicsConstraint in physicsConstraints)
|
|
|
physicsConstraint.translate(x, y);
|
|
|
}
|
|
|
|
|
|
+ /** Calls {@link PhysicsConstraint#rotate(float, float, float)} for each physics constraint. */
|
|
|
public function physicsRotate (x:Float, y:Float, degrees:Float):Void {
|
|
|
for (physicsConstraint in physicsConstraints)
|
|
|
physicsConstraint.rotate(x, y, degrees);
|