Merge branch '3.6' into 3.7-beta

This commit is contained in:
badlogic 2017-09-28 11:20:31 +02:00
commit bd987963dc
12 changed files with 90 additions and 88 deletions

View File

@ -156,6 +156,8 @@
* Added `stride` parameter to `VertexAttachment.computeWorldVertices`.
* Removed `RegionAttachment.vertices` field. The vertices array is provided to `RegionAttachment.computeWorldVertices` by the API user now.
* Removed `RegionAttachment.updateWorldVertices`, added `RegionAttachment.computeWorldVertices`. The new method now computes the x/y positions of the 4 vertices of the corner and places them in the provided `worldVertices` array, starting at `offset`, then moving by `stride` array elements when advancing to the next vertex. This allows to directly compose the vertex buffer and avoids a copy. The computation of the full vertices, including vertex colors and texture coordinates, is now done by the backend's respective renderer.
* Skeleton attachments: Moved update of attached skeleton out of libGDX `SkeletonRenderer`, added overloaded method `Skeleton#updateWorldTransform(Bone), used for `SkeletonAttachment`. You now MUST call this new method
with the bone of the parent skeleton to which the child skeleton is attached. See `SkeletonAttachmentTest` for and example.
* **Additions**
* Added support for local and relative transform constraint calculation, including additional fields in `TransformConstraintData`
* Added `Bone.localToWorldRotation`(rotation given relative to x-axis, counter-clockwise, in degrees).
@ -164,7 +166,7 @@
* Added `ClippingAttachment`, additional method `newClippingAttachment` in `AttachmentLoader` interface.
* Added `SkeletonClipper` and `Triangulator`, used to implement software clipping of attachments.
* `AnimationState#apply` returns boolean indicating if any timeline was applied or not.
* `Animation#apply` and `Timeline#apply`` now take enums `MixPose` and `MixDirection` instead of booleans
* `Animation#apply` and `Timeline#apply`` now take enums `MixPose` and `MixDirection` instead of booleans
### libGDX
* Fixed renderer to work with 3.6 changes

View File

@ -160,7 +160,7 @@ void spIkConstraint_apply2 (spBone* parent, spBone* child, float targetX, float
y = SQRT(dd - r * r) * bendDir;
a1 = ta - ATAN2(y, r);
a2 = ATAN2(y / psy, (r - l1) / psx);
goto outer;
goto break_outer;
}
}
{
@ -194,7 +194,7 @@ void spIkConstraint_apply2 (spBone* parent, spBone* child, float targetX, float
}
}
}
outer: {
break_outer: {
float os = ATAN2(cy, cx) * s2;
a1 = (a1 - os) * RAD_DEG + o1 - parent->arotation;
if (a1 > 180) a1 -= 360;

View File

@ -351,14 +351,14 @@ void spSkeleton_updateCache (spSkeleton* self) {
constraintCount = ikCount + transformCount + pathCount;
i = 0;
outer:
continue_outer:
for (; i < constraintCount; i++) {
for (ii = 0; ii < ikCount; ii++) {
spIkConstraint* ikConstraint = ikConstraints[ii];
if (ikConstraint->data->order == i) {
_sortIkConstraint(internal, ikConstraint);
i++;
goto outer;
goto continue_outer;
}
}
@ -367,7 +367,7 @@ void spSkeleton_updateCache (spSkeleton* self) {
if (transformConstraint->data->order == i) {
_sortTransformConstraint(internal, transformConstraint);
i++;
goto outer;
goto continue_outer;
}
}
@ -376,7 +376,7 @@ void spSkeleton_updateCache (spSkeleton* self) {
if (pathConstraint->data->order == i) {
_sortPathConstraint(internal, pathConstraint);
i++;
goto outer;
goto continue_outer;
}
}
}

View File

@ -220,7 +220,7 @@ void spSkeletonClipping_clipTriangles(spSkeletonClipping* self, float* vertices,
spFloatArray_clear(clippedUVs);
spUnsignedShortArray_clear(clippedTriangles);
i = 0;
outer:
continue_outer:
for (; i < trianglesLength; i += 3) {
int p;
int vertexOffset = triangles[i] * stride;
@ -306,7 +306,7 @@ void spSkeletonClipping_clipTriangles(spSkeletonClipping* self, float* vertices,
clippedTrianglesItems[s + 2] = (unsigned short)(index + 2);
index += 3;
i += 3;
goto outer;
goto continue_outer;
}
}
}

View File

@ -168,13 +168,13 @@ spShortArray* spTriangulator_triangulate(spTriangulator* self, spFloatArray* ver
vx = vertices[v]; vy = vertices[v + 1];
if (_positiveArea(p3x, p3y, p1x, p1y, vx, vy)) {
if (_positiveArea(p1x, p1y, p2x, p2y, vx, vy)) {
if (_positiveArea(p2x, p2y, p3x, p3y, vx, vy)) goto outer;
if (_positiveArea(p2x, p2y, p3x, p3y, vx, vy)) goto break_outer;
}
}
}
break;
}
outer:
break_outer:
if (next == 0) {
do {

View File

@ -712,14 +712,14 @@ namespace Spine {
if (entry.mixDuration > 0) {
timelineDataItems[i] = AnimationState.DipMix;
timelineDipMixItems[i] = entry;
goto outer; // continue outer;
goto continue_outer; // continue outer;
}
break;
}
}
timelineDataItems[i] = AnimationState.Dip;
}
outer: {}
continue_outer: {}
}
return lastEntry;
}

