From 1f92218c232860e94d5f2724c7f45fff0ead44c5 Mon Sep 17 00:00:00 2001 From: Nathan Sweet Date: Fri, 18 Apr 2025 12:40:54 -0400 Subject: [PATCH] [libgdx] Give all arrays types, direct array access, removed casts. --- .../spine/AttachmentTimelineTests.java | 4 +- .../com/esotericsoftware/spine/Animation.java | 425 ++++++------------ .../spine/AnimationState.java | 121 +++-- .../src/com/esotericsoftware/spine/Bone.java | 2 +- .../esotericsoftware/spine/IkConstraint.java | 18 +- .../spine/IkConstraintData.java | 2 +- .../spine/PathConstraint.java | 28 +- .../spine/PathConstraintData.java | 2 +- .../spine/PhysicsConstraint.java | 2 +- .../src/com/esotericsoftware/spine/Posed.java | 8 +- .../com/esotericsoftware/spine/Skeleton.java | 135 +++--- .../spine/SkeletonBinary.java | 48 +- .../spine/SkeletonBounds.java | 26 +- .../esotericsoftware/spine/SkeletonData.java | 42 +- .../esotericsoftware/spine/SkeletonJson.java | 12 +- .../spine/SkeletonRenderer.java | 12 +- .../spine/SkeletonRendererDebug.java | 41 +- .../src/com/esotericsoftware/spine/Skin.java | 11 +- .../com/esotericsoftware/spine/Slider.java | 34 +- .../src/com/esotericsoftware/spine/Slot.java | 2 +- .../spine/TransformConstraint.java | 29 +- .../spine/TransformConstraintData.java | 6 +- .../spine/attachments/VertexAttachment.java | 6 +- .../spine/utils/SkeletonActorPool.java | 6 +- .../spine/utils/SkeletonClipping.java | 12 +- .../spine/utils/Triangulator.java | 26 +- 26 files changed, 461 insertions(+), 599 deletions(-) diff --git a/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/AttachmentTimelineTests.java b/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/AttachmentTimelineTests.java index f57bbc54d..4b37f7c99 100644 --- a/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/AttachmentTimelineTests.java +++ b/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/AttachmentTimelineTests.java @@ -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 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)); diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Animation.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Animation.java index 9320c6f76..2aafe5e7d 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Animation.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Animation.java @@ -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 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 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 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 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 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 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 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 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 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 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 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 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 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 frameCount, 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 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 frameCount, 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 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 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 frameCount, 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 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 frameCount, 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 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 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. *

* 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 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 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 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 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 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 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 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; diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/AnimationState.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/AnimationState.java index 4fb0c9681..6726b2945 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/AnimationState.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/AnimationState.java @@ -51,7 +51,7 @@ import com.esotericsoftware.spine.Animation.Timeline; *

