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