From f7c8c6deb12478295689cb2f1e7848bdd8f047a8 Mon Sep 17 00:00:00 2001 From: Nathan Sweet <> Date: Fri, 10 Nov 2023 21:17:41 -0400 Subject: [PATCH] [libgdx] Physics reset timelines data loading. Fixed physics rotate/shear. --- .../spine/PhysicsConstraint.java | 44 +++++++++------- .../spine/SkeletonBinary.java | 21 +++++++- .../esotericsoftware/spine/SkeletonJson.java | 51 +++++++++++++------ 3 files changed, 80 insertions(+), 36 deletions(-) diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PhysicsConstraint.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PhysicsConstraint.java index b7300b85b..e3418f426 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PhysicsConstraint.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PhysicsConstraint.java @@ -217,28 +217,34 @@ public class PhysicsConstraint implements Updatable { } if (rotateOrShearX) { - float r = rotateOffset * mix, a = bone.a, s, c; - if (data.rotate > 0) { - if (data.shearX > 0) { - r *= 0.5f; - s = sin(r * data.shearX); - c = cos(r * data.shearX); - bone.a = c * a - s * bone.c; - bone.c = s * a + c * bone.c; - a = bone.a; - } else { - s = sin(r * data.rotate); - c = cos(r * data.rotate); + float o = rotateOffset * mix, s, c, a; + if (data.shearX > 0) { + float r = 0; + if (data.rotate > 0) { + r = o * data.rotate; + s = sin(r); + c = cos(r); + a = bone.b; + bone.b = c * a - s * bone.d; + bone.d = s * a + c * bone.d; } - float b = bone.b; - bone.b = c * b - s * bone.d; - bone.d = s * b + c * bone.d; + r += o * data.shearX; + s = sin(r); + c = cos(r); + a = bone.a; + bone.a = c * a - s * bone.c; + bone.c = s * a + c * bone.c; } else { - s = sin(r * data.shearX); - c = cos(r * data.shearX); + o *= data.rotate; + s = sin(o); + c = cos(o); + a = bone.a; + bone.a = c * a - s * bone.c; + bone.c = s * a + c * bone.c; + a = bone.b; + bone.b = c * a - s * bone.d; + bone.d = s * a + c * bone.d; } - bone.a = c * a - s * bone.c; - bone.c = s * a + c * bone.c; } if (scaleX) { float s = 1 + scaleOffset * mix * data.scaleX; diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonBinary.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonBinary.java index dcf95597f..60857a185 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonBinary.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonBinary.java @@ -60,6 +60,7 @@ import com.esotericsoftware.spine.Animation.PhysicsConstraintGravityTimeline; import com.esotericsoftware.spine.Animation.PhysicsConstraintInertiaTimeline; import com.esotericsoftware.spine.Animation.PhysicsConstraintMassTimeline; import com.esotericsoftware.spine.Animation.PhysicsConstraintMixTimeline; +import com.esotericsoftware.spine.Animation.PhysicsConstraintResetTimeline; import com.esotericsoftware.spine.Animation.PhysicsConstraintStrengthTimeline; import com.esotericsoftware.spine.Animation.PhysicsConstraintWindTimeline; import com.esotericsoftware.spine.Animation.RGB2Timeline; @@ -134,6 +135,7 @@ public class SkeletonBinary extends SkeletonLoader { static public final int PHYSICS_WIND = 5; static public final int PHYSICS_GRAVITY = 6; static public final int PHYSICS_MIX = 7; + static public final int PHYSICS_RESET = 8; static public final int CURVE_LINEAR = 0; static public final int CURVE_STEPPED = 1; @@ -959,7 +961,15 @@ public class SkeletonBinary extends SkeletonLoader { for (int i = 0, n = input.readInt(true); i < n; i++) { int index = input.readInt(true); 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); + if (type == PHYSICS_RESET) { + PhysicsConstraintResetTimeline timeline = new PhysicsConstraintResetTimeline(frameCount, index); + for (int frame = 0; frame < frameCount; frame++) + timeline.setFrame(frame, input.readFloat()); + timelines.add(timeline); + continue; + } + int bezierCount = input.readInt(true); switch (type) { case PHYSICS_INERTIA: readTimeline(input, timelines, new PhysicsConstraintInertiaTimeline(frameCount, bezierCount, index), 1); @@ -1056,6 +1066,15 @@ public class SkeletonBinary extends SkeletonLoader { } } + // Physics constraint reset all timeline. + int resetCount = input.readInt(true); + if (resetCount > 0) { + PhysicsConstraintResetTimeline timeline = new PhysicsConstraintResetTimeline(resetCount, -1); + for (int i = 0; i < resetCount; i++) + timeline.setFrame(i, input.readFloat()); + timelines.add(timeline); + } + // Draw order timeline. int drawOrderCount = input.readInt(true); if (drawOrderCount > 0) { diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonJson.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonJson.java index 3242a42af..855f811f8 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonJson.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonJson.java @@ -61,6 +61,7 @@ import com.esotericsoftware.spine.Animation.PhysicsConstraintGravityTimeline; import com.esotericsoftware.spine.Animation.PhysicsConstraintInertiaTimeline; import com.esotericsoftware.spine.Animation.PhysicsConstraintMassTimeline; import com.esotericsoftware.spine.Animation.PhysicsConstraintMixTimeline; +import com.esotericsoftware.spine.Animation.PhysicsConstraintResetTimeline; import com.esotericsoftware.spine.Animation.PhysicsConstraintStrengthTimeline; import com.esotericsoftware.spine.Animation.PhysicsConstraintWindTimeline; import com.esotericsoftware.spine.Animation.RGB2Timeline; @@ -310,7 +311,7 @@ public class SkeletonJson extends SkeletonLoader { data.damping = constraintMap.getFloat("damping", 1); data.massInverse = 1f / constraintMap.getFloat("mass", 1); data.wind = constraintMap.getFloat("wind", 0); - data.gravity = constraintMap.getFloat("getFloat", 0); + data.gravity = constraintMap.getFloat("gravity", 0); data.mix = constraintMap.getFloat("mix", 1); skeletonData.physicsConstraints.add(data); @@ -932,6 +933,14 @@ public class SkeletonJson extends SkeletonLoader { int frames = timelineMap.size; String timelineName = timelineMap.name; + if (timelineName.equals("reset")) { + PhysicsConstraintResetTimeline timeline = new PhysicsConstraintResetTimeline(timelineMap.size, index); + for (int frame = 0; keyMap != null; keyMap = keyMap.next, frame++) + timeline.setFrame(frame, keyMap.getFloat("time", 0)); + timelines.add(timeline); + continue; + } + CurveTimeline1 timeline; if (timelineName.equals("inertia")) timeline = new PhysicsConstraintInertiaTimeline(frames, frames, index); @@ -1023,15 +1032,25 @@ public class SkeletonJson extends SkeletonLoader { } } + // Physics constraint reset all timeline. + JsonValue resetMap = map.get("physicsReset"); + if (resetMap != null) { + PhysicsConstraintResetTimeline timeline = new PhysicsConstraintResetTimeline(resetMap.size, -1); + int frame = 0; + for (JsonValue keyMap = resetMap.child; keyMap != null; keyMap = keyMap.next, frame++) + timeline.setFrame(frame, keyMap.getFloat("time", 0)); + timelines.add(timeline); + } + // Draw order timeline. - JsonValue drawOrdersMap = map.get("drawOrder"); - if (drawOrdersMap != null) { - DrawOrderTimeline timeline = new DrawOrderTimeline(drawOrdersMap.size); + JsonValue drawOrderMap = map.get("drawOrder"); + if (drawOrderMap != null) { + DrawOrderTimeline timeline = new DrawOrderTimeline(drawOrderMap.size); int slotCount = skeletonData.slots.size; int frame = 0; - for (JsonValue drawOrderMap = drawOrdersMap.child; drawOrderMap != null; drawOrderMap = drawOrderMap.next, frame++) { + for (JsonValue keyMap = drawOrderMap.child; keyMap != null; keyMap = keyMap.next, frame++) { int[] drawOrder = null; - JsonValue offsets = drawOrderMap.get("offsets"); + JsonValue offsets = keyMap.get("offsets"); if (offsets != null) { drawOrder = new int[slotCount]; for (int i = slotCount - 1; i >= 0; i--) @@ -1054,7 +1073,7 @@ public class SkeletonJson extends SkeletonLoader { for (int i = slotCount - 1; i >= 0; i--) if (drawOrder[i] == -1) drawOrder[i] = unchanged[--unchangedIndex]; } - timeline.setFrame(frame, drawOrderMap.getFloat("time", 0), drawOrder); + timeline.setFrame(frame, keyMap.getFloat("time", 0), drawOrder); } timelines.add(timeline); } @@ -1064,16 +1083,16 @@ public class SkeletonJson extends SkeletonLoader { if (eventsMap != null) { EventTimeline timeline = new EventTimeline(eventsMap.size); int frame = 0; - for (JsonValue eventMap = eventsMap.child; eventMap != null; eventMap = eventMap.next, frame++) { - EventData eventData = skeletonData.findEvent(eventMap.getString("name")); - if (eventData == null) throw new SerializationException("Event not found: " + eventMap.getString("name")); - Event event = new Event(eventMap.getFloat("time", 0), eventData); - event.intValue = eventMap.getInt("int", eventData.intValue); - event.floatValue = eventMap.getFloat("float", eventData.floatValue); - event.stringValue = eventMap.getString("string", eventData.stringValue); + for (JsonValue keyMap = eventsMap.child; keyMap != null; keyMap = keyMap.next, frame++) { + EventData eventData = skeletonData.findEvent(keyMap.getString("name")); + if (eventData == null) throw new SerializationException("Event not found: " + keyMap.getString("name")); + Event event = new Event(keyMap.getFloat("time", 0), eventData); + event.intValue = keyMap.getInt("int", eventData.intValue); + event.floatValue = keyMap.getFloat("float", eventData.floatValue); + event.stringValue = keyMap.getString("string", eventData.stringValue); if (event.getData().audioPath != null) { - event.volume = eventMap.getFloat("volume", eventData.volume); - event.balance = eventMap.getFloat("balance", eventData.balance); + event.volume = keyMap.getFloat("volume", eventData.volume); + event.balance = keyMap.getFloat("balance", eventData.balance); } timeline.setFrame(frame, event); }