View File

@ -176,7 +176,7 @@ namespace Spine {
y = (float)Math.Sqrt(dd - r * r) * bendDir;
a1 = ta - (float)Math.Atan2(y, r);
a2 = (float)Math.Atan2(y / psy, (r - l1) / psx);
goto outer; // break outer;
goto break_outer; // break outer;
}
}
float minAngle = MathUtils.PI, minX = l1 - a, minDist = minX * minX, minY = 0;
@ -208,7 +208,7 @@ namespace Spine {
a2 = maxAngle * bendDir;
}
}
outer:
break_outer:
float os = (float)Math.Atan2(cy, cx) * s2;
float rotation = parent.arotation;
a1 = (a1 - os) * MathUtils.RadDeg + os1 - rotation;

View File

@ -135,24 +135,24 @@ namespace Spine {
IkConstraint constraint = ikConstraints.Items[ii];
if (constraint.data.order == i) {
SortIkConstraint(constraint);
goto outer; //continue outer;
goto continue_outer; //continue outer;
}
}
for (int ii = 0; ii < transformCount; ii++) {
TransformConstraint constraint = transformConstraints.Items[ii];
if (constraint.data.order == i) {
SortTransformConstraint(constraint);
goto outer; //continue outer;
goto continue_outer; //continue outer;
}
}
for (int ii = 0; ii < pathCount; ii++) {
PathConstraint constraint = pathConstraints.Items[ii];
if (constraint.data.order == i) {
SortPathConstraint(constraint);
goto outer; //continue outer;
goto continue_outer; //continue outer;
}
}
outer: {}
continue_outer: {}
}
for (int i = 0, n = bones.Count; i < n; i++)

View File

