spine-as3 updated to v3.1.

This commit is contained in:
NathanSweet 2016-04-15 17:40:02 +02:00
parent 516c59b303
commit 1ccfaab4c9
15 changed files with 711 additions and 567 deletions

View File

@ -10,7 +10,7 @@ The Spine Runtimes are developed with the intent to be used with data exported f
## Spine version
spine-as3 works with data exported from the latest version of Spine, except linked meshes are [not yet supported](https://trello.com/c/bERJAFEq/73-update-runtimes-to-support-v3-1-linked-meshes).
spine-as3 works with data exported from the latest version of Spine.
spine-as3 supports all Spine features, including meshes. If using the `spine.flash` classes for rendering, meshes are not supported.

View File

@ -119,7 +119,8 @@ public class Bone implements Updatable {
_b = pa * lb + pb * ld;
_c = pc * la + pd * lc;
_d = pc * lb + pd * ld;
} else if (data.inheritRotation) { // No scale inheritance.
} else {
if (data.inheritRotation) { // No scale inheritance.
pa = 1;
pb = 0;
pc = 0;
@ -142,14 +143,6 @@ public class Bone implements Updatable {
_b = pa * lb + pb * ld;
_c = pc * la + pd * lc;
_d = pc * lb + pd * ld;
if (_skeleton.flipX) {
_a = -_a;
_b = -_b;
}
if (_skeleton.flipY != yDown) {
_c = -_c;
_d = -_d;
}
} else if (data.inheritScale) { // No rotation inheritance.
pa = 1;
pb = 0;
@ -185,6 +178,12 @@ public class Bone implements Updatable {
_b = pa * lb + pb * ld;
_c = pc * la + pd * lc;
_d = pc * lb + pd * ld;
} else {
_a = la;
_b = lb;
_c = lc;
_d = ld;
}
if (_skeleton.flipX) {
_a = -_a;
_b = -_b;
@ -193,11 +192,6 @@ public class Bone implements Updatable {
_c = -_c;
_d = -_d;
}
} else {
_a = la;
_b = lb;
_c = lc;
_d = ld;
}
}

View File

@ -84,7 +84,7 @@ public class IkConstraint implements Updatable {
rotationIK = 360 - rotationIK;
if (rotationIK > 180) rotationIK -= 360;
else if (rotationIK < -180) rotationIK += 360;
bone.updateWorldTransformWith(bone.x, bone.y, rotation + (rotationIK - rotation) * alpha, bone.scaleX, bone.scaleY);
bone.updateWorldTransformWith(bone.x, bone.y, rotation + (rotationIK - rotation) * alpha, bone.appliedScaleX, bone.appliedScaleY);
}
/** Adjusts the parent and child bone rotations so the tip of the child is as close to the target position as possible. The
@ -92,26 +92,32 @@ public class IkConstraint implements Updatable {
* @param child Any descendant bone of the parent. */
static public function apply2 (parent:Bone, child:Bone, targetX:Number, targetY:Number, bendDir:int, alpha:Number) : void {
if (alpha == 0) return;
var px:Number = parent.x, py:Number = parent.y, psx:Number = parent.scaleX, psy:Number = parent.scaleY;
var csx:Number = child.scaleX, cy:Number = child.y;
var offset1:int, offset2:int, sign2:int;
var px:Number = parent.x, py:Number = parent.y, psx:Number = parent.appliedScaleX, psy:Number = parent.appliedScaleY;
var o1:int, o2:int, s2:int;
if (psx < 0) {
psx = -psx;
offset1 = 180;
sign2 = -1;
o1 = 180;
s2 = -1;
} else {
offset1 = 0;
sign2 = 1;
o1 = 0;
s2 = 1;
}
if (psy < 0) {
psy = -psy;
sign2 = -sign2;
s2 = -s2;
}
var cx:Number = child.x, cy:Number = child.y, csx:Number = child.appliedScaleX;
var u:Boolean = Math.abs(psx - psy) <= 0.0001;
if (!u && cy != 0) {
child._worldX = parent.a * cx + parent.worldX;
child._worldY = parent.c * cx + parent.worldY;
cy = 0;
}
if (csx < 0) {
csx = -csx;
offset2 = 180;
o2 = 180;
} else
offset2 = 0;
o2 = 0;
var pp:Bone = parent.parent;
var tx:Number, ty:Number, dx:Number, dy:Number;
if (!pp) {
@ -132,7 +138,7 @@ public class IkConstraint implements Updatable {
}
var l1:Number = Math.sqrt(dx * dx + dy * dy), l2:Number = child.data.length * csx, a1:Number, a2:Number;
outer:
if (Math.abs(psx - psy) <= 0.0001) {
if (u) {
l2 *= psx;
var cos:Number = (tx * tx + ty * ty - l1 * l1 - l2 * l2) / (2 * l1 * l2);
if (cos < -1) cos = -1;
@ -141,7 +147,6 @@ public class IkConstraint implements Updatable {
var ad:Number = l1 + l2 * cos, o:Number = l2 * Math.sin(a2);
a1 = Math.atan2(ty * ad - tx * o, tx * ad + ty * o);
} else {
cy = 0;
var a:Number = psx * l2, b:Number = psy * l2, ta:Number = Math.atan2(ty, tx);
var aa:Number = a * a, bb:Number = b * b, ll:Number = l1 * l1, dd:Number = tx * tx + ty * ty;
var c0:Number = bb * ll + aa * dd - aa * bb, c1:Number = -2 * bb * l1, c2:Number = bb - aa;
@ -198,17 +203,17 @@ public class IkConstraint implements Updatable {
a2 = maxAngle * bendDir;
}
}
var offset:Number = Math.atan2(cy, child.x) * sign2;
a1 = (a1 - offset) * MathUtils.radDeg + offset1;
a2 = (a2 + offset) * MathUtils.radDeg * sign2 + offset2;
var os:Number = Math.atan2(cy, cx) * s2;
a1 = (a1 - os) * MathUtils.radDeg + o1;
a2 = (a2 + os) * MathUtils.radDeg * s2 + o2;
if (a1 > 180) a1 -= 360;
else if (a1 < -180) a1 += 360;
if (a2 > 180) a2 -= 360;
else if (a2 < -180) a2 += 360;
var rotation:Number = parent.rotation;
parent.updateWorldTransformWith(parent.x, parent.y, rotation + (a1 - rotation) * alpha, parent.scaleX, parent.scaleY);
parent.updateWorldTransformWith(px, py, rotation + (a1 - rotation) * alpha, parent.appliedScaleX, parent.appliedScaleY);
rotation = child.rotation;
child.updateWorldTransformWith(child.x, cy, rotation + (a2 - rotation) * alpha, child.scaleX, child.scaleY);
child.updateWorldTransformWith(cx, cy, rotation + (a2 - rotation) * alpha, child.appliedScaleX, child.appliedScaleY);
}
}

View File

@ -54,6 +54,7 @@ package spine {
public class SkeletonJson {
public var attachmentLoader:AttachmentLoader;
public var scale:Number = 1;
private var linkedMeshes:Vector.<LinkedMesh> = new Vector.<LinkedMesh>();
public function SkeletonJson (attachmentLoader:AttachmentLoader = null) {
this.attachmentLoader = attachmentLoader;
@ -172,7 +173,7 @@ package spine {
var slotIndex:int = skeletonData.findSlotIndex(slotName);
var slotEntry:Object = skinMap[slotName];
for (var attachmentName:String in slotEntry) {
var attachment:Attachment = readAttachment(skin, attachmentName, slotEntry[attachmentName]);
var attachment:Attachment = readAttachment(skin, slotIndex, attachmentName, slotEntry[attachmentName]);
if (attachment != null)
skin.addAttachment(slotIndex, attachmentName, attachment);
}
@ -182,6 +183,24 @@ package spine {
skeletonData.defaultSkin = skin;
}
// Linked meshes.
for each (var linkedMesh:LinkedMesh in linkedMeshes) {
var parentSkin:Skin = !linkedMesh.skin ? skeletonData.defaultSkin : skeletonData.findSkin(linkedMesh.skin);
if (!parentSkin) throw new Error("Skin not found: " + linkedMesh.skin);
var parentMesh:Attachment = parentSkin.getAttachment(linkedMesh.slotIndex, linkedMesh.parent);
if (!parentMesh) throw new Error("Parent mesh not found: " + linkedMesh.parent);
if (linkedMesh.mesh is MeshAttachment) {
var mesh:MeshAttachment = MeshAttachment(linkedMesh.mesh);
mesh.parentMesh = MeshAttachment(parentMesh);
mesh.updateUVs();
} else {
var weightedMesh:WeightedMeshAttachment = WeightedMeshAttachment(linkedMesh.mesh);
weightedMesh.parentMesh = WeightedMeshAttachment(parentMesh);
weightedMesh.updateUVs();
}
}
linkedMeshes.length = 0;
// Events.
var events:Object = root["events"];
if (events) {
@ -203,7 +222,7 @@ package spine {
return skeletonData;
}
private function readAttachment(skin:Skin, name:String, map:Object) : Attachment {
private function readAttachment (skin:Skin, slotIndex:int, name:String, map:Object) : Attachment {
name = map["name"] || name;
var typeName:String = map["type"] || "region";
@ -235,13 +254,11 @@ package spine {
region.updateOffset();
return region;
case AttachmentType.mesh:
case AttachmentType.linkedmesh:
var mesh:MeshAttachment = attachmentLoader.newMeshAttachment(skin, name, path);
if (!mesh) return null;
mesh.path = path;
mesh.vertices = getFloatArray(map, "vertices", scale);
mesh.triangles = getUintArray(map, "triangles");
mesh.regionUVs = getFloatArray(map, "uvs", 1);
mesh.updateUVs();
color = map["color"];
if (color) {
mesh.r = toColor(color, 0);
@ -249,15 +266,42 @@ package spine {
mesh.b = toColor(color, 2);
mesh.a = toColor(color, 3);
}
mesh.hullLength = int(map["hull"] || 0) * 2;
if (map["edges"]) mesh.edges = getIntArray(map, "edges");
mesh.width = Number(map["width"] || 0) * scale;
mesh.height = Number(map["height"] || 0) * scale;
if (!map["parent"]) {
mesh.vertices = getFloatArray(map, "vertices", scale);
mesh.triangles = getUintArray(map, "triangles");
mesh.regionUVs = getFloatArray(map, "uvs", 1);
mesh.updateUVs();
mesh.hullLength = int(map["hull"] || 0) * 2;
if (map["edges"]) mesh.edges = getIntArray(map, "edges");
} else {
mesh.inheritFFD = map.hasOwnProperty("ffd") ? map["ffd"] : true;
linkedMeshes[linkedMeshes.length] = new LinkedMesh(mesh, map["skin"], slotIndex, map["parent"]);
}
return mesh;
case AttachmentType.weightedmesh:
case AttachmentType.weightedlinkedmesh:
var weightedMesh:WeightedMeshAttachment = attachmentLoader.newWeightedMeshAttachment(skin, name, path);
if (!weightedMesh) return null;
weightedMesh.path = path;
color = map["color"];
if (color) {
weightedMesh.r = toColor(color, 0);
weightedMesh.g = toColor(color, 1);
weightedMesh.b = toColor(color, 2);
weightedMesh.a = toColor(color, 3);
}
weightedMesh.width = Number(map["width"] || 0) * scale;
weightedMesh.height = Number(map["height"] || 0) * scale;
if (!map["parent"]) {
var uvs:Vector.<Number> = getFloatArray(map, "uvs", 1);
vertices = getFloatArray(map, "vertices", 1);
var weights:Vector.<Number> = new Vector.<Number>();
@ -278,17 +322,13 @@ package spine {
weightedMesh.triangles = getUintArray(map, "triangles");
weightedMesh.regionUVs = uvs;
weightedMesh.updateUVs();
color = map["color"];
if (color) {
weightedMesh.r = toColor(color, 0);
weightedMesh.g = toColor(color, 1);
weightedMesh.b = toColor(color, 2);
weightedMesh.a = toColor(color, 3);
}
weightedMesh.hullLength = int(map["hull"] || 0) * 2;
if (map["edges"]) weightedMesh.edges = getIntArray(map, "edges");
weightedMesh.width = Number(map["width"] || 0) * scale;
weightedMesh.height = Number(map["height"] || 0) * scale;
} else {
weightedMesh.inheritFFD = map.hasOwnProperty("ffd") ? map["ffd"] : true;
linkedMeshes[linkedMeshes.length] = new LinkedMesh(weightedMesh, map["skin"], slotIndex, map["parent"]);
}
return weightedMesh;
case AttachmentType.boundingbox:
var box:BoundingBoxAttachment = attachmentLoader.newBoundingBoxAttachment(skin, name);
@ -571,4 +611,20 @@ package spine {
return values;
}
}
}
import spine.attachments.Attachment;
internal class LinkedMesh {
internal var parent:String, skin:String;
internal var slotIndex:int;
internal var mesh:Attachment;
public function LinkedMesh (mesh:Attachment, skin:String, slotIndex:int, parent:String) {
this.mesh = mesh;
this.skin = skin;
this.slotIndex = slotIndex;
this.parent = parent;
}
}

View File

@ -30,6 +30,7 @@
*****************************************************************************/
package spine.animation {
import spine.attachments.FfdAttachment;
import spine.Event;
import spine.Skeleton;
import spine.Slot;
@ -55,7 +56,8 @@ public class FfdTimeline extends CurveTimeline {
override public function apply (skeleton:Skeleton, lastTime:Number, time:Number, firedEvents:Vector.<Event>, alpha:Number) : void {
var slot:Slot = skeleton.slots[slotIndex];
if (slot.attachment != attachment) return;
var slotAttachment:FfdAttachment = slot.attachment as FfdAttachment;
if (!slotAttachment || !slotAttachment.applyFFD(attachment)) return;
var frames:Vector.<Number> = this.frames;
if (time < frames[0]) return; // Time is before first frame.

View File

@ -37,6 +37,8 @@ public class AttachmentType {
public static const boundingbox:AttachmentType = new AttachmentType(2, "boundingbox");
public static const mesh:AttachmentType = new AttachmentType(3, "mesh");
public static const weightedmesh:AttachmentType = new AttachmentType(4, "weightedmesh");
public static const linkedmesh:AttachmentType = new AttachmentType(3, "linkedmesh");
public static const weightedlinkedmesh:AttachmentType = new AttachmentType(4, "weightedlinkedmesh");
public var ordinal:int;
public var name:String;

View File

@ -0,0 +1,38 @@
/******************************************************************************
* Spine Runtimes Software License
* Version 2.3
*
* Copyright (c) 2013-2015, Esoteric Software
* All rights reserved.
*
* You are granted a perpetual, non-exclusive, non-sublicensable and
* non-transferable license to use, install, execute and perform the Spine
* Runtimes Software (the "Software") and derivative works solely for personal
* or internal use. Without the written permission of Esoteric Software (see
* Section 2 of the Spine Software License Agreement), you may not (a) modify,
* translate, adapt or otherwise create derivative works, improvements of the
* Software or develop new applications using the Software or (b) remove,
* delete, alter or obscure any trademarks or any copyright, trademark, patent
* or other intellectual property or proprietary rights notices on or in the
* Software, including any copy thereof. Redistributions in binary or source
* form must include this license and terms.
*
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
package spine.attachments {
public interface FfdAttachment {
function applyFFD (sourceAttachment:Attachment) : Boolean;
}
}

View File

@ -33,7 +33,7 @@ package spine.attachments {
import spine.Slot;
import spine.Bone;
public dynamic class MeshAttachment extends Attachment {
public dynamic class MeshAttachment extends Attachment implements FfdAttachment {
public var vertices:Vector.<Number>;
public var uvs:Vector.<Number>;
public var regionUVs:Vector.<Number>;
@ -43,6 +43,8 @@ public dynamic class MeshAttachment extends Attachment {
public var g:Number = 1;
public var b:Number = 1;
public var a:Number = 1;
private var _parentMesh:MeshAttachment;
public var inheritFFD:Boolean;
public var path:String;
public var rendererObject:Object;
@ -102,6 +104,27 @@ public dynamic class MeshAttachment extends Attachment {
worldVertices[int(ii + 1)] = vx * m10 + vy * m11 + y;
}
}
public function applyFFD (sourceAttachment:Attachment) : Boolean {
return this == sourceAttachment || (inheritFFD && _parentMesh == sourceAttachment);
}
public function get parentMesh () : MeshAttachment {
return _parentMesh;
}
public function set parentMesh (parentMesh:MeshAttachment) : void {
_parentMesh = parentMesh;
if (parentMesh != null) {
vertices = parentMesh.vertices;
regionUVs = parentMesh.regionUVs;
triangles = parentMesh.triangles;
hullLength = parentMesh.hullLength;
edges = parentMesh.edges;
width = parentMesh.width;
height = parentMesh.height;
}
}
}
}

View File

@ -33,7 +33,7 @@ package spine.attachments {
import spine.Slot;
import spine.Bone;
public dynamic class WeightedMeshAttachment extends Attachment {
public dynamic class WeightedMeshAttachment extends Attachment implements FfdAttachment {
public var bones:Vector.<int>;
public var weights:Vector.<Number>;
public var uvs:Vector.<Number>;
@ -44,6 +44,8 @@ public dynamic class WeightedMeshAttachment extends Attachment {
public var g:Number = 1;
public var b:Number = 1;
public var a:Number = 1;
private var _parentMesh:WeightedMeshAttachment;
public var inheritFFD:Boolean;
public var path:String;
public var rendererObject:Object;
@ -127,6 +129,28 @@ public dynamic class WeightedMeshAttachment extends Attachment {
}
}
}
public function applyFFD (sourceAttachment:Attachment) : Boolean {
return this == sourceAttachment || (inheritFFD && _parentMesh == sourceAttachment);
}
public function get parentMesh () : WeightedMeshAttachment {
return _parentMesh;
}
public function set parentMesh (parentMesh:WeightedMeshAttachment) : void {
_parentMesh = parentMesh;
if (parentMesh != null) {
bones = parentMesh.bones;
weights = parentMesh.weights;
regionUVs = parentMesh.regionUVs;
triangles = parentMesh.triangles;
hullLength = parentMesh.hullLength;
edges = parentMesh.edges;
width = parentMesh.width;
height = parentMesh.height;
}
}
}
}

View File

@ -78,7 +78,7 @@ public class SkeletonSprite extends Sprite {
for (var i:int = 0, n:int = drawOrder.length; i < n; i++) {
var slot:Slot = drawOrder[i];
var regionAttachment:RegionAttachment = slot.attachment as RegionAttachment;
if (regionAttachment != null) {
if (regionAttachment) {
var wrapper:Sprite = regionAttachment["wrapper"];
var region:AtlasRegion = AtlasRegion(regionAttachment.rendererObject);
if (!wrapper) {

View File

@ -10,7 +10,7 @@ The Spine Runtimes are developed with the intent to be used with data exported f
## Spine version
spine-starling works with data exported from the latest version of Spine, except linked meshes are [not yet supported](https://trello.com/c/bERJAFEq/73-update-runtimes-to-support-v3-1-linked-meshes).
spine-starling works with data exported from the latest version of Spine.
spine-starling supports all Spine features.