mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-02-04 22:34:53 +08:00
[libgdx] updateCache sorting improvements.
This commit is contained in:
parent
020cd51b96
commit
589200250b
@ -65,12 +65,4 @@ public class Bone extends PosedActive<BoneData, BoneLocal, BonePose> {
|
||||
public Array<Bone> getChildren () {
|
||||
return children;
|
||||
}
|
||||
|
||||
void resetUpdate (Skeleton skeleton) {
|
||||
if (applied.world != skeleton.update) return;
|
||||
applied.world = 0;
|
||||
Bone[] children = this.children.items;
|
||||
for (int i = 0, n = this.children.size; i < n; i++)
|
||||
children[i].resetUpdate(skeleton);
|
||||
}
|
||||
}
|
||||
|
||||
@ -139,8 +139,8 @@ public class BonePose extends BoneLocal implements Update {
|
||||
* Some information is ambiguous in the world transform, such as -1,-1 scale versus 180 rotation. The local transform after
|
||||
* calling this method is equivalent to the local transform used to compute the world transform, but may not be identical. */
|
||||
public void updateLocalTransform (Skeleton skeleton) {
|
||||
world = skeleton.update;
|
||||
local = 0;
|
||||
world = skeleton.update;
|
||||
|
||||
if (bone.parent == null) {
|
||||
x = worldX - skeleton.x;
|
||||
@ -219,10 +219,33 @@ public class BonePose extends BoneLocal implements Update {
|
||||
}
|
||||
}
|
||||
|
||||
/** When true, the world transform has been modified and the local transform no longer matches. Call
|
||||
* {@link #updateLocalTransform(Skeleton)} before using the local transform. */
|
||||
public boolean isLocalDirty (Skeleton skeleton) {
|
||||
return local == skeleton.update;
|
||||
/** If the world transform has been modified and the local transform no longer matches, {@link #updateLocalTransform(Skeleton)}
|
||||
* is called. */
|
||||
public void validateLocalTransform (Skeleton skeleton) {
|
||||
if (local == skeleton.update) updateLocalTransform(skeleton);
|
||||
}
|
||||
|
||||
void modifyLocal (Skeleton skeleton) {
|
||||
if (local == skeleton.update) updateLocalTransform(skeleton);
|
||||
world = 0;
|
||||
resetWorld(skeleton.update);
|
||||
}
|
||||
|
||||
void modifyWorld (int update) {
|
||||
local = update;
|
||||
world = update;
|
||||
resetWorld(update);
|
||||
}
|
||||
|
||||
void resetWorld (int update) {
|
||||
Bone[] children = bone.children.items;
|
||||
for (int i = 0, n = bone.children.size; i < n; i++) {
|
||||
BonePose child = children[i].applied;
|
||||
if (child.world == update) {
|
||||
child.world = 0;
|
||||
child.resetWorld(update);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Part of the world transform matrix for the X axis. If changed, {@link #updateLocalTransform(Skeleton)} should be called. */
|
||||
|
||||
@ -76,19 +76,12 @@ public class IkConstraint extends Constraint<IkConstraint, IkConstraintData, IkC
|
||||
void sort (Skeleton skeleton) {
|
||||
skeleton.sortBone(target);
|
||||
Bone parent = bones.items[0].bone;
|
||||
skeleton.resetCache(parent);
|
||||
skeleton.sortBone(parent);
|
||||
if (bones.size == 1) {
|
||||
skeleton.updateCache.add(this);
|
||||
skeleton.sortReset(parent.children);
|
||||
} else {
|
||||
Bone child = bones.items[1].bone;
|
||||
skeleton.resetCache(child);
|
||||
skeleton.sortBone(child);
|
||||
skeleton.updateCache.add(this);
|
||||
skeleton.sortReset(parent.children);
|
||||
child.sorted = true;
|
||||
}
|
||||
skeleton.updateCache.add(this);
|
||||
parent.sorted = false;
|
||||
skeleton.sortReset(parent.children);
|
||||
skeleton.constrained(parent);
|
||||
if (bones.size > 1) skeleton.constrained(bones.items[1].bone);
|
||||
}
|
||||
|
||||
boolean isSourceActive () {
|
||||
@ -112,9 +105,9 @@ public class IkConstraint extends Constraint<IkConstraint, IkConstraintData, IkC
|
||||
|
||||
/** Applies 1 bone IK. The target is specified in the world coordinate system. */
|
||||
static public void apply (Skeleton skeleton, BonePose bone, float targetX, float targetY, boolean compress, boolean stretch,
|
||||
boolean uniform, float alpha) {
|
||||
boolean uniform, float mix) {
|
||||
if (bone == null) throw new IllegalArgumentException("bone cannot be null.");
|
||||
if (bone.local == skeleton.update) bone.updateLocalTransform(skeleton);
|
||||
bone.modifyLocal(skeleton);
|
||||
BonePose p = bone.bone.parent.applied;
|
||||
float pa = p.a, pb = p.b, pc = p.c, pd = p.d;
|
||||
float rotationIK = -bone.shearX - bone.rotation, tx, ty;
|
||||
@ -148,7 +141,7 @@ public class IkConstraint extends Constraint<IkConstraint, IkConstraintData, IkC
|
||||
rotationIK -= 360;
|
||||
else if (rotationIK < -180) //
|
||||
rotationIK += 360;
|
||||
bone.rotation += rotationIK * alpha;
|
||||
bone.rotation += rotationIK * mix;
|
||||
if (compress || stretch) {
|
||||
switch (bone.inherit) {
|
||||
case noScale, noScaleOrReflection -> {
|
||||
@ -160,25 +153,23 @@ public class IkConstraint extends Constraint<IkConstraint, IkConstraintData, IkC
|
||||
if (b > 0.0001f) {
|
||||
float dd = tx * tx + ty * ty;
|
||||
if ((compress && dd < b * b) || (stretch && dd > b * b)) {
|
||||
float s = ((float)Math.sqrt(dd) / b - 1) * alpha + 1;
|
||||
float s = ((float)Math.sqrt(dd) / b - 1) * mix + 1;
|
||||
bone.scaleX *= s;
|
||||
if (uniform) bone.scaleY *= s;
|
||||
}
|
||||
}
|
||||
}
|
||||
bone.updateWorldTransform(skeleton);
|
||||
bone.bone.resetUpdate(skeleton);
|
||||
}
|
||||
|
||||
/** Applies 2 bone IK. The target is specified in the world coordinate system.
|
||||
* @param child A direct descendant of the parent bone. */
|
||||
static public void apply (Skeleton skeleton, BonePose parent, BonePose child, float targetX, float targetY, int bendDir,
|
||||
boolean stretch, boolean uniform, float softness, float alpha) {
|
||||
boolean stretch, boolean uniform, float softness, float mix) {
|
||||
if (parent == null) throw new IllegalArgumentException("parent cannot be null.");
|
||||
if (child == null) throw new IllegalArgumentException("child cannot be null.");
|
||||
if (parent.inherit != Inherit.normal || child.inherit != Inherit.normal) return;
|
||||
if (parent.local == skeleton.update) parent.updateLocalTransform(skeleton);
|
||||
if (child.local == skeleton.update) child.updateLocalTransform(skeleton);
|
||||
parent.modifyLocal(skeleton);
|
||||
child.modifyLocal(skeleton);
|
||||
float px = parent.x, py = parent.y, psx = parent.scaleX, psy = parent.scaleY, csx = child.scaleX;
|
||||
int os1, os2, s2;
|
||||
if (psx < 0) {
|
||||
@ -218,10 +209,8 @@ public class IkConstraint extends Constraint<IkConstraint, IkConstraintData, IkC
|
||||
float dx = (x * d - y * b) * id - px, dy = (y * a - x * c) * id - py;
|
||||
float l1 = (float)Math.sqrt(dx * dx + dy * dy), l2 = child.bone.data.length * csx, a1, a2;
|
||||
if (l1 < 0.0001f) {
|
||||
apply(skeleton, parent, targetX, targetY, false, stretch, false, alpha);
|
||||
apply(skeleton, parent, targetX, targetY, false, stretch, false, mix);
|
||||
child.rotation = 0;
|
||||
child.updateWorldTransform(skeleton);
|
||||
child.bone.resetUpdate(skeleton);
|
||||
return;
|
||||
}
|
||||
x = targetX - pp.worldX;
|
||||
@ -250,7 +239,7 @@ public class IkConstraint extends Constraint<IkConstraint, IkConstraintData, IkC
|
||||
cos = 1;
|
||||
a2 = 0;
|
||||
if (stretch) {
|
||||
a = ((float)Math.sqrt(dd) / (l1 + l2) - 1) * alpha + 1;
|
||||
a = ((float)Math.sqrt(dd) / (l1 + l2) - 1) * mix + 1;
|
||||
parent.scaleX *= a;
|
||||
if (uniform) parent.scaleY *= a;
|
||||
}
|
||||
@ -315,15 +304,12 @@ public class IkConstraint extends Constraint<IkConstraint, IkConstraintData, IkC
|
||||
a1 -= 360;
|
||||
else if (a1 < -180) //
|
||||
a1 += 360;
|
||||
parent.rotation += a1 * alpha;
|
||||
parent.updateWorldTransform(skeleton);
|
||||
parent.rotation += a1 * mix;
|
||||
a2 = ((a2 + os) * radDeg - child.shearX) * s2 + os2 - child.rotation;
|
||||
if (a2 > 180)
|
||||
a2 -= 360;
|
||||
else if (a2 < -180) //
|
||||
a2 += 360;
|
||||
child.rotation += a2 * alpha;
|
||||
child.updateWorldTransform(skeleton);
|
||||
parent.bone.resetUpdate(skeleton);
|
||||
child.rotation += a2 * mix;
|
||||
}
|
||||
}
|
||||
|
||||
@ -152,7 +152,7 @@ public class PathConstraint extends Constraint<PathConstraint, PathConstraintDat
|
||||
BonePose p = slot.bone.applied;
|
||||
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, u = skeleton.update; i < boneCount; i++, p += 3) {
|
||||
BonePose bone = bones[i];
|
||||
bone.worldX += (boneX - bone.worldX) * mixX;
|
||||
bone.worldY += (boneY - bone.worldY) * mixY;
|
||||
@ -196,8 +196,7 @@ public class PathConstraint extends Constraint<PathConstraint, PathConstraintDat
|
||||
bone.c = sin * a + cos * c;
|
||||
bone.d = sin * b + cos * d;
|
||||
}
|
||||
bone.local = skeleton.update;
|
||||
bone.bone.resetUpdate(skeleton);
|
||||
bone.modifyWorld(u);
|
||||
}
|
||||
}
|
||||
|
||||
@ -462,16 +461,16 @@ public class PathConstraint extends Constraint<PathConstraint, PathConstraintDat
|
||||
void sort (Skeleton skeleton) {
|
||||
int slotIndex = slot.getData().index;
|
||||
Bone slotBone = slot.bone;
|
||||
if (skeleton.skin != null) sortPathConstraintAttachment(skeleton, skeleton.skin, slotIndex, slotBone);
|
||||
if (skeleton.skin != null) sortPathSlot(skeleton, skeleton.skin, slotIndex, slotBone);
|
||||
if (skeleton.data.defaultSkin != null && skeleton.data.defaultSkin != skeleton.skin)
|
||||
sortPathConstraintAttachment(skeleton, skeleton.data.defaultSkin, slotIndex, slotBone);
|
||||
sortPathConstraintAttachment(skeleton, slot.pose.attachment, slotBone);
|
||||
sortPathSlot(skeleton, skeleton.data.defaultSkin, slotIndex, slotBone);
|
||||
sortPath(skeleton, slot.pose.attachment, slotBone);
|
||||
BonePose[] bones = this.bones.items;
|
||||
int boneCount = this.bones.size;
|
||||
for (int i = 0; i < boneCount; i++) {
|
||||
Bone bone = bones[i].bone;
|
||||
skeleton.resetCache(bone);
|
||||
skeleton.sortBone(bone);
|
||||
skeleton.constrained(bone);
|
||||
}
|
||||
skeleton.updateCache.add(this);
|
||||
for (int i = 0; i < boneCount; i++)
|
||||
@ -480,15 +479,15 @@ public class PathConstraint extends Constraint<PathConstraint, PathConstraintDat
|
||||
bones[i].bone.sorted = true;
|
||||
}
|
||||
|
||||
private void sortPathConstraintAttachment (Skeleton skeleton, Skin skin, int slotIndex, Bone slotBone) {
|
||||
private void sortPathSlot (Skeleton skeleton, Skin skin, int slotIndex, Bone slotBone) {
|
||||
Object[] entries = skin.attachments.orderedItems().items;
|
||||
for (int i = 0, n = skin.attachments.size; i < n; i++) {
|
||||
var entry = (SkinEntry)entries[i];
|
||||
if (entry.slotIndex == slotIndex) sortPathConstraintAttachment(skeleton, entry.attachment, slotBone);
|
||||
if (entry.slotIndex == slotIndex) sortPath(skeleton, entry.attachment, slotBone);
|
||||
}
|
||||
}
|
||||
|
||||
private void sortPathConstraintAttachment (Skeleton skeleton, Attachment attachment, Bone slotBone) {
|
||||
private void sortPath (Skeleton skeleton, Attachment attachment, Bone slotBone) {
|
||||
if (!(attachment instanceof PathAttachment pathAttachment)) return;
|
||||
int[] pathBones = pathAttachment.getBones();
|
||||
if (pathBones == null)
|
||||
|
||||
@ -263,16 +263,15 @@ public class PhysicsConstraint extends Constraint<PhysicsConstraint, PhysicsCons
|
||||
tx = l * bone.a;
|
||||
ty = l * bone.c;
|
||||
}
|
||||
bone.local = skeleton.update;
|
||||
bone.bone.resetUpdate(skeleton);
|
||||
bone.modifyWorld(skeleton.update);
|
||||
}
|
||||
|
||||
void sort (Skeleton skeleton) {
|
||||
Bone bone = this.bone.bone;
|
||||
skeleton.sortBone(bone);
|
||||
skeleton.resetCache(bone);
|
||||
skeleton.updateCache.add(this);
|
||||
skeleton.sortReset(bone.children);
|
||||
skeleton.constrained(bone);
|
||||
}
|
||||
|
||||
boolean isSourceActive () {
|
||||
|
||||
@ -202,7 +202,7 @@ public class Skeleton {
|
||||
if (updateCache[i] instanceof Bone bone) updateCache[i] = bone.applied;
|
||||
}
|
||||
|
||||
void resetCache (Posed object) {
|
||||
void constrained (Posed object) {
|
||||
if (object.pose == object.applied) {
|
||||
object.applied = object.constrained;
|
||||
resetCache.add(object);
|
||||
|
||||
@ -70,22 +70,10 @@ public class Slider extends Constraint<Slider, SliderData, SliderPose> {
|
||||
pose.time = Math.max(0, pose.time);
|
||||
}
|
||||
|
||||
SliderData data = this.data;
|
||||
Timeline[] timelines = animation.timelines.items;
|
||||
int timelineCount = animation.timelines.size;
|
||||
Bone[] bones = skeleton.bones.items;
|
||||
if (pose.mix == 1) {
|
||||
for (int i = 0; i < timelineCount; i++)
|
||||
if (timelines[i] instanceof BoneTimeline timeline) bones[timeline.getBoneIndex()].resetUpdate(skeleton);
|
||||
} else {
|
||||
for (int i = 0; i < timelineCount; i++) {
|
||||
if (timelines[i] instanceof BoneTimeline timeline) {
|
||||
Bone bone = bones[timeline.getBoneIndex()];
|
||||
bone.resetUpdate(skeleton);
|
||||
if (bone.applied.local == skeleton.update) bone.applied.updateLocalTransform(skeleton);
|
||||
}
|
||||
}
|
||||
}
|
||||
Timeline[] timelines = animation.timelines.items;
|
||||
for (int i = 0, n = animation.timelines.size; i < n; i++)
|
||||
if (timelines[i] instanceof BoneTimeline timeline) bones[timeline.getBoneIndex()].applied.modifyLocal(skeleton);
|
||||
|
||||
SliderPose pose = applied;
|
||||
animation.apply(skeleton, pose.time, pose.time, data.loop, null, pose.mix, data.additive ? MixBlend.add : MixBlend.replace,
|
||||
@ -93,35 +81,32 @@ public class Slider extends Constraint<Slider, SliderData, SliderPose> {
|
||||
}
|
||||
|
||||
void sort (Skeleton skeleton) {
|
||||
Timeline[] timelines = data.animation.timelines.items;
|
||||
int timelineCount = data.animation.timelines.size;
|
||||
Bone[] bones = skeleton.bones.items;
|
||||
for (int i = 0; i < timelineCount; i++)
|
||||
if (timelines[i] instanceof BoneTimeline timeline) skeleton.sortBone(bones[timeline.getBoneIndex()]);
|
||||
|
||||
if (bone != null && !data.local) skeleton.sortBone(bone);
|
||||
skeleton.updateCache.add(this);
|
||||
|
||||
Timeline[] timelines = data.animation.timelines.items;
|
||||
Bone[] bones = skeleton.bones.items;
|
||||
Slot[] slots = skeleton.slots.items;
|
||||
Constraint[] constraints = skeleton.constraints.items;
|
||||
PhysicsConstraint[] physics = skeleton.physics.items;
|
||||
int physicsCount = skeleton.physics.size;
|
||||
for (int i = 0; i < timelineCount; i++) {
|
||||
for (int i = 0, n = data.animation.timelines.size; i < n; i++) {
|
||||
Timeline t = timelines[i];
|
||||
if (t instanceof BoneTimeline timeline) {
|
||||
Bone bone = bones[timeline.getBoneIndex()];
|
||||
skeleton.resetCache(bone);
|
||||
skeleton.sortReset(bone.children);
|
||||
bone.sorted = false;
|
||||
skeleton.sortReset(bone.children);
|
||||
skeleton.constrained(bone);
|
||||
} else if (t instanceof SlotTimeline timeline)
|
||||
skeleton.resetCache(slots[timeline.getSlotIndex()]);
|
||||
skeleton.constrained(slots[timeline.getSlotIndex()]);
|
||||
else if (t instanceof PhysicsConstraintTimeline timeline) {
|
||||
if (timeline.constraintIndex == -1) {
|
||||
for (int ii = 0; ii < physicsCount; ii++)
|
||||
skeleton.resetCache(physics[ii]);
|
||||
skeleton.constrained(physics[ii]);
|
||||
} else
|
||||
skeleton.resetCache(constraints[timeline.constraintIndex]);
|
||||
skeleton.constrained(constraints[timeline.constraintIndex]);
|
||||
} else if (t instanceof ConstraintTimeline timeline) //
|
||||
skeleton.resetCache(constraints[timeline.getConstraintIndex()]);
|
||||
skeleton.constrained(constraints[timeline.getConstraintIndex()]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -72,13 +72,16 @@ public class TransformConstraint extends Constraint<TransformConstraint, Transfo
|
||||
float[] offsets = data.offsets;
|
||||
BonePose source = this.source.applied;
|
||||
int update = skeleton.update;
|
||||
if (localSource && source.local == skeleton.update) source.updateLocalTransform(skeleton);
|
||||
if (localSource) source.modifyLocal(skeleton);
|
||||
FromProperty[] fromItems = data.properties.items;
|
||||
int fn = data.properties.size;
|
||||
BonePose[] bones = this.bones.items;
|
||||
for (int i = 0, n = this.bones.size; i < n; i++) {
|
||||
BonePose bone = bones[i];
|
||||
if (localTarget && bone.local == update) bone.updateLocalTransform(skeleton);
|
||||
if (localTarget)
|
||||
bone.modifyLocal(skeleton);
|
||||
else
|
||||
bone.modifyWorld(update);
|
||||
for (int f = 0; f < fn; f++) {
|
||||
FromProperty from = fromItems[f];
|
||||
float value = from.value(source, localSource, offsets) - from.offset;
|
||||
@ -97,28 +100,26 @@ public class TransformConstraint extends Constraint<TransformConstraint, Transfo
|
||||
}
|
||||
}
|
||||
}
|
||||
if (localTarget)
|
||||
bone.updateWorldTransform(skeleton);
|
||||
else
|
||||
bone.local = update;
|
||||
bone.bone.resetUpdate(skeleton);
|
||||
}
|
||||
}
|
||||
|
||||
void sort (Skeleton skeleton) {
|
||||
skeleton.sortBone(source);
|
||||
if (!data.localSource) skeleton.sortBone(source);
|
||||
BonePose[] bones = this.bones.items;
|
||||
int boneCount = this.bones.size;
|
||||
for (int i = 0; i < boneCount; i++) {
|
||||
Bone bone = bones[i].bone;
|
||||
skeleton.resetCache(bone);
|
||||
skeleton.sortBone(bone);
|
||||
boolean worldTarget = !data.localTarget;
|
||||
if (worldTarget) {
|
||||
for (int i = 0; i < boneCount; i++)
|
||||
skeleton.sortBone(bones[i].bone);
|
||||
}
|
||||
skeleton.updateCache.add(this);
|
||||
for (int i = 0; i < boneCount; i++) {
|
||||
Bone bone = bones[i].bone;
|
||||
skeleton.sortReset(bone.children);
|
||||
skeleton.constrained(bone);
|
||||
}
|
||||
for (int i = 0; i < boneCount; i++)
|
||||
skeleton.sortReset(bones[i].bone.children);
|
||||
for (int i = 0; i < boneCount; i++)
|
||||
bones[i].bone.sorted = true;
|
||||
bones[i].bone.sorted = worldTarget;
|
||||
}
|
||||
|
||||
boolean isSourceActive () {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user