|
@@ -55,6 +55,7 @@ public class Skeleton {
|
|
|
final Array<IkConstraint> ikConstraints;
|
|
|
final Array<TransformConstraint> transformConstraints;
|
|
|
final Array<PathConstraint> pathConstraints;
|
|
|
+ final Array<SpringConstraint> springConstraints;
|
|
|
final Array<Updatable> updateCache = new Array();
|
|
|
@Null Skin skin;
|
|
|
final Color color;
|
|
@@ -101,6 +102,10 @@ public class Skeleton {
|
|
|
for (PathConstraintData pathConstraintData : data.pathConstraints)
|
|
|
pathConstraints.add(new PathConstraint(pathConstraintData, this));
|
|
|
|
|
|
+ springConstraints = new Array(data.springConstraints.size);
|
|
|
+ for (SpringConstraintData springConstraintData : data.springConstraints)
|
|
|
+ springConstraints.add(new SpringConstraint(springConstraintData, this));
|
|
|
+
|
|
|
color = new Color(1, 1, 1, 1);
|
|
|
|
|
|
updateCache();
|
|
@@ -146,6 +151,10 @@ public class Skeleton {
|
|
|
for (PathConstraint pathConstraint : skeleton.pathConstraints)
|
|
|
pathConstraints.add(new PathConstraint(pathConstraint, this));
|
|
|
|
|
|
+ springConstraints = new Array(skeleton.springConstraints.size);
|
|
|
+ for (SpringConstraint springConstraint : skeleton.springConstraints)
|
|
|
+ springConstraints.add(new SpringConstraint(springConstraint, this));
|
|
|
+
|
|
|
skin = skeleton.skin;
|
|
|
color = new Color(skeleton.color);
|
|
|
time = skeleton.time;
|
|
@@ -180,11 +189,11 @@ public class Skeleton {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- int ikCount = ikConstraints.size, transformCount = transformConstraints.size, pathCount = pathConstraints.size;
|
|
|
- Object[] ikConstraints = this.ikConstraints.items;
|
|
|
- Object[] transformConstraints = this.transformConstraints.items;
|
|
|
- Object[] pathConstraints = this.pathConstraints.items;
|
|
|
- int constraintCount = ikCount + transformCount + pathCount;
|
|
|
+ int ikCount = ikConstraints.size, transformCount = transformConstraints.size, pathCount = pathConstraints.size,
|
|
|
+ springCount = springConstraints.size;
|
|
|
+ Object[] ikConstraints = this.ikConstraints.items, transformConstraints = this.transformConstraints.items,
|
|
|
+ pathConstraints = this.pathConstraints.items, springConstraints = this.springConstraints.items;
|
|
|
+ int constraintCount = ikCount + transformCount + pathCount + springCount;
|
|
|
outer:
|
|
|
for (int i = 0; i < constraintCount; i++) {
|
|
|
for (int ii = 0; ii < ikCount; ii++) {
|
|
@@ -208,6 +217,13 @@ public class Skeleton {
|
|
|
continue outer;
|
|
|
}
|
|
|
}
|
|
|
+ for (int ii = 0; ii < springCount; ii++) {
|
|
|
+ SpringConstraint constraint = (SpringConstraint)springConstraints[ii];
|
|
|
+ if (constraint.data.order == i) {
|
|
|
+ sortSpringConstraint(constraint);
|
|
|
+ continue outer;
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
for (int i = 0; i < boneCount; i++)
|
|
@@ -239,25 +255,25 @@ public class Skeleton {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- private void sortPathConstraint (PathConstraint constraint) {
|
|
|
- constraint.active = constraint.target.bone.active
|
|
|
+ private void sortTransformConstraint (TransformConstraint constraint) {
|
|
|
+ constraint.active = constraint.target.active
|
|
|
&& (!constraint.data.skinRequired || (skin != null && skin.constraints.contains(constraint.data, true)));
|
|
|
if (!constraint.active) return;
|
|
|
|
|
|
- Slot slot = constraint.target;
|
|
|
- int slotIndex = slot.getData().index;
|
|
|
- Bone slotBone = slot.bone;
|
|
|
- if (skin != null) sortPathConstraintAttachment(skin, slotIndex, slotBone);
|
|
|
- if (data.defaultSkin != null && data.defaultSkin != skin)
|
|
|
- sortPathConstraintAttachment(data.defaultSkin, slotIndex, slotBone);
|
|
|
-
|
|
|
- Attachment attachment = slot.attachment;
|
|
|
- if (attachment instanceof PathAttachment) sortPathConstraintAttachment(attachment, slotBone);
|
|
|
+ sortBone(constraint.target);
|
|
|
|
|
|
Object[] constrained = constraint.bones.items;
|
|
|
int boneCount = constraint.bones.size;
|
|
|
- for (int i = 0; i < boneCount; i++)
|
|
|
- sortBone((Bone)constrained[i]);
|
|
|
+ if (constraint.data.local) {
|
|
|
+ for (int i = 0; i < boneCount; i++) {
|
|
|
+ Bone child = (Bone)constrained[i];
|
|
|
+ sortBone(child.parent);
|
|
|
+ sortBone(child);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ for (int i = 0; i < boneCount; i++)
|
|
|
+ sortBone((Bone)constrained[i]);
|
|
|
+ }
|
|
|
|
|
|
updateCache.add(constraint);
|
|
|
|
|
@@ -267,25 +283,25 @@ public class Skeleton {
|
|
|
((Bone)constrained[i]).sorted = true;
|
|
|
}
|
|
|
|
|
|
- private void sortTransformConstraint (TransformConstraint constraint) {
|
|
|
- constraint.active = constraint.target.active
|
|
|
+ private void sortPathConstraint (PathConstraint constraint) {
|
|
|
+ constraint.active = constraint.target.bone.active
|
|
|
&& (!constraint.data.skinRequired || (skin != null && skin.constraints.contains(constraint.data, true)));
|
|
|
if (!constraint.active) return;
|
|
|
|
|
|
- sortBone(constraint.target);
|
|
|
+ Slot slot = constraint.target;
|
|
|
+ int slotIndex = slot.getData().index;
|
|
|
+ Bone slotBone = slot.bone;
|
|
|
+ if (skin != null) sortPathConstraintAttachment(skin, slotIndex, slotBone);
|
|
|
+ if (data.defaultSkin != null && data.defaultSkin != skin)
|
|
|
+ sortPathConstraintAttachment(data.defaultSkin, slotIndex, slotBone);
|
|
|
+
|
|
|
+ Attachment attachment = slot.attachment;
|
|
|
+ if (attachment instanceof PathAttachment) sortPathConstraintAttachment(attachment, slotBone);
|
|
|
|
|
|
Object[] constrained = constraint.bones.items;
|
|
|
int boneCount = constraint.bones.size;
|
|
|
- if (constraint.data.local) {
|
|
|
- for (int i = 0; i < boneCount; i++) {
|
|
|
- Bone child = (Bone)constrained[i];
|
|
|
- sortBone(child.parent);
|
|
|
- sortBone(child);
|
|
|
- }
|
|
|
- } else {
|
|
|
- for (int i = 0; i < boneCount; i++)
|
|
|
- sortBone((Bone)constrained[i]);
|
|
|
- }
|
|
|
+ for (int i = 0; i < boneCount; i++)
|
|
|
+ sortBone((Bone)constrained[i]);
|
|
|
|
|
|
updateCache.add(constraint);
|
|
|
|
|
@@ -319,6 +335,23 @@ public class Skeleton {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ private void sortSpringConstraint (SpringConstraint constraint) {
|
|
|
+ constraint.active = !constraint.data.skinRequired || (skin != null && skin.constraints.contains(constraint.data, true));
|
|
|
+ if (!constraint.active) return;
|
|
|
+
|
|
|
+ Object[] constrained = constraint.bones.items;
|
|
|
+ int boneCount = constraint.bones.size;
|
|
|
+ for (int i = 0; i < boneCount; i++)
|
|
|
+ sortBone((Bone)constrained[i]);
|
|
|
+
|
|
|
+ updateCache.add(constraint);
|
|
|
+
|
|
|
+ for (int i = 0; i < boneCount; i++)
|
|
|
+ sortReset(((Bone)constrained[i]).children);
|
|
|
+ for (int i = 0; i < boneCount; i++)
|
|
|
+ ((Bone)constrained[i]).sorted = true;
|
|
|
+ }
|
|
|
+
|
|
|
private void sortBone (Bone bone) {
|
|
|
if (bone.sorted) return;
|
|
|
Bone parent = bone.parent;
|
|
@@ -435,6 +468,20 @@ public class Skeleton {
|
|
|
constraint.mixX = data.mixX;
|
|
|
constraint.mixY = data.mixY;
|
|
|
}
|
|
|
+
|
|
|
+ Object[] springConstraints = this.springConstraints.items;
|
|
|
+ for (int i = 0, n = this.springConstraints.size; i < n; i++) {
|
|
|
+ SpringConstraint constraint = (SpringConstraint)springConstraints[i];
|
|
|
+ SpringConstraintData data = constraint.data;
|
|
|
+ constraint.mix = data.mix;
|
|
|
+ constraint.friction = data.friction;
|
|
|
+ constraint.gravity = data.gravity;
|
|
|
+ constraint.wind = data.wind;
|
|
|
+ constraint.stiffness = data.stiffness;
|
|
|
+ constraint.damping = data.damping;
|
|
|
+ constraint.rope = data.rope;
|
|
|
+ constraint.stretch = data.stretch;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/** Sets the slots and draw order to their setup pose values. */
|
|
@@ -641,6 +688,23 @@ public class Skeleton {
|
|
|
return null;
|
|
|
}
|
|
|
|
|
|
+ /** The skeleton's spring constraints. */
|
|
|
+ public Array<SpringConstraint> getSpringConstraints () {
|
|
|
+ return springConstraints;
|
|
|
+ }
|
|
|
+
|
|
|
+ /** Finds a spring constraint by comparing each spring constraint's name. It is more efficient to cache the results of this
|
|
|
+ * method than to call it repeatedly. */
|
|
|
+ public @Null SpringConstraint findSpringConstraint (String constraintName) {
|
|
|
+ if (constraintName == null) throw new IllegalArgumentException("constraintName cannot be null.");
|
|
|
+ Object[] springConstraints = this.springConstraints.items;
|
|
|
+ for (int i = 0, n = this.springConstraints.size; i < n; i++) {
|
|
|
+ SpringConstraint constraint = (SpringConstraint)springConstraints[i];
|
|
|
+ if (constraint.data.name.equals(constraintName)) return constraint;
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
/** Returns the axis aligned bounding box (AABB) of the region and mesh attachments for the current pose.
|
|
|
* @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.
|