* See Applying Animations in the Spine Runtimes Guide. */ public class AnimationState { - static final Animation emptyAnimation = new Animation("", new Array(0), 0); + static final Animation emptyAnimation = new Animation("", new Array(true, 0, Timeline[]::new), 0); /** 1) A previously applied timeline has set this property.
* 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 tracks = new Array(); - private final Array events = new Array(); - final SnapshotArray listeners = new SnapshotArray(); + final Array tracks = new Array(true, 4, TrackEntry[]::new); + private final Array events = new Array(true, 4, Event[]::new); + final SnapshotArray listeners = new SnapshotArray(true, 16, AnimationStateListener[]::new); private final EventQueue queue = new EventQueue(); private final ObjectSet 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 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 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 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 timelineHoldMix = new Array(); + final Array 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 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(); diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Bone.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Bone.java index 8a3abd6dd..82bffa40c 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Bone.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Bone.java @@ -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 { @Null final Bone parent; - final Array children = new Array(); + final Array children = new Array(true, 4, Bone[]::new); boolean sorted; public Bone (BoneData data, @Null Bone parent) { diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/IkConstraint.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/IkConstraint.java index ac357fb50..4e0236ef0 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/IkConstraint.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/IkConstraint.java @@ -47,11 +47,11 @@ public class IkConstraint extends Constraint 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); diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/IkConstraintData.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/IkConstraintData.java index 92fc97e48..d7c06f2d0 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/IkConstraintData.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/IkConstraintData.java @@ -35,7 +35,7 @@ import com.badlogic.gdx.utils.Array; *

* See IK constraints in the Spine User Guide. */ public class IkConstraintData extends ConstraintData { - final Array bones = new Array(); + final Array bones = new Array(true, 2, BoneData[]::new); BoneData target; boolean uniform; diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PathConstraint.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PathConstraint.java index 6f30ddf22..ccc58f043 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PathConstraint.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PathConstraint.java @@ -62,11 +62,11 @@ public class PathConstraint extends Constraint { 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 { 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 { 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 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 * See Path constraints in the Spine User Guide. */ public class PathConstraintData extends ConstraintData { - final Array bones = new Array(); + final Array bones = new Array(true, 0, BoneData[]::new); SlotData slot; PositionMode positionMode; SpacingMode spacingMode; diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PhysicsConstraint.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PhysicsConstraint.java index 95cd72d6a..d6229d374 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PhysicsConstraint.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PhysicsConstraint.java @@ -49,7 +49,7 @@ public class PhysicsConstraint extends Constraint constraints; final Array physics; final Array updateCache = new Array(); - final Array resetCache = new Array(); + final Array 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 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 World transforms 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 findConstraint (String constraintName, Class 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}. diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonBinary.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonBinary.java index c628fadd5..6eedba5d9 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonBinary.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonBinary.java @@ -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 linkedMeshes = new Array(); + private final Array 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(input.readInt(true)); + var timelines = new Array(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); } diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonBounds.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonBounds.java index d014f4707..e57f6b3b4 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonBounds.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonBounds.java @@ -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 boundingBoxes = new Array(); - private Array polygons = new Array(); + private Array boundingBoxes = new Array(true, 8, BoundingBoxAttachment[]::new); + private Array polygons = new Array(true, 8, FloatArray[]::new); private Pool 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 boundingBoxes = this.boundingBoxes; Array 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]; } } diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonData.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonData.java index 396a7de23..27df09e0e 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonData.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonData.java @@ -38,13 +38,13 @@ import com.badlogic.gdx.utils.Null; * Guide. */ public class SkeletonData { @Null String name; - final Array bones = new Array(); // Ordered parents first. - final Array slots = new Array(); // Setup pose draw order. - final Array skins = new Array(); + final Array bones = new Array(true, 0, BoneData[]::new); // Ordered parents first. + final Array slots = new Array(true, 0, SlotData[]::new); // Setup pose draw order. + final Array skins = new Array(true, 0, Skin[]::new); @Null Skin defaultSkin; - final Array events = new Array(); - final Array animations = new Array(); - final Array constraints = new Array(); + final Array events = new Array(true, 0, EventData[]::new); + final Array animations = new Array(true, 0, Animation[]::new); + final Array 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 findConstraint (String constraintName, Class 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; } diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonJson.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonJson.java index 81203dc0f..f93fc24f6 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonJson.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonJson.java @@ -121,7 +121,7 @@ import com.esotericsoftware.spine.attachments.VertexAttachment; * JSON and binary data in the Spine * Runtimes Guide. */ public class SkeletonJson extends SkeletonLoader { - private final Array linkedMeshes = new Array(); + private final Array 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(); + var timelines = new Array(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)); } diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonRenderer.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonRenderer.java index 5c1f622f3..b6546053d 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonRenderer.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonRenderer.java @@ -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; diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonRendererDebug.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonRendererDebug.java index b9ae5743b..b6537a06b 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonRendererDebug.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonRendererDebug.java @@ -79,14 +79,15 @@ public class SkeletonRendererDebug { Gdx.gl.glBlendFunc(srcFunc, GL20.GL_ONE_MINUS_SRC_ALPHA); ShapeRenderer shapes = this.shapes; - Array bones = skeleton.bones; - Array 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 polygons = bounds.getPolygons(); Array 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); diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skin.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skin.java index a4c6f2d49..c063bcb39 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skin.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skin.java @@ -44,8 +44,8 @@ import com.esotericsoftware.spine.attachments.MeshAttachment; public class Skin { final String name; final OrderedSet attachments = new OrderedSet(); - final Array bones = new Array(0); - final Array constraints = new Array(0); + final Array bones = new Array(true, 0, BoneData[]::new); + final Array 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); } } diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Slider.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Slider.java index b97355447..77739be7f 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Slider.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Slider.java @@ -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 { } 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()]); } } diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Slot.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Slot.java index 18425c6a5..f19569f76 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Slot.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Slot.java @@ -43,7 +43,7 @@ public class Slot extends Posed { 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(); diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/TransformConstraint.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/TransformConstraint.java index 8a4eaa4bf..8d0dc8946 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/TransformConstraint.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/TransformConstraint.java @@ -48,11 +48,11 @@ public class TransformConstraint extends Constraint * See Transform constraints in the Spine User Guide. */ public class TransformConstraintData extends ConstraintData { - final Array bones = new Array(); + final Array bones = new Array(true, 0, BoneData[]::new); BoneData source; float offsetRotation, offsetX, offsetY, offsetScaleX, offsetScaleY, offsetShearY; boolean localSource, localTarget, additive, clamp; - final Array properties = new Array(); + final Array properties = new Array(true, 1, FromProperty[]::new); public TransformConstraintData (String name) { super(name, new TransformConstraintPose()); @@ -167,7 +167,7 @@ public class TransformConstraintData extends ConstraintData to = new Array(); + public final Array to = new Array(true, 1, ToProperty[]::new); /** Reads this property from the specified bone. */ abstract public float value (TransformConstraintData data, BonePose source, boolean local); diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/VertexAttachment.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/VertexAttachment.java index 49440254f..f18c0a59c 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/VertexAttachment.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/VertexAttachment.java @@ -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; diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/utils/SkeletonActorPool.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/utils/SkeletonActorPool.java index 8c98d0ba2..f6f7b9c8e 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/utils/SkeletonActorPool.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/utils/SkeletonActorPool.java @@ -61,7 +61,7 @@ public class SkeletonActorPool extends Pool { this.skeletonData = skeletonData; this.stateData = stateData; - obtained = new Array(false, initialCapacity); + obtained = new Array(false, initialCapacity, SkeletonActor[]::new); skeletonPool = new Pool(initialCapacity, max) { protected Skeleton newObject () { @@ -91,10 +91,10 @@ public class SkeletonActorPool extends Pool { /** 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 tracks = actor.state.getTracks(); for (int ii = 0, nn = tracks.size; ii < nn; ii++) if (tracks.get(ii) != null) continue outer; diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/utils/SkeletonClipping.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/utils/SkeletonClipping.java index 07a59c648..003932f79 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/utils/SkeletonClipping.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/utils/SkeletonClipping.java @@ -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; diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/utils/Triangulator.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/utils/Triangulator.java index 848803f17..7e6986e4d 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/utils/Triangulator.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/utils/Triangulator.java @@ -36,8 +36,8 @@ import com.badlogic.gdx.utils.Pool; import com.badlogic.gdx.utils.ShortArray; class Triangulator { - private final Array convexPolygons = new Array(false, 16); - private final Array convexPolygonsIndices = new Array(false, 16); + private final Array convexPolygons = new Array(false, 8, FloatArray[]::new); + private final Array 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; }