mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-02-04 22:34:53 +08:00
[libgdx] Give all arrays types, direct array access, removed casts.
This commit is contained in:
parent
6c1d2f625e
commit
1f92218c23
@ -73,7 +73,9 @@ public class AttachmentTimelineTests {
|
||||
timeline.setFrame(0, 0, "attachment1");
|
||||
timeline.setFrame(1, 0.5f, "attachment2");
|
||||
|
||||
Animation animation = new Animation("animation", Array.with((Timeline)timeline), 1);
|
||||
Array<Timeline> timelines = new Array(true, 1, Timeline[]::new);
|
||||
timelines.add(timeline);
|
||||
Animation animation = new Animation("animation", timelines, 1);
|
||||
animation.setDuration(1);
|
||||
|
||||
state = new AnimationState(new AnimationStateData(skeletonData));
|
||||
|
||||
@ -72,9 +72,9 @@ public class Animation {
|
||||
|
||||
int n = timelines.size;
|
||||
timelineIds.clear(n);
|
||||
Object[] items = timelines.items;
|
||||
Timeline[] items = timelines.items;
|
||||
for (int i = 0; i < n; i++)
|
||||
timelineIds.addAll(((Timeline)items[i]).getPropertyIds());
|
||||
timelineIds.addAll(items[i].getPropertyIds());
|
||||
}
|
||||
|
||||
/** Returns true if this animation contains a timeline with any of the specified property IDs. */
|
||||
@ -123,9 +123,9 @@ public class Animation {
|
||||
if (lastTime > 0) lastTime %= duration;
|
||||
}
|
||||
|
||||
Object[] timelines = this.timelines.items;
|
||||
Timeline[] timelines = this.timelines.items;
|
||||
for (int i = 0, n = this.timelines.size; i < n; i++)
|
||||
((Timeline)timelines[i]).apply(skeleton, lastTime, time, events, alpha, blend, direction, appliedPose);
|
||||
timelines[i].apply(skeleton, lastTime, time, events, alpha, blend, direction, appliedPose);
|
||||
}
|
||||
|
||||
/** The animation's name, which is unique across all animations in the skeleton. */
|
||||
@ -265,12 +265,6 @@ public class Animation {
|
||||
}
|
||||
}
|
||||
|
||||
/** An interface for timelines which change the property of a bone. */
|
||||
static public interface BoneTimeline {
|
||||
/** The index of the bone in {@link Skeleton#getBones()} that will be changed when this timeline is applied. */
|
||||
public int getBoneIndex ();
|
||||
}
|
||||
|
||||
/** An interface for timelines which change the property of a slot. */
|
||||
static public interface SlotTimeline {
|
||||
/** The index of the slot in {@link Skeleton#getSlots()} that will be changed when this timeline is applied. */
|
||||
@ -544,12 +538,17 @@ public class Animation {
|
||||
}
|
||||
}
|
||||
|
||||
/** Changes a bone's local {@link BoneLocal#getRotation()}. */
|
||||
static public class RotateTimeline extends CurveTimeline1 implements BoneTimeline {
|
||||
/** An interface for timelines which change the property of a bone. */
|
||||
static public interface BoneTimeline {
|
||||
/** The index of the bone in {@link Skeleton#getBones()} that will be changed when this timeline is applied. */
|
||||
public int getBoneIndex ();
|
||||
}
|
||||
|
||||
static abstract public class BoneTimeline1 extends CurveTimeline1 implements BoneTimeline {
|
||||
final int boneIndex;
|
||||
|
||||
public RotateTimeline (int frameCount, int bezierCount, int boneIndex) {
|
||||
super(frameCount, bezierCount, Property.rotate.ordinal() + "|" + boneIndex);
|
||||
public BoneTimeline1 (int frameCount, int bezierCount, int boneIndex, Property property) {
|
||||
super(frameCount, bezierCount, property.ordinal() + "|" + boneIndex);
|
||||
this.boneIndex = boneIndex;
|
||||
}
|
||||
|
||||
@ -560,36 +559,55 @@ public class Animation {
|
||||
public void apply (Skeleton skeleton, float lastTime, float time, @Null Array<Event> events, float alpha, MixBlend blend,
|
||||
MixDirection direction, boolean appliedPose) {
|
||||
|
||||
Bone bone = skeleton.bones.get(boneIndex);
|
||||
if (bone.active) {
|
||||
BoneLocal pose = appliedPose ? bone.applied : bone.pose;
|
||||
pose.rotation = getRelativeValue(time, alpha, blend, pose.rotation, bone.data.setup.rotation);
|
||||
}
|
||||
Bone bone = skeleton.bones.items[boneIndex];
|
||||
if (bone.active) apply(appliedPose ? bone.applied : bone.pose, bone.data.setup, time, alpha, blend, direction);
|
||||
}
|
||||
|
||||
abstract protected void apply (BoneLocal pose, BoneLocal setup, float time, float alpha, MixBlend blend,
|
||||
MixDirection direction);
|
||||
}
|
||||
|
||||
static abstract public class BoneTimeline2 extends CurveTimeline2 implements BoneTimeline {
|
||||
final int boneIndex;
|
||||
|
||||
public BoneTimeline2 (int frameCount, int bezierCount, int boneIndex, Property property1, Property property2) {
|
||||
super(frameCount, bezierCount, property1.ordinal() + "|" + boneIndex, property2.ordinal() + "|" + boneIndex);
|
||||
this.boneIndex = boneIndex;
|
||||
}
|
||||
|
||||
public int getBoneIndex () {
|
||||
return boneIndex;
|
||||
}
|
||||
|
||||
public void apply (Skeleton skeleton, float lastTime, float time, @Null Array<Event> events, float alpha, MixBlend blend,
|
||||
MixDirection direction, boolean appliedPose) {
|
||||
|
||||
Bone bone = skeleton.bones.items[boneIndex];
|
||||
if (bone.active) apply(appliedPose ? bone.applied : bone.pose, bone.data.setup, time, alpha, blend, direction);
|
||||
}
|
||||
|
||||
abstract protected void apply (BoneLocal pose, BoneLocal setup, float time, float alpha, MixBlend blend,
|
||||
MixDirection direction);
|
||||
}
|
||||
|
||||
/** Changes a bone's local {@link BoneLocal#getRotation()}. */
|
||||
static public class RotateTimeline extends BoneTimeline1 {
|
||||
public RotateTimeline (int frameCount, int bezierCount, int boneIndex) {
|
||||
super(frameCount, bezierCount, boneIndex, Property.rotate);
|
||||
}
|
||||
|
||||
protected void apply (BoneLocal pose, BoneLocal setup, float time, float alpha, MixBlend blend, MixDirection direction) {
|
||||
pose.rotation = getRelativeValue(time, alpha, blend, pose.rotation, setup.rotation);
|
||||
}
|
||||
}
|
||||
|
||||
/** Changes a bone's local {@link BoneLocal#getX()} and {@link BoneLocal#getY()}. */
|
||||
static public class TranslateTimeline extends CurveTimeline2 implements BoneTimeline {
|
||||
final int boneIndex;
|
||||
|
||||
static public class TranslateTimeline extends BoneTimeline2 {
|
||||
public TranslateTimeline (int frameCount, int bezierCount, int boneIndex) {
|
||||
super(frameCount, bezierCount, //
|
||||
Property.x.ordinal() + "|" + boneIndex, //
|
||||
Property.y.ordinal() + "|" + boneIndex);
|
||||
this.boneIndex = boneIndex;
|
||||
super(frameCount, bezierCount, boneIndex, Property.x, Property.y);
|
||||
}
|
||||
|
||||
public int getBoneIndex () {
|
||||
return boneIndex;
|
||||
}
|
||||
|
||||
public void apply (Skeleton skeleton, float lastTime, float time, @Null Array<Event> events, float alpha, MixBlend blend,
|
||||
MixDirection direction, boolean appliedPose) {
|
||||
|
||||
Bone bone = skeleton.bones.get(boneIndex);
|
||||
if (!bone.active) return;
|
||||
BoneLocal pose = appliedPose ? bone.applied : bone.pose, setup = bone.data.setup;
|
||||
|
||||
protected void apply (BoneLocal pose, BoneLocal setup, float time, float alpha, MixBlend blend, MixDirection direction) {
|
||||
float[] frames = this.frames;
|
||||
if (time < frames[0]) {
|
||||
switch (blend) {
|
||||
@ -642,75 +660,34 @@ public class Animation {
|
||||
}
|
||||
|
||||
/** Changes a bone's local {@link BoneLocal#getX()}. */
|
||||
static public class TranslateXTimeline extends CurveTimeline1 implements BoneTimeline {
|
||||
final int boneIndex;
|
||||
|
||||
static public class TranslateXTimeline extends BoneTimeline1 {
|
||||
public TranslateXTimeline (int frameCount, int bezierCount, int boneIndex) {
|
||||
super(frameCount, bezierCount, Property.x.ordinal() + "|" + boneIndex);
|
||||
this.boneIndex = boneIndex;
|
||||
super(frameCount, bezierCount, boneIndex, Property.x);
|
||||
}
|
||||
|
||||
public int getBoneIndex () {
|
||||
return boneIndex;
|
||||
}
|
||||
|
||||
public void apply (Skeleton skeleton, float lastTime, float time, @Null Array<Event> events, float alpha, MixBlend blend,
|
||||
MixDirection direction, boolean appliedPose) {
|
||||
|
||||
Bone bone = skeleton.bones.get(boneIndex);
|
||||
if (bone.active) {
|
||||
BoneLocal pose = appliedPose ? bone.applied : bone.pose;
|
||||
pose.x = getRelativeValue(time, alpha, blend, pose.x, bone.data.setup.x);
|
||||
}
|
||||
protected void apply (BoneLocal pose, BoneLocal setup, float time, float alpha, MixBlend blend, MixDirection direction) {
|
||||
pose.x = getRelativeValue(time, alpha, blend, pose.x, setup.x);
|
||||
}
|
||||
}
|
||||
|
||||
/** Changes a bone's local {@link BoneLocal#getY()}. */
|
||||
static public class TranslateYTimeline extends CurveTimeline1 implements BoneTimeline {
|
||||
final int boneIndex;
|
||||
|
||||
static public class TranslateYTimeline extends BoneTimeline1 {
|
||||
public TranslateYTimeline (int frameCount, int bezierCount, int boneIndex) {
|
||||
super(frameCount, bezierCount, Property.y.ordinal() + "|" + boneIndex);
|
||||
this.boneIndex = boneIndex;
|
||||
super(frameCount, bezierCount, boneIndex, Property.y);
|
||||
}
|
||||
|
||||
public int getBoneIndex () {
|
||||
return boneIndex;
|
||||
}
|
||||
|
||||
public void apply (Skeleton skeleton, float lastTime, float time, @Null Array<Event> events, float alpha, MixBlend blend,
|
||||
MixDirection direction, boolean appliedPose) {
|
||||
|
||||
Bone bone = skeleton.bones.get(boneIndex);
|
||||
if (bone.active) {
|
||||
BoneLocal pose = appliedPose ? bone.applied : bone.pose;
|
||||
pose.y = getRelativeValue(time, alpha, blend, pose.y, bone.data.setup.y);
|
||||
}
|
||||
protected void apply (BoneLocal pose, BoneLocal setup, float time, float alpha, MixBlend blend, MixDirection direction) {
|
||||
pose.y = getRelativeValue(time, alpha, blend, pose.y, setup.y);
|
||||
}
|
||||
}
|
||||
|
||||
/** Changes a bone's local {@link BoneLocal#getScaleX()} and {@link BoneLocal#getScaleY()}. */
|
||||
static public class ScaleTimeline extends CurveTimeline2 implements BoneTimeline {
|
||||
final int boneIndex;
|
||||
|
||||
static public class ScaleTimeline extends BoneTimeline2 {
|
||||
public ScaleTimeline (int frameCount, int bezierCount, int boneIndex) {
|
||||
super(frameCount, bezierCount, //
|
||||
Property.scaleX.ordinal() + "|" + boneIndex, //
|
||||
Property.scaleY.ordinal() + "|" + boneIndex);
|
||||
this.boneIndex = boneIndex;
|
||||
super(frameCount, bezierCount, boneIndex, Property.scaleX, Property.scaleY);
|
||||
}
|
||||
|
||||
public int getBoneIndex () {
|
||||
return boneIndex;
|
||||
}
|
||||
|
||||
public void apply (Skeleton skeleton, float lastTime, float time, @Null Array<Event> events, float alpha, MixBlend blend,
|
||||
MixDirection direction, boolean appliedPose) {
|
||||
|
||||
Bone bone = skeleton.bones.get(boneIndex);
|
||||
if (!bone.active) return;
|
||||
BoneLocal pose = appliedPose ? bone.applied : bone.pose, setup = bone.data.setup;
|
||||
|
||||
protected void apply (BoneLocal pose, BoneLocal setup, float time, float alpha, MixBlend blend, MixDirection direction) {
|
||||
float[] frames = this.frames;
|
||||
if (time < frames[0]) {
|
||||
switch (blend) {
|
||||
@ -802,75 +779,34 @@ public class Animation {
|
||||
}
|
||||
|
||||
/** Changes a bone's local {@link BoneLocal#getScaleX()}. */
|
||||
static public class ScaleXTimeline extends CurveTimeline1 implements BoneTimeline {
|
||||
final int boneIndex;
|
||||
|
||||
static public class ScaleXTimeline extends BoneTimeline1 {
|
||||
public ScaleXTimeline (int frameCount, int bezierCount, int boneIndex) {
|
||||
super(frameCount, bezierCount, Property.scaleX.ordinal() + "|" + boneIndex);
|
||||
this.boneIndex = boneIndex;
|
||||
super(frameCount, bezierCount, boneIndex, Property.scaleX);
|
||||
}
|
||||
|
||||
public int getBoneIndex () {
|
||||
return boneIndex;
|
||||
}
|
||||
|
||||
public void apply (Skeleton skeleton, float lastTime, float time, @Null Array<Event> events, float alpha, MixBlend blend,
|
||||
MixDirection direction, boolean appliedPose) {
|
||||
|
||||
Bone bone = skeleton.bones.get(boneIndex);
|
||||
if (bone.active) {
|
||||
BoneLocal pose = appliedPose ? bone.applied : bone.pose;
|
||||
pose.scaleX = getScaleValue(time, alpha, blend, direction, pose.scaleX, bone.data.setup.scaleX);
|
||||
}
|
||||
protected void apply (BoneLocal pose, BoneLocal setup, float time, float alpha, MixBlend blend, MixDirection direction) {
|
||||
pose.scaleX = getScaleValue(time, alpha, blend, direction, pose.scaleX, setup.scaleX);
|
||||
}
|
||||
}
|
||||
|
||||
/** Changes a bone's local {@link BoneLocal#getScaleY()}. */
|
||||
static public class ScaleYTimeline extends CurveTimeline1 implements BoneTimeline {
|
||||
final int boneIndex;
|
||||
|
||||
static public class ScaleYTimeline extends BoneTimeline1 {
|
||||
public ScaleYTimeline (int frameCount, int bezierCount, int boneIndex) {
|
||||
super(frameCount, bezierCount, Property.scaleY.ordinal() + "|" + boneIndex);
|
||||
this.boneIndex = boneIndex;
|
||||
super(frameCount, bezierCount, boneIndex, Property.scaleY);
|
||||
}
|
||||
|
||||
public int getBoneIndex () {
|
||||
return boneIndex;
|
||||
}
|
||||
|
||||
public void apply (Skeleton skeleton, float lastTime, float time, @Null Array<Event> events, float alpha, MixBlend blend,
|
||||
MixDirection direction, boolean appliedPose) {
|
||||
|
||||
Bone bone = skeleton.bones.get(boneIndex);
|
||||
if (bone.active) {
|
||||
BoneLocal pose = appliedPose ? bone.applied : bone.pose;
|
||||
pose.scaleY = getScaleValue(time, alpha, blend, direction, pose.scaleY, bone.data.setup.scaleY);
|
||||
}
|
||||
protected void apply (BoneLocal pose, BoneLocal setup, float time, float alpha, MixBlend blend, MixDirection direction) {
|
||||
pose.scaleY = getScaleValue(time, alpha, blend, direction, pose.scaleY, setup.scaleY);
|
||||
}
|
||||
}
|
||||
|
||||
/** Changes a bone's local {@link BoneLocal#getShearX()} and {@link BoneLocal#getShearY()}. */
|
||||
static public class ShearTimeline extends CurveTimeline2 implements BoneTimeline {
|
||||
final int boneIndex;
|
||||
|
||||
static public class ShearTimeline extends BoneTimeline2 {
|
||||
public ShearTimeline (int frameCount, int bezierCount, int boneIndex) {
|
||||
super(frameCount, bezierCount, //
|
||||
Property.shearX.ordinal() + "|" + boneIndex, //
|
||||
Property.shearY.ordinal() + "|" + boneIndex);
|
||||
this.boneIndex = boneIndex;
|
||||
super(frameCount, bezierCount, boneIndex, Property.shearX, Property.shearY);
|
||||
}
|
||||
|
||||
public int getBoneIndex () {
|
||||
return boneIndex;
|
||||
}
|
||||
|
||||
public void apply (Skeleton skeleton, float lastTime, float time, @Null Array<Event> events, float alpha, MixBlend blend,
|
||||
MixDirection direction, boolean appliedPose) {
|
||||
|
||||
Bone bone = skeleton.bones.get(boneIndex);
|
||||
if (!bone.active) return;
|
||||
BoneLocal pose = appliedPose ? bone.applied : bone.pose, setup = bone.data.setup;
|
||||
|
||||
protected void apply (BoneLocal pose, BoneLocal setup, float time, float alpha, MixBlend blend, MixDirection direction) {
|
||||
float[] frames = this.frames;
|
||||
if (time < frames[0]) {
|
||||
switch (blend) {
|
||||
@ -923,50 +859,24 @@ public class Animation {
|
||||
}
|
||||
|
||||
/** Changes a bone's local {@link BoneLocal#getShearX()}. */
|
||||
static public class ShearXTimeline extends CurveTimeline1 implements BoneTimeline {
|
||||
final int boneIndex;
|
||||
|
||||
static public class ShearXTimeline extends BoneTimeline1 {
|
||||
public ShearXTimeline (int frameCount, int bezierCount, int boneIndex) {
|
||||
super(frameCount, bezierCount, Property.shearX.ordinal() + "|" + boneIndex);
|
||||
this.boneIndex = boneIndex;
|
||||
super(frameCount, bezierCount, boneIndex, Property.shearX);
|
||||
}
|
||||
|
||||
public int getBoneIndex () {
|
||||
return boneIndex;
|
||||
}
|
||||
|
||||
public void apply (Skeleton skeleton, float lastTime, float time, @Null Array<Event> events, float alpha, MixBlend blend,
|
||||
MixDirection direction, boolean appliedPose) {
|
||||
|
||||
Bone bone = skeleton.bones.get(boneIndex);
|
||||
if (bone.active) {
|
||||
BoneLocal pose = appliedPose ? bone.applied : bone.pose;
|
||||
pose.shearX = getRelativeValue(time, alpha, blend, pose.shearX, bone.data.setup.shearX);
|
||||
}
|
||||
protected void apply (BoneLocal pose, BoneLocal setup, float time, float alpha, MixBlend blend, MixDirection direction) {
|
||||
pose.shearX = getRelativeValue(time, alpha, blend, pose.shearX, setup.shearX);
|
||||
}
|
||||
}
|
||||
|
||||
/** Changes a bone's local {@link BoneLocal#getShearY()}. */
|
||||
static public class ShearYTimeline extends CurveTimeline1 implements BoneTimeline {
|
||||
final int boneIndex;
|
||||
|
||||
static public class ShearYTimeline extends BoneTimeline1 {
|
||||
public ShearYTimeline (int frameCount, int bezierCount, int boneIndex) {
|
||||
super(frameCount, bezierCount, Property.shearY.ordinal() + "|" + boneIndex);
|
||||
this.boneIndex = boneIndex;
|
||||
super(frameCount, bezierCount, boneIndex, Property.shearY);
|
||||
}
|
||||
|
||||
public int getBoneIndex () {
|
||||
return boneIndex;
|
||||
}
|
||||
|
||||
public void apply (Skeleton skeleton, float lastTime, float time, @Null Array<Event> events, float alpha, MixBlend blend,
|
||||
MixDirection direction, boolean appliedPose) {
|
||||
|
||||
Bone bone = skeleton.bones.get(boneIndex);
|
||||
if (bone.active) {
|
||||
BoneLocal pose = appliedPose ? bone.applied : bone.pose;
|
||||
pose.shearY = getRelativeValue(time, alpha, blend, pose.shearY, bone.data.setup.shearY);
|
||||
}
|
||||
protected void apply (BoneLocal pose, BoneLocal setup, float time, float alpha, MixBlend blend, MixDirection direction) {
|
||||
pose.shearY = getRelativeValue(time, alpha, blend, pose.shearY, setup.shearY);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1002,7 +912,7 @@ public class Animation {
|
||||
public void apply (Skeleton skeleton, float lastTime, float time, @Null Array<Event> events, float alpha, MixBlend blend,
|
||||
MixDirection direction, boolean appliedPose) {
|
||||
|
||||
Bone bone = skeleton.bones.get(boneIndex);
|
||||
Bone bone = skeleton.bones.items[boneIndex];
|
||||
if (!bone.active) return;
|
||||
BoneLocal pose = appliedPose ? bone.applied : bone.pose;
|
||||
|
||||
@ -1020,28 +930,43 @@ public class Animation {
|
||||
}
|
||||
}
|
||||
|
||||
/** Changes a slot's {@link SlotPose#getColor()}. */
|
||||
static public class RGBATimeline extends CurveTimeline implements SlotTimeline {
|
||||
static public final int ENTRIES = 5;
|
||||
static private final int R = 1, G = 2, B = 3, A = 4;
|
||||
|
||||
static abstract public class SlotCurveTimeline extends CurveTimeline implements SlotTimeline {
|
||||
final int slotIndex;
|
||||
|
||||
public RGBATimeline (int frameCount, int bezierCount, int slotIndex) {
|
||||
super(frameCount, bezierCount, //
|
||||
Property.rgb.ordinal() + "|" + slotIndex, //
|
||||
Property.alpha.ordinal() + "|" + slotIndex);
|
||||
public SlotCurveTimeline (int frameCount, int bezierCount, int slotIndex, String... propertyIds) {
|
||||
super(frameCount, bezierCount, propertyIds);
|
||||
this.slotIndex = slotIndex;
|
||||
}
|
||||
|
||||
public int getFrameEntries () {
|
||||
return ENTRIES;
|
||||
}
|
||||
|
||||
public int getSlotIndex () {
|
||||
return slotIndex;
|
||||
}
|
||||
|
||||
public void apply (Skeleton skeleton, float lastTime, float time, @Null Array<Event> events, float alpha, MixBlend blend,
|
||||
MixDirection direction, boolean appliedPose) {
|
||||
|
||||
Slot slot = skeleton.slots.items[slotIndex];
|
||||
if (slot.bone.active) apply(slot, appliedPose ? slot.applied : slot.pose, time, alpha, blend);
|
||||
}
|
||||
|
||||
abstract protected void apply (Slot slot, SlotPose pose, float time, float alpha, MixBlend blend);
|
||||
}
|
||||
|
||||
/** Changes a slot's {@link SlotPose#getColor()}. */
|
||||
static public class RGBATimeline extends SlotCurveTimeline {
|
||||
static public final int ENTRIES = 5;
|
||||
static private final int R = 1, G = 2, B = 3, A = 4;
|
||||
|
||||
public RGBATimeline (int frameCount, int bezierCount, int slotIndex) {
|
||||
super(frameCount, bezierCount, slotIndex, //
|
||||
Property.rgb.ordinal() + "|" + slotIndex, //
|
||||
Property.alpha.ordinal() + "|" + slotIndex);
|
||||
}
|
||||
|
||||
public int getFrameEntries () {
|
||||
return ENTRIES;
|
||||
}
|
||||
|
||||
/** Sets the time and color for the specified frame.
|
||||
* @param frame Between 0 and <code>frameCount</code>, inclusive.
|
||||
* @param time The frame time in seconds. */
|
||||
@ -1054,13 +979,7 @@ public class Animation {
|
||||
frames[frame + A] = a;
|
||||
}
|
||||
|
||||
public void apply (Skeleton skeleton, float lastTime, float time, @Null Array<Event> events, float alpha, MixBlend blend,
|
||||
MixDirection direction, boolean appliedPose) {
|
||||
|
||||
Slot slot = skeleton.slots.get(slotIndex);
|
||||
if (!slot.bone.active) return;
|
||||
SlotPose pose = appliedPose ? slot.applied : slot.pose;
|
||||
|
||||
protected void apply (Slot slot, SlotPose pose, float time, float alpha, MixBlend blend) {
|
||||
float[] frames = this.frames;
|
||||
Color color = pose.color;
|
||||
if (time < frames[0]) {
|
||||
@ -1114,25 +1033,18 @@ public class Animation {
|
||||
}
|
||||
|
||||
/** Changes the RGB for a slot's {@link SlotPose#getColor()}. */
|
||||
static public class RGBTimeline extends CurveTimeline implements SlotTimeline {
|
||||
static public class RGBTimeline extends SlotCurveTimeline {
|
||||
static public final int ENTRIES = 4;
|
||||
static private final int R = 1, G = 2, B = 3;
|
||||
|
||||
final int slotIndex;
|
||||
|
||||
public RGBTimeline (int frameCount, int bezierCount, int slotIndex) {
|
||||
super(frameCount, bezierCount, Property.rgb.ordinal() + "|" + slotIndex);
|
||||
this.slotIndex = slotIndex;
|
||||
super(frameCount, bezierCount, slotIndex, Property.rgb.ordinal() + "|" + slotIndex);
|
||||
}
|
||||
|
||||
public int getFrameEntries () {
|
||||
return ENTRIES;
|
||||
}
|
||||
|
||||
public int getSlotIndex () {
|
||||
return slotIndex;
|
||||
}
|
||||
|
||||
/** Sets the time and color for the specified frame.
|
||||
* @param frame Between 0 and <code>frameCount</code>, inclusive.
|
||||
* @param time The frame time in seconds. */
|
||||
@ -1144,13 +1056,7 @@ public class Animation {
|
||||
frames[frame + B] = b;
|
||||
}
|
||||
|
||||
public void apply (Skeleton skeleton, float lastTime, float time, @Null Array<Event> events, float alpha, MixBlend blend,
|
||||
MixDirection direction, boolean appliedPose) {
|
||||
|
||||
Slot slot = skeleton.slots.get(slotIndex);
|
||||
if (!slot.bone.active) return;
|
||||
SlotPose pose = appliedPose ? slot.applied : slot.pose;
|
||||
|
||||
protected void apply (Slot slot, SlotPose pose, float time, float alpha, MixBlend blend) {
|
||||
float[] frames = this.frames;
|
||||
Color color = pose.color;
|
||||
if (time < frames[0]) {
|
||||
@ -1227,7 +1133,7 @@ public class Animation {
|
||||
public void apply (Skeleton skeleton, float lastTime, float time, @Null Array<Event> events, float alpha, MixBlend blend,
|
||||
MixDirection direction, boolean appliedPose) {
|
||||
|
||||
Slot slot = skeleton.slots.get(slotIndex);
|
||||
Slot slot = skeleton.slots.items[slotIndex];
|
||||
if (!slot.bone.active) return;
|
||||
SlotPose pose = appliedPose ? slot.applied : slot.pose;
|
||||
|
||||
@ -1256,30 +1162,21 @@ public class Animation {
|
||||
}
|
||||
|
||||
/** Changes a slot's {@link SlotPose#getColor()} and {@link SlotPose#getDarkColor()} for two color tinting. */
|
||||
static public class RGBA2Timeline extends CurveTimeline implements SlotTimeline {
|
||||
static public class RGBA2Timeline extends SlotCurveTimeline {
|
||||
static public final int ENTRIES = 8;
|
||||
static private final int R = 1, G = 2, B = 3, A = 4, R2 = 5, G2 = 6, B2 = 7;
|
||||
|
||||
final int slotIndex;
|
||||
|
||||
public RGBA2Timeline (int frameCount, int bezierCount, int slotIndex) {
|
||||
super(frameCount, bezierCount, //
|
||||
super(frameCount, bezierCount, slotIndex, //
|
||||
Property.rgb.ordinal() + "|" + slotIndex, //
|
||||
Property.alpha.ordinal() + "|" + slotIndex, //
|
||||
Property.rgb2.ordinal() + "|" + slotIndex);
|
||||
this.slotIndex = slotIndex;
|
||||
}
|
||||
|
||||
public int getFrameEntries () {
|
||||
return ENTRIES;
|
||||
}
|
||||
|
||||
/** The index of the slot in {@link Skeleton#getSlots()} that will be changed when this timeline is applied. The
|
||||
* {@link SlotPose#getDarkColor()} must not be null. */
|
||||
public int getSlotIndex () {
|
||||
return slotIndex;
|
||||
}
|
||||
|
||||
/** Sets the time, light color, and dark color for the specified frame.
|
||||
* @param frame Between 0 and <code>frameCount</code>, inclusive.
|
||||
* @param time The frame time in seconds. */
|
||||
@ -1295,13 +1192,7 @@ public class Animation {
|
||||
frames[frame + B2] = b2;
|
||||
}
|
||||
|
||||
public void apply (Skeleton skeleton, float lastTime, float time, @Null Array<Event> events, float alpha, MixBlend blend,
|
||||
MixDirection direction, boolean appliedPose) {
|
||||
|
||||
Slot slot = skeleton.slots.get(slotIndex);
|
||||
if (!slot.bone.active) return;
|
||||
SlotPose pose = appliedPose ? slot.applied : slot.pose;
|
||||
|
||||
protected void apply (Slot slot, SlotPose pose, float time, float alpha, MixBlend blend) {
|
||||
float[] frames = this.frames;
|
||||
Color light = pose.color, dark = pose.darkColor;
|
||||
if (time < frames[0]) {
|
||||
@ -1387,29 +1278,20 @@ public class Animation {
|
||||
}
|
||||
|
||||
/** Changes the RGB for a slot's {@link SlotPose#getColor()} and {@link SlotPose#getDarkColor()} for two color tinting. */
|
||||
static public class RGB2Timeline extends CurveTimeline implements SlotTimeline {
|
||||
static public class RGB2Timeline extends SlotCurveTimeline {
|
||||
static public final int ENTRIES = 7;
|
||||
static private final int R = 1, G = 2, B = 3, R2 = 4, G2 = 5, B2 = 6;
|
||||
|
||||
final int slotIndex;
|
||||
|
||||
public RGB2Timeline (int frameCount, int bezierCount, int slotIndex) {
|
||||
super(frameCount, bezierCount, //
|
||||
super(frameCount, bezierCount, slotIndex, //
|
||||
Property.rgb.ordinal() + "|" + slotIndex, //
|
||||
Property.rgb2.ordinal() + "|" + slotIndex);
|
||||
this.slotIndex = slotIndex;
|
||||
}
|
||||
|
||||
public int getFrameEntries () {
|
||||
return ENTRIES;
|
||||
}
|
||||
|
||||
/** The index of the slot in {@link Skeleton#getSlots()} that will be changed when this timeline is applied. The
|
||||
* {@link SlotPose#getDarkColor()} must not be null. */
|
||||
public int getSlotIndex () {
|
||||
return slotIndex;
|
||||
}
|
||||
|
||||
/** Sets the time, light color, and dark color for the specified frame.
|
||||
* @param frame Between 0 and <code>frameCount</code>, inclusive.
|
||||
* @param time The frame time in seconds. */
|
||||
@ -1424,13 +1306,7 @@ public class Animation {
|
||||
frames[frame + B2] = b2;
|
||||
}
|
||||
|
||||
public void apply (Skeleton skeleton, float lastTime, float time, @Null Array<Event> events, float alpha, MixBlend blend,
|
||||
MixDirection direction, boolean appliedPose) {
|
||||
|
||||
Slot slot = skeleton.slots.get(slotIndex);
|
||||
if (!slot.bone.active) return;
|
||||
SlotPose pose = appliedPose ? slot.applied : slot.pose;
|
||||
|
||||
protected void apply (Slot slot, SlotPose pose, float time, float alpha, MixBlend blend) {
|
||||
float[] frames = this.frames;
|
||||
Color light = pose.color, dark = pose.darkColor;
|
||||
if (time < frames[0]) {
|
||||
@ -1555,7 +1431,7 @@ public class Animation {
|
||||
public void apply (Skeleton skeleton, float lastTime, float time, @Null Array<Event> events, float alpha, MixBlend blend,
|
||||
MixDirection direction, boolean appliedPose) {
|
||||
|
||||
Slot slot = skeleton.slots.get(slotIndex);
|
||||
Slot slot = skeleton.slots.items[slotIndex];
|
||||
if (!slot.bone.active) return;
|
||||
SlotPose pose = appliedPose ? slot.applied : slot.pose;
|
||||
|
||||
@ -1578,14 +1454,12 @@ public class Animation {
|
||||
}
|
||||
|
||||
/** Changes a slot's {@link SlotPose#getDeform()} to deform a {@link VertexAttachment}. */
|
||||
static public class DeformTimeline extends CurveTimeline implements SlotTimeline {
|
||||
final int slotIndex;
|
||||
static public class DeformTimeline extends SlotCurveTimeline {
|
||||
final VertexAttachment attachment;
|
||||
private final float[][] vertices;
|
||||
|
||||
public DeformTimeline (int frameCount, int bezierCount, int slotIndex, VertexAttachment attachment) {
|
||||
super(frameCount, bezierCount, Property.deform.ordinal() + "|" + slotIndex + "|" + attachment.getId());
|
||||
this.slotIndex = slotIndex;
|
||||
super(frameCount, bezierCount, slotIndex, Property.deform.ordinal() + "|" + slotIndex + "|" + attachment.getId());
|
||||
this.attachment = attachment;
|
||||
vertices = new float[frameCount][];
|
||||
}
|
||||
@ -1594,10 +1468,6 @@ public class Animation {
|
||||
return frames.length;
|
||||
}
|
||||
|
||||
public int getSlotIndex () {
|
||||
return slotIndex;
|
||||
}
|
||||
|
||||
/** The attachment that will be deformed.
|
||||
* <p>
|
||||
* See {@link VertexAttachment#getTimelineAttachment()}. */
|
||||
@ -1671,12 +1541,7 @@ public class Animation {
|
||||
return y + (1 - y) * (time - x) / (frames[frame + getFrameEntries()] - x);
|
||||
}
|
||||
|
||||
public void apply (Skeleton skeleton, float lastTime, float time, @Null Array<Event> events, float alpha, MixBlend blend,
|
||||
MixDirection direction, boolean appliedPose) {
|
||||
|
||||
Slot slot = skeleton.slots.get(slotIndex);
|
||||
if (!slot.bone.active) return;
|
||||
SlotPose pose = appliedPose ? slot.applied : slot.pose;
|
||||
protected void apply (Slot slot, SlotPose pose, float time, float alpha, MixBlend blend) {
|
||||
if (!(pose.attachment instanceof VertexAttachment vertexAttachment)
|
||||
|| vertexAttachment.getTimelineAttachment() != attachment) return;
|
||||
|
||||
@ -1954,8 +1819,8 @@ public class Animation {
|
||||
if (drawOrderToSetupIndex == null)
|
||||
arraycopy(skeleton.slots.items, 0, skeleton.drawOrder.items, 0, skeleton.slots.size);
|
||||
else {
|
||||
Object[] slots = skeleton.slots.items;
|
||||
Object[] drawOrder = skeleton.drawOrder.items;
|
||||
Slot[] slots = skeleton.slots.items;
|
||||
Slot[] drawOrder = skeleton.drawOrder.items;
|
||||
for (int i = 0, n = drawOrderToSetupIndex.length; i < n; i++)
|
||||
drawOrder[i] = slots[drawOrderToSetupIndex[i]];
|
||||
}
|
||||
@ -2004,12 +1869,13 @@ public class Animation {
|
||||
public void apply (Skeleton skeleton, float lastTime, float time, @Null Array<Event> events, float alpha, MixBlend blend,
|
||||
MixDirection direction, boolean appliedPose) {
|
||||
|
||||
var constraint = (IkConstraint)skeleton.constraints.get(constraintIndex);
|
||||
var constraint = (IkConstraint)skeleton.constraints.items[constraintIndex];
|
||||
if (!constraint.active) return;
|
||||
IkConstraintPose pose = appliedPose ? constraint.applied : constraint.pose, setup = constraint.data.setup;
|
||||
IkConstraintPose pose = appliedPose ? constraint.applied : constraint.pose;
|
||||
|
||||
float[] frames = this.frames;
|
||||
if (time < frames[0]) {
|
||||
IkConstraintPose setup = constraint.data.setup;
|
||||
switch (blend) {
|
||||
case setup:
|
||||
pose.mix = setup.mix;
|
||||
@ -2049,6 +1915,7 @@ public class Animation {
|
||||
}
|
||||
|
||||
if (blend == MixBlend.setup) {
|
||||
IkConstraintPose setup = constraint.data.setup;
|
||||
pose.mix = setup.mix + (mix - setup.mix) * alpha;
|
||||
pose.softness = setup.softness + (softness - setup.softness) * alpha;
|
||||
if (direction == out) {
|
||||
@ -2114,7 +1981,7 @@ public class Animation {
|
||||
public void apply (Skeleton skeleton, float lastTime, float time, @Null Array<Event> events, float alpha, MixBlend blend,
|
||||
MixDirection direction, boolean appliedPose) {
|
||||
|
||||
var constraint = (TransformConstraint)skeleton.constraints.get(constraintIndex);
|
||||
var constraint = (TransformConstraint)skeleton.constraints.items[constraintIndex];
|
||||
if (!constraint.active) return;
|
||||
TransformConstraintPose pose = appliedPose ? constraint.applied : constraint.pose;
|
||||
|
||||
@ -2214,7 +2081,7 @@ public class Animation {
|
||||
public void apply (Skeleton skeleton, float lastTime, float time, @Null Array<Event> events, float alpha, MixBlend blend,
|
||||
MixDirection direction, boolean appliedPose) {
|
||||
|
||||
var constraint = (PathConstraint)skeleton.constraints.get(constraintIndex);
|
||||
var constraint = (PathConstraint)skeleton.constraints.items[constraintIndex];
|
||||
if (constraint.active) {
|
||||
PathConstraintPose pose = appliedPose ? constraint.applied : constraint.pose;
|
||||
pose.position = getAbsoluteValue(time, alpha, blend, pose.position, constraint.data.setup.position);
|
||||
@ -2240,7 +2107,7 @@ public class Animation {
|
||||
public void apply (Skeleton skeleton, float lastTime, float time, @Null Array<Event> events, float alpha, MixBlend blend,
|
||||
MixDirection direction, boolean appliedPose) {
|
||||
|
||||
var constraint = (PathConstraint)skeleton.constraints.get(constraintIndex);
|
||||
var constraint = (PathConstraint)skeleton.constraints.items[constraintIndex];
|
||||
if (constraint.active) {
|
||||
PathConstraintPose pose = appliedPose ? constraint.applied : constraint.pose;
|
||||
pose.spacing = getAbsoluteValue(time, alpha, blend, pose.spacing, constraint.data.setup.spacing);
|
||||
@ -2285,7 +2152,7 @@ public class Animation {
|
||||
public void apply (Skeleton skeleton, float lastTime, float time, @Null Array<Event> events, float alpha, MixBlend blend,
|
||||
MixDirection direction, boolean appliedPose) {
|
||||
|
||||
var constraint = (PathConstraint)skeleton.constraints.get(constraintIndex);
|
||||
var constraint = (PathConstraint)skeleton.constraints.items[constraintIndex];
|
||||
if (!constraint.active) return;
|
||||
PathConstraintPose pose = appliedPose ? constraint.applied : constraint.pose;
|
||||
|
||||
@ -2365,16 +2232,16 @@ public class Animation {
|
||||
if (constraintIndex == -1) {
|
||||
float value = time >= frames[0] ? getCurveValue(time) : 0;
|
||||
|
||||
Object[] constraints = skeleton.physics.items;
|
||||
PhysicsConstraint[] constraints = skeleton.physics.items;
|
||||
for (int i = 0, n = skeleton.physics.size; i < n; i++) {
|
||||
var constraint = (PhysicsConstraint)constraints[i];
|
||||
PhysicsConstraint constraint = constraints[i];
|
||||
if (constraint.active && global(constraint.data)) {
|
||||
PhysicsConstraintPose pose = appliedPose ? constraint.applied : constraint.pose;
|
||||
set(pose, getAbsoluteValue(time, alpha, blend, get(pose), get(constraint.data.setup), value));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var constraint = (PhysicsConstraint)skeleton.constraints.get(constraintIndex);
|
||||
var constraint = (PhysicsConstraint)skeleton.constraints.items[constraintIndex];
|
||||
if (constraint.active) {
|
||||
PhysicsConstraintPose pose = appliedPose ? constraint.applied : constraint.pose;
|
||||
set(pose, getAbsoluteValue(time, alpha, blend, get(pose), get(constraint.data.setup)));
|
||||
@ -2556,7 +2423,7 @@ public class Animation {
|
||||
|
||||
PhysicsConstraint constraint = null;
|
||||
if (constraintIndex != -1) {
|
||||
constraint = (PhysicsConstraint)skeleton.constraints.get(constraintIndex);
|
||||
constraint = (PhysicsConstraint)skeleton.constraints.items[constraintIndex];
|
||||
if (!constraint.active) return;
|
||||
}
|
||||
|
||||
@ -2573,9 +2440,9 @@ public class Animation {
|
||||
if (constraint != null)
|
||||
constraint.reset(skeleton);
|
||||
else {
|
||||
Object[] constraints = skeleton.physics.items;
|
||||
PhysicsConstraint[] constraints = skeleton.physics.items;
|
||||
for (int i = 0, n = skeleton.physics.size; i < n; i++) {
|
||||
constraint = (PhysicsConstraint)constraints[i];
|
||||
constraint = constraints[i];
|
||||
if (constraint.active) constraint.reset(skeleton);
|
||||
}
|
||||
}
|
||||
@ -2623,7 +2490,7 @@ public class Animation {
|
||||
public void apply (Skeleton skeleton, float lastTime, float time, @Null Array<Event> events, float alpha, MixBlend blend,
|
||||
MixDirection direction, boolean appliedPose) {
|
||||
|
||||
Slot slot = skeleton.slots.get(slotIndex);
|
||||
Slot slot = skeleton.slots.items[slotIndex];
|
||||
if (!slot.bone.active) return;
|
||||
SlotPose pose = appliedPose ? slot.applied : slot.pose;
|
||||
|
||||
|
||||
@ -51,7 +51,7 @@ import com.esotericsoftware.spine.Animation.Timeline;
|
||||
* <p>
|
||||
* See <a href='https://esotericsoftware.com/spine-applying-animations/'>Applying Animations</a> in the Spine Runtimes Guide. */
|
||||
public class AnimationState {
|
||||
static final Animation emptyAnimation = new Animation("<empty>", new Array(0), 0);
|
||||
static final Animation emptyAnimation = new Animation("<empty>", new Array(true, 0, Timeline[]::new), 0);
|
||||
|
||||
/** 1) A previously applied timeline has set this property.<br>
|
||||
* Result: Mix from the current pose to the timeline pose. */
|
||||
@ -87,9 +87,9 @@ public class AnimationState {
|
||||
static private final int SETUP = 1, CURRENT = 2;
|
||||
|
||||
private AnimationStateData data;
|
||||
final Array<TrackEntry> tracks = new Array();
|
||||
private final Array<Event> events = new Array();
|
||||
final SnapshotArray<AnimationStateListener> listeners = new SnapshotArray();
|
||||
final Array<TrackEntry> tracks = new Array(true, 4, TrackEntry[]::new);
|
||||
private final Array<Event> events = new Array(true, 4, Event[]::new);
|
||||
final SnapshotArray<AnimationStateListener> listeners = new SnapshotArray(true, 16, AnimationStateListener[]::new);
|
||||
private final EventQueue queue = new EventQueue();
|
||||
private final ObjectSet<String> propertyIds = new ObjectSet();
|
||||
boolean animationsChanged;
|
||||
@ -114,9 +114,9 @@ public class AnimationState {
|
||||
/** Increments each track entry {@link TrackEntry#getTrackTime()}, setting queued animations as current if needed. */
|
||||
public void update (float delta) {
|
||||
delta *= timeScale;
|
||||
Object[] tracks = this.tracks.items;
|
||||
TrackEntry[] tracks = this.tracks.items;
|
||||
for (int i = 0, n = this.tracks.size; i < n; i++) {
|
||||
var current = (TrackEntry)tracks[i];
|
||||
TrackEntry current = tracks[i];
|
||||
if (current == null) continue;
|
||||
|
||||
current.animationLast = current.nextAnimationLast;
|
||||
@ -206,9 +206,9 @@ public class AnimationState {
|
||||
|
||||
Array<Event> events = this.events;
|
||||
boolean applied = false;
|
||||
Object[] tracks = this.tracks.items;
|
||||
TrackEntry[] tracks = this.tracks.items;
|
||||
for (int i = 0, n = this.tracks.size; i < n; i++) {
|
||||
var current = (TrackEntry)tracks[i];
|
||||
TrackEntry current = tracks[i];
|
||||
if (current == null || current.delay > 0) continue;
|
||||
applied = true;
|
||||
|
||||
@ -231,17 +231,15 @@ public class AnimationState {
|
||||
applyEvents = null;
|
||||
}
|
||||
int timelineCount = current.animation.timelines.size;
|
||||
Object[] timelines = current.animation.timelines.items;
|
||||
Timeline[] timelines = current.animation.timelines.items;
|
||||
if ((i == 0 && alpha == 1) || blend == MixBlend.add) {
|
||||
if (i == 0) attachments = true;
|
||||
for (int ii = 0; ii < timelineCount; ii++) {
|
||||
Object timeline = timelines[ii];
|
||||
Timeline timeline = timelines[ii];
|
||||
if (timeline instanceof AttachmentTimeline attachmentTimeline)
|
||||
applyAttachmentTimeline(attachmentTimeline, skeleton, applyTime, blend, attachments);
|
||||
else {
|
||||
((Timeline)timeline).apply(skeleton, animationLast, applyTime, applyEvents, alpha, blend, MixDirection.in,
|
||||
false);
|
||||
}
|
||||
else
|
||||
timeline.apply(skeleton, animationLast, applyTime, applyEvents, alpha, blend, MixDirection.in, false);
|
||||
}
|
||||
} else {
|
||||
int[] timelineMode = current.timelineMode.items;
|
||||
@ -252,7 +250,7 @@ public class AnimationState {
|
||||
float[] timelinesRotation = current.timelinesRotation.items;
|
||||
|
||||
for (int ii = 0; ii < timelineCount; ii++) {
|
||||
var timeline = (Timeline)timelines[ii];
|
||||
Timeline timeline = timelines[ii];
|
||||
MixBlend timelineBlend = timelineMode[ii] == SUBSEQUENT ? blend : MixBlend.setup;
|
||||
if (!shortestRotation && timeline instanceof RotateTimeline rotateTimeline) {
|
||||
applyRotateTimeline(rotateTimeline, skeleton, applyTime, alpha, timelineBlend, timelinesRotation, ii << 1,
|
||||
@ -273,9 +271,9 @@ public class AnimationState {
|
||||
// subsequent timelines see any deform, but the subsequent timelines don't set an attachment (eg they are also mixing out or
|
||||
// the time is before the first key).
|
||||
int setupState = unkeyedState + SETUP;
|
||||
Object[] slots = skeleton.slots.items;
|
||||
Slot[] slots = skeleton.slots.items;
|
||||
for (int i = 0, n = skeleton.slots.size; i < n; i++) {
|
||||
var slot = (Slot)slots[i];
|
||||
var slot = slots[i];
|
||||
if (slot.attachmentState == setupState) {
|
||||
String attachmentName = slot.data.attachmentName;
|
||||
slot.pose.setAttachment(attachmentName == null ? null : skeleton.getAttachment(slot.data.index, attachmentName));
|
||||
@ -303,7 +301,7 @@ public class AnimationState {
|
||||
|
||||
boolean attachments = mix < from.mixAttachmentThreshold, drawOrder = mix < from.mixDrawOrderThreshold;
|
||||
int timelineCount = from.animation.timelines.size;
|
||||
Object[] timelines = from.animation.timelines.items;
|
||||
Timeline[] timelines = from.animation.timelines.items;
|
||||
float alphaHold = from.alpha * to.interruptAlpha, alphaMix = alphaHold * (1 - mix);
|
||||
float animationLast = from.animationLast, animationTime = from.getAnimationTime(), applyTime = animationTime;
|
||||
Array<Event> events = null;
|
||||
@ -315,10 +313,10 @@ public class AnimationState {
|
||||
|
||||
if (blend == MixBlend.add) {
|
||||
for (int i = 0; i < timelineCount; i++)
|
||||
((Timeline)timelines[i]).apply(skeleton, animationLast, applyTime, events, alphaMix, blend, MixDirection.out, false);
|
||||
timelines[i].apply(skeleton, animationLast, applyTime, events, alphaMix, blend, MixDirection.out, false);
|
||||
} else {
|
||||
int[] timelineMode = from.timelineMode.items;
|
||||
Object[] timelineHoldMix = from.timelineHoldMix.items;
|
||||
TrackEntry[] timelineHoldMix = from.timelineHoldMix.items;
|
||||
|
||||
boolean shortestRotation = from.shortestRotation;
|
||||
boolean firstFrame = !shortestRotation && from.timelinesRotation.size != timelineCount << 1;
|
||||
@ -327,7 +325,7 @@ public class AnimationState {
|
||||
|
||||
from.totalAlpha = 0;
|
||||
for (int i = 0; i < timelineCount; i++) {
|
||||
var timeline = (Timeline)timelines[i];
|
||||
Timeline timeline = timelines[i];
|
||||
MixDirection direction = MixDirection.out;
|
||||
MixBlend timelineBlend;
|
||||
float alpha;
|
||||
@ -351,7 +349,7 @@ public class AnimationState {
|
||||
break;
|
||||
default: // HOLD_MIX
|
||||
timelineBlend = MixBlend.setup;
|
||||
var holdMix = (TrackEntry)timelineHoldMix[i];
|
||||
TrackEntry holdMix = timelineHoldMix[i];
|
||||
alpha = alphaHold * Math.max(0, 1 - holdMix.mixTime / holdMix.mixDuration);
|
||||
break;
|
||||
}
|
||||
@ -385,7 +383,7 @@ public class AnimationState {
|
||||
private void applyAttachmentTimeline (AttachmentTimeline timeline, Skeleton skeleton, float time, MixBlend blend,
|
||||
boolean attachments) {
|
||||
|
||||
Slot slot = skeleton.slots.get(timeline.slotIndex);
|
||||
Slot slot = skeleton.slots.items[timeline.slotIndex];
|
||||
if (!slot.bone.active) return;
|
||||
|
||||
if (time < timeline.frames[0]) { // Time is before first frame.
|
||||
@ -415,7 +413,7 @@ public class AnimationState {
|
||||
return;
|
||||
}
|
||||
|
||||
Bone bone = skeleton.bones.get(timeline.boneIndex);
|
||||
Bone bone = skeleton.bones.items[timeline.boneIndex];
|
||||
if (!bone.active) return;
|
||||
BoneLocal pose = bone.pose, setup = bone.data.setup;
|
||||
float[] frames = timeline.frames;
|
||||
@ -475,10 +473,10 @@ public class AnimationState {
|
||||
float trackLastWrapped = entry.trackLast % duration;
|
||||
|
||||
// Queue events before complete.
|
||||
Object[] events = this.events.items;
|
||||
Event[] events = this.events.items;
|
||||
int i = 0, n = this.events.size;
|
||||
for (; i < n; i++) {
|
||||
var event = (Event)events[i];
|
||||
Event event = events[i];
|
||||
if (event.time < trackLastWrapped) break;
|
||||
if (event.time > animationEnd) continue; // Discard events outside animation start/end.
|
||||
queue.event(entry, event);
|
||||
@ -499,7 +497,7 @@ public class AnimationState {
|
||||
|
||||
// Queue events after complete.
|
||||
for (; i < n; i++) {
|
||||
var event = (Event)events[i];
|
||||
Event event = events[i];
|
||||
if (event.time < animationStart) continue; // Discard events outside animation start/end.
|
||||
queue.event(entry, event);
|
||||
}
|
||||
@ -526,7 +524,7 @@ public class AnimationState {
|
||||
public void clearTrack (int trackIndex) {
|
||||
if (trackIndex < 0) throw new IllegalArgumentException("trackIndex must be >= 0.");
|
||||
if (trackIndex >= tracks.size) return;
|
||||
TrackEntry current = tracks.get(trackIndex);
|
||||
TrackEntry current = tracks.items[trackIndex];
|
||||
if (current == null) return;
|
||||
|
||||
queue.end(current);
|
||||
@ -543,14 +541,14 @@ public class AnimationState {
|
||||
entry = from;
|
||||
}
|
||||
|
||||
tracks.set(current.trackIndex, null);
|
||||
tracks.items[current.trackIndex] = null;
|
||||
|
||||
queue.drain();
|
||||
}
|
||||
|
||||
private void setCurrent (int index, TrackEntry current, boolean interrupt) {
|
||||
TrackEntry from = expandToIndex(index);
|
||||
tracks.set(index, current);
|
||||
tracks.items[index] = current;
|
||||
current.previous = null;
|
||||
|
||||
if (from != null) {
|
||||
@ -594,7 +592,7 @@ public class AnimationState {
|
||||
if (current != null) {
|
||||
if (current.nextTrackLast == -1 && current.animation == animation) {
|
||||
// Don't mix from an entry that was never applied.
|
||||
tracks.set(trackIndex, current.mixingFrom);
|
||||
tracks.items[trackIndex] = current.mixingFrom;
|
||||
queue.interrupt(current);
|
||||
queue.end(current);
|
||||
clearNext(current);
|
||||
@ -704,9 +702,9 @@ public class AnimationState {
|
||||
public void setEmptyAnimations (float mixDuration) {
|
||||
boolean oldDrainDisabled = queue.drainDisabled;
|
||||
queue.drainDisabled = true;
|
||||
Object[] tracks = this.tracks.items;
|
||||
TrackEntry[] tracks = this.tracks.items;
|
||||
for (int i = 0, n = this.tracks.size; i < n; i++) {
|
||||
var current = (TrackEntry)tracks[i];
|
||||
TrackEntry current = tracks[i];
|
||||
if (current != null) setEmptyAnimation(current.trackIndex, mixDuration);
|
||||
}
|
||||
queue.drainDisabled = oldDrainDisabled;
|
||||
@ -714,7 +712,7 @@ public class AnimationState {
|
||||
}
|
||||
|
||||
private TrackEntry expandToIndex (int index) {
|
||||
if (index < tracks.size) return tracks.get(index);
|
||||
if (index < tracks.size) return tracks.items[index];
|
||||
tracks.ensureCapacity(index - tracks.size + 1);
|
||||
tracks.size = index + 1;
|
||||
return null;
|
||||
@ -772,9 +770,9 @@ public class AnimationState {
|
||||
// Process in the order that animations are applied.
|
||||
propertyIds.clear(2048);
|
||||
int n = tracks.size;
|
||||
Object[] tracks = this.tracks.items;
|
||||
TrackEntry[] tracks = this.tracks.items;
|
||||
for (int i = 0; i < n; i++) {
|
||||
var entry = (TrackEntry)tracks[i];
|
||||
TrackEntry entry = tracks[i];
|
||||
if (entry == null) continue;
|
||||
while (entry.mixingFrom != null) // Move to last entry, then iterate in reverse.
|
||||
entry = entry.mixingFrom;
|
||||
@ -787,22 +785,22 @@ public class AnimationState {
|
||||
|
||||
private void computeHold (TrackEntry entry) {
|
||||
TrackEntry to = entry.mixingTo;
|
||||
Object[] timelines = entry.animation.timelines.items;
|
||||
Timeline[] timelines = entry.animation.timelines.items;
|
||||
int timelinesCount = entry.animation.timelines.size;
|
||||
int[] timelineMode = entry.timelineMode.setSize(timelinesCount);
|
||||
entry.timelineHoldMix.clear();
|
||||
Object[] timelineHoldMix = entry.timelineHoldMix.setSize(timelinesCount);
|
||||
TrackEntry[] timelineHoldMix = entry.timelineHoldMix.setSize(timelinesCount);
|
||||
ObjectSet<String> propertyIds = this.propertyIds;
|
||||
|
||||
if (to != null && to.holdPrevious) {
|
||||
for (int i = 0; i < timelinesCount; i++)
|
||||
timelineMode[i] = propertyIds.addAll(((Timeline)timelines[i]).getPropertyIds()) ? HOLD_FIRST : HOLD_SUBSEQUENT;
|
||||
timelineMode[i] = propertyIds.addAll(timelines[i].getPropertyIds()) ? HOLD_FIRST : HOLD_SUBSEQUENT;
|
||||
return;
|
||||
}
|
||||
|
||||
outer:
|
||||
for (int i = 0; i < timelinesCount; i++) {
|
||||
var timeline = (Timeline)timelines[i];
|
||||
Timeline timeline = timelines[i];
|
||||
String[] ids = timeline.getPropertyIds();
|
||||
if (!propertyIds.addAll(ids))
|
||||
timelineMode[i] = SUBSEQUENT;
|
||||
@ -828,7 +826,7 @@ public class AnimationState {
|
||||
public @Null TrackEntry getCurrent (int trackIndex) {
|
||||
if (trackIndex < 0) throw new IllegalArgumentException("trackIndex must be >= 0.");
|
||||
if (trackIndex >= tracks.size) return null;
|
||||
return tracks.get(trackIndex);
|
||||
return tracks.items[trackIndex];
|
||||
}
|
||||
|
||||
/** Adds a listener to receive events for all track entries. */
|
||||
@ -883,9 +881,9 @@ public class AnimationState {
|
||||
|
||||
public String toString () {
|
||||
var buffer = new StringBuilder(64);
|
||||
Object[] tracks = this.tracks.items;
|
||||
TrackEntry[] tracks = this.tracks.items;
|
||||
for (int i = 0, n = this.tracks.size; i < n; i++) {
|
||||
var entry = (TrackEntry)tracks[i];
|
||||
TrackEntry entry = tracks[i];
|
||||
if (entry == null) continue;
|
||||
if (buffer.length() > 0) buffer.append(", ");
|
||||
buffer.append(entry.toString());
|
||||
@ -910,7 +908,7 @@ public class AnimationState {
|
||||
MixBlend mixBlend = MixBlend.replace;
|
||||
|
||||
final IntArray timelineMode = new IntArray();
|
||||
final Array<TrackEntry> timelineHoldMix = new Array();
|
||||
final Array<TrackEntry> timelineHoldMix = new Array(true, 8, TrackEntry[]::new);
|
||||
final FloatArray timelinesRotation = new FloatArray();
|
||||
|
||||
public void reset () {
|
||||
@ -1366,43 +1364,44 @@ public class AnimationState {
|
||||
drainDisabled = true;
|
||||
|
||||
SnapshotArray<AnimationStateListener> listenersArray = AnimationState.this.listeners;
|
||||
Object[] objects = this.objects.items;
|
||||
for (int i = 0; i < this.objects.size; i += 2) {
|
||||
var type = (EventType)objects.get(i);
|
||||
var entry = (TrackEntry)objects.get(i + 1);
|
||||
int listenersCount = listenersArray.size;
|
||||
Object[] listeners = listenersArray.begin();
|
||||
var type = (EventType)objects[i];
|
||||
var entry = (TrackEntry)objects[i + 1];
|
||||
int nn = listenersArray.size;
|
||||
AnimationStateListener[] listeners = listenersArray.begin();
|
||||
switch (type) {
|
||||
case start:
|
||||
if (entry.listener != null) entry.listener.start(entry);
|
||||
for (int ii = 0; ii < listenersCount; ii++)
|
||||
((AnimationStateListener)listeners[ii]).start(entry);
|
||||
for (int ii = 0; ii < nn; ii++)
|
||||
listeners[ii].start(entry);
|
||||
break;
|
||||
case interrupt:
|
||||
if (entry.listener != null) entry.listener.interrupt(entry);
|
||||
for (int ii = 0; ii < listenersCount; ii++)
|
||||
((AnimationStateListener)listeners[ii]).interrupt(entry);
|
||||
for (int ii = 0; ii < nn; ii++)
|
||||
listeners[ii].interrupt(entry);
|
||||
break;
|
||||
case end:
|
||||
if (entry.listener != null) entry.listener.end(entry);
|
||||
for (int ii = 0; ii < listenersCount; ii++)
|
||||
((AnimationStateListener)listeners[ii]).end(entry);
|
||||
for (int ii = 0; ii < nn; ii++)
|
||||
listeners[ii].end(entry);
|
||||
// Fall through.
|
||||
case dispose:
|
||||
if (entry.listener != null) entry.listener.dispose(entry);
|
||||
for (int ii = 0; ii < listenersCount; ii++)
|
||||
((AnimationStateListener)listeners[ii]).dispose(entry);
|
||||
for (int ii = 0; ii < nn; ii++)
|
||||
listeners[ii].dispose(entry);
|
||||
trackEntryPool.free(entry);
|
||||
break;
|
||||
case complete:
|
||||
if (entry.listener != null) entry.listener.complete(entry);
|
||||
for (int ii = 0; ii < listenersCount; ii++)
|
||||
((AnimationStateListener)listeners[ii]).complete(entry);
|
||||
for (int ii = 0; ii < nn; ii++)
|
||||
listeners[ii].complete(entry);
|
||||
break;
|
||||
case event:
|
||||
var event = (Event)objects.get(i++ + 2);
|
||||
var event = (Event)objects[i++ + 2];
|
||||
if (entry.listener != null) entry.listener.event(entry, event);
|
||||
for (int ii = 0; ii < listenersCount; ii++)
|
||||
((AnimationStateListener)listeners[ii]).event(entry, event);
|
||||
for (int ii = 0; ii < nn; ii++)
|
||||
listeners[ii].event(entry, event);
|
||||
break;
|
||||
}
|
||||
listenersArray.end();
|
||||
|
||||
@ -40,7 +40,7 @@ import com.badlogic.gdx.utils.Null;
|
||||
* constraint or application code modifies the world transform after it was computed from the local transform. */
|
||||
public class Bone extends PosedActive<BoneData, BoneLocal, BonePose> {
|
||||
@Null final Bone parent;
|
||||
final Array<Bone> children = new Array();
|
||||
final Array<Bone> children = new Array(true, 4, Bone[]::new);
|
||||
boolean sorted;
|
||||
|
||||
public Bone (BoneData data, @Null Bone parent) {
|
||||
|
||||
@ -47,11 +47,11 @@ public class IkConstraint extends Constraint<IkConstraint, IkConstraintData, IkC
|
||||
super(data, new IkConstraintPose(), new IkConstraintPose());
|
||||
if (skeleton == null) throw new IllegalArgumentException("skeleton cannot be null.");
|
||||
|
||||
bones = new Array(data.bones.size);
|
||||
bones = new Array(true, data.bones.size, BonePose[]::new);
|
||||
for (BoneData boneData : data.bones)
|
||||
bones.add(skeleton.bones.get(boneData.index).constrained);
|
||||
bones.add(skeleton.bones.items[boneData.index].constrained);
|
||||
|
||||
target = skeleton.bones.get(data.target.index);
|
||||
target = skeleton.bones.items[data.target.index];
|
||||
}
|
||||
|
||||
public IkConstraint copy (Skeleton skeleton) {
|
||||
@ -65,25 +65,25 @@ public class IkConstraint extends Constraint<IkConstraint, IkConstraintData, IkC
|
||||
IkConstraintPose a = applied;
|
||||
if (a.mix == 0) return;
|
||||
BonePose target = this.target.applied;
|
||||
Object[] bones = this.bones.items;
|
||||
BonePose[] bones = this.bones.items;
|
||||
switch (this.bones.size) {
|
||||
case 1 -> apply(skeleton, (BonePose)bones[0], target.worldX, target.worldY, a.compress, a.stretch, data.uniform, a.mix);
|
||||
case 2 -> apply(skeleton, (BonePose)bones[0], (BonePose)bones[1], target.worldX, target.worldY, a.bendDirection, a.stretch,
|
||||
data.uniform, a.softness, a.mix);
|
||||
case 1 -> apply(skeleton, bones[0], target.worldX, target.worldY, a.compress, a.stretch, data.uniform, a.mix);
|
||||
case 2 -> apply(skeleton, bones[0], bones[1], target.worldX, target.worldY, a.bendDirection, a.stretch, data.uniform,
|
||||
a.softness, a.mix);
|
||||
}
|
||||
}
|
||||
|
||||
void sort (Skeleton skeleton) {
|
||||
skeleton.sortBone(target);
|
||||
|
||||
Bone parent = bones.first().bone;
|
||||
Bone parent = bones.items[0].bone;
|
||||
skeleton.sortBone(parent);
|
||||
skeleton.resetCache(parent);
|
||||
if (bones.size == 1) {
|
||||
skeleton.updateCache.add(this);
|
||||
skeleton.sortReset(parent.children);
|
||||
} else {
|
||||
Bone child = bones.peek().bone;
|
||||
Bone child = bones.items[1].bone;
|
||||
skeleton.resetCache(child);
|
||||
skeleton.sortBone(child);
|
||||
|
||||
|
||||
@ -35,7 +35,7 @@ import com.badlogic.gdx.utils.Array;
|
||||
* <p>
|
||||
* See <a href="https://esotericsoftware.com/spine-ik-constraints">IK constraints</a> in the Spine User Guide. */
|
||||
public class IkConstraintData extends ConstraintData<IkConstraint, IkConstraintPose> {
|
||||
final Array<BoneData> bones = new Array();
|
||||
final Array<BoneData> bones = new Array(true, 2, BoneData[]::new);
|
||||
BoneData target;
|
||||
boolean uniform;
|
||||
|
||||
|
||||
@ -62,11 +62,11 @@ public class PathConstraint extends Constraint<PathConstraint, PathConstraintDat
|
||||
super(data, new PathConstraintPose(), new PathConstraintPose());
|
||||
if (skeleton == null) throw new IllegalArgumentException("skeleton cannot be null.");
|
||||
|
||||
bones = new Array(data.bones.size);
|
||||
bones = new Array(true, data.bones.size, BonePose[]::new);
|
||||
for (BoneData boneData : data.bones)
|
||||
bones.add(skeleton.bones.get(boneData.index).constrained);
|
||||
bones.add(skeleton.bones.items[boneData.index].constrained);
|
||||
|
||||
slot = skeleton.slots.get(data.slot.index);
|
||||
slot = skeleton.slots.items[data.slot.index];
|
||||
}
|
||||
|
||||
public PathConstraint copy (Skeleton skeleton) {
|
||||
@ -86,7 +86,7 @@ public class PathConstraint extends Constraint<PathConstraint, PathConstraintDat
|
||||
PathConstraintData data = this.data;
|
||||
boolean tangents = data.rotateMode == RotateMode.tangent, scale = data.rotateMode == RotateMode.chainScale;
|
||||
int boneCount = this.bones.size, spacesCount = tangents ? boneCount : boneCount + 1;
|
||||
Object[] bones = this.bones.items;
|
||||
BonePose[] bones = this.bones.items;
|
||||
float[] spaces = this.spaces.setSize(spacesCount), lengths = scale ? this.lengths.setSize(boneCount) : null;
|
||||
float spacing = pose.spacing;
|
||||
|
||||
@ -94,7 +94,7 @@ public class PathConstraint extends Constraint<PathConstraint, PathConstraintDat
|
||||
case percent -> {
|
||||
if (scale) {
|
||||
for (int i = 0, n = spacesCount - 1; i < n; i++) {
|
||||
var bone = (BonePose)bones[i];
|
||||
BonePose bone = bones[i];
|
||||
float setupLength = bone.bone.data.length;
|
||||
float x = setupLength * bone.a, y = setupLength * bone.c;
|
||||
lengths[i] = (float)Math.sqrt(x * x + y * y);
|
||||
@ -105,7 +105,7 @@ public class PathConstraint extends Constraint<PathConstraint, PathConstraintDat
|
||||
case proportional -> {
|
||||
float sum = 0;
|
||||
for (int i = 0, n = spacesCount - 1; i < n;) {
|
||||
var bone = (BonePose)bones[i];
|
||||
BonePose bone = bones[i];
|
||||
float setupLength = bone.bone.data.length;
|
||||
if (setupLength < epsilon) {
|
||||
if (scale) lengths[i] = 0;
|
||||
@ -127,7 +127,7 @@ public class PathConstraint extends Constraint<PathConstraint, PathConstraintDat
|
||||
default -> {
|
||||
boolean lengthSpacing = data.spacingMode == SpacingMode.length;
|
||||
for (int i = 0, n = spacesCount - 1; i < n;) {
|
||||
var bone = (BonePose)bones[i];
|
||||
BonePose bone = bones[i];
|
||||
float setupLength = bone.bone.data.length;
|
||||
if (setupLength < epsilon) {
|
||||
if (scale) lengths[i] = 0;
|
||||
@ -153,7 +153,7 @@ public class PathConstraint extends Constraint<PathConstraint, PathConstraintDat
|
||||
offsetRotation *= p.a * p.d - p.b * p.c > 0 ? degRad : -degRad;
|
||||
}
|
||||
for (int i = 0, p = 3; i < boneCount; i++, p += 3) {
|
||||
var bone = (BonePose)bones[i];
|
||||
BonePose bone = bones[i];
|
||||
bone.worldX += (boneX - bone.worldX) * mixX;
|
||||
bone.worldY += (boneY - bone.worldY) * mixY;
|
||||
float x = positions[p], y = positions[p + 1], dx = x - boneX, dy = y - boneY;
|
||||
@ -467,10 +467,10 @@ public class PathConstraint extends Constraint<PathConstraint, PathConstraintDat
|
||||
|
||||
sortPathConstraintAttachment(skeleton, slot.pose.attachment, slotBone);
|
||||
|
||||
Object[] bones = this.bones.items;
|
||||
BonePose[] bones = this.bones.items;
|
||||
int boneCount = this.bones.size;
|
||||
for (int i = 0; i < boneCount; i++) {
|
||||
Bone bone = ((BonePose)bones[i]).bone;
|
||||
Bone bone = bones[i].bone;
|
||||
skeleton.resetCache(bone);
|
||||
skeleton.sortBone(bone);
|
||||
}
|
||||
@ -478,9 +478,9 @@ public class PathConstraint extends Constraint<PathConstraint, PathConstraintDat
|
||||
skeleton.updateCache.add(this);
|
||||
|
||||
for (int i = 0; i < boneCount; i++)
|
||||
skeleton.sortReset(((BonePose)bones[i]).bone.children);
|
||||
skeleton.sortReset(bones[i].bone.children);
|
||||
for (int i = 0; i < boneCount; i++)
|
||||
((BonePose)bones[i]).bone.sorted = true;
|
||||
bones[i].bone.sorted = true;
|
||||
}
|
||||
|
||||
private void sortPathConstraintAttachment (Skeleton skeleton, Skin skin, int slotIndex, Bone slotBone) {
|
||||
@ -497,12 +497,12 @@ public class PathConstraint extends Constraint<PathConstraint, PathConstraintDat
|
||||
if (pathBones == null)
|
||||
skeleton.sortBone(slotBone);
|
||||
else {
|
||||
Object[] bones = skeleton.bones.items;
|
||||
Bone[] bones = skeleton.bones.items;
|
||||
for (int i = 0, n = pathBones.length; i < n;) {
|
||||
int nn = pathBones[i++];
|
||||
nn += i;
|
||||
while (i < nn)
|
||||
skeleton.sortBone((Bone)bones[pathBones[i++]]);
|
||||
skeleton.sortBone(bones[pathBones[i++]]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -35,7 +35,7 @@ import com.badlogic.gdx.utils.Array;
|
||||
* <p>
|
||||
* See <a href="https://esotericsoftware.com/spine-path-constraints">Path constraints</a> in the Spine User Guide. */
|
||||
public class PathConstraintData extends ConstraintData<PathConstraint, PathConstraintPose> {
|
||||
final Array<BoneData> bones = new Array();
|
||||
final Array<BoneData> bones = new Array(true, 0, BoneData[]::new);
|
||||
SlotData slot;
|
||||
PositionMode positionMode;
|
||||
SpacingMode spacingMode;
|
||||
|
||||
@ -49,7 +49,7 @@ public class PhysicsConstraint extends Constraint<PhysicsConstraint, PhysicsCons
|
||||
super(data, new PhysicsConstraintPose(), new PhysicsConstraintPose());
|
||||
if (skeleton == null) throw new IllegalArgumentException("skeleton cannot be null.");
|
||||
|
||||
bone = skeleton.bones.get(data.bone.index).constrained;
|
||||
bone = skeleton.bones.items[data.bone.index].constrained;
|
||||
}
|
||||
|
||||
public PhysicsConstraint copy (Skeleton skeleton) {
|
||||
|
||||
@ -36,15 +36,11 @@ abstract public class Posed< //
|
||||
return applied;
|
||||
}
|
||||
|
||||
public A getConstrainedPose () {
|
||||
return constrained;
|
||||
}
|
||||
|
||||
public void setConstrained (boolean constrained) {
|
||||
void setConstrained (boolean constrained) {
|
||||
applied = constrained ? this.constrained : (A)pose;
|
||||
}
|
||||
|
||||
public void resetAppliedPose () {
|
||||
void resetAppliedPose () {
|
||||
applied.set(pose);
|
||||
}
|
||||
|
||||
|
||||
@ -57,7 +57,7 @@ public class Skeleton {
|
||||
final Array<Constraint> constraints;
|
||||
final Array<PhysicsConstraint> physics;
|
||||
final Array updateCache = new Array();
|
||||
final Array<Posed> resetCache = new Array();
|
||||
final Array<Posed> resetCache = new Array(true, 16, Posed[]::new);
|
||||
@Null Skin skin;
|
||||
final Color color;
|
||||
float x, y, scaleX = 1, scaleY = 1, time;
|
||||
@ -66,35 +66,36 @@ public class Skeleton {
|
||||
if (data == null) throw new IllegalArgumentException("data cannot be null.");
|
||||
this.data = data;
|
||||
|
||||
bones = new Array(data.bones.size);
|
||||
Object[] bones = this.bones.items;
|
||||
bones = new Array(true, data.bones.size, Bone[]::new);
|
||||
Bone[] bones = this.bones.items;
|
||||
for (BoneData boneData : data.bones) {
|
||||
Bone bone;
|
||||
if (boneData.parent == null)
|
||||
bone = new Bone(boneData, null);
|
||||
else {
|
||||
var parent = (Bone)bones[boneData.parent.index];
|
||||
Bone parent = bones[boneData.parent.index];
|
||||
bone = new Bone(boneData, parent);
|
||||
parent.children.add(bone);
|
||||
}
|
||||
this.bones.add(bone);
|
||||
}
|
||||
|
||||
slots = new Array(data.slots.size);
|
||||
drawOrder = new Array(data.slots.size);
|
||||
slots = new Array(true, data.slots.size, Slot[]::new);
|
||||
drawOrder = new Array(true, data.slots.size, Slot[]::new);
|
||||
for (SlotData slotData : data.slots) {
|
||||
var slot = new Slot(slotData, this);
|
||||
slots.add(slot);
|
||||
drawOrder.add(slot);
|
||||
}
|
||||
|
||||
constraints = new Array(data.constraints.size);
|
||||
physics = new Array();
|
||||
physics = new Array(true, 8, PhysicsConstraint[]::new);
|
||||
constraints = new Array(true, data.constraints.size, Constraint[]::new);
|
||||
for (ConstraintData constraintData : data.constraints) {
|
||||
Constraint constraint = constraintData.create(this);
|
||||
if (constraint instanceof PhysicsConstraint physicsConstraint) physics.add(physicsConstraint);
|
||||
constraints.add(constraint);
|
||||
}
|
||||
physics.shrink();
|
||||
|
||||
color = new Color(1, 1, 1, 1);
|
||||
|
||||
@ -106,31 +107,29 @@ public class Skeleton {
|
||||
if (skeleton == null) throw new IllegalArgumentException("skeleton cannot be null.");
|
||||
data = skeleton.data;
|
||||
|
||||
bones = new Array(skeleton.bones.size);
|
||||
bones = new Array(true, skeleton.bones.size, Bone[]::new);
|
||||
for (Bone bone : skeleton.bones) {
|
||||
Bone newBone;
|
||||
if (bone.parent == null)
|
||||
newBone = new Bone(bone, null);
|
||||
else {
|
||||
Bone parent = bones.get(bone.parent.data.index);
|
||||
Bone parent = bones.items[bone.parent.data.index];
|
||||
newBone = new Bone(bone, parent);
|
||||
parent.children.add(newBone);
|
||||
}
|
||||
bones.add(newBone);
|
||||
}
|
||||
|
||||
slots = new Array(skeleton.slots.size);
|
||||
for (Slot slot : skeleton.slots) {
|
||||
Bone bone = bones.get(slot.bone.data.index);
|
||||
slots.add(new Slot(slot, bone, this));
|
||||
}
|
||||
slots = new Array(true, skeleton.slots.size, Slot[]::new);
|
||||
for (Slot slot : skeleton.slots)
|
||||
slots.add(new Slot(slot, bones.items[slot.bone.data.index], this));
|
||||
|
||||
drawOrder = new Array(slots.size);
|
||||
drawOrder = new Array(true, slots.size, Slot[]::new);
|
||||
for (Slot slot : skeleton.drawOrder)
|
||||
drawOrder.add(slots.get(slot.data.index));
|
||||
drawOrder.add(slots.items[slot.data.index]);
|
||||
|
||||
physics = new Array(skeleton.physics.size);
|
||||
constraints = new Array(skeleton.constraints.size);
|
||||
physics = new Array(true, skeleton.physics.size, PhysicsConstraint[]::new);
|
||||
constraints = new Array(true, skeleton.constraints.size, Constraint[]::new);
|
||||
for (Constraint other : skeleton.constraints) {
|
||||
Constraint constraint = other.copy(this);
|
||||
if (constraint instanceof PhysicsConstraint physicsConstraint) physics.add(physicsConstraint);
|
||||
@ -155,17 +154,17 @@ public class Skeleton {
|
||||
resetCache.clear();
|
||||
|
||||
int boneCount = bones.size;
|
||||
Object[] bones = this.bones.items;
|
||||
Bone[] bones = this.bones.items;
|
||||
for (int i = 0; i < boneCount; i++) {
|
||||
var bone = (Bone)bones[i];
|
||||
Bone bone = bones[i];
|
||||
bone.sorted = bone.data.skinRequired;
|
||||
bone.active = !bone.sorted;
|
||||
bone.setConstrained(false);
|
||||
}
|
||||
if (skin != null) {
|
||||
Object[] objects = skin.bones.items;
|
||||
BoneData[] skinBones = skin.bones.items;
|
||||
for (int i = 0, n = skin.bones.size; i < n; i++) {
|
||||
var bone = (Bone)objects[((BoneData)objects[i]).index];
|
||||
var bone = bones[skinBones[i].index];
|
||||
do {
|
||||
bone.sorted = false;
|
||||
bone.active = true;
|
||||
@ -174,30 +173,30 @@ public class Skeleton {
|
||||
}
|
||||
}
|
||||
|
||||
Object[] objects = constraints.items;
|
||||
int n = constraints.size;
|
||||
Constraint[] constraints = this.constraints.items;
|
||||
int n = this.constraints.size;
|
||||
for (int i = 0; i < n; i++)
|
||||
((Constraint)objects[i]).setConstrained(false);
|
||||
constraints[i].setConstrained(false);
|
||||
for (int i = 0; i < n; i++) {
|
||||
var constraint = (Constraint<?, ?, ?>)objects[i];
|
||||
Constraint<?, ?, ?> constraint = constraints[i];
|
||||
constraint.active = constraint.isSourceActive()
|
||||
&& (!constraint.data.skinRequired || (skin != null && skin.constraints.contains(constraint.data, true)));
|
||||
if (constraint.active) constraint.sort(this);
|
||||
}
|
||||
|
||||
for (int i = 0; i < boneCount; i++)
|
||||
sortBone((Bone)bones[i]);
|
||||
sortBone(bones[i]);
|
||||
|
||||
objects = this.updateCache.items;
|
||||
Object[] updateCache = this.updateCache.items;
|
||||
n = this.updateCache.size;
|
||||
for (int i = 0; i < n; i++)
|
||||
if (objects[i] instanceof Bone bone) objects[i] = bone.applied;
|
||||
if (updateCache[i] instanceof Bone bone) updateCache[i] = bone.applied;
|
||||
}
|
||||
|
||||
void resetCache (Posed object) {
|
||||
if (!resetCache.contains(object, true)) { // BOZO
|
||||
resetCache.add(object);
|
||||
if (object.pose == object.applied) {
|
||||
object.setConstrained(true);
|
||||
resetCache.add(object);
|
||||
}
|
||||
}
|
||||
|
||||
@ -210,9 +209,9 @@ public class Skeleton {
|
||||
}
|
||||
|
||||
void sortReset (Array<Bone> bones) {
|
||||
Object[] items = bones.items;
|
||||
Bone[] items = bones.items;
|
||||
for (int i = 0, n = bones.size; i < n; i++) {
|
||||
var bone = (Bone)items[i];
|
||||
Bone bone = items[i];
|
||||
if (!bone.active) continue;
|
||||
if (bone.sorted) sortReset(bone.children);
|
||||
bone.sorted = false;
|
||||
@ -224,13 +223,13 @@ public class Skeleton {
|
||||
* See <a href="https://esotericsoftware.com/spine-runtime-skeletons#World-transforms">World transforms</a> in the Spine
|
||||
* Runtimes Guide. */
|
||||
public void updateWorldTransform (Physics physics) {
|
||||
Object[] objects = this.resetCache.items;
|
||||
Posed[] resetCache = this.resetCache.items;
|
||||
for (int i = 0, n = this.resetCache.size; i < n; i++)
|
||||
((Posed)objects[i]).resetAppliedPose();
|
||||
resetCache[i].resetAppliedPose();
|
||||
|
||||
objects = this.updateCache.items;
|
||||
Object[] updateCache = this.updateCache.items;
|
||||
for (int i = 0, n = this.updateCache.size; i < n; i++)
|
||||
((Update)objects[i]).update(this, physics);
|
||||
((Update)updateCache[i]).update(this, physics);
|
||||
}
|
||||
|
||||
/** Temporarily sets the root bone as a child of the specified bone, then updates the world transform for each bone and applies
|
||||
@ -241,9 +240,9 @@ public class Skeleton {
|
||||
public void updateWorldTransform (Physics physics, BonePose parent) {
|
||||
if (parent == null) throw new IllegalArgumentException("parent cannot be null.");
|
||||
|
||||
Object[] objects = this.resetCache.items;
|
||||
Posed[] resetCache = this.resetCache.items;
|
||||
for (int i = 0, n = this.resetCache.size; i < n; i++)
|
||||
((Posed)objects[i]).resetAppliedPose();
|
||||
resetCache[i].resetAppliedPose();
|
||||
|
||||
// Apply the parent bone transform to the root bone. The root bone always inherits scale, rotation and reflection.
|
||||
BonePose rootBone = getRootBone().applied;
|
||||
@ -263,9 +262,9 @@ public class Skeleton {
|
||||
rootBone.d = (pc * lb + pd * ld) * scaleY;
|
||||
|
||||
// Update everything except root bone.
|
||||
objects = this.updateCache.items;
|
||||
Object[] updateCache = this.updateCache.items;
|
||||
for (int i = 0, n = this.updateCache.size; i < n; i++) {
|
||||
var updatable = (Update)objects[i];
|
||||
var updatable = (Update)updateCache[i];
|
||||
if (updatable != rootBone) updatable.update(this, physics);
|
||||
}
|
||||
}
|
||||
@ -278,22 +277,22 @@ public class Skeleton {
|
||||
|
||||
/** Sets the bones and constraints to their setup pose values. */
|
||||
public void setupPoseBones () {
|
||||
Object[] objects = this.bones.items;
|
||||
Bone[] bones = this.bones.items;
|
||||
for (int i = 0, n = this.bones.size; i < n; i++)
|
||||
((Bone)objects[i]).setupPose();
|
||||
bones[i].setupPose();
|
||||
|
||||
objects = constraints.items;
|
||||
for (int i = 0, n = constraints.size; i < n; i++)
|
||||
((Constraint)objects[i]).setupPose();
|
||||
Constraint[] constraints = this.constraints.items;
|
||||
for (int i = 0, n = this.constraints.size; i < n; i++)
|
||||
constraints[i].setupPose();
|
||||
}
|
||||
|
||||
/** Sets the slots and draw order to their setup pose values. */
|
||||
public void setupPoseSlots () {
|
||||
Object[] slots = this.slots.items;
|
||||
Slot[] slots = this.slots.items;
|
||||
int n = this.slots.size;
|
||||
arraycopy(slots, 0, drawOrder.items, 0, n);
|
||||
for (int i = 0; i < n; i++)
|
||||
((Slot)slots[i]).setupPose();
|
||||
slots[i].setupPose();
|
||||
}
|
||||
|
||||
/** The skeleton's setup pose data. */
|
||||
@ -320,11 +319,9 @@ public class Skeleton {
|
||||
* repeatedly. */
|
||||
public @Null Bone findBone (String boneName) {
|
||||
if (boneName == null) throw new IllegalArgumentException("boneName cannot be null.");
|
||||
Object[] bones = this.bones.items;
|
||||
for (int i = 0, n = this.bones.size; i < n; i++) {
|
||||
var bone = (Bone)bones[i];
|
||||
if (bone.data.name.equals(boneName)) return bone;
|
||||
}
|
||||
Bone[] bones = this.bones.items;
|
||||
for (int i = 0, n = this.bones.size; i < n; i++)
|
||||
if (bones[i].data.name.equals(boneName)) return bones[i];
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -337,11 +334,9 @@ public class Skeleton {
|
||||
* repeatedly. */
|
||||
public @Null Slot findSlot (String slotName) {
|
||||
if (slotName == null) throw new IllegalArgumentException("slotName cannot be null.");
|
||||
Object[] slots = this.slots.items;
|
||||
for (int i = 0, n = this.slots.size; i < n; i++) {
|
||||
var slot = (Slot)slots[i];
|
||||
if (slot.data.name.equals(slotName)) return slot;
|
||||
}
|
||||
Slot[] slots = this.slots.items;
|
||||
for (int i = 0, n = this.slots.size; i < n; i++)
|
||||
if (slots[i].data.name.equals(slotName)) return slots[i];
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -384,9 +379,9 @@ public class Skeleton {
|
||||
if (skin != null)
|
||||
newSkin.attachAll(this, skin);
|
||||
else {
|
||||
Object[] slots = this.slots.items;
|
||||
Slot[] slots = this.slots.items;
|
||||
for (int i = 0, n = this.slots.size; i < n; i++) {
|
||||
var slot = (Slot)slots[i];
|
||||
Slot slot = slots[i];
|
||||
String name = slot.data.attachmentName;
|
||||
if (name != null) {
|
||||
Attachment attachment = newSkin.getAttachment(i, name);
|
||||
@ -451,10 +446,10 @@ public class Skeleton {
|
||||
public @Null <T extends Constraint> T findConstraint (String constraintName, Class<T> type) {
|
||||
if (constraintName == null) throw new IllegalArgumentException("constraintName cannot be null.");
|
||||
if (type == null) throw new IllegalArgumentException("type cannot be null.");
|
||||
Object[] constraints = this.constraints.items;
|
||||
Constraint[] constraints = this.constraints.items;
|
||||
for (int i = 0, n = this.constraints.size; i < n; i++) {
|
||||
Object constraint = constraints[i];
|
||||
if (type.isInstance(constraint) && ((PosedData)constraint).name.equals(constraintName)) return (T)constraint;
|
||||
Constraint constraint = constraints[i];
|
||||
if (type.isInstance(constraint) && constraint.data.name.equals(constraintName)) return (T)constraint;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@ -477,10 +472,10 @@ public class Skeleton {
|
||||
if (offset == null) throw new IllegalArgumentException("offset cannot be null.");
|
||||
if (size == null) throw new IllegalArgumentException("size cannot be null.");
|
||||
if (temp == null) throw new IllegalArgumentException("temp cannot be null.");
|
||||
Object[] drawOrder = this.drawOrder.items;
|
||||
Slot[] drawOrder = this.drawOrder.items;
|
||||
float minX = Integer.MAX_VALUE, minY = Integer.MAX_VALUE, maxX = Integer.MIN_VALUE, maxY = Integer.MIN_VALUE;
|
||||
for (int i = 0, n = this.drawOrder.size; i < n; i++) {
|
||||
var slot = (Slot)drawOrder[i];
|
||||
Slot slot = drawOrder[i];
|
||||
if (!slot.bone.active) continue;
|
||||
int verticesLength = 0;
|
||||
float[] vertices = null;
|
||||
@ -601,16 +596,16 @@ public class Skeleton {
|
||||
|
||||
/** Calls {@link PhysicsConstraint#translate(float, float)} for each physics constraint. */
|
||||
public void physicsTranslate (float x, float y) {
|
||||
Object[] physicsConstraints = this.physics.items;
|
||||
PhysicsConstraint[] constraints = this.physics.items;
|
||||
for (int i = 0, n = this.physics.size; i < n; i++)
|
||||
((PhysicsConstraint)physicsConstraints[i]).translate(x, y);
|
||||
constraints[i].translate(x, y);
|
||||
}
|
||||
|
||||
/** Calls {@link PhysicsConstraint#rotate(float, float, float)} for each physics constraint. */
|
||||
public void physicsRotate (float x, float y, float degrees) {
|
||||
Object[] physicsConstraints = this.physics.items;
|
||||
PhysicsConstraint[] constraints = this.physics.items;
|
||||
for (int i = 0, n = this.physics.size; i < n; i++)
|
||||
((PhysicsConstraint)physicsConstraints[i]).rotate(x, y, degrees);
|
||||
constraints[i].rotate(x, y, degrees);
|
||||
}
|
||||
|
||||
/** Returns the skeleton's time. This is used for time-based manipulations, such as {@link PhysicsConstraint}.
|
||||
|
||||
@ -162,7 +162,7 @@ public class SkeletonBinary extends SkeletonLoader {
|
||||
static public final int CURVE_STEPPED = 1;
|
||||
static public final int CURVE_BEZIER = 2;
|
||||
|
||||
private final Array<LinkedMesh> linkedMeshes = new Array();
|
||||
private final Array<LinkedMesh> linkedMeshes = new Array(true, 8, LinkedMesh[]::new);
|
||||
|
||||
public SkeletonBinary (AttachmentLoader attachmentLoader) {
|
||||
super(attachmentLoader);
|
||||
@ -217,10 +217,10 @@ public class SkeletonBinary extends SkeletonLoader {
|
||||
o[i] = input.readString();
|
||||
|
||||
// Bones.
|
||||
Object[] bones = skeletonData.bones.setSize(n = input.readInt(true));
|
||||
BoneData[] bones = skeletonData.bones.setSize(n = input.readInt(true));
|
||||
for (int i = 0; i < n; i++) {
|
||||
String name = input.readString();
|
||||
BoneData parent = i == 0 ? null : (BoneData)bones[input.readInt(true)];
|
||||
BoneData parent = i == 0 ? null : bones[input.readInt(true)];
|
||||
var data = new BoneData(i, name, parent);
|
||||
BoneLocal setup = data.setup;
|
||||
setup.rotation = input.readFloat();
|
||||
@ -242,10 +242,10 @@ public class SkeletonBinary extends SkeletonLoader {
|
||||
}
|
||||
|
||||
// Slots.
|
||||
Object[] slots = skeletonData.slots.setSize(n = input.readInt(true));
|
||||
SlotData[] slots = skeletonData.slots.setSize(n = input.readInt(true));
|
||||
for (int i = 0; i < n; i++) {
|
||||
String slotName = input.readString();
|
||||
var boneData = (BoneData)bones[input.readInt(true)];
|
||||
var boneData = bones[input.readInt(true)];
|
||||
var data = new SlotData(i, slotName, boneData);
|
||||
Color.rgba8888ToColor(data.setup.color, input.readInt());
|
||||
|
||||
@ -264,10 +264,10 @@ public class SkeletonBinary extends SkeletonLoader {
|
||||
switch (input.readByte()) {
|
||||
case CONSTRAINT_IK -> {
|
||||
var data = new IkConstraintData(input.readString());
|
||||
Object[] constraintBones = data.bones.setSize(nn = input.readInt(true));
|
||||
BoneData[] constraintBones = data.bones.setSize(nn = input.readInt(true));
|
||||
for (int ii = 0; ii < nn; ii++)
|
||||
constraintBones[ii] = bones[input.readInt(true)];
|
||||
data.target = (BoneData)bones[input.readInt(true)];
|
||||
data.target = bones[input.readInt(true)];
|
||||
int flags = input.read();
|
||||
data.skinRequired = (flags & 1) != 0;
|
||||
data.uniform = (flags & 2) != 0;
|
||||
@ -281,17 +281,17 @@ public class SkeletonBinary extends SkeletonLoader {
|
||||
}
|
||||
case CONSTRAINT_TRANSFORM -> {
|
||||
var data = new TransformConstraintData(input.readString());
|
||||
Object[] constraintBones = data.bones.setSize(nn = input.readInt(true));
|
||||
BoneData[] constraintBones = data.bones.setSize(nn = input.readInt(true));
|
||||
for (int ii = 0; ii < nn; ii++)
|
||||
constraintBones[ii] = bones[input.readInt(true)];
|
||||
data.source = (BoneData)bones[input.readInt(true)];
|
||||
data.source = bones[input.readInt(true)];
|
||||
int flags = input.read();
|
||||
data.skinRequired = (flags & 1) != 0;
|
||||
data.localSource = (flags & 2) != 0;
|
||||
data.localTarget = (flags & 4) != 0;
|
||||
data.additive = (flags & 8) != 0;
|
||||
data.clamp = (flags & 16) != 0;
|
||||
Object[] froms = data.properties.setSize(nn = flags >> 5);
|
||||
FromProperty[] froms = data.properties.setSize(nn = flags >> 5);
|
||||
for (int ii = 0, tn; ii < nn; ii++) {
|
||||
float fromScale = 1;
|
||||
FromProperty from;
|
||||
@ -311,7 +311,7 @@ public class SkeletonBinary extends SkeletonLoader {
|
||||
default -> from = null;
|
||||
}
|
||||
from.offset = input.readFloat() * fromScale;
|
||||
Object[] tos = from.to.setSize(tn = input.readByte());
|
||||
ToProperty[] tos = from.to.setSize(tn = input.readByte());
|
||||
for (int t = 0; t < tn; t++) {
|
||||
float toScale = 1;
|
||||
ToProperty to;
|
||||
@ -356,10 +356,10 @@ public class SkeletonBinary extends SkeletonLoader {
|
||||
}
|
||||
case CONSTRAINT_PATH -> {
|
||||
var data = new PathConstraintData(input.readString());
|
||||
Object[] constraintBones = data.bones.setSize(nn = input.readInt(true));
|
||||
BoneData[] constraintBones = data.bones.setSize(nn = input.readInt(true));
|
||||
for (int ii = 0; ii < nn; ii++)
|
||||
constraintBones[ii] = bones[input.readInt(true)];
|
||||
data.slot = (SlotData)slots[input.readInt(true)];
|
||||
data.slot = slots[input.readInt(true)];
|
||||
int flags = input.read();
|
||||
data.skinRequired = (flags & 1) != 0;
|
||||
data.positionMode = PositionMode.values[flags & 2];
|
||||
@ -378,7 +378,7 @@ public class SkeletonBinary extends SkeletonLoader {
|
||||
}
|
||||
case CONSTRAINT_PHYSICS -> {
|
||||
var data = new PhysicsConstraintData(input.readString());
|
||||
data.bone = (BoneData)bones[input.readInt(true)];
|
||||
data.bone = bones[input.readInt(true)];
|
||||
int flags = input.read();
|
||||
data.skinRequired = (flags & 1) != 0;
|
||||
if ((flags & 2) != 0) data.x = input.readFloat();
|
||||
@ -426,10 +426,10 @@ public class SkeletonBinary extends SkeletonLoader {
|
||||
|
||||
// Linked meshes.
|
||||
n = linkedMeshes.size;
|
||||
Object[] items = linkedMeshes.items;
|
||||
LinkedMesh[] items = linkedMeshes.items;
|
||||
for (int i = 0; i < n; i++) {
|
||||
var linkedMesh = (LinkedMesh)items[i];
|
||||
Skin skin = skeletonData.skins.get(linkedMesh.skinIndex);
|
||||
LinkedMesh linkedMesh = items[i];
|
||||
Skin skin = skeletonData.skins.items[linkedMesh.skinIndex];
|
||||
Attachment parent = skin.getAttachment(linkedMesh.slotIndex, linkedMesh.parent);
|
||||
if (parent == null) throw new SerializationException("Parent mesh not found: " + linkedMesh.parent);
|
||||
linkedMesh.mesh.setTimelineAttachment(linkedMesh.inheritTimelines ? (VertexAttachment)parent : linkedMesh.mesh);
|
||||
@ -656,7 +656,7 @@ public class SkeletonBinary extends SkeletonLoader {
|
||||
|
||||
ClippingAttachment clip = attachmentLoader.newClippingAttachment(skin, name);
|
||||
if (clip == null) return null;
|
||||
clip.setEndSlot(skeletonData.slots.get(endSlotIndex));
|
||||
clip.setEndSlot(skeletonData.slots.items[endSlotIndex]);
|
||||
clip.setWorldVerticesLength(vertices.length);
|
||||
clip.setVertices(vertices.vertices);
|
||||
clip.setBones(vertices.bones);
|
||||
@ -720,7 +720,7 @@ public class SkeletonBinary extends SkeletonLoader {
|
||||
}
|
||||
|
||||
private Animation readAnimation (SkeletonInput input, String name, SkeletonData skeletonData) throws IOException {
|
||||
var timelines = new Array<Timeline>(input.readInt(true));
|
||||
var timelines = new Array<Timeline>(true, input.readInt(true), Timeline[]::new);
|
||||
float scale = this.scale;
|
||||
|
||||
// Slot timelines.
|
||||
@ -969,7 +969,7 @@ public class SkeletonBinary extends SkeletonLoader {
|
||||
// Path constraint timelines.
|
||||
for (int i = 0, n = input.readInt(true); i < n; i++) {
|
||||
int index = input.readInt(true);
|
||||
var data = (PathConstraintData)skeletonData.constraints.get(index);
|
||||
var data = (PathConstraintData)skeletonData.constraints.items[index];
|
||||
for (int ii = 0, nn = input.readInt(true); ii < nn; ii++) {
|
||||
int type = input.readByte(), frameCount = input.readInt(true), bezierCount = input.readInt(true);
|
||||
switch (type) {
|
||||
@ -1036,7 +1036,7 @@ public class SkeletonBinary extends SkeletonLoader {
|
||||
|
||||
// Attachment timelines.
|
||||
for (int i = 0, n = input.readInt(true); i < n; i++) {
|
||||
Skin skin = skeletonData.skins.get(input.readInt(true));
|
||||
Skin skin = skeletonData.skins.items[input.readInt(true)];
|
||||
for (int ii = 0, nn = input.readInt(true); ii < nn; ii++) {
|
||||
int slotIndex = input.readInt(true);
|
||||
for (int iii = 0, nnn = input.readInt(true); iii < nnn; iii++) {
|
||||
@ -1140,7 +1140,7 @@ public class SkeletonBinary extends SkeletonLoader {
|
||||
var timeline = new EventTimeline(eventCount);
|
||||
for (int i = 0; i < eventCount; i++) {
|
||||
float time = input.readFloat();
|
||||
EventData eventData = skeletonData.events.get(input.readInt(true));
|
||||
EventData eventData = skeletonData.events.items[input.readInt(true)];
|
||||
var event = new Event(time, eventData);
|
||||
event.intValue = input.readInt(false);
|
||||
event.floatValue = input.readFloat();
|
||||
@ -1156,9 +1156,9 @@ public class SkeletonBinary extends SkeletonLoader {
|
||||
}
|
||||
|
||||
float duration = 0;
|
||||
Object[] items = timelines.items;
|
||||
Timeline[] items = timelines.items;
|
||||
for (int i = 0, n = timelines.size; i < n; i++)
|
||||
duration = Math.max(duration, ((Timeline)items[i]).getDuration());
|
||||
duration = Math.max(duration, items[i].getDuration());
|
||||
return new Animation(name, timelines, duration);
|
||||
}
|
||||
|
||||
|
||||
@ -41,8 +41,8 @@ import com.esotericsoftware.spine.attachments.BoundingBoxAttachment;
|
||||
* provided along with convenience methods for doing hit detection. */
|
||||
public class SkeletonBounds {
|
||||
private float minX, minY, maxX, maxY;
|
||||
private Array<BoundingBoxAttachment> boundingBoxes = new Array();
|
||||
private Array<FloatArray> polygons = new Array();
|
||||
private Array<BoundingBoxAttachment> boundingBoxes = new Array(true, 8, BoundingBoxAttachment[]::new);
|
||||
private Array<FloatArray> polygons = new Array(true, 8, FloatArray[]::new);
|
||||
private Pool<FloatArray> polygonPool = new Pool() {
|
||||
protected Object newObject () {
|
||||
return new FloatArray();
|
||||
@ -55,17 +55,17 @@ public class SkeletonBounds {
|
||||
* 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;
|
||||
Array<FloatArray> polygons = this.polygons;
|
||||
Object[] slots = skeleton.slots.items;
|
||||
int slotCount = skeleton.slots.size;
|
||||
|
||||
boundingBoxes.clear();
|
||||
polygonPool.freeAll(polygons);
|
||||
polygons.clear();
|
||||
|
||||
Slot[] slots = skeleton.slots.items;
|
||||
int slotCount = skeleton.slots.size;
|
||||
for (int i = 0; i < slotCount; i++) {
|
||||
var slot = (Slot)slots[i];
|
||||
Slot slot = slots[i];
|
||||
if (!slot.bone.active) continue;
|
||||
Attachment attachment = slot.applied.attachment;
|
||||
if (attachment instanceof BoundingBoxAttachment boundingBox) {
|
||||
@ -90,9 +90,9 @@ public class SkeletonBounds {
|
||||
|
||||
private void aabbCompute () {
|
||||
float minX = Integer.MAX_VALUE, minY = Integer.MAX_VALUE, maxX = Integer.MIN_VALUE, maxY = Integer.MIN_VALUE;
|
||||
Object[] polygons = this.polygons.items;
|
||||
FloatArray[] polygons = this.polygons.items;
|
||||
for (int i = 0, n = this.polygons.size; i < n; i++) {
|
||||
var polygon = (FloatArray)polygons[i];
|
||||
FloatArray polygon = polygons[i];
|
||||
float[] vertices = polygon.items;
|
||||
for (int ii = 0, nn = polygon.size; ii < nn; ii += 2) {
|
||||
float x = vertices[ii];
|
||||
@ -143,9 +143,9 @@ public class SkeletonBounds {
|
||||
/** Returns the first bounding box attachment that contains the point, or null. When doing many checks, it is usually more
|
||||
* efficient to only call this method if {@link #aabbContainsPoint(float, float)} returns true. */
|
||||
public @Null BoundingBoxAttachment containsPoint (float x, float y) {
|
||||
Object[] polygons = this.polygons.items;
|
||||
FloatArray[] polygons = this.polygons.items;
|
||||
for (int i = 0, n = this.polygons.size; i < n; i++)
|
||||
if (containsPoint((FloatArray)polygons[i], x, y)) return boundingBoxes.get(i);
|
||||
if (containsPoint(polygons[i], x, y)) return boundingBoxes.items[i];
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -173,9 +173,9 @@ public class SkeletonBounds {
|
||||
* is usually more efficient to only call this method if {@link #aabbIntersectsSegment(float, float, float, float)} returns
|
||||
* true. */
|
||||
public @Null BoundingBoxAttachment intersectsSegment (float x1, float y1, float x2, float y2) {
|
||||
Object[] polygons = this.polygons.items;
|
||||
FloatArray[] polygons = this.polygons.items;
|
||||
for (int i = 0, n = this.polygons.size; i < n; i++)
|
||||
if (intersectsSegment((FloatArray)polygons[i], x1, y1, x2, y2)) return boundingBoxes.get(i);
|
||||
if (intersectsSegment(polygons[i], x1, y1, x2, y2)) return boundingBoxes.items[i];
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -248,6 +248,6 @@ public class SkeletonBounds {
|
||||
public @Null FloatArray getPolygon (BoundingBoxAttachment boundingBox) {
|
||||
if (boundingBox == null) throw new IllegalArgumentException("boundingBox cannot be null.");
|
||||
int index = boundingBoxes.indexOf(boundingBox, true);
|
||||
return index == -1 ? null : polygons.get(index);
|
||||
return index == -1 ? null : polygons.items[index];
|
||||
}
|
||||
}
|
||||
|
||||
@ -38,13 +38,13 @@ import com.badlogic.gdx.utils.Null;
|
||||
* Guide. */
|
||||
public class SkeletonData {
|
||||
@Null String name;
|
||||
final Array<BoneData> bones = new Array(); // Ordered parents first.
|
||||
final Array<SlotData> slots = new Array(); // Setup pose draw order.
|
||||
final Array<Skin> skins = new Array();
|
||||
final Array<BoneData> bones = new Array(true, 0, BoneData[]::new); // Ordered parents first.
|
||||
final Array<SlotData> slots = new Array(true, 0, SlotData[]::new); // Setup pose draw order.
|
||||
final Array<Skin> skins = new Array(true, 0, Skin[]::new);
|
||||
@Null Skin defaultSkin;
|
||||
final Array<EventData> events = new Array();
|
||||
final Array<Animation> animations = new Array();
|
||||
final Array<ConstraintData> constraints = new Array();
|
||||
final Array<EventData> events = new Array(true, 0, EventData[]::new);
|
||||
final Array<Animation> animations = new Array(true, 0, Animation[]::new);
|
||||
final Array<ConstraintData> constraints = new Array(true, 0, ConstraintData[]::new);
|
||||
float x, y, width, height, referenceScale = 100;
|
||||
@Null String version, hash;
|
||||
|
||||
@ -67,11 +67,9 @@ public class SkeletonData {
|
||||
* multiple times. */
|
||||
public @Null BoneData findBone (String boneName) {
|
||||
if (boneName == null) throw new IllegalArgumentException("boneName cannot be null.");
|
||||
Object[] bones = this.bones.items;
|
||||
for (int i = 0, n = this.bones.size; i < n; i++) {
|
||||
var bone = (BoneData)bones[i];
|
||||
if (bone.name.equals(boneName)) return bone;
|
||||
}
|
||||
BoneData[] bones = this.bones.items;
|
||||
for (int i = 0, n = this.bones.size; i < n; i++)
|
||||
if (bones[i].name.equals(boneName)) return bones[i];
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -86,11 +84,9 @@ public class SkeletonData {
|
||||
* multiple times. */
|
||||
public @Null SlotData findSlot (String slotName) {
|
||||
if (slotName == null) throw new IllegalArgumentException("slotName cannot be null.");
|
||||
Object[] slots = this.slots.items;
|
||||
for (int i = 0, n = this.slots.size; i < n; i++) {
|
||||
var slot = (SlotData)slots[i];
|
||||
if (slot.name.equals(slotName)) return slot;
|
||||
}
|
||||
SlotData[] slots = this.slots.items;
|
||||
for (int i = 0, n = this.slots.size; i < n; i++)
|
||||
if (slots[i].name.equals(slotName)) return slots[i];
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -148,11 +144,9 @@ public class SkeletonData {
|
||||
* call it multiple times. */
|
||||
public @Null Animation findAnimation (String animationName) {
|
||||
if (animationName == null) throw new IllegalArgumentException("animationName cannot be null.");
|
||||
Object[] animations = this.animations.items;
|
||||
for (int i = 0, n = this.animations.size; i < n; i++) {
|
||||
var animation = (Animation)animations[i];
|
||||
if (animation.name.equals(animationName)) return animation;
|
||||
}
|
||||
Animation[] animations = this.animations.items;
|
||||
for (int i = 0, n = this.animations.size; i < n; i++)
|
||||
if (animations[i].name.equals(animationName)) return animations[i];
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -166,10 +160,10 @@ public class SkeletonData {
|
||||
public @Null <T extends ConstraintData> T findConstraint (String constraintName, Class<T> type) {
|
||||
if (constraintName == null) throw new IllegalArgumentException("constraintName cannot be null.");
|
||||
if (type == null) throw new IllegalArgumentException("type cannot be null.");
|
||||
Object[] constraints = this.constraints.items;
|
||||
ConstraintData[] constraints = this.constraints.items;
|
||||
for (int i = 0, n = this.constraints.size; i < n; i++) {
|
||||
Object constraint = constraints[i];
|
||||
if (type.isInstance(constraint) && ((PosedData)constraint).name.equals(constraintName)) return (T)constraint;
|
||||
ConstraintData constraint = constraints[i];
|
||||
if (type.isInstance(constraint) && constraint.name.equals(constraintName)) return (T)constraint;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -121,7 +121,7 @@ import com.esotericsoftware.spine.attachments.VertexAttachment;
|
||||
* <a href="https://esotericsoftware.com/spine-loading-skeleton-data#JSON-and-binary-data">JSON and binary data</a> in the Spine
|
||||
* Runtimes Guide. */
|
||||
public class SkeletonJson extends SkeletonLoader {
|
||||
private final Array<LinkedMesh> linkedMeshes = new Array();
|
||||
private final Array<LinkedMesh> linkedMeshes = new Array(true, 8, LinkedMesh[]::new);
|
||||
|
||||
public SkeletonJson (AttachmentLoader attachmentLoader) {
|
||||
super(attachmentLoader);
|
||||
@ -456,9 +456,9 @@ public class SkeletonJson extends SkeletonLoader {
|
||||
}
|
||||
|
||||
// Linked meshes.
|
||||
Object[] items = linkedMeshes.items;
|
||||
LinkedMesh[] items = linkedMeshes.items;
|
||||
for (int i = 0, n = linkedMeshes.size; i < n; i++) {
|
||||
var linkedMesh = (LinkedMesh)items[i];
|
||||
LinkedMesh linkedMesh = items[i];
|
||||
Skin skin = linkedMesh.skin == null ? skeletonData.defaultSkin : skeletonData.findSkin(linkedMesh.skin);
|
||||
if (skin == null) throw new SerializationException("Skin not found: " + linkedMesh.skin);
|
||||
Attachment parent = skin.getAttachment(linkedMesh.slotIndex, linkedMesh.parent);
|
||||
@ -656,7 +656,7 @@ public class SkeletonJson extends SkeletonLoader {
|
||||
|
||||
private void readAnimation (JsonValue map, String name, SkeletonData skeletonData) {
|
||||
float scale = this.scale;
|
||||
var timelines = new Array<Timeline>();
|
||||
var timelines = new Array<Timeline>(true, 16, Timeline[]::new);
|
||||
|
||||
// Slot timelines.
|
||||
for (JsonValue slotMap = map.getChild("slots"); slotMap != null; slotMap = slotMap.next) {
|
||||
@ -1186,9 +1186,9 @@ public class SkeletonJson extends SkeletonLoader {
|
||||
|
||||
timelines.shrink();
|
||||
float duration = 0;
|
||||
Object[] items = timelines.items;
|
||||
Timeline[] items = timelines.items;
|
||||
for (int i = 0, n = timelines.size; i < n; i++)
|
||||
duration = Math.max(duration, ((Timeline)items[i]).getDuration());
|
||||
duration = Math.max(duration, items[i].getDuration());
|
||||
skeletonData.animations.add(new Animation(name, timelines, duration));
|
||||
}
|
||||
|
||||
|
||||
@ -76,9 +76,9 @@ public class SkeletonRenderer {
|
||||
float[] vertices = this.vertices.items;
|
||||
Color skeletonColor = skeleton.color;
|
||||
float r = skeletonColor.r, g = skeletonColor.g, b = skeletonColor.b, a = skeletonColor.a;
|
||||
Object[] drawOrder = skeleton.drawOrder.items;
|
||||
Slot[] drawOrder = skeleton.drawOrder.items;
|
||||
for (int i = 0, n = skeleton.drawOrder.size; i < n; i++) {
|
||||
var slot = (Slot)drawOrder[i];
|
||||
Slot slot = drawOrder[i];
|
||||
if (!slot.bone.active) continue;
|
||||
SlotPose pose = slot.applied;
|
||||
Attachment attachment = pose.attachment;
|
||||
@ -142,9 +142,9 @@ public class SkeletonRenderer {
|
||||
short[] triangles = null;
|
||||
Color color = null, skeletonColor = skeleton.color;
|
||||
float r = skeletonColor.r, g = skeletonColor.g, b = skeletonColor.b, a = skeletonColor.a;
|
||||
Object[] drawOrder = skeleton.drawOrder.items;
|
||||
Slot[] drawOrder = skeleton.drawOrder.items;
|
||||
for (int i = 0, n = skeleton.drawOrder.size; i < n; i++) {
|
||||
var slot = (Slot)drawOrder[i];
|
||||
Slot slot = drawOrder[i];
|
||||
if (slot.bone.active) {
|
||||
SlotPose pose = slot.applied;
|
||||
Attachment attachment = pose.attachment;
|
||||
@ -237,9 +237,9 @@ public class SkeletonRenderer {
|
||||
short[] triangles = null;
|
||||
Color color = null, skeletonColor = skeleton.color;
|
||||
float r = skeletonColor.r, g = skeletonColor.g, b = skeletonColor.b, a = skeletonColor.a;
|
||||
Object[] drawOrder = skeleton.drawOrder.items;
|
||||
Slot[] drawOrder = skeleton.drawOrder.items;
|
||||
for (int i = 0, n = skeleton.drawOrder.size; i < n; i++) {
|
||||
var slot = (Slot)drawOrder[i];
|
||||
Slot slot = drawOrder[i];
|
||||
if (slot.bone.active) {
|
||||
SlotPose pose = slot.applied;
|
||||
Attachment attachment = pose.attachment;
|
||||
|
||||
@ -79,14 +79,15 @@ public class SkeletonRendererDebug {
|
||||
Gdx.gl.glBlendFunc(srcFunc, GL20.GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
ShapeRenderer shapes = this.shapes;
|
||||
Array<Bone> bones = skeleton.bones;
|
||||
Array<Slot> slots = skeleton.slots;
|
||||
Bone[] bones = skeleton.bones.items;
|
||||
Slot[] slots = skeleton.slots.items;
|
||||
int boneCount = skeleton.bones.size, slotCount = skeleton.slots.size;
|
||||
|
||||
shapes.begin(ShapeType.Filled);
|
||||
|
||||
if (drawBones) {
|
||||
for (int i = 0, n = bones.size; i < n; i++) {
|
||||
Bone bone = bones.get(i);
|
||||
for (int i = 0; i < boneCount; i++) {
|
||||
Bone bone = bones[i];
|
||||
if (bone.parent == null || !bone.active) continue;
|
||||
float length = bone.data.length, width = boneWidth;
|
||||
if (length == 0) {
|
||||
@ -105,8 +106,8 @@ public class SkeletonRendererDebug {
|
||||
|
||||
if (drawPoints) {
|
||||
shapes.setColor(boneOriginColor);
|
||||
for (int i = 0, n = slots.size; i < n; i++) {
|
||||
Slot slot = slots.get(i);
|
||||
for (int i = 0; i < slotCount; i++) {
|
||||
Slot slot = slots[i];
|
||||
if (!slot.bone.active) continue;
|
||||
if (!(slot.applied.attachment instanceof PointAttachment point)) continue;
|
||||
point.computeWorldPosition(slot.bone.applied, temp1);
|
||||
@ -120,8 +121,8 @@ public class SkeletonRendererDebug {
|
||||
|
||||
if (drawRegionAttachments) {
|
||||
shapes.setColor(attachmentLineColor);
|
||||
for (int i = 0, n = slots.size; i < n; i++) {
|
||||
Slot slot = slots.get(i);
|
||||
for (int i = 0; i < slotCount; i++) {
|
||||
Slot slot = slots[i];
|
||||
if (!slot.bone.active) continue;
|
||||
if (slot.pose.attachment instanceof RegionAttachment region) {
|
||||
float[] vertices = this.vertices.items;
|
||||
@ -135,8 +136,8 @@ public class SkeletonRendererDebug {
|
||||
}
|
||||
|
||||
if (drawMeshHull || drawMeshTriangles) {
|
||||
for (int i = 0, n = slots.size; i < n; i++) {
|
||||
Slot slot = slots.get(i);
|
||||
for (int i = 0; i < slotCount; i++) {
|
||||
Slot slot = slots[i];
|
||||
if (!slot.bone.active) continue;
|
||||
if (!(slot.pose.attachment instanceof MeshAttachment mesh)) continue;
|
||||
float[] vertices = this.vertices.setSize(mesh.getWorldVerticesLength());
|
||||
@ -174,15 +175,15 @@ public class SkeletonRendererDebug {
|
||||
Array<FloatArray> polygons = bounds.getPolygons();
|
||||
Array<BoundingBoxAttachment> boxes = bounds.getBoundingBoxes();
|
||||
for (int i = 0, n = polygons.size; i < n; i++) {
|
||||
FloatArray polygon = polygons.get(i);
|
||||
shapes.setColor(boxes.get(i).getColor());
|
||||
FloatArray polygon = polygons.items[i];
|
||||
shapes.setColor(boxes.items[i].getColor());
|
||||
shapes.polygon(polygon.items, 0, polygon.size);
|
||||
}
|
||||
}
|
||||
|
||||
if (drawClipping) {
|
||||
for (int i = 0, n = slots.size; i < n; i++) {
|
||||
Slot slot = slots.get(i);
|
||||
for (int i = 0; i < slotCount; i++) {
|
||||
Slot slot = slots[i];
|
||||
if (!slot.bone.active) continue;
|
||||
if (!(slot.pose.attachment instanceof ClippingAttachment clip)) continue;
|
||||
int nn = clip.getWorldVerticesLength();
|
||||
@ -196,8 +197,8 @@ public class SkeletonRendererDebug {
|
||||
}
|
||||
|
||||
if (drawPaths) {
|
||||
for (int i = 0, n = slots.size; i < n; i++) {
|
||||
Slot slot = slots.get(i);
|
||||
for (int i = 0; i < slotCount; i++) {
|
||||
Slot slot = slots[i];
|
||||
if (!slot.bone.active) continue;
|
||||
if (!(slot.pose.attachment instanceof PathAttachment path)) continue;
|
||||
int nn = path.getWorldVerticesLength();
|
||||
@ -236,8 +237,8 @@ public class SkeletonRendererDebug {
|
||||
|
||||
if (drawBones) {
|
||||
shapes.setColor(boneOriginColor);
|
||||
for (int i = 0, n = bones.size; i < n; i++) {
|
||||
Bone bone = bones.get(i);
|
||||
for (int i = 0; i < boneCount; i++) {
|
||||
Bone bone = bones[i];
|
||||
if (!bone.active) continue;
|
||||
shapes.circle(bone.applied.worldX, bone.applied.worldY, 3 * scale, 8);
|
||||
}
|
||||
@ -245,8 +246,8 @@ public class SkeletonRendererDebug {
|
||||
|
||||
if (drawPoints) {
|
||||
shapes.setColor(boneOriginColor);
|
||||
for (int i = 0, n = slots.size; i < n; i++) {
|
||||
Slot slot = slots.get(i);
|
||||
for (int i = 0; i < slotCount; i++) {
|
||||
Slot slot = slots[i];
|
||||
if (!slot.bone.active) continue;
|
||||
if (!(slot.pose.attachment instanceof PointAttachment point)) continue;
|
||||
point.computeWorldPosition(slot.bone.applied, temp1);
|
||||
|
||||
@ -44,8 +44,8 @@ import com.esotericsoftware.spine.attachments.MeshAttachment;
|
||||
public class Skin {
|
||||
final String name;
|
||||
final OrderedSet<SkinEntry> attachments = new OrderedSet();
|
||||
final Array<BoneData> bones = new Array(0);
|
||||
final Array<ConstraintData> constraints = new Array(0);
|
||||
final Array<BoneData> bones = new Array(true, 0, BoneData[]::new);
|
||||
final Array<ConstraintData> constraints = new Array(true, 0, ConstraintData[]::new);
|
||||
private final SkinEntry lookup = new SkinEntry(0, "", null);
|
||||
|
||||
// Nonessential.
|
||||
@ -154,12 +154,11 @@ public class Skin {
|
||||
|
||||
/** Attach each attachment in this skin if the corresponding attachment in the old skin is currently attached. */
|
||||
void attachAll (Skeleton skeleton, Skin oldSkin) {
|
||||
Object[] slots = skeleton.slots.items;
|
||||
Slot[] slots = skeleton.slots.items;
|
||||
for (SkinEntry entry : oldSkin.attachments.orderedItems()) {
|
||||
int slotIndex = entry.slotIndex;
|
||||
SlotPose slot = ((Slot)slots[slotIndex]).pose;
|
||||
SlotPose slot = slots[entry.slotIndex].pose;
|
||||
if (slot.attachment == entry.attachment) {
|
||||
Attachment attachment = getAttachment(slotIndex, entry.name);
|
||||
Attachment attachment = getAttachment(entry.slotIndex, entry.name);
|
||||
if (attachment != null) slot.setAttachment(attachment);
|
||||
}
|
||||
}
|
||||
|
||||
@ -32,6 +32,7 @@ package com.esotericsoftware.spine;
|
||||
import com.esotericsoftware.spine.Animation.BoneTimeline;
|
||||
import com.esotericsoftware.spine.Animation.MixBlend;
|
||||
import com.esotericsoftware.spine.Animation.MixDirection;
|
||||
import com.esotericsoftware.spine.Animation.SlotTimeline;
|
||||
import com.esotericsoftware.spine.Animation.Timeline;
|
||||
|
||||
/** Stores the setup pose for a {@link PhysicsConstraint}.
|
||||
@ -54,27 +55,36 @@ public class Slider extends Constraint<Slider, SliderData, SliderPose> {
|
||||
}
|
||||
|
||||
void sort (Skeleton skeleton) {
|
||||
Object[] timelines = data.animation.timelines.items;
|
||||
Timeline[] timelines = data.animation.timelines.items;
|
||||
int timelineCount = data.animation.timelines.size;
|
||||
|
||||
// BOZO - Sort and reset other timeline types.
|
||||
Object[] bones = skeleton.bones.items;
|
||||
for (int i = 0; i < timelineCount; i++) {
|
||||
var timeline = (Timeline)timelines[i];
|
||||
if (timeline instanceof BoneTimeline boneTimeline) skeleton.sortBone((Bone)bones[boneTimeline.getBoneIndex()]);
|
||||
}
|
||||
Bone[] bones = skeleton.bones.items;
|
||||
for (int i = 0; i < timelineCount; i++)
|
||||
if (timelines[i] instanceof BoneTimeline boneTimeline) skeleton.sortBone(bones[boneTimeline.getBoneIndex()]);
|
||||
|
||||
skeleton.updateCache.add(this);
|
||||
|
||||
Slot[] slots = skeleton.slots.items;
|
||||
for (int i = 0; i < timelineCount; i++) {
|
||||
if (timelines[i] instanceof BoneTimeline boneTimeline) {
|
||||
var bone = (Bone)bones[boneTimeline.getBoneIndex()];
|
||||
skeleton.resetCache(bone);
|
||||
Timeline timeline = timelines[i];
|
||||
if (timeline instanceof BoneTimeline boneTimeline) {
|
||||
Bone bone = bones[boneTimeline.getBoneIndex()];
|
||||
skeleton.sortBone(bone);
|
||||
skeleton.sortReset(bone.children);
|
||||
bone.sorted = false;
|
||||
}
|
||||
} else if (timeline instanceof SlotTimeline slotTimeline) //
|
||||
skeleton.resetCache(slots[slotTimeline.getSlotIndex()]);
|
||||
// BOZO!
|
||||
// skeleton.resetCache(skeleton.constraints.items[constraintIndex]);
|
||||
|
||||
// if (constraintIndex == -1) {
|
||||
// Object[] constraints = skeleton.physics.items;
|
||||
// for (int i = 0, n = skeleton.physics.size; i < n; i++)
|
||||
// skeleton.resetCache((PhysicsConstraint)constraints[i]);
|
||||
// } else
|
||||
// skeleton.resetCache(skeleton.constraints.items[constraintIndex]);
|
||||
}
|
||||
for (int i = 0; i < timelineCount; i++)
|
||||
if (timelines[i] instanceof BoneTimeline boneTimeline) skeleton.sortBone((Bone)bones[boneTimeline.getBoneIndex()]);
|
||||
if (timelines[i] instanceof BoneTimeline boneTimeline) skeleton.sortBone(bones[boneTimeline.getBoneIndex()]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -43,7 +43,7 @@ public class Slot extends Posed<SlotData, SlotPose, SlotPose> {
|
||||
super(data, new SlotPose(), new SlotPose());
|
||||
if (skeleton == null) throw new IllegalArgumentException("skeleton cannot be null.");
|
||||
this.skeleton = skeleton;
|
||||
bone = skeleton.bones.get(data.boneData.index);
|
||||
bone = skeleton.bones.items[data.boneData.index];
|
||||
if (data.setup.darkColor != null) {
|
||||
pose.darkColor = new Color();
|
||||
applied.darkColor = new Color();
|
||||
|
||||
@ -48,11 +48,11 @@ public class TransformConstraint extends Constraint<TransformConstraint, Transfo
|
||||
super(data, new TransformConstraintPose(), new TransformConstraintPose());
|
||||
if (skeleton == null) throw new IllegalArgumentException("skeleton cannot be null.");
|
||||
|
||||
bones = new Array(data.bones.size);
|
||||
bones = new Array(true, data.bones.size, BonePose[]::new);
|
||||
for (BoneData boneData : data.bones)
|
||||
bones.add(skeleton.bones.get(boneData.index).constrained);
|
||||
bones.add(skeleton.bones.items[boneData.index].constrained);
|
||||
|
||||
source = skeleton.bones.get(data.source.index);
|
||||
source = skeleton.bones.items[data.source.index];
|
||||
}
|
||||
|
||||
public TransformConstraint copy (Skeleton skeleton) {
|
||||
@ -70,18 +70,17 @@ public class TransformConstraint extends Constraint<TransformConstraint, Transfo
|
||||
TransformConstraintData data = this.data;
|
||||
boolean localFrom = data.localSource, localTarget = data.localTarget, additive = data.additive, clamp = data.clamp;
|
||||
BonePose source = this.source.applied;
|
||||
Object[] fromItems = data.properties.items;
|
||||
FromProperty[] fromItems = data.properties.items;
|
||||
int fn = data.properties.size;
|
||||
Object[] bones = this.bones.items;
|
||||
BonePose[] bones = this.bones.items;
|
||||
for (int i = 0, n = this.bones.size; i < n; i++) {
|
||||
var bone = (BonePose)bones[i];
|
||||
if (bone.bone.applied != bone.bone.constrained) System.out.println();
|
||||
BonePose bone = bones[i];
|
||||
for (int f = 0; f < fn; f++) {
|
||||
var from = (FromProperty)fromItems[f];
|
||||
FromProperty from = fromItems[f];
|
||||
float value = from.value(data, source, localFrom) - from.offset;
|
||||
Object[] toItems = from.to.items;
|
||||
ToProperty[] toItems = from.to.items;
|
||||
for (int t = 0, tn = from.to.size; t < tn; t++) {
|
||||
var to = (ToProperty)toItems[t];
|
||||
ToProperty to = toItems[t];
|
||||
if (to.mix(pose) != 0) {
|
||||
float clamped = to.offset + value * to.scale;
|
||||
if (clamp) {
|
||||
@ -104,18 +103,18 @@ public class TransformConstraint extends Constraint<TransformConstraint, Transfo
|
||||
void sort (Skeleton skeleton) {
|
||||
skeleton.sortBone(source);
|
||||
|
||||
Object[] bones = this.bones.items;
|
||||
BonePose[] bones = this.bones.items;
|
||||
int boneCount = this.bones.size;
|
||||
if (data.localSource) {
|
||||
for (int i = 0; i < boneCount; i++) {
|
||||
Bone child = ((BonePose)bones[i]).bone;
|
||||
Bone child = bones[i].bone;
|
||||
skeleton.resetCache(child);
|
||||
skeleton.sortBone(child.parent);
|
||||
skeleton.sortBone(child);
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < boneCount; i++) {
|
||||
Bone bone = ((BonePose)bones[i]).bone;
|
||||
Bone bone = bones[i].bone;
|
||||
skeleton.resetCache(bone);
|
||||
skeleton.sortBone(bone);
|
||||
}
|
||||
@ -124,9 +123,9 @@ public class TransformConstraint extends Constraint<TransformConstraint, Transfo
|
||||
skeleton.updateCache.add(this);
|
||||
|
||||
for (int i = 0; i < boneCount; i++)
|
||||
skeleton.sortReset(((BonePose)bones[i]).bone.children);
|
||||
skeleton.sortReset(bones[i].bone.children);
|
||||
for (int i = 0; i < boneCount; i++)
|
||||
((BonePose)bones[i]).bone.sorted = true;
|
||||
bones[i].bone.sorted = true;
|
||||
}
|
||||
|
||||
boolean isSourceActive () {
|
||||
|
||||
@ -37,11 +37,11 @@ import com.badlogic.gdx.utils.Array;
|
||||
* <p>
|
||||
* See <a href="https://esotericsoftware.com/spine-transform-constraints">Transform constraints</a> in the Spine User Guide. */
|
||||
public class TransformConstraintData extends ConstraintData<TransformConstraint, TransformConstraintPose> {
|
||||
final Array<BoneData> bones = new Array();
|
||||
final Array<BoneData> bones = new Array(true, 0, BoneData[]::new);
|
||||
BoneData source;
|
||||
float offsetRotation, offsetX, offsetY, offsetScaleX, offsetScaleY, offsetShearY;
|
||||
boolean localSource, localTarget, additive, clamp;
|
||||
final Array<FromProperty> properties = new Array();
|
||||
final Array<FromProperty> properties = new Array(true, 1, FromProperty[]::new);
|
||||
|
||||
public TransformConstraintData (String name) {
|
||||
super(name, new TransformConstraintPose());
|
||||
@ -167,7 +167,7 @@ public class TransformConstraintData extends ConstraintData<TransformConstraint,
|
||||
public float offset;
|
||||
|
||||
/** Constrained properties. */
|
||||
public final Array<ToProperty> to = new Array();
|
||||
public final Array<ToProperty> to = new Array(true, 1, ToProperty[]::new);
|
||||
|
||||
/** Reads this property from the specified bone. */
|
||||
abstract public float value (TransformConstraintData data, BonePose source, boolean local);
|
||||
|
||||
@ -111,14 +111,14 @@ abstract public class VertexAttachment extends Attachment {
|
||||
v += n + 1;
|
||||
skip += n;
|
||||
}
|
||||
Object[] skeletonBones = skeleton.getBones().items;
|
||||
Bone[] skeletonBones = skeleton.getBones().items;
|
||||
if (deformArray.size == 0) {
|
||||
for (int w = offset, b = skip * 3; w < count; w += stride) {
|
||||
float wx = 0, wy = 0;
|
||||
int n = bones[v++];
|
||||
n += v;
|
||||
for (; v < n; v++, b += 3) {
|
||||
BonePose bone = ((Bone)skeletonBones[bones[v]]).getAppliedPose();
|
||||
BonePose bone = skeletonBones[bones[v]].getAppliedPose();
|
||||
float vx = vertices[b], vy = vertices[b + 1], weight = vertices[b + 2];
|
||||
wx += (vx * bone.getA() + vy * bone.getB() + bone.getWorldX()) * weight;
|
||||
wy += (vx * bone.getC() + vy * bone.getD() + bone.getWorldY()) * weight;
|
||||
@ -133,7 +133,7 @@ abstract public class VertexAttachment extends Attachment {
|
||||
int n = bones[v++];
|
||||
n += v;
|
||||
for (; v < n; v++, b += 3, f += 2) {
|
||||
BonePose bone = ((Bone)skeletonBones[bones[v]]).getAppliedPose();
|
||||
BonePose bone = skeletonBones[bones[v]].getAppliedPose();
|
||||
float vx = vertices[b] + deform[f], vy = vertices[b + 1] + deform[f + 1], weight = vertices[b + 2];
|
||||
wx += (vx * bone.getA() + vy * bone.getB() + bone.getWorldX()) * weight;
|
||||
wy += (vx * bone.getC() + vy * bone.getD() + bone.getWorldY()) * weight;
|
||||
|
||||
@ -61,7 +61,7 @@ public class SkeletonActorPool extends Pool<SkeletonActor> {
|
||||
this.skeletonData = skeletonData;
|
||||
this.stateData = stateData;
|
||||
|
||||
obtained = new Array(false, initialCapacity);
|
||||
obtained = new Array(false, initialCapacity, SkeletonActor[]::new);
|
||||
|
||||
skeletonPool = new Pool<Skeleton>(initialCapacity, max) {
|
||||
protected Skeleton newObject () {
|
||||
@ -91,10 +91,10 @@ public class SkeletonActorPool extends Pool<SkeletonActor> {
|
||||
|
||||
/** Each obtained skeleton actor that is no longer playing an animation is removed from the stage and returned to the pool. */
|
||||
public void freeComplete () {
|
||||
Object[] obtained = this.obtained.items;
|
||||
SkeletonActor[] obtained = this.obtained.items;
|
||||
outer:
|
||||
for (int i = this.obtained.size - 1; i >= 0; i--) {
|
||||
var actor = (SkeletonActor)obtained[i];
|
||||
SkeletonActor actor = obtained[i];
|
||||
Array<TrackEntry> tracks = actor.state.getTracks();
|
||||
for (int ii = 0, nn = tracks.size; ii < nn; ii++)
|
||||
if (tracks.get(ii) != null) continue outer;
|
||||
|
||||
@ -88,7 +88,7 @@ public class SkeletonClipping {
|
||||
public boolean clipTriangles (float[] vertices, short[] triangles, int trianglesLength) {
|
||||
FloatArray clipOutput = this.clipOutput, clippedVertices = this.clippedVertices;
|
||||
ShortArray clippedTriangles = this.clippedTriangles;
|
||||
Object[] polygons = clippingPolygons.items;
|
||||
FloatArray[] polygons = clippingPolygons.items;
|
||||
int polygonsCount = clippingPolygons.size;
|
||||
|
||||
short index = 0;
|
||||
@ -108,7 +108,7 @@ public class SkeletonClipping {
|
||||
|
||||
for (int p = 0; p < polygonsCount; p++) {
|
||||
int s = clippedVertices.size;
|
||||
if (clip(x1, y1, x2, y2, x3, y3, (FloatArray)polygons[p], clipOutput)) {
|
||||
if (clip(x1, y1, x2, y2, x3, y3, polygons[p], clipOutput)) {
|
||||
clipOutputItems = clipOutput.items;
|
||||
int clipOutputLength = clipOutput.size;
|
||||
if (clipOutputLength == 0) continue;
|
||||
@ -160,7 +160,7 @@ public class SkeletonClipping {
|
||||
|
||||
FloatArray clipOutput = this.clipOutput, clippedVertices = this.clippedVertices;
|
||||
ShortArray clippedTriangles = this.clippedTriangles;
|
||||
Object[] polygons = clippingPolygons.items;
|
||||
FloatArray[] polygons = clippingPolygons.items;
|
||||
int polygonsCount = clippingPolygons.size;
|
||||
|
||||
short index = 0;
|
||||
@ -183,7 +183,7 @@ public class SkeletonClipping {
|
||||
|
||||
for (int p = 0; p < polygonsCount; p++) {
|
||||
int s = clippedVertices.size;
|
||||
if (clip(x1, y1, x2, y2, x3, y3, (FloatArray)polygons[p], clipOutput)) {
|
||||
if (clip(x1, y1, x2, y2, x3, y3, polygons[p], clipOutput)) {
|
||||
clipOutputItems = clipOutput.items;
|
||||
int clipOutputLength = clipOutput.size;
|
||||
if (clipOutputLength == 0) continue;
|
||||
@ -277,7 +277,7 @@ public class SkeletonClipping {
|
||||
FloatArray clipOutput = this.clipOutput, clippedVertices = this.clippedVertices;
|
||||
FloatArray clippedUvs = this.clippedUvs;
|
||||
ShortArray clippedTriangles = this.clippedTriangles;
|
||||
Object[] polygons = clippingPolygons.items;
|
||||
FloatArray[] polygons = clippingPolygons.items;
|
||||
int polygonsCount = clippingPolygons.size;
|
||||
int vertexSize = 2;
|
||||
|
||||
@ -300,7 +300,7 @@ public class SkeletonClipping {
|
||||
|
||||
for (int p = 0; p < polygonsCount; p++) {
|
||||
int s = clippedVertices.size;
|
||||
if (clip(x1, y1, x2, y2, x3, y3, (FloatArray)polygons[p], clipOutput)) {
|
||||
if (clip(x1, y1, x2, y2, x3, y3, polygons[p], clipOutput)) {
|
||||
int clipOutputLength = clipOutput.size;
|
||||
if (clipOutputLength == 0) continue;
|
||||
float d0 = y2 - y3, d1 = x3 - x2, d2 = x1 - x3, d4 = y3 - y1;
|
||||
|
||||
@ -36,8 +36,8 @@ import com.badlogic.gdx.utils.Pool;
|
||||
import com.badlogic.gdx.utils.ShortArray;
|
||||
|
||||
class Triangulator {
|
||||
private final Array<FloatArray> convexPolygons = new Array(false, 16);
|
||||
private final Array<ShortArray> convexPolygonsIndices = new Array(false, 16);
|
||||
private final Array<FloatArray> convexPolygons = new Array(false, 8, FloatArray[]::new);
|
||||
private final Array<ShortArray> convexPolygonsIndices = new Array(false, 8, FloatArray[]::new);
|
||||
|
||||
private final ShortArray indicesArray = new ShortArray();
|
||||
private final BooleanArray isConcaveArray = new BooleanArray();
|
||||
@ -204,14 +204,15 @@ class Triangulator {
|
||||
}
|
||||
|
||||
// Go through the list of polygons and try to merge the remaining triangles with the found triangle fans.
|
||||
Object[] convexPolygonsIndicesItems = convexPolygonsIndices.items, convexPolygonsItems = convexPolygons.items;
|
||||
ShortArray[] convexPolygonsIndicesItems = convexPolygonsIndices.items;
|
||||
FloatArray[] convexPolygonsItems = convexPolygons.items;
|
||||
for (int i = 0, n = convexPolygons.size; i < n; i++) {
|
||||
polygonIndices = (ShortArray)convexPolygonsIndicesItems[i];
|
||||
polygonIndices = convexPolygonsIndicesItems[i];
|
||||
if (polygonIndices.size == 0) continue;
|
||||
int firstIndex = polygonIndices.first();
|
||||
int lastIndex = polygonIndices.get(polygonIndices.size - 1);
|
||||
int lastIndex = polygonIndices.items[polygonIndices.size - 1];
|
||||
|
||||
polygon = (FloatArray)convexPolygonsItems[i];
|
||||
polygon = convexPolygonsItems[i];
|
||||
int o = polygon.size - 4;
|
||||
float[] p = polygon.items;
|
||||
float prevPrevX = p[o], prevPrevY = p[o + 1];
|
||||
@ -222,14 +223,14 @@ class Triangulator {
|
||||
|
||||
for (int ii = 0; ii < n; ii++) {
|
||||
if (ii == i) continue;
|
||||
var otherIndices = (ShortArray)convexPolygonsIndicesItems[ii];
|
||||
ShortArray otherIndices = convexPolygonsIndicesItems[ii];
|
||||
if (otherIndices.size != 3) continue;
|
||||
int otherFirstIndex = otherIndices.first();
|
||||
int otherSecondIndex = otherIndices.get(1);
|
||||
int otherLastIndex = otherIndices.get(2);
|
||||
int otherSecondIndex = otherIndices.items[1];
|
||||
int otherLastIndex = otherIndices.items[2];
|
||||
|
||||
var otherPoly = (FloatArray)convexPolygonsItems[ii];
|
||||
float x3 = otherPoly.get(otherPoly.size - 2), y3 = otherPoly.get(otherPoly.size - 1);
|
||||
FloatArray otherPoly = convexPolygonsItems[ii];
|
||||
float x3 = otherPoly.items[otherPoly.size - 2], y3 = otherPoly.items[otherPoly.size - 1];
|
||||
|
||||
if (otherFirstIndex != firstIndex || otherSecondIndex != lastIndex) continue;
|
||||
int winding1 = winding(prevPrevX, prevPrevY, prevX, prevY, x3, y3);
|
||||
@ -251,7 +252,7 @@ class Triangulator {
|
||||
|
||||
// Remove empty polygons that resulted from the merge step above.
|
||||
for (int i = convexPolygons.size - 1; i >= 0; i--) {
|
||||
polygon = (FloatArray)convexPolygonsItems[i];
|
||||
polygon = convexPolygonsItems[i];
|
||||
if (polygon.size == 0) {
|
||||
convexPolygons.removeIndex(i);
|
||||
polygonPool.free(polygon);
|
||||
@ -259,7 +260,6 @@ class Triangulator {
|
||||
polygonIndicesPool.free(polygonIndices);
|
||||
}
|
||||
}
|
||||
|
||||
return convexPolygons;
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user