@ -78,13 +78,13 @@ namespace Spine {
float vx = vertices[v], vy = vertices[v + 1];
if (PositiveArea(p3x, p3y, p1x, p1y, vx, vy)) {
if (PositiveArea(p1x, p1y, p2x, p2y, vx, vy)) {
if (PositiveArea(p2x, p2y, p3x, p3y, vx, vy)) goto outer; // break outer;
if (PositiveArea(p2x, p2y, p3x, p3y, vx, vy)) goto break_outer; // break outer;
}
}
}
break;
}
outer:
break_outer:
if (next == 0) {
do {

View File

@ -46,6 +46,7 @@ public class SkeletonAttachmentTest extends ApplicationAdapter {
Skeleton spineboy, goblin;
AnimationState spineboyState, goblinState;
Bone attachmentBone;
public void create () {
camera = new OrthographicCamera();
@ -82,7 +83,9 @@ public class SkeletonAttachmentTest extends ApplicationAdapter {
// Instead of a right shoulder, spineboy will have a goblin!
SkeletonAttachment skeletonAttachment = new SkeletonAttachment("goblin");
skeletonAttachment.setSkeleton(goblin);
spineboy.findSlot("front-upper-arm").setAttachment(skeletonAttachment);
Slot slot = spineboy.findSlot("front-upper-arm");
slot.setAttachment(skeletonAttachment);
attachmentBone = slot.getBone();
}
}
@ -93,7 +96,7 @@ public class SkeletonAttachmentTest extends ApplicationAdapter {
goblinState.update(Gdx.graphics.getDeltaTime());
goblinState.apply(goblin);
goblin.updateWorldTransform();
goblin.updateWorldTransform(attachmentBone);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

View File

@ -30,6 +30,9 @@
package com.esotericsoftware.spine;
import static com.esotericsoftware.spine.utils.SpineUtils.cosDeg;
import static com.esotericsoftware.spine.utils.SpineUtils.sinDeg;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.utils.Array;
@ -328,6 +331,62 @@ public class Skeleton {
for (int i = 0, n = updateCache.size; i < n; i++)
updateCache.get(i).update();
}
/** Updates the world transform for each bone and applies all constraints. The
* root bone will be temporarily parented to the specified bone.
* <p>
* See <a href="http://esotericsoftware.com/spine-runtime-skeletons#World-transforms">World transforms</a> in the Spine
* Runtimes Guide. */
public void updateWorldTransform (Bone parent) {
// This partial update avoids computing the world transform for constrained bones when 1) the bone is not updated
// before the constraint, 2) the constraint only needs to access the applied local transform, and 3) the constraint calls
// updateWorldTransform.
Array<Bone> updateCacheReset = this.updateCacheReset;
for (int i = 0, n = updateCacheReset.size; i < n; i++) {
Bone bone = updateCacheReset.get(i);
bone.ax = bone.x;
bone.ay = bone.y;
bone.arotation = bone.rotation;
bone.ascaleX = bone.scaleX;
bone.ascaleY = bone.scaleY;
bone.ashearX = bone.shearX;
bone.ashearY = bone.shearY;
bone.appliedValid = true;
}
// Apply the parent bone transform to the root bone. The root bone
// always inherits scale, rotation and reflection.
Bone rootBone = getRootBone();
float pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d;
rootBone.worldX = pa * x + pb * y + parent.worldX;
rootBone.worldY = pc * x + pd * y + parent.worldY;
float rotationY = rootBone.rotation + 90 + rootBone.shearY;
float la = cosDeg(rootBone.rotation + rootBone.shearX) * rootBone.scaleX;
float lb = cosDeg(rotationY) * rootBone.scaleY;
float lc = sinDeg(rootBone.rotation + rootBone.shearX) * rootBone.scaleX;
float ld = sinDeg(rotationY) * rootBone.scaleY;
rootBone.a = pa * la + pb * lc;
rootBone.b = pa * lb + pb * ld;
rootBone.c = pc * la + pd * lc;
rootBone.d = pc * lb + pd * ld;
if (flipY) {
rootBone.a = -rootBone.a;
rootBone.b = -rootBone.b;
}
if (flipX) {
rootBone.c = -rootBone.c;
rootBone.d = -rootBone.d;
}
// Update everything except root bone.
Array<Updatable> updateCache = this.updateCache;
for (int i = 0, n = updateCache.size; i < n; i++) {
Updatable updatable = updateCache.get(i);
if (updatable != rootBone) updatable.update();
}
}
/** Sets the bones, constraints, slots, and draw order to their setup pose values. */
public void setToSetupPose () {

View File

@ -106,29 +106,7 @@ public class SkeletonRenderer {
} else if (attachment instanceof SkeletonAttachment) {
Skeleton attachmentSkeleton = ((SkeletonAttachment)attachment).getSkeleton();
if (attachmentSkeleton != null) {
Bone bone = slot.getBone();
Bone rootBone = attachmentSkeleton.getRootBone();
float oldScaleX = rootBone.getScaleX();
float oldScaleY = rootBone.getScaleY();
float oldRotation = rootBone.getRotation();
attachmentSkeleton.setPosition(bone.getWorldX(), bone.getWorldY());
// rootBone.setScaleX(1 + bone.getWorldScaleX() -
// oldScaleX);
// rootBone.setScaleY(1 + bone.getWorldScaleY() -
// oldScaleY);
// Set shear.
rootBone.setRotation(oldRotation + bone.getWorldRotationX());
attachmentSkeleton.updateWorldTransform();
draw(batch, attachmentSkeleton);
attachmentSkeleton.setX(0);
attachmentSkeleton.setY(0);
rootBone.setScaleX(oldScaleX);
rootBone.setScaleY(oldScaleY);
rootBone.setRotation(oldRotation);
}
if (attachmentSkeleton != null) draw(batch, attachmentSkeleton);
}
clipper.clipEnd(slot);
@ -189,28 +167,7 @@ public class SkeletonRenderer {
} else if (attachment instanceof SkeletonAttachment) {
Skeleton attachmentSkeleton = ((SkeletonAttachment)attachment).getSkeleton();
if (attachmentSkeleton != null) {
Bone bone = slot.getBone();
Bone rootBone = attachmentSkeleton.getRootBone();
float oldScaleX = rootBone.getScaleX();
float oldScaleY = rootBone.getScaleY();
float oldRotation = rootBone.getRotation();
attachmentSkeleton.setPosition(bone.getWorldX(), bone.getWorldY());
// rootBone.setScaleX(1 + bone.getWorldScaleX() -
// oldScaleX);
// rootBone.setScaleY(1 + bone.getWorldScaleY() -
// oldScaleY);
// Also set shear.
rootBone.setRotation(oldRotation + bone.getWorldRotationX());
attachmentSkeleton.updateWorldTransform();
draw(batch, attachmentSkeleton);
attachmentSkeleton.setPosition(0, 0);
rootBone.setScaleX(oldScaleX);
rootBone.setScaleY(oldScaleY);
rootBone.setRotation(oldRotation);
}
if (attachmentSkeleton != null) draw(batch, attachmentSkeleton);
}
if (texture != null) {
@ -321,26 +278,7 @@ public class SkeletonRenderer {
} else if (attachment instanceof SkeletonAttachment) {
Skeleton attachmentSkeleton = ((SkeletonAttachment)attachment).getSkeleton();
if (attachmentSkeleton != null) {
Bone bone = slot.getBone();
Bone rootBone = attachmentSkeleton.getRootBone();
float oldScaleX = rootBone.getScaleX();
float oldScaleY = rootBone.getScaleY();
float oldRotation = rootBone.getRotation();
attachmentSkeleton.setPosition(bone.getWorldX(), bone.getWorldY());
// rootBone.setScaleX(1 + bone.getWorldScaleX() - oldScaleX);
// rootBone.setScaleY(1 + bone.getWorldScaleY() - oldScaleY);
// Also set shear.
rootBone.setRotation(oldRotation + bone.getWorldRotationX());
attachmentSkeleton.updateWorldTransform();
draw(batch, attachmentSkeleton);
attachmentSkeleton.setPosition(0, 0);
rootBone.setScaleX(oldScaleX);
rootBone.setScaleY(oldScaleY);
rootBone.setRotation(oldRotation);
}
if (attachmentSkeleton != null) draw(batch, attachmentSkeleton);
}
if (texture != null) {