[libgdx] Physics reset timelines data loading. Fixed physics rotate/shear.

This commit is contained in:
Nathan Sweet 2023-11-10 21:17:41 -04:00
parent 7fae9e54ae
commit f7c8c6deb1
3 changed files with 80 additions and 36 deletions

View File

@ -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;

View File

@ -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) {

View File

@ -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);
}