diff --git a/spine-as3/spine-as3-example/lib/spine-as3.swc b/spine-as3/spine-as3-example/lib/spine-as3.swc index ba34e4854..537b129f5 100644 Binary files a/spine-as3/spine-as3-example/lib/spine-as3.swc and b/spine-as3/spine-as3-example/lib/spine-as3.swc differ diff --git a/spine-as3/spine-as3/.settings/org.eclipse.core.resources.prefs b/spine-as3/spine-as3/.settings/org.eclipse.core.resources.prefs index 99f26c020..620e9f497 100644 --- a/spine-as3/spine-as3/.settings/org.eclipse.core.resources.prefs +++ b/spine-as3/spine-as3/.settings/org.eclipse.core.resources.prefs @@ -1,2 +1,4 @@ eclipse.preferences.version=1 +encoding//src/spine/animation/TwoColorTimeline.as=UTF-8 +encoding//src/spine/attachments/PointAttachment.as=UTF-8 encoding/=UTF-8 diff --git a/spine-as3/spine-as3/src/spine/Bone.as b/spine-as3/spine-as3/src/spine/Bone.as index deefb3fa6..3690eab76 100644 --- a/spine-as3/spine-as3/src/spine/Bone.as +++ b/spine-as3/spine-as3/src/spine/Bone.as @@ -53,12 +53,12 @@ public class Bone implements Updatable { public var ashearY:Number; public var appliedValid:Boolean; - internal var _a:Number; - internal var _b:Number; - internal var _c:Number; - internal var _d:Number; - internal var _worldX:Number; - internal var _worldY:Number; + public var a:Number; + public var b:Number; + public var c:Number; + public var d:Number; + public var worldX:Number; + public var worldY:Number; internal var _sorted:Boolean; @@ -115,38 +115,38 @@ public class Bone implements Updatable { lc = -lc; ld = -ld; } - _a = la; - _b = lb; - _c = lc; - _d = ld; - _worldX = x + skeleton.x; - _worldY = y + skeleton.y; + this.a = la; + this.b = lb; + this.c = lc; + this.d = ld; + worldX = x + skeleton.x; + worldY = y + skeleton.y; return; } - var pa:Number = parent._a, pb:Number = parent._b, pc:Number = parent._c, pd:Number = parent._d; - _worldX = pa * x + pb * y + parent._worldX; - _worldY = pc * x + pd * y + parent._worldY; + var pa:Number = parent.a, pb:Number = parent.b, pc:Number = parent.c, pd:Number = parent.d; + worldX = pa * x + pb * y + parent.worldX; + worldY = pc * x + pd * y + parent.worldY; - switch (_data.transformMode) { + switch (this.data.transformMode) { case TransformMode.normal: { rotationY = rotation + 90 + shearY; la = MathUtils.cosDeg(rotation + shearX) * scaleX; lb = MathUtils.cosDeg(rotationY) * scaleY; lc = MathUtils.sinDeg(rotation + shearX) * scaleX; ld = MathUtils.sinDeg(rotationY) * scaleY; - _a = pa * la + pb * lc; - _b = pa * lb + pb * ld; - _c = pc * la + pd * lc; - _d = pc * lb + pd * ld; + this.a = pa * la + pb * lc; + this.b = pa * lb + pb * ld; + this.c = pc * la + pd * lc; + this.d = pc * lb + pd * ld; return; } case TransformMode.onlyTranslation: { rotationY = rotation + 90 + shearY; - _a = MathUtils.cosDeg(rotation + shearX) * scaleX; - _b = MathUtils.cosDeg(rotationY) * scaleY; - _c = MathUtils.sinDeg(rotation + shearX) * scaleX; - _d = MathUtils.sinDeg(rotationY) * scaleY; + this.a = MathUtils.cosDeg(rotation + shearX) * scaleX; + this.b = MathUtils.cosDeg(rotationY) * scaleY; + this.c = MathUtils.sinDeg(rotation + shearX) * scaleX; + this.d = MathUtils.sinDeg(rotationY) * scaleY; break; } case TransformMode.noRotationOrReflection: { @@ -168,10 +168,10 @@ public class Bone implements Updatable { lb = MathUtils.cosDeg(ry) * scaleY; lc = MathUtils.sinDeg(rx) * scaleX; ld = MathUtils.sinDeg(ry) * scaleY; - _a = pa * la - pb * lc; - _b = pa * lb - pb * ld; - _c = pc * la + pd * lc; - _d = pc * lb + pd * ld; + this.a = pa * la - pb * lc; + this.b = pa * lb - pb * ld; + this.c = pc * la + pd * lc; + this.d = pc * lb + pd * ld; break; } case TransformMode.noScale: @@ -192,35 +192,35 @@ public class Bone implements Updatable { lb = MathUtils.cosDeg(90 + shearY) * scaleY; lc = MathUtils.sinDeg(shearX) * scaleX; ld = MathUtils.sinDeg(90 + shearY) * scaleY; - _a = za * la + zb * lc; - _b = za * lb + zb * ld; - _c = zc * la + zd * lc; - _d = zc * lb + zd * ld; - if (_data.transformMode != TransformMode.noScaleOrReflection ? pa * pd - pb * pc < 0 : skeleton.flipX != skeleton.flipY) { - _b = -_b; - _d = -_d; + this.a = za * la + zb * lc; + this.b = za * lb + zb * ld; + this.c = zc * la + zd * lc; + this.d = zc * lb + zd * ld; + if (this.data.transformMode != TransformMode.noScaleOrReflection ? pa * pd - pb * pc < 0 : skeleton.flipX != skeleton.flipY) { + this.b = -this.b; + this.d = -this.d; } return; } } if (_skeleton.flipX) { - _a = -_a; - _b = -_b; + this.a = -this.a; + this.b = -this.b; } if (_skeleton.flipY != yDown) { - _c = -_c; - _d = -_d; + this.c = -this.c; + this.d = -this.d; } } public function setToSetupPose () : void { - x = _data.x; - y = _data.y; - rotation = _data.rotation; - scaleX = _data.scaleX; - scaleY = _data.scaleY; - shearX = _data.shearX; - shearY = _data.shearY; + x = this.data.x; + y = this.data.y; + rotation = this.data.rotation; + scaleX = this.data.scaleX; + scaleY = this.data.scaleY; + shearX = this.data.shearX; + shearY = this.data.shearY; } public function get data () : BoneData { @@ -237,70 +237,22 @@ public class Bone implements Updatable { public function get children () : Vector. {; return _children; - } - - public function get a () : Number { - return _a; - } - - public function get b () : Number { - return _b; - } - - public function get c () : Number { - return _c; - } - - public function get d () : Number { - return _d; - } - - public function get worldX () : Number { - return _worldX; - } - - public function get worldY () : Number { - return _worldY; - } + } public function get worldRotationX () : Number { - return Math.atan2(_c, _a) * MathUtils.radDeg; + return Math.atan2(this.c, this.a) * MathUtils.radDeg; } public function get worldRotationY () : Number { - return Math.atan2(_d, _b) * MathUtils.radDeg; + return Math.atan2(this.d, this.b) * MathUtils.radDeg; } public function get worldScaleX () : Number { - return Math.sqrt(_a * _a + _c * _c); + return Math.sqrt(this.a * this.a + this.c * this.c); } public function get worldScaleY () : Number { - return Math.sqrt(_b * _b + _d * _d); - } - - public function worldToLocalRotationX () : Number { - var parent:Bone = _parent; - if (parent == null) return arotation; - var pa:Number = parent.a, pb:Number = parent.b, pc:Number = parent.c, pd:Number = parent.d, a:Number = this.a, c:Number = this.c; - return Math.atan2(pa * c - pc * a, pd * a - pb * c) * MathUtils.radDeg; - } - - public function worldToLocalRotationY () : Number { - var parent:Bone = _parent; - if (parent == null) return arotation; - var pa:Number = parent.a, pb:Number = parent.b, pc:Number = parent.c, pd:Number = parent.d, b:Number = this.b, d:Number = this.d; - return Math.atan2(pa * d - pc * b, pd * b - pb * d) * MathUtils.radDeg; - } - - public function rotateWorld (degrees:Number) : void { - var a:Number = this.a, b:Number = this.b, c:Number = this.c, d:Number = this.d; - var cos:Number = MathUtils.cosDeg(degrees), sin:Number = MathUtils.sinDeg(degrees); - this._a = cos * a - sin * c; - this._b = cos * b - sin * d; - this._c = sin * a + cos * c; - this._d = sin * b + cos * d; - this.appliedValid = false; + return Math.sqrt(this.b * this.b + this.d * this.d); } /** Computes the individual applied transform values from the world transform. This can be useful to perform processing using @@ -349,21 +301,41 @@ public class Bone implements Updatable { } public function worldToLocal (world:Vector.) : void { - var a:Number = _a, b:Number = _b, c:Number = _c, d:Number = _d; + var a:Number = this.a, b:Number = this.b, c:Number = this.c, d:Number = this.d; var invDet:Number = 1 / (a * d - b * c); - var x:Number = world[0] - _worldX, y:Number = world[1] - _worldY; + var x:Number = world[0] - this.worldX, y:Number = world[1] - this.worldY; world[0] = (x * d * invDet - y * b * invDet); world[1] = (y * a * invDet - x * c * invDet); } public function localToWorld (local:Vector.) : void { var localX:Number = local[0], localY:Number = local[1]; - local[0] = localX * _a + localY * _b + _worldX; - local[1] = localX * _c + localY * _d + _worldY; + local[0] = localX * this.a + localY * this.b + this.worldX; + local[1] = localX * this.c + localY * this.d + this.worldY; + } + + public function worldToLocalRotation (worldRotation:Number) : Number { + var sin:Number = MathUtils.sinDeg(worldRotation), cos:Number = MathUtils.cosDeg(worldRotation); + return Math.atan2(this.a * sin - this.c * cos, this.d * cos - this.b * sin) * MathUtils.radDeg; + } + + public function localToWorldRotation (localRotation:Number) : Number { + var sin:Number = MathUtils.sinDeg(localRotation), cos:Number = MathUtils.cosDeg(localRotation); + return Math.atan2(cos * this.c + sin * this.d, cos * this.a + sin * this.b) * MathUtils.radDeg; + } + + public function rotateWorld (degrees:Number) : void { + var a:Number = this.a, b:Number = this.b, c:Number = this.c, d:Number = this.d; + var cos:Number = MathUtils.cosDeg(degrees), sin:Number = MathUtils.sinDeg(degrees); + this.a = cos * a - sin * c; + this.b = cos * b - sin * d; + this.c = sin * a + cos * c; + this.d = sin * b + cos * d; + this.appliedValid = false; } public function toString () : String { - return _data._name; + return this.data._name; } } diff --git a/spine-as3/spine-as3/src/spine/Color.as b/spine-as3/spine-as3/src/spine/Color.as new file mode 100644 index 000000000..bf64bca44 --- /dev/null +++ b/spine-as3/spine-as3/src/spine/Color.as @@ -0,0 +1,101 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, 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 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 develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes 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, BUSINESS INTERRUPTION, OR LOSS OF + * USE, DATA, OR PROFITS) 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 { + public class Color { + public static var WHITE:Color = new Color(1, 1, 1, 1); + public static var RED:Color = new Color(1, 0, 0, 1); + public static var GREEN:Color = new Color(0, 1, 0, 1); + public static var BLUE:Color = new Color(0, 0, 1, 1); + public static var MAGENTA:Color = new Color(1, 0, 1, 1); + + public var r:Number = 0; + public var g:Number = 0; + public var b:Number = 0; + public var a:Number = 0; + + public function Color (r:Number, g:Number, b:Number, a:Number = 0) { + this.r = r; + this.g = g; + this.b = b; + this.a = a; + } + + public function setFrom (r:Number, g:Number, b:Number, a:Number): Color { + this.r = r; + this.g = g; + this.b = b; + this.a = a; + this.clamp(); + return this; + } + + public function setFromColor (c:Color): Color{ + this.r = c.r; + this.g = c.g; + this.b = c.b; + this.a = c.a; + return this; + } + + public function setFromString (hex:String): Color { + hex = hex.charAt(0) == '#' ? hex.substr(1) : hex; + this.r = parseInt(hex.substr(0, 2), 16) / 255.0; + this.g = parseInt(hex.substr(2, 2), 16) / 255.0; + this.b = parseInt(hex.substr(4, 2), 16) / 255.0; + this.a = (hex.length != 8 ? 255 : parseInt(hex.substr(6, 2), 16)) / 255.0; + return this; + } + + public function add (r:Number, g:Number, b:Number, a:Number): Color { + this.r += r; + this.g += g; + this.b += b; + this.a += a; + this.clamp(); + return this; + } + + public function clamp (): Color { + if (this.r < 0) this.r = 0; + else if (this.r > 1) this.r = 1; + + if (this.g < 0) this.g = 0; + else if (this.g > 1) this.g = 1; + + if (this.b < 0) this.b = 0; + else if (this.b > 1) this.b = 1; + + if (this.a < 0) this.a = 0; + else if (this.a > 1) this.a = 1; + return this; + } + } +} \ No newline at end of file diff --git a/spine-as3/spine-as3/src/spine/IkConstraint.as b/spine-as3/spine-as3/src/spine/IkConstraint.as index b5d9cdf5e..1970fad6e 100644 --- a/spine-as3/spine-as3/src/spine/IkConstraint.as +++ b/spine-as3/spine-as3/src/spine/IkConstraint.as @@ -57,10 +57,10 @@ public class IkConstraint implements Constraint { public function update () : void { switch (bones.length) { case 1: - apply1(bones[0], target._worldX, target._worldY, mix); + apply1(bones[0], target.worldX, target.worldY, mix); break; case 2: - apply2(bones[0], bones[1], target._worldX, target._worldY, bendDirection, mix); + apply2(bones[0], bones[1], target.worldX, target.worldY, bendDirection, mix); break; } } diff --git a/spine-as3/spine-as3/src/spine/MathUtils.as b/spine-as3/spine-as3/src/spine/MathUtils.as index bf05ba406..6bbf633ac 100644 --- a/spine-as3/spine-as3/src/spine/MathUtils.as +++ b/spine-as3/spine-as3/src/spine/MathUtils.as @@ -31,6 +31,8 @@ package spine { public class MathUtils { + static public var PI:Number = Math.PI; + static public var PI2:Number = Math.PI * 2; static public var radDeg:Number = 180 / Math.PI; static public var degRad:Number = Math.PI / 180; diff --git a/spine-as3/spine-as3/src/spine/PathConstraint.as b/spine-as3/spine-as3/src/spine/PathConstraint.as index 61f84a3b8..2b4ff23cc 100644 --- a/spine-as3/spine-as3/src/spine/PathConstraint.as +++ b/spine-as3/spine-as3/src/spine/PathConstraint.as @@ -89,10 +89,10 @@ public class PathConstraint implements Constraint { } for (var i:int = 0, n:int = spacesCount - 1; i < n;) { var bone:Bone = bones[i]; - var length:Number = bone.data.length, x:Number = length * bone.a, y:Number = length * bone.c; - length = Math.sqrt(x * x + y * y); + var setupLength:Number = bone.data.length, x:Number = setupLength * bone.a, y:Number = setupLength * bone.c; + var length:Number = Math.sqrt(x * x + y * y); if (scale) lengths[i] = length; - spaces[++i] = lengthSpacing ? Math.max(0, length + spacing) : spacing; + spaces[++i] = (lengthSpacing ? setupLength + spacing : spacing) * length / setupLength; } } else { for (i = 1; i < spacesCount; i++) @@ -113,15 +113,15 @@ public class PathConstraint implements Constraint { var p:Number; for (i = 0, p = 3; i < boneCount; i++, p += 3) { bone = bones[i]; - bone._worldX += (boneX - bone.worldX) * translateMix; - bone._worldY += (boneY - bone.worldY) * translateMix; + bone.worldX += (boneX - bone.worldX) * translateMix; + bone.worldY += (boneY - bone.worldY) * translateMix; x = positions[p]; y = positions[p + 1]; var dx:Number = x - boneX, dy:Number = y - boneY; if (scale) { length = lengths[i]; if (length != 0) { var s:Number = (Math.sqrt(dx * dx + dy * dy) / length - 1) * rotateMix + 1; - bone._a *= s; - bone._c *= s; + bone.a *= s; + bone.c *= s; } } boneX = x; @@ -151,10 +151,10 @@ public class PathConstraint implements Constraint { r *= rotateMix; cos = Math.cos(r); sin = Math.sin(r); - bone._a = cos * a - sin * c; - bone._b = cos * b - sin * d; - bone._c = sin * a + cos * c; - bone._d = sin * b + cos * d; + bone.a = cos * a - sin * c; + bone.b = cos * b - sin * d; + bone.c = sin * a + cos * c; + bone.d = sin * b + cos * d; } bone.appliedValid = false; } @@ -194,14 +194,14 @@ public class PathConstraint implements Constraint { } else if (p < 0) { if (prevCurve != BEFORE) { prevCurve = BEFORE; - path.computeWorldVertices2(target, 2, 4, world, 0); + path.computeWorldVertices(target, 2, 4, world, 0, 2); } addBeforePosition(p, world, 0, out, o); continue; } else if (p > pathLength) { if (prevCurve != AFTER) { prevCurve = AFTER; - path.computeWorldVertices2(target, verticesLength - 6, 4, world, 0); + path.computeWorldVertices(target, verticesLength - 6, 4, world, 0, 2); } addAfterPosition(p - pathLength, world, 0, out, o); continue; @@ -222,10 +222,10 @@ public class PathConstraint implements Constraint { if (curve != prevCurve) { prevCurve = curve; if (closed && curve == curveCount) { - path.computeWorldVertices2(target, verticesLength - 4, 4, world, 0); - path.computeWorldVertices2(target, 0, 4, world, 4); + path.computeWorldVertices(target, verticesLength - 4, 4, world, 0, 2); + path.computeWorldVertices(target, 0, 4, world, 4, 2); } else - path.computeWorldVertices2(target, curve * 6 + 2, 8, world, 0); + path.computeWorldVertices(target, curve * 6 + 2, 8, world, 0, 2); } addCurvePosition(p, world[0], world[1], world[2], world[3], world[4], world[5], world[6], world[7], out, o, tangents || (i > 0 && space == 0)); @@ -238,8 +238,8 @@ public class PathConstraint implements Constraint { verticesLength += 2; this._world.length = verticesLength; world = this._world; - path.computeWorldVertices2(target, 2, verticesLength - 4, world, 0); - path.computeWorldVertices2(target, 0, 2, world, verticesLength - 4); + path.computeWorldVertices(target, 2, verticesLength - 4, world, 0, 2); + path.computeWorldVertices(target, 0, 2, world, verticesLength - 4, 2); world[verticesLength - 2] = world[0]; world[verticesLength - 1] = world[1]; } else { @@ -247,7 +247,7 @@ public class PathConstraint implements Constraint { verticesLength -= 4; this._world.length = verticesLength; world = this._world; - path.computeWorldVertices2(target, 2, verticesLength, world, 0); + path.computeWorldVertices(target, 2, verticesLength, world, 0, 2); } // Curve lengths. diff --git a/spine-as3/spine-as3/src/spine/Skeleton.as b/spine-as3/spine-as3/src/spine/Skeleton.as index 8aa25550f..6228e649e 100644 --- a/spine-as3/spine-as3/src/spine/Skeleton.as +++ b/spine-as3/spine-as3/src/spine/Skeleton.as @@ -29,6 +29,8 @@ *****************************************************************************/ package spine { +import spine.attachments.MeshAttachment; +import spine.attachments.RegionAttachment; import flash.utils.Dictionary; import spine.attachments.PathAttachment; import spine.attachments.Attachment; @@ -44,7 +46,7 @@ public class Skeleton { private var _updateCache:Vector. = new Vector.(); private var _updateCacheReset:Vector. = new Vector.(); private var _skin:Skin; - public var r:Number = 1, g:Number = 1, b:Number = 1, a:Number = 1; + public var color:Color = new Color(1, 1, 1, 1); public var time:Number = 0; public var flipX:Boolean, flipY:Boolean; public var x:Number = 0, y:Number = 0; @@ -167,25 +169,25 @@ public class Skeleton { if (skin != null) sortPathConstraintAttachment(skin, slotIndex, slotBone); if (data.defaultSkin != null && data.defaultSkin != skin) sortPathConstraintAttachment(data.defaultSkin, slotIndex, slotBone); - var ii:Number = 0; - var nn:Number = 0; - for (ii = 0, nn = data.skins.length; ii < nn; ii++) - sortPathConstraintAttachment(data.skins[ii], slotIndex, slotBone); + var i:Number = 0; + var n:Number = 0; + for (i = 0, n = data.skins.length; i < n; i++) + sortPathConstraintAttachment(data.skins[i], slotIndex, slotBone); var attachment:Attachment = slot.attachment; if (attachment is PathAttachment) sortPathConstraintAttachment2(attachment, slotBone); var constrained:Vector. = constraint.bones; var boneCount:Number = constrained.length; - for (ii = 0; ii < boneCount; ii++) - sortBone(constrained[ii]); + for (i = 0; i < boneCount; i++) + sortBone(constrained[i]); _updateCache.push(constraint); - for (ii = 0; ii < boneCount; ii++) - sortReset(constrained[ii].children); - for (ii = 0; ii < boneCount; ii++) - constrained[ii]._sorted = true; + for (i = 0; i < boneCount; i++) + sortReset(constrained[i].children); + for (i = 0; i < boneCount; i++) + constrained[i]._sorted = true; } private function sortTransformConstraint (constraint:TransformConstraint): void { @@ -193,16 +195,24 @@ public class Skeleton { var constrained:Vector. = constraint.bones; var boneCount:Number = constrained.length; - var ii:Number = 0; - for (ii = 0; ii < boneCount; ii++) - sortBone(constrained[ii]); + var i:Number = 0; + if (constraint.data.local) { + for (i = 0; i < boneCount; i++) { + var child:Bone = constrained[constrained.length - 1]; + sortBone(child.parent); + if (!(_updateCache.indexOf(child) > -1)) _updateCacheReset.push(child); + } + } else { + for (i = 0; i < boneCount; i++) + sortBone(constrained[i]); + } _updateCache.push(constraint); - for (ii = 0; ii < boneCount; ii++) - sortReset(constrained[ii].children); - for (ii = 0; ii < boneCount; ii++) - constrained[ii]._sorted = true; + for (i = 0; i < boneCount; i++) + sortReset(constrained[i].children); + for (i = 0; i < boneCount; i++) + constrained[i]._sorted = true; } private function sortPathConstraintAttachment (skin:Skin, slotIndex:int, slotBone:Bone) : void { @@ -464,6 +474,44 @@ public class Skeleton { public function toString () : String { return _data.name != null ? _data.name : super.toString(); } + + public function getBounds (offset: Vector., size: Vector., temp: Vector.) : void { + if (offset == null) throw new ArgumentError("offset cannot be null."); + if (size == null) throw new ArgumentError("size cannot be null."); + var drawOrder:Vector. = this.drawOrder; + var minX:Number = Number.POSITIVE_INFINITY, minY:Number = Number.POSITIVE_INFINITY, maxX:Number = Number.NEGATIVE_INFINITY, maxY:Number = Number.NEGATIVE_INFINITY; + for (var i:int = 0, n:int = drawOrder.length; i < n; i++) { + var slot:Slot = drawOrder[i]; + var verticesLength:int = 0; + var vertices: Vector. = null; + var attachment:Attachment = slot.attachment; + if (attachment is RegionAttachment) { + verticesLength = 8; + temp.length = verticesLength; + vertices = temp; + (attachment as RegionAttachment).computeWorldVertices(slot.bone, vertices, 0, 2); + } else if (attachment is MeshAttachment) { + var mesh:MeshAttachment = attachment as MeshAttachment; + verticesLength = mesh.worldVerticesLength; + temp.length = verticesLength; + vertices = temp; + mesh.computeWorldVertices(slot, 0, verticesLength, vertices, 0, 2); + } + if (vertices != null) { + for (var ii:int = 0, nn:int = vertices.length; ii < nn; ii += 8) { + var x:Number = vertices[ii], y:Number = vertices[ii + 1]; + minX = Math.min(minX, x); + minY = Math.min(minY, y); + maxX = Math.max(maxX, x); + maxY = Math.max(maxY, y); + } + } + } + offset[0] = minX; + offset[1] = minY; + size[0] = maxX - minX; + size[1] = maxY - minY; + } } } diff --git a/spine-as3/spine-as3/src/spine/SkeletonBounds.as b/spine-as3/spine-as3/src/spine/SkeletonBounds.as index 663b44335..c4da1bec9 100644 --- a/spine-as3/spine-as3/src/spine/SkeletonBounds.as +++ b/spine-as3/spine-as3/src/spine/SkeletonBounds.as @@ -65,7 +65,7 @@ public class SkeletonBounds { polygons[polygons.length] = polygon; polygon.vertices.length = boundingBox.worldVerticesLength; - boundingBox.computeWorldVertices(slot, polygon.vertices); + boundingBox.computeWorldVertices(slot, 0, boundingBox.worldVerticesLength, polygon.vertices, 0, 2); } if (updateAabb) diff --git a/spine-as3/spine-as3/src/spine/SkeletonJson.as b/spine-as3/spine-as3/src/spine/SkeletonJson.as index 6514f6780..5b77a8d77 100644 --- a/spine-as3/spine-as3/src/spine/SkeletonJson.as +++ b/spine-as3/spine-as3/src/spine/SkeletonJson.as @@ -29,6 +29,8 @@ *****************************************************************************/ package spine { + import spine.animation.TwoColorTimeline; + import spine.attachments.PointAttachment; import spine.animation.PathConstraintMixTimeline; import spine.animation.PathConstraintSpacingTimeline; import spine.animation.PathConstraintPositionTimeline; @@ -126,10 +128,12 @@ public class SkeletonJson { var color:String = slotMap["color"]; if (color) { - slotData.r = toColor(color, 0); - slotData.g = toColor(color, 1); - slotData.b = toColor(color, 2); - slotData.a = toColor(color, 3); + slotData.color.setFrom(toColor(color, 0), toColor(color, 1), toColor(color, 2), toColor(color, 3)); + } + + var dark:String = slotMap["dark"]; + if (dark) { + slotData.darkColor.setFrom(toColor(dark, 0), toColor(dark, 1), toColor(dark, 2), toColor(dark, 3)); } slotData.attachmentName = slotMap["attachment"]; @@ -288,10 +292,7 @@ public class SkeletonJson { region.height = Number(map["height"] || 0) * scale; color = map["color"]; if (color) { - region.r = toColor(color, 0); - region.g = toColor(color, 1); - region.b = toColor(color, 2); - region.a = toColor(color, 3); + region.color.setFrom(toColor(color, 0), toColor(color, 1), toColor(color, 2), toColor(color, 3)); } region.updateOffset(); return region; @@ -303,10 +304,7 @@ public class SkeletonJson { color = map["color"]; if (color) { - mesh.r = toColor(color, 0); - mesh.g = toColor(color, 1); - mesh.b = toColor(color, 2); - mesh.a = toColor(color, 3); + mesh.color.setFrom(toColor(color, 0), toColor(color, 1), toColor(color, 2), toColor(color, 3)); } mesh.width = Number(map["width"] || 0) * scale; @@ -347,6 +345,18 @@ public class SkeletonJson { } path.lengths = lengths; return path; + case AttachmentType.point: + var point:PointAttachment = attachmentLoader.newPointAttachment(skin, name); + if (!point) return null; + point.x = map.hasOwnProperty("x") ? Number(map["x"]) * scale : 0; + point.y = map.hasOwnProperty("y") ? Number(map["y"]) * scale : 0; + point.rotation = map.hasOwnProperty("rotation") ? Number(map["rotation"]) : 0; + + color = map["color"]; + if (color) { + point.color.setFrom(toColor(color, 0), toColor(color, 1), toColor(color, 2), toColor(color, 3)); + } + return point; } return null; @@ -400,7 +410,16 @@ public class SkeletonJson { for (timelineName in slotMap) { values = slotMap[timelineName]; - if (timelineName == "color") { + if (timelineName == "attachment") { + var attachmentTimeline:AttachmentTimeline = new AttachmentTimeline(values.length); + attachmentTimeline.slotIndex = slotIndex; + + frameIndex = 0; + for each (valueMap in values) + attachmentTimeline.setFrame(frameIndex++, valueMap["time"], valueMap["name"]); + timelines[timelines.length] = attachmentTimeline; + duration = Math.max(duration, attachmentTimeline.frames[attachmentTimeline.frameCount - 1]); + } else if (timelineName == "color") { var colorTimeline:ColorTimeline = new ColorTimeline(values.length); colorTimeline.slotIndex = slotIndex; @@ -417,15 +436,24 @@ public class SkeletonJson { } timelines[timelines.length] = colorTimeline; duration = Math.max(duration, colorTimeline.frames[(colorTimeline.frameCount - 1) * ColorTimeline.ENTRIES]); - } else if (timelineName == "attachment") { - var attachmentTimeline:AttachmentTimeline = new AttachmentTimeline(values.length); - attachmentTimeline.slotIndex = slotIndex; + } else if (timelineName == "twoColor") { + var twoColorTimeline:TwoColorTimeline = new TwoColorTimeline(values.length); + twoColorTimeline.slotIndex = slotIndex; frameIndex = 0; - for each (valueMap in values) - attachmentTimeline.setFrame(frameIndex++, valueMap["time"], valueMap["name"]); - timelines[timelines.length] = attachmentTimeline; - duration = Math.max(duration, attachmentTimeline.frames[attachmentTimeline.frameCount - 1]); + for each (valueMap in values) { + color = valueMap["color"]; + var darkColor:String = valueMap["dark"]; + var light:Color = new Color(0, 0, 0, 0); + var dark:Color = new Color(0, 0, 0, 0); + light.setFrom(toColor(color, 0), toColor(color, 1), toColor(color, 2), toColor(color, 3)); + dark.setFrom(toColor(darkColor, 0), toColor(darkColor, 1), toColor(darkColor, 2), toColor(darkColor, 3)); + twoColorTimeline.setFrame(frameIndex, valueMap["time"], light.r, light.g, light.b, light.a, dark.r, dark.g, dark.b); + readCurve(valueMap, twoColorTimeline, frameIndex); + frameIndex++; + } + timelines[timelines.length] = twoColorTimeline; + duration = Math.max(duration, twoColorTimeline.frames[(twoColorTimeline.frameCount - 1) * TwoColorTimeline.ENTRIES]); } else throw new Error("Invalid timeline type for a slot: " + timelineName + " (" + slotName + ")"); } diff --git a/spine-as3/spine-as3/src/spine/Slot.as b/spine-as3/spine-as3/src/spine/Slot.as index 5e6bce0fb..b0b4d1b9b 100644 --- a/spine-as3/spine-as3/src/spine/Slot.as +++ b/spine-as3/spine-as3/src/spine/Slot.as @@ -34,10 +34,8 @@ import spine.attachments.Attachment; public class Slot { internal var _data:SlotData; internal var _bone:Bone; - public var r:Number; - public var g:Number; - public var b:Number; - public var a:Number; + public var color:Color; + public var darkColor:Color; internal var _attachment:Attachment; private var _attachmentTime:Number; public var attachmentVertices:Vector. = new Vector.(); @@ -47,6 +45,8 @@ public class Slot { if (bone == null) throw new ArgumentError("bone cannot be null."); _data = data; _bone = bone; + this.color = new Color(1, 1, 1, 1); + this.darkColor = data.darkColor == null ? null : new Color(1, 1, 1, 1); setToSetupPose(); } @@ -86,10 +86,8 @@ public class Slot { } public function setToSetupPose () : void { - r = _data.r; - g = _data.g; - b = _data.b; - a = _data.a; + color.setFromColor(data.color); + if (darkColor != null) darkColor.setFromColor(this.data.darkColor); if (_data.attachmentName == null) attachment = null; else { diff --git a/spine-as3/spine-as3/src/spine/SlotData.as b/spine-as3/spine-as3/src/spine/SlotData.as index e0130fc87..f2c1722ef 100644 --- a/spine-as3/spine-as3/src/spine/SlotData.as +++ b/spine-as3/spine-as3/src/spine/SlotData.as @@ -34,10 +34,8 @@ public class SlotData { internal var _index:int; internal var _name:String; internal var _boneData:BoneData; - public var r:Number = 1; - public var g:Number = 1; - public var b:Number = 1; - public var a:Number = 1; + public var color: Color = new Color(1, 1, 1, 1); + public var darkColor: Color; public var attachmentName:String; public var blendMode:BlendMode; diff --git a/spine-as3/spine-as3/src/spine/TransformConstraint.as b/spine-as3/spine-as3/src/spine/TransformConstraint.as index cff6571ff..b3a9c6e81 100644 --- a/spine-as3/spine-as3/src/spine/TransformConstraint.as +++ b/spine-as3/spine-as3/src/spine/TransformConstraint.as @@ -57,8 +57,23 @@ public class TransformConstraint implements Constraint { public function apply () : void { update(); } - + public function update () : void { + if (data.local) { + if (data.relative) + applyRelativeLocal(); + else + applyAbsoluteLocal(); + + } else { + if (data.relative) + applyRelativeWorld(); + else + applyAbsoluteWorld(); + } + } + + internal function applyAbsoluteWorld () : void { var rotateMix:Number = this.rotateMix, translateMix:Number = this.translateMix, scaleMix:Number = this.scaleMix, shearMix:Number = this.shearMix; var target:Bone = this.target; var ta:Number = target.a, tb:Number = target.b, tc:Number = target.c, td:Number = target.d; @@ -78,10 +93,10 @@ public class TransformConstraint implements Constraint { else if (r < -Math.PI) r += Math.PI * 2; r *= rotateMix; var cos:Number = Math.cos(r), sin:Number = Math.sin(r); - bone._a = cos * a - sin * c; - bone._b = cos * b - sin * d; - bone._c = sin * a + cos * c; - bone._d = sin * b + cos * d; + bone.a = cos * a - sin * c; + bone.b = cos * b - sin * d; + bone.c = sin * a + cos * c; + bone.d = sin * b + cos * d; modified = true; } @@ -89,8 +104,8 @@ public class TransformConstraint implements Constraint { _temp[0] = data.offsetX; _temp[1] = data.offsetY; target.localToWorld(_temp); - bone._worldX += (_temp[0] - bone.worldX) * translateMix; - bone._worldY += (_temp[1] - bone.worldY) * translateMix; + bone.worldX += (_temp[0] - bone.worldX) * translateMix; + bone.worldY += (_temp[1] - bone.worldY) * translateMix; modified = true; } @@ -98,13 +113,13 @@ public class TransformConstraint implements Constraint { var s:Number = Math.sqrt(bone.a * bone.a + bone.c * bone.c); var ts:Number = Math.sqrt(ta * ta + tc * tc); if (s > 0.00001) s = (s + (ts - s + data.offsetScaleX) * scaleMix) / s; - bone._a *= s; - bone._c *= s; + bone.a *= s; + bone.c *= s; s = Math.sqrt(bone.b * bone.b + bone.d * bone.d); ts = Math.sqrt(tb * tb + td * td); if (s > 0.00001) s = (s + (ts - s + data.offsetScaleY) * scaleMix) / s; - bone._b *= s; - bone._d *= s; + bone.b *= s; + bone.d *= s; modified = true; } @@ -117,8 +132,8 @@ public class TransformConstraint implements Constraint { else if (r < -Math.PI) r += Math.PI * 2; r = by + (r + offsetShearY) * shearMix; s = Math.sqrt(b * b + d * d); - bone._b = Math.cos(r) * s; - bone._d = Math.sin(r) * s; + bone.b = Math.cos(r) * s; + bone.d = Math.sin(r) * s; modified = true; } @@ -126,6 +141,141 @@ public class TransformConstraint implements Constraint { } } + public function applyRelativeWorld () : void { + var rotateMix:Number = this.rotateMix, translateMix:Number = this.translateMix, scaleMix:Number = this.scaleMix, shearMix:Number = this.shearMix; + var target:Bone = this.target; + var ta:Number = target.a, tb:Number = target.b, tc:Number = target.c, td:Number = target.d; + var degRadReflect:Number = ta * td - tb * tc > 0 ? MathUtils.degRad : -MathUtils.degRad; + var offsetRotation:Number = this.data.offsetRotation * degRadReflect, offsetShearY:Number = this.data.offsetShearY * degRadReflect; + var bones:Vector. = this.bones; + for (var i:int = 0, n:int = bones.length; i < n; i++) { + var bone:Bone = bones[i]; + var modified:Boolean = false; + + if (rotateMix != 0) { + var a:Number = bone.a, b:Number = bone.b, c:Number = bone.c, d:Number = bone.d; + var r:Number = Math.atan2(tc, ta) + offsetRotation; + if (r > MathUtils.PI) + r -= MathUtils.PI2; + else if (r < -MathUtils.PI) r += MathUtils.PI2; + r *= rotateMix; + var cos:Number = Math.cos(r), sin:Number = Math.sin(r); + bone.a = cos * a - sin * c; + bone.b = cos * b - sin * d; + bone.c = sin * a + cos * c; + bone.d = sin * b + cos * d; + modified = true; + } + + if (translateMix != 0) { + var temp:Vector. = this._temp; + temp[0] = this._data.offsetX; + temp[1] = this._data.offsetY; + target.localToWorld(temp); + bone.worldX += temp[0] * translateMix; + bone.worldY += temp[1] * translateMix; + modified = true; + } + + if (scaleMix > 0) { + var s:Number = (Math.sqrt(ta * ta + tc * tc) - 1 + this.data.offsetScaleX) * scaleMix + 1; + bone.a *= s; + bone.c *= s; + s = (Math.sqrt(tb * tb + td * td) - 1 + this.data.offsetScaleY) * scaleMix + 1; + bone.b *= s; + bone.d *= s; + modified = true; + } + + if (shearMix > 0) { + r = Math.atan2(td, tb) - Math.atan2(tc, ta); + if (r > MathUtils.PI) + r -= MathUtils.PI2; + else if (r < -MathUtils.PI) r += MathUtils.PI2; + b = bone.b; d = bone.d; + r = Math.atan2(d, b) + (r - MathUtils.PI / 2 + offsetShearY) * shearMix; + s = Math.sqrt(b * b + d * d); + bone.b = Math.cos(r) * s; + bone.d = Math.sin(r) * s; + modified = true; + } + + if (modified) bone.appliedValid = false; + } + } + + public function applyAbsoluteLocal () : void { + var rotateMix:Number = this.rotateMix, translateMix:Number = this.translateMix, scaleMix:Number = this.scaleMix, shearMix:Number = this.shearMix; + var target:Bone = this.target; + if (!target.appliedValid) target.updateAppliedTransform(); + var bones:Vector. = this.bones; + for (var i:int = 0, n:int = bones.length; i < n; i++) { + var bone:Bone = bones[i]; + if (!bone.appliedValid) bone.updateAppliedTransform(); + + var rotation:Number = bone.arotation; + if (rotateMix != 0) { + var r:Number = target.arotation - rotation + this.data.offsetRotation; + r -= (16384 - ((16384.499999999996 - r / 360) | 0)) * 360; + rotation += r * rotateMix; + } + + var x:Number = bone.ax, y:Number = bone.ay; + if (translateMix != 0) { + x += (target.ax - x + this.data.offsetX) * translateMix; + y += (target.ay - y + this.data.offsetY) * translateMix; + } + + var scaleX:Number = bone.ascaleX, scaleY:Number = bone.ascaleY; + if (scaleMix > 0) { + if (scaleX > 0.00001) scaleX = (scaleX + (target.ascaleX - scaleX + this.data.offsetScaleX) * scaleMix) / scaleX; + if (scaleY > 0.00001) scaleY = (scaleY + (target.ascaleY - scaleY + this.data.offsetScaleY) * scaleMix) / scaleY; + } + + var shearY:Number = bone.ashearY; + if (shearMix > 0) { + r = target.ashearY - shearY + this.data.offsetShearY; + r -= (16384 - ((16384.499999999996 - r / 360) | 0)) * 360; + bone.shearY += r * shearMix; + } + + bone.updateWorldTransformWith(x, y, rotation, scaleX, scaleY, bone.ashearX, shearY); + } + } + + public function applyRelativeLocal () : void { + var rotateMix:Number = this.rotateMix, translateMix:Number = this.translateMix, scaleMix:Number = this.scaleMix, shearMix:Number = this.shearMix; + var target:Bone = this.target; + if (!target.appliedValid) target.updateAppliedTransform(); + var bones:Vector. = this.bones; + for (var i:int = 0, n:int = bones.length; i < n; i++) { + var bone:Bone = bones[i]; + if (!bone.appliedValid) bone.updateAppliedTransform(); + + var rotation:Number = bone.arotation; + if (rotateMix != 0) rotation += (target.arotation + this.data.offsetRotation) * rotateMix; + + var x:Number = bone.ax, y:Number = bone.ay; + if (translateMix != 0) { + x += (target.ax + this.data.offsetX) * translateMix; + y += (target.ay + this.data.offsetY) * translateMix; + } + + var scaleX:Number = bone.ascaleX, scaleY:Number = bone.ascaleY; + if (scaleMix > 0) { + if (scaleX > 0.00001) scaleX *= ((target.ascaleX - 1 + this.data.offsetScaleX) * scaleMix) + 1; + if (scaleY > 0.00001) scaleY *= ((target.ascaleY - 1 + this.data.offsetScaleY) * scaleMix) + 1; + } + + var shearY:Number = bone.ashearY; + if (shearMix > 0) shearY += (target.ashearY + this.data.offsetShearY) * shearMix; + + bone.updateWorldTransformWith(x, y, rotation, scaleX, scaleY, bone.ashearX, shearY); + } + } + + + public function getOrder () : Number { return _data.order; } diff --git a/spine-as3/spine-as3/src/spine/TransformConstraintData.as b/spine-as3/spine-as3/src/spine/TransformConstraintData.as index 52fdb9d2b..0ca1c4d3f 100644 --- a/spine-as3/spine-as3/src/spine/TransformConstraintData.as +++ b/spine-as3/spine-as3/src/spine/TransformConstraintData.as @@ -45,6 +45,8 @@ public class TransformConstraintData { public var offsetScaleX:Number; public var offsetScaleY:Number; public var offsetShearY:Number; + public var relative:Boolean = false; + public var local:Boolean = false; public function TransformConstraintData (name:String) { if (name == null) throw new ArgumentError("name cannot be null."); diff --git a/spine-as3/spine-as3/src/spine/animation/ColorTimeline.as b/spine-as3/spine-as3/src/spine/animation/ColorTimeline.as index b3c09efcb..be13c6132 100644 --- a/spine-as3/spine-as3/src/spine/animation/ColorTimeline.as +++ b/spine-as3/spine-as3/src/spine/animation/ColorTimeline.as @@ -66,10 +66,7 @@ public class ColorTimeline extends CurveTimeline { if (time < frames[0]) { if (setupPose) { - slot.r = slot.data.r; - slot.g = slot.data.g; - slot.b = slot.data.b; - slot.a = slot.data.a; + slot.color.setFromColor(slot.data.color); } return; } @@ -98,21 +95,15 @@ public class ColorTimeline extends CurveTimeline { a += (frames[frame + A] - a) * percent; } if (alpha == 1) { - slot.r = r; - slot.g = g; - slot.b = b; - slot.a = a; + slot.color.setFrom(r, g, b, a); } else { if (setupPose) { - slot.r = slot.data.r; - slot.g = slot.data.g; - slot.b = slot.data.b; - slot.a = slot.data.a; + slot.color.setFromColor(slot.data.color); } - slot.r += (r - slot.r) * alpha; - slot.g += (g - slot.g) * alpha; - slot.b += (b - slot.b) * alpha; - slot.a += (a - slot.a) * alpha; + slot.color.r += (r - slot.color.r) * alpha; + slot.color.g += (g - slot.color.g) * alpha; + slot.color.b += (b - slot.color.b) * alpha; + slot.color.a += (a - slot.color.a) * alpha; } } } diff --git a/spine-as3/spine-as3/src/spine/animation/TimelineType.as b/spine-as3/spine-as3/src/spine/animation/TimelineType.as index e20010027..a7db87c28 100644 --- a/spine-as3/spine-as3/src/spine/animation/TimelineType.as +++ b/spine-as3/spine-as3/src/spine/animation/TimelineType.as @@ -51,6 +51,7 @@ public class TimelineType { public static const pathConstraintPosition:TimelineType = new TimelineType(11); public static const pathConstraintSpacing:TimelineType = new TimelineType(12); public static const pathConstraintMix:TimelineType = new TimelineType(13); + public static const twoColor:TimelineType = new TimelineType(14); } } diff --git a/spine-as3/spine-as3/src/spine/animation/TwoColorTimeline.as b/spine-as3/spine-as3/src/spine/animation/TwoColorTimeline.as new file mode 100644 index 000000000..96dd8bde8 --- /dev/null +++ b/spine-as3/spine-as3/src/spine/animation/TwoColorTimeline.as @@ -0,0 +1,128 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, 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 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 develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes 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, BUSINESS INTERRUPTION, OR LOSS OF + * USE, DATA, OR PROFITS) 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.animation { + import spine.Color; +import spine.Event; +import spine.Skeleton; +import spine.Slot; + +public class TwoColorTimeline extends CurveTimeline { + static public const ENTRIES:int = 8; + static internal const PREV_TIME:int = -8, PREV_R:int = -7, PREV_G:int = -6, PREV_B:int = -5, PREV_A:int = -4; + static internal const PREV_R2:int = -3, PREV_G2:int = -2, PREV_B2:int = -1; + static internal const R:int = 1, G:int = 2, B:int = 3, A:int = 4, R2:int = 5, G2:int = 6, B2:int = 7; + + public var slotIndex:int; + public var frames:Vector.; // time, r, g, b, a, ... + + public function TwoColorTimeline (frameCount:int) { + super(frameCount); + frames = new Vector.(frameCount * ENTRIES, true); + } + + override public function getPropertyId () : int { + return (TimelineType.twoColor.ordinal << 24) + slotIndex; + } + + /** Sets the time and value of the specified keyframe. */ + public function setFrame (frameIndex:int, time:Number, r:Number, g:Number, b:Number, a:Number, r2:Number, g2:Number, b2:Number) : void { + frameIndex *= TwoColorTimeline.ENTRIES; + this.frames[frameIndex] = time; + this.frames[frameIndex + TwoColorTimeline.R] = r; + this.frames[frameIndex + TwoColorTimeline.G] = g; + this.frames[frameIndex + TwoColorTimeline.B] = b; + this.frames[frameIndex + TwoColorTimeline.A] = a; + this.frames[frameIndex + TwoColorTimeline.R2] = r2; + this.frames[frameIndex + TwoColorTimeline.G2] = g2; + this.frames[frameIndex + TwoColorTimeline.B2] = b2; + } + + override public function apply (skeleton:Skeleton, lastTime:Number, time:Number, firedEvents:Vector., alpha:Number, setupPose:Boolean, mixingOut:Boolean) : void { + var frames:Vector. = this.frames; + var slot:Slot = skeleton.slots[slotIndex]; + + if (time < frames[0]) { + if (setupPose) { + slot.color.setFromColor(slot.data.color); + slot.darkColor.setFromColor(slot.data.darkColor); + } + return; + } + + var r:Number, g:Number, b:Number, a:Number, r2:Number, g2:Number, b2:Number; + if (time >= frames[frames.length - ENTRIES]) { // Time is after last frame. + var i:int = frames.length; + r = frames[i + PREV_R]; + g = frames[i + PREV_G]; + b = frames[i + PREV_B]; + a = frames[i + PREV_A]; + r2 = frames[i + PREV_R2]; + g2 = frames[i + PREV_G2]; + b2 = frames[i + PREV_B2]; + } else { + // Interpolate between the previous frame and the current frame. + var frame:int = Animation.binarySearch(frames, time, ENTRIES); + r = frames[frame + PREV_R]; + g = frames[frame + PREV_G]; + b = frames[frame + PREV_B]; + a = frames[frame + PREV_A]; + r2 = frames[frame + PREV_R2]; + g2 = frames[frame + PREV_G2]; + b2 = frames[frame + PREV_B2]; + var frameTime:Number = frames[frame]; + var percent:Number = getCurvePercent(frame / ENTRIES - 1, + 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime)); + + r += (frames[frame + R] - r) * percent; + g += (frames[frame + G] - g) * percent; + b += (frames[frame + B] - b) * percent; + a += (frames[frame + A] - a) * percent; + r2 += (frames[frame + R2] - a) * percent; + g2 += (frames[frame + G2] - a) * percent; + b2 += (frames[frame + B2] - a) * percent; + } + if (alpha == 1) { + slot.color.setFrom(r, g, b, a); + slot.darkColor.setFrom(r2, g2, b2, 1); + } else { + var light:Color = slot.color; + var dark:Color = slot.darkColor; + if (setupPose) { + light.setFromColor(slot.data.color); + dark.setFromColor(slot.data.darkColor); + } + light.add((r - light.r) * alpha, (g - light.g) * alpha, (b - light.b) * alpha, (a - light.a) * alpha); + dark.add((r2 - dark.r) * alpha, (g2 - dark.g) * alpha, (b2 - dark.b) * alpha, 0); + } + } +} + +} diff --git a/spine-as3/spine-as3/src/spine/attachments/AtlasAttachmentLoader.as b/spine-as3/spine-as3/src/spine/attachments/AtlasAttachmentLoader.as index 4d5766e67..e20c61499 100644 --- a/spine-as3/spine-as3/src/spine/attachments/AtlasAttachmentLoader.as +++ b/spine-as3/spine-as3/src/spine/attachments/AtlasAttachmentLoader.as @@ -89,6 +89,10 @@ public class AtlasAttachmentLoader implements AttachmentLoader { public function newPathAttachment(skin:Skin, name:String) : PathAttachment { return new PathAttachment(name); } + + public function newPointAttachment(skin:Skin, name:String) : PointAttachment { + return new PointAttachment(name); + } static public function nextPOT (value:int) : int { value--; diff --git a/spine-as3/spine-as3/src/spine/attachments/AttachmentLoader.as b/spine-as3/spine-as3/src/spine/attachments/AttachmentLoader.as index e043afd1a..c5708a99e 100644 --- a/spine-as3/spine-as3/src/spine/attachments/AttachmentLoader.as +++ b/spine-as3/spine-as3/src/spine/attachments/AttachmentLoader.as @@ -43,6 +43,9 @@ public interface AttachmentLoader { /** @return May be null to not load an attachment */ function newPathAttachment(skin:Skin, name:String): PathAttachment; + + /** @return May be null to not load an attachment */ + function newPointAttachment(skin:Skin, name:String): PointAttachment; } } diff --git a/spine-as3/spine-as3/src/spine/attachments/AttachmentType.as b/spine-as3/spine-as3/src/spine/attachments/AttachmentType.as index 42e4641a6..8d24dcf80 100644 --- a/spine-as3/spine-as3/src/spine/attachments/AttachmentType.as +++ b/spine-as3/spine-as3/src/spine/attachments/AttachmentType.as @@ -37,6 +37,7 @@ public class AttachmentType { public static const mesh:AttachmentType = new AttachmentType(3, "mesh"); public static const linkedmesh:AttachmentType = new AttachmentType(3, "linkedmesh"); public static const path:AttachmentType = new AttachmentType(4, "path"); + public static const point:AttachmentType = new AttachmentType(5, "point"); public var ordinal:int; public var name:String; diff --git a/spine-as3/spine-as3/src/spine/attachments/MeshAttachment.as b/spine-as3/spine-as3/src/spine/attachments/MeshAttachment.as index 32f86ec6a..e12375797 100644 --- a/spine-as3/spine-as3/src/spine/attachments/MeshAttachment.as +++ b/spine-as3/spine-as3/src/spine/attachments/MeshAttachment.as @@ -29,16 +29,13 @@ *****************************************************************************/ package spine.attachments { +import spine.Color; -public dynamic class MeshAttachment extends VertexAttachment { - public var worldVertices:Vector.; +public dynamic class MeshAttachment extends VertexAttachment { public var uvs:Vector.; public var regionUVs:Vector.; public var triangles:Vector.; - public var r:Number = 1; - public var g:Number = 1; - public var b:Number = 1; - public var a:Number = 1; + public var color:Color = new Color(1, 1, 1, 1); public var hullLength:int; private var _parentMesh:MeshAttachment; public var inheritDeform:Boolean; diff --git a/spine-as3/spine-as3/src/spine/attachments/PointAttachment.as b/spine-as3/spine-as3/src/spine/attachments/PointAttachment.as new file mode 100644 index 000000000..823ff0a2d --- /dev/null +++ b/spine-as3/spine-as3/src/spine/attachments/PointAttachment.as @@ -0,0 +1,57 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, 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 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 develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes 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, BUSINESS INTERRUPTION, OR LOSS OF + * USE, DATA, OR PROFITS) 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 { +import spine.Color; +import spine.MathUtils; +import spine.Bone; + +public dynamic class PointAttachment extends VertexAttachment { + public var x: Number, y: Number, rotation: Number; + public var color:Color = new Color(0.38, 0.94, 0, 1); + + public function PointAttachment (name:String) { + super(name); + } + + public function computeWorldPosition (bone: Bone, point: Vector.): Vector. { + point[0] = this.x * bone.a + this.y * bone.b + bone.worldX; + point[1] = this.x * bone.c + this.y * bone.d + bone.worldY; + return point; + } + + public function computeWorldRotation (bone: Bone): Number { + var cos:Number = MathUtils.cosDeg(this.rotation), sin: Number = MathUtils.sinDeg(this.rotation); + var x:Number = cos * bone.a + sin * bone.b; + var y:Number = cos * bone.c + sin * bone.d; + return Math.atan2(y, x) * MathUtils.radDeg; + } +} +} diff --git a/spine-as3/spine-as3/src/spine/attachments/RegionAttachment.as b/spine-as3/spine-as3/src/spine/attachments/RegionAttachment.as index d2abe6331..c48bb1a7c 100644 --- a/spine-as3/spine-as3/src/spine/attachments/RegionAttachment.as +++ b/spine-as3/spine-as3/src/spine/attachments/RegionAttachment.as @@ -29,6 +29,7 @@ *****************************************************************************/ package spine.attachments { +import spine.Color; import spine.Bone; public dynamic class RegionAttachment extends Attachment { @@ -48,10 +49,7 @@ public dynamic class RegionAttachment extends Attachment { public var rotation:Number; public var width:Number; public var height:Number; - public var r:Number = 1; - public var g:Number = 1; - public var b:Number = 1; - public var a:Number = 1; + public var color:Color = new Color(1, 1, 1, 1); public var path:String; public var rendererObject:Object; @@ -71,28 +69,6 @@ public dynamic class RegionAttachment extends Attachment { uvs.length = 8; } - public function setUVs (u:Number, v:Number, u2:Number, v2:Number, rotate:Boolean) : void { - if (rotate) { - uvs[X2] = u; - uvs[Y2] = v2; - uvs[X3] = u; - uvs[Y3] = v; - uvs[X4] = u2; - uvs[Y4] = v; - uvs[X1] = u2; - uvs[Y1] = v2; - } else { - uvs[X1] = u; - uvs[Y1] = v2; - uvs[X2] = u; - uvs[Y2] = v; - uvs[X3] = u2; - uvs[Y3] = v; - uvs[X4] = u2; - uvs[Y4] = v2; - } - } - public function updateOffset () : void { var regionScaleX:Number = width / regionOriginalWidth * scaleX; var regionScaleY:Number = height / regionOriginalHeight * scaleY; @@ -120,30 +96,58 @@ public dynamic class RegionAttachment extends Attachment { offset[X4] = localX2Cos - localYSin; offset[Y4] = localYCos + localX2Sin; } + + public function setUVs (u:Number, v:Number, u2:Number, v2:Number, rotate:Boolean) : void { + var uvs:Vector. = this.uvs; + if (rotate) { + uvs[X2] = u; + uvs[Y2] = v2; + uvs[X3] = u; + uvs[Y3] = v; + uvs[X4] = u2; + uvs[Y4] = v; + uvs[X1] = u2; + uvs[Y1] = v2; + } else { + uvs[X1] = u; + uvs[Y1] = v2; + uvs[X2] = u; + uvs[Y2] = v; + uvs[X3] = u2; + uvs[Y3] = v; + uvs[X4] = u2; + uvs[Y4] = v2; + } + } - public function computeWorldVertices (x:Number, y:Number, bone:Bone, worldVertices:Vector.) : void { - x += bone.worldX; - y += bone.worldY; - var m00:Number = bone.a; - var m01:Number = bone.b; - var m10:Number = bone.c; - var m11:Number = bone.d; - var x1:Number = offset[X1]; - var y1:Number = offset[Y1]; - var x2:Number = offset[X2]; - var y2:Number = offset[Y2]; - var x3:Number = offset[X3]; - var y3:Number = offset[Y3]; - var x4:Number = offset[X4]; - var y4:Number = offset[Y4]; - worldVertices[X1] = x1 * m00 + y1 * m01 + x; - worldVertices[Y1] = x1 * m10 + y1 * m11 + y; - worldVertices[X2] = x2 * m00 + y2 * m01 + x; - worldVertices[Y2] = x2 * m10 + y2 * m11 + y; - worldVertices[X3] = x3 * m00 + y3 * m01 + x; - worldVertices[Y3] = x3 * m10 + y3 * m11 + y; - worldVertices[X4] = x4 * m00 + y4 * m01 + x; - worldVertices[Y4] = x4 * m10 + y4 * m11 + y; + public function computeWorldVertices (bone:Bone, worldVertices:Vector., offset:int, stride:int) : void { + var vertexOffset:Vector. = this.offset; + var x:Number = bone.worldX, y:Number = bone.worldY; + var a:Number = bone.a, b:Number = bone.b, c:Number = bone.c, d:Number = bone.d; + var offsetX:Number = 0, offsetY:Number = 0; + + offsetX = vertexOffset[X1]; + offsetY = vertexOffset[Y1]; + worldVertices[offset] = offsetX * a + offsetY * b + x; // br + worldVertices[offset + 1] = offsetX * c + offsetY * d + y; + offset += stride; + + offsetX = vertexOffset[X2]; + offsetY = vertexOffset[Y2]; + worldVertices[offset] = offsetX * a + offsetY * b + x; // bl + worldVertices[offset + 1] = offsetX * c + offsetY * d + y; + offset += stride; + + offsetX = vertexOffset[X3]; + offsetY = vertexOffset[Y3]; + worldVertices[offset] = offsetX * a + offsetY * b + x; // ul + worldVertices[offset + 1] = offsetX * c + offsetY * d + y; + offset += stride; + + offsetX = vertexOffset[X4]; + offsetY = vertexOffset[Y4]; + worldVertices[offset] = offsetX * a + offsetY * b + x; // ur + worldVertices[offset + 1] = offsetX * c + offsetY * d + y; } } diff --git a/spine-as3/spine-as3/src/spine/attachments/VertexAttachment.as b/spine-as3/spine-as3/src/spine/attachments/VertexAttachment.as index 2193558d8..ef959ecc7 100644 --- a/spine-as3/spine-as3/src/spine/attachments/VertexAttachment.as +++ b/spine-as3/spine-as3/src/spine/attachments/VertexAttachment.as @@ -42,17 +42,13 @@ public dynamic class VertexAttachment extends Attachment { super(name); } - public function computeWorldVertices (slot:Slot, worldVertices:Vector.): void { - computeWorldVertices2(slot, 0, worldVerticesLength, worldVertices, 0); - } - /** Transforms local vertices to world coordinates. * @param start The index of the first local vertex value to transform. Each vertex has 2 values, x and y. * @param count The number of world vertex values to output. Must be <= {@link #getWorldVerticesLength()} - start. * @param worldVertices The output world vertices. Must have a length >= offset + count. * @param offset The worldVertices index to begin writing values. */ - public function computeWorldVertices2 (slot:Slot, start:int, count:int, worldVertices:Vector., offset:int): void { - count += offset; + public function computeWorldVertices (slot:Slot, start:int, count:int, worldVertices:Vector., offset:int, stride:int): void { + count = offset + (count >> 1) * stride; var skeleton:Skeleton = slot.skeleton; var deformArray:Vector. = slot.attachmentVertices; var vertices:Vector. = this.vertices; @@ -70,7 +66,7 @@ public dynamic class VertexAttachment extends Attachment { var x:Number = bone.worldX; var y:Number = bone.worldY; var a:Number = bone.a, bb:Number = bone.b, c:Number = bone.c, d:Number = bone.d; - for (v = start, w = offset; w < count; v += 2, w += 2) { + for (v = start, w = offset; w < count; v += 2, w += stride) { vx = vertices[v], vy = vertices[v + 1]; worldVertices[w] = vx * a + vy * bb + x; worldVertices[w + 1] = vx * c + vy * d + y; @@ -85,7 +81,7 @@ public dynamic class VertexAttachment extends Attachment { } var skeletonBones:Vector. = skeleton.bones; if (deformArray.length == 0) { - for (w = offset, b = skip * 3; w < count; w += 2) { + for (w = offset, b = skip * 3; w < count; w += stride) { wx = 0, wy = 0; n = bones[v++]; n += v; @@ -100,7 +96,7 @@ public dynamic class VertexAttachment extends Attachment { } } else { deform = deformArray; - for (w = offset, b = skip * 3, f = skip << 1; w < count; w += 2) { + for (w = offset, b = skip * 3, f = skip << 1; w < count; w += stride) { wx = 0; wy = 0; n = bones[v++]; n += v; diff --git a/spine-as3/spine-as3/src/spine/flash/SkeletonSprite.as b/spine-as3/spine-as3/src/spine/flash/SkeletonSprite.as index e7c2c5be5..9c7665167 100644 --- a/spine-as3/spine-as3/src/spine/flash/SkeletonSprite.as +++ b/spine-as3/spine-as3/src/spine/flash/SkeletonSprite.as @@ -125,10 +125,10 @@ public class SkeletonSprite extends Sprite { wrapper.blendMode = blendModes[slot.data.blendMode.ordinal]; var colorTransform:ColorTransform = wrapper.transform.colorTransform; - colorTransform.redMultiplier = skeleton.r * slot.r * regionAttachment.r; - colorTransform.greenMultiplier = skeleton.g * slot.g * regionAttachment.g; - colorTransform.blueMultiplier = skeleton.b * slot.b * regionAttachment.b; - colorTransform.alphaMultiplier = skeleton.a * slot.a * regionAttachment.a; + colorTransform.redMultiplier = skeleton.color.r * slot.color.r * regionAttachment.color.r; + colorTransform.greenMultiplier = skeleton.color.g * slot.color.g * regionAttachment.color.g; + colorTransform.blueMultiplier = skeleton.color.b * slot.color.b * regionAttachment.color.b; + colorTransform.alphaMultiplier = skeleton.color.a * slot.color.a * regionAttachment.color.a; wrapper.transform.colorTransform = colorTransform; var bone:Bone = slot.bone; diff --git a/spine-starling/spine-starling-example/lib/spine-as3.swc b/spine-starling/spine-starling-example/lib/spine-as3.swc index ba34e4854..537b129f5 100644 Binary files a/spine-starling/spine-starling-example/lib/spine-as3.swc and b/spine-starling/spine-starling-example/lib/spine-as3.swc differ diff --git a/spine-starling/spine-starling-example/lib/spine-starling.swc b/spine-starling/spine-starling-example/lib/spine-starling.swc index 01dd51a7c..840e10f1b 100644 Binary files a/spine-starling/spine-starling-example/lib/spine-starling.swc and b/spine-starling/spine-starling-example/lib/spine-starling.swc differ diff --git a/spine-starling/spine-starling-example/src/spine/examples/Main.as b/spine-starling/spine-starling-example/src/spine/examples/Main.as index 39481a60e..838669a84 100644 --- a/spine-starling/spine-starling-example/src/spine/examples/Main.as +++ b/spine-starling/spine-starling-example/src/spine/examples/Main.as @@ -40,12 +40,12 @@ public class Main extends Sprite { public function Main () { var example:Class; - example = SpineboyExample; + // example = SpineboyExample; // example = GoblinsExample; - example = RaptorExample; + // example = RaptorExample; // example = TankExample; // example = VineExample; - // example = StretchymanExample; + example = StretchymanExample; _starling = new Starling(example, stage); _starling.enableErrorChecking = true; diff --git a/spine-starling/spine-starling/lib/spine-as3.swc b/spine-starling/spine-starling/lib/spine-as3.swc index ba34e4854..537b129f5 100644 Binary files a/spine-starling/spine-starling/lib/spine-as3.swc and b/spine-starling/spine-starling/lib/spine-as3.swc differ diff --git a/spine-starling/spine-starling/src/spine/starling/SkeletonSprite.as b/spine-starling/spine-starling/src/spine/starling/SkeletonSprite.as index 0530753cf..3624b3f9d 100644 --- a/spine-starling/spine-starling/src/spine/starling/SkeletonSprite.as +++ b/spine-starling/spine-starling/src/spine/starling/SkeletonSprite.as @@ -69,13 +69,11 @@ public class SkeletonSprite extends DisplayObject { } override public function render (painter:Painter) : void { - alpha *= this.alpha * skeleton.a; + alpha *= this.alpha * skeleton.color.a; var originalBlendMode:String = painter.state.blendMode; - var r:Number = skeleton.r * 255; - var g:Number = skeleton.g * 255; - var b:Number = skeleton.b * 255; - var x:Number = skeleton.x; - var y:Number = skeleton.y; + var r:Number = skeleton.color.r * 255; + var g:Number = skeleton.color.g * 255; + var b:Number = skeleton.color.b * 255; var drawOrder:Vector. = skeleton.drawOrder; var worldVertices:Vector. = _tempVertices; var ii:int, iii:int; @@ -89,13 +87,12 @@ public class SkeletonSprite extends DisplayObject { var slot:Slot = drawOrder[i]; if (slot.attachment is RegionAttachment) { var region:RegionAttachment = slot.attachment as RegionAttachment; - region.computeWorldVertices(x, y, slot.bone, worldVertices); - // FIXME pre-multiplied alpha? - a = slot.a * region.a; + region.computeWorldVertices(slot.bone, worldVertices, 0, 2); + a = slot.color.a * region.color.a; rgb = Color.rgb( - r * slot.r * region.r, - g * slot.g * region.g, - b * slot.b * region.b); + r * slot.color.r * region.color.r, + g * slot.color.g * region.color.g, + b * slot.color.b * region.color.b); var image:Image = region.rendererObject as Image; if (image == null) { @@ -132,7 +129,7 @@ public class SkeletonSprite extends DisplayObject { verticesLength = meshAttachment.worldVerticesLength; verticesCount = verticesLength >> 1; if (worldVertices.length < verticesLength) worldVertices.length = verticesLength; - meshAttachment.computeWorldVertices(slot, worldVertices); + meshAttachment.computeWorldVertices(slot, 0, meshAttachment.worldVerticesLength, worldVertices, 0, 2); mesh = meshAttachment.rendererObject as SkeletonMesh; if (mesh == null) { if (meshAttachment.rendererObject is Image) @@ -153,11 +150,11 @@ public class SkeletonSprite extends DisplayObject { } // FIXME pre-multiplied alpha? - a = slot.a * meshAttachment.a; + a = slot.color.a * meshAttachment.color.a; rgb = Color.rgb( - r * slot.r * meshAttachment.r, - g * slot.g * meshAttachment.g, - b * slot.b * meshAttachment.b); + r * slot.color.r * meshAttachment.color.r, + g * slot.color.g * meshAttachment.color.g, + b * slot.color.b * meshAttachment.color.b); vertexData = mesh.getVertexData(); uvs = meshAttachment.uvs; @@ -191,12 +188,12 @@ public class SkeletonSprite extends DisplayObject { if (attachment is RegionAttachment) { var region:RegionAttachment = RegionAttachment(slot.attachment); verticesLength = 8; - region.computeWorldVertices(0, 0, slot.bone, worldVertices); + region.computeWorldVertices(slot.bone, worldVertices, 0, 2); } else if (attachment is MeshAttachment) { var mesh:MeshAttachment = MeshAttachment(attachment); verticesLength = mesh.worldVerticesLength; if (worldVertices.length < verticesLength) worldVertices.length = verticesLength; - mesh.computeWorldVertices(slot, worldVertices); + mesh.computeWorldVertices(slot, 0, verticesLength, worldVertices, 0, 2); } else continue; for (var ii:int = 0; ii < verticesLength; ii += 2) { diff --git a/spine-starling/spine-starling/src/spine/starling/StarlingAtlasAttachmentLoader.as b/spine-starling/spine-starling/src/spine/starling/StarlingAtlasAttachmentLoader.as index 33b154085..0a32c4522 100644 --- a/spine-starling/spine-starling/src/spine/starling/StarlingAtlasAttachmentLoader.as +++ b/spine-starling/spine-starling/src/spine/starling/StarlingAtlasAttachmentLoader.as @@ -29,6 +29,7 @@ *****************************************************************************/ package spine.starling { + import spine.attachments.PointAttachment; import spine.attachments.PathAttachment; import starling.display.Image; import spine.Bone; @@ -123,6 +124,10 @@ public class StarlingAtlasAttachmentLoader implements AttachmentLoader { public function newPathAttachment (skin:Skin, name:String) : PathAttachment { return new PathAttachment(name); } + + public function newPointAttachment (skin:Skin, name:String) : PointAttachment { + return new PointAttachment(name); + } } } diff --git a/spine-ts/core/src/Skeleton.ts b/spine-ts/core/src/Skeleton.ts index cffc9f7b9..3e2965d90 100644 --- a/spine-ts/core/src/Skeleton.ts +++ b/spine-ts/core/src/Skeleton.ts @@ -489,8 +489,8 @@ module spine { mesh.computeWorldVertices(slot, 0, verticesLength, vertices, 0, 2); } if (vertices != null) { - for (let i = 0, nn = vertices.length; i < nn; i += 8) { - let x = vertices[i], y = vertices[i + 1]; + for (let ii = 0, nn = vertices.length; ii < nn; ii += 8) { + let x = vertices[ii], y = vertices[ii + 1]; minX = Math.min(minX, x); minY = Math.min(minY, y); maxX = Math.max(maxX, x);