1/****************************************************************************** 2 * Spine Runtimes Software License 3 * Version 2.3 4 * 5 * Copyright (c) 2013-2015, Esoteric Software 6 * All rights reserved. 7 * 8 * You are granted a perpetual, non-exclusive, non-sublicensable and 9 * non-transferable license to use, install, execute and perform the Spine 10 * Runtimes Software (the "Software") and derivative works solely for personal 11 * or internal use. Without the written permission of Esoteric Software (see 12 * Section 2 of the Spine Software License Agreement), you may not (a) modify, 13 * translate, adapt or otherwise create derivative works, improvements of the 14 * Software or develop new applications using the Software or (b) remove, 15 * delete, alter or obscure any trademarks or any copyright, trademark, patent 16 * or other intellectual property or proprietary rights notices on or in the 17 * Software, including any copy thereof. Redistributions in binary or source 18 * form must include this license and terms. 19 * 20 * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR 21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 22 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 23 * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 29 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 *****************************************************************************/ 31 32var spine = { 33 radDeg: 180 / Math.PI, 34 degRad: Math.PI / 180, 35 temp: [], 36 Float32Array: (typeof(Float32Array) === 'undefined') ? Array : Float32Array, 37 Uint16Array: (typeof(Uint16Array) === 'undefined') ? Array : Uint16Array 38}; 39 40spine.BoneData = function (name, parent) { 41 this.name = name; 42 this.parent = parent; 43}; 44spine.BoneData.prototype = { 45 length: 0, 46 x: 0, y: 0, 47 rotation: 0, 48 scaleX: 1, scaleY: 1, 49 inheritScale: true, 50 inheritRotation: true, 51 flipX: false, flipY: false 52}; 53 54spine.BlendMode = { 55 normal: 0, 56 additive: 1, 57 multiply: 2, 58 screen: 3 59}; 60 61spine.SlotData = function (name, boneData) { 62 this.name = name; 63 this.boneData = boneData; 64}; 65spine.SlotData.prototype = { 66 r: 1, g: 1, b: 1, a: 1, 67 attachmentName: null, 68 blendMode: spine.BlendMode.normal 69}; 70 71spine.IkConstraintData = function (name) { 72 this.name = name; 73 this.bones = []; 74}; 75spine.IkConstraintData.prototype = { 76 target: null, 77 bendDirection: 1, 78 mix: 1 79}; 80 81spine.Bone = function (boneData, skeleton, parent) { 82 this.data = boneData; 83 this.skeleton = skeleton; 84 this.parent = parent; 85 this.setToSetupPose(); 86}; 87spine.Bone.yDown = false; 88spine.Bone.prototype = { 89 x: 0, y: 0, 90 rotation: 0, rotationIK: 0, 91 scaleX: 1, scaleY: 1, 92 flipX: false, flipY: false, 93 m00: 0, m01: 0, worldX: 0, // a b x 94 m10: 0, m11: 0, worldY: 0, // c d y 95 worldRotation: 0, 96 worldScaleX: 1, worldScaleY: 1, 97 worldFlipX: false, worldFlipY: false, 98 updateWorldTransform: function () { 99 var parent = this.parent; 100 if (parent) { 101 this.worldX = this.x * parent.m00 + this.y * parent.m01 + parent.worldX; 102 this.worldY = this.x * parent.m10 + this.y * parent.m11 + parent.worldY; 103 if (this.data.inheritScale) { 104 this.worldScaleX = parent.worldScaleX * this.scaleX; 105 this.worldScaleY = parent.worldScaleY * this.scaleY; 106 } else { 107 this.worldScaleX = this.scaleX; 108 this.worldScaleY = this.scaleY; 109 } 110 this.worldRotation = this.data.inheritRotation ? (parent.worldRotation + this.rotationIK) : this.rotationIK; 111 this.worldFlipX = parent.worldFlipX != this.flipX; 112 this.worldFlipY = parent.worldFlipY != this.flipY; 113 } else { 114 var skeletonFlipX = this.skeleton.flipX, skeletonFlipY = this.skeleton.flipY; 115 this.worldX = skeletonFlipX ? -this.x : this.x; 116 this.worldY = (skeletonFlipY != spine.Bone.yDown) ? -this.y : this.y; 117 this.worldScaleX = this.scaleX; 118 this.worldScaleY = this.scaleY; 119 this.worldRotation = this.rotationIK; 120 this.worldFlipX = skeletonFlipX != this.flipX; 121 this.worldFlipY = skeletonFlipY != this.flipY; 122 } 123 var radians = this.worldRotation * spine.degRad; 124 var cos = Math.cos(radians); 125 var sin = Math.sin(radians); 126 if (this.worldFlipX) { 127 this.m00 = -cos * this.worldScaleX; 128 this.m01 = sin * this.worldScaleY; 129 } else { 130 this.m00 = cos * this.worldScaleX; 131 this.m01 = -sin * this.worldScaleY; 132 } 133 if (this.worldFlipY != spine.Bone.yDown) { 134 this.m10 = -sin * this.worldScaleX; 135 this.m11 = -cos * this.worldScaleY; 136 } else { 137 this.m10 = sin * this.worldScaleX; 138 this.m11 = cos * this.worldScaleY; 139 } 140 }, 141 setToSetupPose: function () { 142 var data = this.data; 143 this.x = data.x; 144 this.y = data.y; 145 this.rotation = data.rotation; 146 this.rotationIK = this.rotation; 147 this.scaleX = data.scaleX; 148 this.scaleY = data.scaleY; 149 this.flipX = data.flipX; 150 this.flipY = data.flipY; 151 }, 152 worldToLocal: function (world) { 153 var dx = world[0] - this.worldX, dy = world[1] - this.worldY; 154 var m00 = this.m00, m10 = this.m10, m01 = this.m01, m11 = this.m11; 155 if (this.worldFlipX != (this.worldFlipY != spine.Bone.yDown)) { 156 m00 = -m00; 157 m11 = -m11; 158 } 159 var invDet = 1 / (m00 * m11 - m01 * m10); 160 world[0] = dx * m00 * invDet - dy * m01 * invDet; 161 world[1] = dy * m11 * invDet - dx * m10 * invDet; 162 }, 163 localToWorld: function (local) { 164 var localX = local[0], localY = local[1]; 165 local[0] = localX * this.m00 + localY * this.m01 + this.worldX; 166 local[1] = localX * this.m10 + localY * this.m11 + this.worldY; 167 } 168}; 169 170spine.Slot = function (slotData, bone) { 171 this.data = slotData; 172 this.bone = bone; 173 this.setToSetupPose(); 174}; 175spine.Slot.prototype = { 176 r: 1, g: 1, b: 1, a: 1, 177 _attachmentTime: 0, 178 attachment: null, 179 attachmentVertices: [], 180 setAttachment: function (attachment) { 181 this.attachment = attachment; 182 this._attachmentTime = this.bone.skeleton.time; 183 this.attachmentVertices.length = 0; 184 }, 185 setAttachmentTime: function (time) { 186 this._attachmentTime = this.bone.skeleton.time - time; 187 }, 188 getAttachmentTime: function () { 189 return this.bone.skeleton.time - this._attachmentTime; 190 }, 191 setToSetupPose: function () { 192 var data = this.data; 193 this.r = data.r; 194 this.g = data.g; 195 this.b = data.b; 196 this.a = data.a; 197 198 var slotDatas = this.bone.skeleton.data.slots; 199 for (var i = 0, n = slotDatas.length; i < n; i++) { 200 if (slotDatas[i] == data) { 201 this.setAttachment(!data.attachmentName ? null : this.bone.skeleton.getAttachmentBySlotIndex(i, data.attachmentName)); 202 break; 203 } 204 } 205 } 206}; 207 208spine.IkConstraint = function (data, skeleton) { 209 this.data = data; 210 this.mix = data.mix; 211 this.bendDirection = data.bendDirection; 212 213 this.bones = []; 214 for (var i = 0, n = data.bones.length; i < n; i++) 215 this.bones.push(skeleton.findBone(data.bones[i].name)); 216 this.target = skeleton.findBone(data.target.name); 217}; 218spine.IkConstraint.prototype = { 219 apply: function () { 220 var target = this.target; 221 var bones = this.bones; 222 switch (bones.length) { 223 case 1: 224 spine.IkConstraint.apply1(bones[0], target.worldX, target.worldY, this.mix); 225 break; 226 case 2: 227 spine.IkConstraint.apply2(bones[0], bones[1], target.worldX, target.worldY, this.bendDirection, this.mix); 228 break; 229 } 230 } 231}; 232/** Adjusts the bone rotation so the tip is as close to the target position as possible. The target is specified in the world 233 * coordinate system. */ 234spine.IkConstraint.apply1 = function (bone, targetX, targetY, alpha) { 235 var parentRotation = (!bone.data.inheritRotation || !bone.parent) ? 0 : bone.parent.worldRotation; 236 var rotation = bone.rotation; 237 var rotationIK = Math.atan2(targetY - bone.worldY, targetX - bone.worldX) * spine.radDeg; 238 if (bone.worldFlipX != (bone.worldFlipY != spine.Bone.yDown)) rotationIK = -rotationIK; 239 rotationIK -= parentRotation; 240 bone.rotationIK = rotation + (rotationIK - rotation) * alpha; 241}; 242/** Adjusts the parent and child bone rotations so the tip of the child is as close to the target position as possible. The 243 * target is specified in the world coordinate system. 244 * @param child Any descendant bone of the parent. */ 245spine.IkConstraint.apply2 = function (parent, child, targetX, targetY, bendDirection, alpha) { 246 var childRotation = child.rotation, parentRotation = parent.rotation; 247 if (!alpha) { 248 child.rotationIK = childRotation; 249 parent.rotationIK = parentRotation; 250 return; 251 } 252 var positionX, positionY, tempPosition = spine.temp; 253 var parentParent = parent.parent; 254 if (parentParent) { 255 tempPosition[0] = targetX; 256 tempPosition[1] = targetY; 257 parentParent.worldToLocal(tempPosition); 258 targetX = (tempPosition[0] - parent.x) * parentParent.worldScaleX; 259 targetY = (tempPosition[1] - parent.y) * parentParent.worldScaleY; 260 } else { 261 targetX -= parent.x; 262 targetY -= parent.y; 263 } 264 if (child.parent == parent) { 265 positionX = child.x; 266 positionY = child.y; 267 } else { 268 tempPosition[0] = child.x; 269 tempPosition[1] = child.y; 270 child.parent.localToWorld(tempPosition); 271 parent.worldToLocal(tempPosition); 272 positionX = tempPosition[0]; 273 positionY = tempPosition[1]; 274 } 275 var childX = positionX * parent.worldScaleX, childY = positionY * parent.worldScaleY; 276 var offset = Math.atan2(childY, childX); 277 var len1 = Math.sqrt(childX * childX + childY * childY), len2 = child.data.length * child.worldScaleX; 278 // Based on code by Ryan Juckett with permission: Copyright (c) 2008-2009 Ryan Juckett, http://www.ryanjuckett.com/ 279 var cosDenom = 2 * len1 * len2; 280 if (cosDenom < 0.0001) { 281 child.rotationIK = childRotation + (Math.atan2(targetY, targetX) * spine.radDeg - parentRotation - childRotation) * alpha; 282 return; 283 } 284 var cos = (targetX * targetX + targetY * targetY - len1 * len1 - len2 * len2) / cosDenom; 285 if (cos < -1) 286 cos = -1; 287 else if (cos > 1) 288 cos = 1; 289 var childAngle = Math.acos(cos) * bendDirection; 290 var adjacent = len1 + len2 * cos, opposite = len2 * Math.sin(childAngle); 291 var parentAngle = Math.atan2(targetY * adjacent - targetX * opposite, targetX * adjacent + targetY * opposite); 292 var rotation = (parentAngle - offset) * spine.radDeg - parentRotation; 293 if (rotation > 180) 294 rotation -= 360; 295 else if (rotation < -180) // 296 rotation += 360; 297 parent.rotationIK = parentRotation + rotation * alpha; 298 rotation = (childAngle + offset) * spine.radDeg - childRotation; 299 if (rotation > 180) 300 rotation -= 360; 301 else if (rotation < -180) // 302 rotation += 360; 303 child.rotationIK = childRotation + (rotation + parent.worldRotation - child.parent.worldRotation) * alpha; 304}; 305 306spine.Skin = function (name) { 307 this.name = name; 308 this.attachments = {}; 309}; 310spine.Skin.prototype = { 311 addAttachment: function (slotIndex, name, attachment) { 312 this.attachments[slotIndex + ":" + name] = attachment; 313 }, 314 getAttachment: function (slotIndex, name) { 315 return this.attachments[slotIndex + ":" + name]; 316 }, 317 _attachAll: function (skeleton, oldSkin) { 318 for (var key in oldSkin.attachments) { 319 var colon = key.indexOf(":"); 320 var slotIndex = parseInt(key.substring(0, colon)); 321 var name = key.substring(colon + 1); 322 var slot = skeleton.slots[slotIndex]; 323 if (slot.attachment && slot.attachment.name == name) { 324 var attachment = this.getAttachment(slotIndex, name); 325 if (attachment) slot.setAttachment(attachment); 326 } 327 } 328 } 329}; 330 331spine.Animation = function (name, timelines, duration) { 332 this.name = name; 333 this.timelines = timelines; 334 this.duration = duration; 335}; 336spine.Animation.prototype = { 337 apply: function (skeleton, lastTime, time, loop, events) { 338 if (loop && this.duration != 0) { 339 time %= this.duration; 340 lastTime %= this.duration; 341 } 342 var timelines = this.timelines; 343 for (var i = 0, n = timelines.length; i < n; i++) 344 timelines[i].apply(skeleton, lastTime, time, events, 1); 345 }, 346 mix: function (skeleton, lastTime, time, loop, events, alpha) { 347 if (loop && this.duration != 0) { 348 time %= this.duration; 349 lastTime %= this.duration; 350 } 351 var timelines = this.timelines; 352 for (var i = 0, n = timelines.length; i < n; i++) 353 timelines[i].apply(skeleton, lastTime, time, events, alpha); 354 } 355}; 356spine.Animation.binarySearch = function (values, target, step) { 357 var low = 0;
vendor: 15,898 bytes, lines 358-832
358 var high = Math.floor(values.length / step) - 2; 359 if (!high) return step; 360 var current = high >>> 1; 361 while (true) { 362 if (values[(current + 1) * step] <= target) 363 low = current + 1; 364 else 365 high = current; 366 if (low == high) return (low + 1) * step; 367 current = (low + high) >>> 1; 368 } 369}; 370spine.Animation.binarySearch1 = function (values, target) { 371 var low = 0; 372 var high = values.length - 2; 373 if (!high) return 1; 374 var current = high >>> 1; 375 while (true) { 376 if (values[current + 1] <= target) 377 low = current + 1; 378 else 379 high = current; 380 if (low == high) return low + 1; 381 current = (low + high) >>> 1; 382 } 383}; 384spine.Animation.linearSearch = function (values, target, step) { 385 for (var i = 0, last = values.length - step; i <= last; i += step) 386 if (values[i] > target) return i; 387 return -1; 388}; 389 390spine.Curves = function (frameCount) { 391 this.curves = []; // type, x, y, ... 392 //this.curves.length = (frameCount - 1) * 19/*BEZIER_SIZE*/; 393}; 394spine.Curves.prototype = { 395 setLinear: function (frameIndex) { 396 this.curves[frameIndex * 19/*BEZIER_SIZE*/] = 0/*LINEAR*/; 397 }, 398 setStepped: function (frameIndex) { 399 this.curves[frameIndex * 19/*BEZIER_SIZE*/] = 1/*STEPPED*/; 400 }, 401 /** Sets the control handle positions for an interpolation bezier curve used to transition from this keyframe to the next. 402 * cx1 and cx2 are from 0 to 1, representing the percent of time between the two keyframes. cy1 and cy2 are the percent of 403 * the difference between the keyframe's values. */ 404 setCurve: function (frameIndex, cx1, cy1, cx2, cy2) { 405 var subdiv1 = 1 / 10/*BEZIER_SEGMENTS*/, subdiv2 = subdiv1 * subdiv1, subdiv3 = subdiv2 * subdiv1; 406 var pre1 = 3 * subdiv1, pre2 = 3 * subdiv2, pre4 = 6 * subdiv2, pre5 = 6 * subdiv3; 407 var tmp1x = -cx1 * 2 + cx2, tmp1y = -cy1 * 2 + cy2, tmp2x = (cx1 - cx2) * 3 + 1, tmp2y = (cy1 - cy2) * 3 + 1; 408 var dfx = cx1 * pre1 + tmp1x * pre2 + tmp2x * subdiv3, dfy = cy1 * pre1 + tmp1y * pre2 + tmp2y * subdiv3; 409 var ddfx = tmp1x * pre4 + tmp2x * pre5, ddfy = tmp1y * pre4 + tmp2y * pre5; 410 var dddfx = tmp2x * pre5, dddfy = tmp2y * pre5; 411 412 var i = frameIndex * 19/*BEZIER_SIZE*/; 413 var curves = this.curves; 414 curves[i++] = 2/*BEZIER*/; 415 416 var x = dfx, y = dfy; 417 for (var n = i + 19/*BEZIER_SIZE*/ - 1; i < n; i += 2) { 418 curves[i] = x; 419 curves[i + 1] = y; 420 dfx += ddfx; 421 dfy += ddfy; 422 ddfx += dddfx; 423 ddfy += dddfy; 424 x += dfx; 425 y += dfy; 426 } 427 }, 428 getCurvePercent: function (frameIndex, percent) { 429 percent = percent < 0 ? 0 : (percent > 1 ? 1 : percent); 430 var curves = this.curves; 431 var i = frameIndex * 19/*BEZIER_SIZE*/; 432 var type = curves[i]; 433 if (type === 0/*LINEAR*/) return percent; 434 if (type == 1/*STEPPED*/) return 0; 435 i++; 436 var x = 0; 437 for (var start = i, n = i + 19/*BEZIER_SIZE*/ - 1; i < n; i += 2) { 438 x = curves[i]; 439 if (x >= percent) { 440 var prevX, prevY; 441 if (i == start) { 442 prevX = 0; 443 prevY = 0; 444 } else { 445 prevX = curves[i - 2]; 446 prevY = curves[i - 1]; 447 } 448 return prevY + (curves[i + 1] - prevY) * (percent - prevX) / (x - prevX); 449 } 450 } 451 var y = curves[i - 1]; 452 return y + (1 - y) * (percent - x) / (1 - x); // Last point is 1,1. 453 } 454}; 455 456spine.RotateTimeline = function (frameCount) { 457 this.curves = new spine.Curves(frameCount); 458 this.frames = []; // time, angle, ... 459 this.frames.length = frameCount * 2; 460}; 461spine.RotateTimeline.prototype = { 462 boneIndex: 0, 463 getFrameCount: function () { 464 return this.frames.length / 2; 465 }, 466 setFrame: function (frameIndex, time, angle) { 467 frameIndex *= 2; 468 this.frames[frameIndex] = time; 469 this.frames[frameIndex + 1] = angle; 470 }, 471 apply: function (skeleton, lastTime, time, firedEvents, alpha) { 472 var frames = this.frames; 473 if (time < frames[0]) return; // Time is before first frame. 474 475 var bone = skeleton.bones[this.boneIndex]; 476 477 if (time >= frames[frames.length - 2]) { // Time is after last frame. 478 var amount = bone.data.rotation + frames[frames.length - 1] - bone.rotation; 479 while (amount > 180) 480 amount -= 360; 481 while (amount < -180) 482 amount += 360; 483 bone.rotation += amount * alpha; 484 return; 485 } 486 487 // Interpolate between the previous frame and the current frame. 488 var frameIndex = spine.Animation.binarySearch(frames, time, 2); 489 var prevFrameValue = frames[frameIndex - 1]; 490 var frameTime = frames[frameIndex]; 491 var percent = 1 - (time - frameTime) / (frames[frameIndex - 2/*PREV_FRAME_TIME*/] - frameTime); 492 percent = this.curves.getCurvePercent(frameIndex / 2 - 1, percent); 493 494 var amount = frames[frameIndex + 1/*FRAME_VALUE*/] - prevFrameValue; 495 while (amount > 180) 496 amount -= 360; 497 while (amount < -180) 498 amount += 360; 499 amount = bone.data.rotation + (prevFrameValue + amount * percent) - bone.rotation; 500 while (amount > 180) 501 amount -= 360; 502 while (amount < -180) 503 amount += 360; 504 bone.rotation += amount * alpha; 505 } 506}; 507 508spine.TranslateTimeline = function (frameCount) { 509 this.curves = new spine.Curves(frameCount); 510 this.frames = []; // time, x, y, ... 511 this.frames.length = frameCount * 3; 512}; 513spine.TranslateTimeline.prototype = { 514 boneIndex: 0, 515 getFrameCount: function () { 516 return this.frames.length / 3; 517 }, 518 setFrame: function (frameIndex, time, x, y) { 519 frameIndex *= 3; 520 this.frames[frameIndex] = time; 521 this.frames[frameIndex + 1] = x; 522 this.frames[frameIndex + 2] = y; 523 }, 524 apply: function (skeleton, lastTime, time, firedEvents, alpha) { 525 var frames = this.frames; 526 if (time < frames[0]) return; // Time is before first frame. 527 528 var bone = skeleton.bones[this.boneIndex]; 529 530 if (time >= frames[frames.length - 3]) { // Time is after last frame. 531 bone.x += (bone.data.x + frames[frames.length - 2] - bone.x) * alpha; 532 bone.y += (bone.data.y + frames[frames.length - 1] - bone.y) * alpha; 533 return; 534 } 535 536 // Interpolate between the previous frame and the current frame. 537 var frameIndex = spine.Animation.binarySearch(frames, time, 3); 538 var prevFrameX = frames[frameIndex - 2]; 539 var prevFrameY = frames[frameIndex - 1]; 540 var frameTime = frames[frameIndex]; 541 var percent = 1 - (time - frameTime) / (frames[frameIndex + -3/*PREV_FRAME_TIME*/] - frameTime); 542 percent = this.curves.getCurvePercent(frameIndex / 3 - 1, percent); 543 544 bone.x += (bone.data.x + prevFrameX + (frames[frameIndex + 1/*FRAME_X*/] - prevFrameX) * percent - bone.x) * alpha; 545 bone.y += (bone.data.y + prevFrameY + (frames[frameIndex + 2/*FRAME_Y*/] - prevFrameY) * percent - bone.y) * alpha; 546 } 547}; 548 549spine.ScaleTimeline = function (frameCount) { 550 this.curves = new spine.Curves(frameCount); 551 this.frames = []; // time, x, y, ... 552 this.frames.length = frameCount * 3; 553}; 554spine.ScaleTimeline.prototype = { 555 boneIndex: 0, 556 getFrameCount: function () { 557 return this.frames.length / 3; 558 }, 559 setFrame: function (frameIndex, time, x, y) { 560 frameIndex *= 3; 561 this.frames[frameIndex] = time; 562 this.frames[frameIndex + 1] = x; 563 this.frames[frameIndex + 2] = y; 564 }, 565 apply: function (skeleton, lastTime, time, firedEvents, alpha) { 566 var frames = this.frames; 567 if (time < frames[0]) return; // Time is before first frame. 568 569 var bone = skeleton.bones[this.boneIndex]; 570 571 if (time >= frames[frames.length - 3]) { // Time is after last frame. 572 bone.scaleX += (bone.data.scaleX * frames[frames.length - 2] - bone.scaleX) * alpha; 573 bone.scaleY += (bone.data.scaleY * frames[frames.length - 1] - bone.scaleY) * alpha; 574 return; 575 } 576 577 // Interpolate between the previous frame and the current frame. 578 var frameIndex = spine.Animation.binarySearch(frames, time, 3); 579 var prevFrameX = frames[frameIndex - 2]; 580 var prevFrameY = frames[frameIndex - 1]; 581 var frameTime = frames[frameIndex]; 582 var percent = 1 - (time - frameTime) / (frames[frameIndex + -3/*PREV_FRAME_TIME*/] - frameTime); 583 percent = this.curves.getCurvePercent(frameIndex / 3 - 1, percent); 584 585 bone.scaleX += (bone.data.scaleX * (prevFrameX + (frames[frameIndex + 1/*FRAME_X*/] - prevFrameX) * percent) - bone.scaleX) * alpha; 586 bone.scaleY += (bone.data.scaleY * (prevFrameY + (frames[frameIndex + 2/*FRAME_Y*/] - prevFrameY) * percent) - bone.scaleY) * alpha; 587 } 588}; 589 590spine.ColorTimeline = function (frameCount) { 591 this.curves = new spine.Curves(frameCount); 592 this.frames = []; // time, r, g, b, a, ... 593 this.frames.length = frameCount * 5; 594}; 595spine.ColorTimeline.prototype = { 596 slotIndex: 0, 597 getFrameCount: function () { 598 return this.frames.length / 5; 599 }, 600 setFrame: function (frameIndex, time, r, g, b, a) { 601 frameIndex *= 5; 602 this.frames[frameIndex] = time; 603 this.frames[frameIndex + 1] = r; 604 this.frames[frameIndex + 2] = g; 605 this.frames[frameIndex + 3] = b; 606 this.frames[frameIndex + 4] = a; 607 }, 608 apply: function (skeleton, lastTime, time, firedEvents, alpha) { 609 var frames = this.frames; 610 if (time < frames[0]) return; // Time is before first frame. 611 612 var r, g, b, a; 613 if (time >= frames[frames.length - 5]) { 614 // Time is after last frame. 615 var i = frames.length - 1; 616 r = frames[i - 3]; 617 g = frames[i - 2]; 618 b = frames[i - 1]; 619 a = frames[i]; 620 } else { 621 // Interpolate between the previous frame and the current frame. 622 var frameIndex = spine.Animation.binarySearch(frames, time, 5); 623 var prevFrameR = frames[frameIndex - 4]; 624 var prevFrameG = frames[frameIndex - 3]; 625 var prevFrameB = frames[frameIndex - 2]; 626 var prevFrameA = frames[frameIndex - 1]; 627 var frameTime = frames[frameIndex]; 628 var percent = 1 - (time - frameTime) / (frames[frameIndex - 5/*PREV_FRAME_TIME*/] - frameTime); 629 percent = this.curves.getCurvePercent(frameIndex / 5 - 1, percent); 630 631 r = prevFrameR + (frames[frameIndex + 1/*FRAME_R*/] - prevFrameR) * percent; 632 g = prevFrameG + (frames[frameIndex + 2/*FRAME_G*/] - prevFrameG) * percent; 633 b = prevFrameB + (frames[frameIndex + 3/*FRAME_B*/] - prevFrameB) * percent; 634 a = prevFrameA + (frames[frameIndex + 4/*FRAME_A*/] - prevFrameA) * percent; 635 } 636 var slot = skeleton.slots[this.slotIndex]; 637 if (alpha < 1) { 638 slot.r += (r - slot.r) * alpha; 639 slot.g += (g - slot.g) * alpha; 640 slot.b += (b - slot.b) * alpha; 641 slot.a += (a - slot.a) * alpha; 642 } else { 643 slot.r = r; 644 slot.g = g; 645 slot.b = b; 646 slot.a = a; 647 } 648 } 649}; 650 651spine.AttachmentTimeline = function (frameCount) { 652 this.curves = new spine.Curves(frameCount); 653 this.frames = []; // time, ... 654 this.frames.length = frameCount; 655 this.attachmentNames = []; 656 this.attachmentNames.length = frameCount; 657}; 658spine.AttachmentTimeline.prototype = { 659 slotIndex: 0, 660 getFrameCount: function () { 661 return this.frames.length; 662 }, 663 setFrame: function (frameIndex, time, attachmentName) { 664 this.frames[frameIndex] = time; 665 this.attachmentNames[frameIndex] = attachmentName; 666 }, 667 apply: function (skeleton, lastTime, time, firedEvents, alpha) { 668 var frames = this.frames; 669 if (time < frames[0]) { 670 if (lastTime > time) this.apply(skeleton, lastTime, Number.MAX_VALUE, null, 0); 671 return; 672 } else if (lastTime > time) // 673 lastTime = -1; 674 675 var frameIndex = time >= frames[frames.length - 1] ? frames.length - 1 : spine.Animation.binarySearch1(frames, time) - 1; 676 if (frames[frameIndex] < lastTime) return; 677 678 var attachmentName = this.attachmentNames[frameIndex]; 679 skeleton.slots[this.slotIndex].setAttachment( 680 !attachmentName ? null : skeleton.getAttachmentBySlotIndex(this.slotIndex, attachmentName)); 681 } 682}; 683 684spine.EventTimeline = function (frameCount) { 685 this.frames = []; // time, ... 686 this.frames.length = frameCount; 687 this.events = []; 688 this.events.length = frameCount; 689}; 690spine.EventTimeline.prototype = { 691 getFrameCount: function () { 692 return this.frames.length; 693 }, 694 setFrame: function (frameIndex, time, event) { 695 this.frames[frameIndex] = time; 696 this.events[frameIndex] = event; 697 }, 698 /** Fires events for frames > lastTime and <= time. */ 699 apply: function (skeleton, lastTime, time, firedEvents, alpha) { 700 if (!firedEvents) return; 701 702 var frames = this.frames; 703 var frameCount = frames.length; 704 705 if (lastTime > time) { // Fire events after last time for looped animations. 706 this.apply(skeleton, lastTime, Number.MAX_VALUE, firedEvents, alpha); 707 lastTime = -1; 708 } else if (lastTime >= frames[frameCount - 1]) // Last time is after last frame. 709 return; 710 if (time < frames[0]) return; // Time is before first frame. 711 712 var frameIndex; 713 if (lastTime < frames[0]) 714 frameIndex = 0; 715 else { 716 frameIndex = spine.Animation.binarySearch1(frames, lastTime); 717 var frame = frames[frameIndex]; 718 while (frameIndex > 0) { // Fire multiple events with the same frame. 719 if (frames[frameIndex - 1] != frame) break; 720 frameIndex--; 721 } 722 } 723 var events = this.events; 724 for (; frameIndex < frameCount && time >= frames[frameIndex]; frameIndex++) 725 firedEvents.push(events[frameIndex]); 726 } 727}; 728 729spine.DrawOrderTimeline = function (frameCount) { 730 this.frames = []; // time, ... 731 this.frames.length = frameCount; 732 this.drawOrders = []; 733 this.drawOrders.length = frameCount; 734}; 735spine.DrawOrderTimeline.prototype = { 736 getFrameCount: function () { 737 return this.frames.length; 738 }, 739 setFrame: function (frameIndex, time, drawOrder) { 740 this.frames[frameIndex] = time; 741 this.drawOrders[frameIndex] = drawOrder; 742 }, 743 apply: function (skeleton, lastTime, time, firedEvents, alpha) { 744 var frames = this.frames; 745 if (time < frames[0]) return; // Time is before first frame. 746 747 var frameIndex; 748 if (time >= frames[frames.length - 1]) // Time is after last frame. 749 frameIndex = frames.length - 1; 750 else 751 frameIndex = spine.Animation.binarySearch1(frames, time) - 1; 752 753 var drawOrder = skeleton.drawOrder; 754 var slots = skeleton.slots; 755 var drawOrderToSetupIndex = this.drawOrders[frameIndex]; 756 if (!drawOrderToSetupIndex) { 757 for (var i = 0, n = slots.length; i < n; i++) 758 drawOrder[i] = slots[i]; 759 } else { 760 for (var i = 0, n = drawOrderToSetupIndex.length; i < n; i++) 761 drawOrder[i] = skeleton.slots[drawOrderToSetupIndex[i]]; 762 } 763 764 } 765}; 766 767spine.FfdTimeline = function (frameCount) { 768 this.curves = new spine.Curves(frameCount); 769 this.frames = []; 770 this.frames.length = frameCount; 771 this.frameVertices = []; 772 this.frameVertices.length = frameCount; 773}; 774spine.FfdTimeline.prototype = { 775 slotIndex: 0, 776 attachment: 0, 777 getFrameCount: function () { 778 return this.frames.length; 779 }, 780 setFrame: function (frameIndex, time, vertices) { 781 this.frames[frameIndex] = time; 782 this.frameVertices[frameIndex] = vertices; 783 }, 784 apply: function (skeleton, lastTime, time, firedEvents, alpha) { 785 var slot = skeleton.slots[this.slotIndex]; 786 if (slot.attachment != this.attachment) return; 787 788 var frames = this.frames; 789 if (time < frames[0]) return; // Time is before first frame. 790 791 var frameVertices = this.frameVertices; 792 var vertexCount = frameVertices[0].length; 793 794 var vertices = slot.attachmentVertices; 795 if (vertices.length != vertexCount) alpha = 1; 796 vertices.length = vertexCount; 797 798 if (time >= frames[frames.length - 1]) { // Time is after last frame. 799 var lastVertices = frameVertices[frames.length - 1]; 800 if (alpha < 1) { 801 for (var i = 0; i < vertexCount; i++) 802 vertices[i] += (lastVertices[i] - vertices[i]) * alpha; 803 } else { 804 for (var i = 0; i < vertexCount; i++) 805 vertices[i] = lastVertices[i]; 806 } 807 return; 808 } 809 810 // Interpolate between the previous frame and the current frame. 811 var frameIndex = spine.Animation.binarySearch1(frames, time); 812 var frameTime = frames[frameIndex]; 813 var percent = 1 - (time - frameTime) / (frames[frameIndex - 1] - frameTime); 814 percent = this.curves.getCurvePercent(frameIndex - 1, percent < 0 ? 0 : (percent > 1 ? 1 : percent)); 815 816 var prevVertices = frameVertices[frameIndex - 1]; 817 var nextVertices = frameVertices[frameIndex]; 818 819 if (alpha < 1) { 820 for (var i = 0; i < vertexCount; i++) { 821 var prev = prevVertices[i]; 822 vertices[i] += (prev + (nextVertices[i] - prev) * percent - vertices[i]) * alpha; 823 } 824 } else { 825 for (var i = 0; i < vertexCount; i++) { 826 var prev = prevVertices[i]; 827 vertices[i] = prev + (nextVertices[i] - prev) * percent; 828 } 829 } 830 } 831}; 832
833spine.IkConstraintTimeline = function (frameCount) { 834 this.curves = new spine.Curves(frameCount); 835 this.frames = []; // time, mix, bendDirection, ... 836 this.frames.length = frameCount * 3; 837}; 838spine.IkConstraintTimeline.prototype = { 839 ikConstraintIndex: 0, 840 getFrameCount: function () { 841 return this.frames.length / 3; 842 }, 843 setFrame: function (frameIndex, time, mix, bendDirection) { 844 frameIndex *= 3; 845 this.frames[frameIndex] = time; 846 this.frames[frameIndex + 1] = mix; 847 this.frames[frameIndex + 2] = bendDirection; 848 }, 849 apply: function (skeleton, lastTime, time, firedEvents, alpha) { 850 var frames = this.frames; 851 if (time < frames[0]) return; // Time is before first frame. 852 853 var ikConstraint = skeleton.ikConstraints[this.ikConstraintIndex]; 854 855 if (time >= frames[frames.length - 3]) { // Time is after last frame. 856 ikConstraint.mix += (frames[frames.length - 2] - ikConstraint.mix) * alpha; 857 ikConstraint.bendDirection = frames[frames.length - 1]; 858 return; 859 } 860 861 // Interpolate between the previous frame and the current frame. 862 var frameIndex = spine.Animation.binarySearch(frames, time, 3); 863 var prevFrameMix = frames[frameIndex + -2/*PREV_FRAME_MIX*/]; 864 var frameTime = frames[frameIndex]; 865 var percent = 1 - (time - frameTime) / (frames[frameIndex + -3/*PREV_FRAME_TIME*/] - frameTime); 866 percent = this.curves.getCurvePercent(frameIndex / 3 - 1, percent); 867 868 var mix = prevFrameMix + (frames[frameIndex + 1/*FRAME_MIX*/] - prevFrameMix) * percent; 869 ikConstraint.mix += (mix - ikConstraint.mix) * alpha; 870 ikConstraint.bendDirection = frames[frameIndex + -1/*PREV_FRAME_BEND_DIRECTION*/]; 871 } 872}; 873 874spine.FlipXTimeline = function (frameCount) { 875 this.curves = new spine.Curves(frameCount); 876 this.frames = []; // time, flip, ... 877 this.frames.length = frameCount * 2; 878}; 879spine.FlipXTimeline.prototype = { 880 boneIndex: 0, 881 getFrameCount: function () { 882 return this.frames.length / 2; 883 }, 884 setFrame: function (frameIndex, time, flip) { 885 frameIndex *= 2; 886 this.frames[frameIndex] = time; 887 this.frames[frameIndex + 1] = flip ? 1 : 0; 888 }, 889 apply: function (skeleton, lastTime, time, firedEvents, alpha) { 890 var frames = this.frames; 891 if (time < frames[0]) { 892 if (lastTime > time) this.apply(skeleton, lastTime, Number.MAX_VALUE, null, 0); 893 return; 894 } else if (lastTime > time) // 895 lastTime = -1; 896 var frameIndex = (time >= frames[frames.length - 2] ? frames.length : spine.Animation.binarySearch(frames, time, 2)) - 2; 897 if (frames[frameIndex] < lastTime) return; 898 skeleton.bones[this.boneIndex].flipX = frames[frameIndex + 1] != 0; 899 } 900}; 901 902spine.FlipYTimeline = function (frameCount) { 903 this.curves = new spine.Curves(frameCount); 904 this.frames = []; // time, flip, ... 905 this.frames.length = frameCount * 2; 906}; 907spine.FlipYTimeline.prototype = { 908 boneIndex: 0, 909 getFrameCount: function () { 910 return this.frames.length / 2; 911 }, 912 setFrame: function (frameIndex, time, flip) { 913 frameIndex *= 2; 914 this.frames[frameIndex] = time; 915 this.frames[frameIndex + 1] = flip ? 1 : 0; 916 }, 917 apply: function (skeleton, lastTime, time, firedEvents, alpha) { 918 var frames = this.frames; 919 if (time < frames[0]) { 920 if (lastTime > time) this.apply(skeleton, lastTime, Number.MAX_VALUE, null, 0); 921 return; 922 } else if (lastTime > time) // 923 lastTime = -1; 924 var frameIndex = (time >= frames[frames.length - 2] ? frames.length : spine.Animation.binarySearch(frames, time, 2)) - 2; 925 if (frames[frameIndex] < lastTime) return; 926 skeleton.bones[this.boneIndex].flipY = frames[frameIndex + 1] != 0; 927 } 928}; 929 930spine.SkeletonData = function () { 931 this.bones = []; 932 this.slots = []; 933 this.skins = []; 934 this.events = []; 935 this.animations = []; 936 this.ikConstraints = []; 937}; 938spine.SkeletonData.prototype = { 939 name: null, 940 defaultSkin: null, 941 width: 0, height: 0, 942 version: null, hash: null, 943 /** @return May be null. */ 944 findBone: function (boneName) { 945 var bones = this.bones; 946 for (var i = 0, n = bones.length; i < n; i++) 947 if (bones[i].name == boneName) return bones[i]; 948 return null; 949 }, 950 /** @return -1 if the bone was not found. */ 951 findBoneIndex: function (boneName) { 952 var bones = this.bones; 953 for (var i = 0, n = bones.length; i < n; i++) 954 if (bones[i].name == boneName) return i; 955 return -1; 956 }, 957 /** @return May be null. */ 958 findSlot: function (slotName) { 959 var slots = this.slots; 960 for (var i = 0, n = slots.length; i < n; i++) { 961 if (slots[i].name == slotName) return slot[i]; 962 } 963 return null; 964 }, 965 /** @return -1 if the bone was not found. */ 966 findSlotIndex: function (slotName) { 967 var slots = this.slots; 968 for (var i = 0, n = slots.length; i < n; i++) 969 if (slots[i].name == slotName) return i; 970 return -1; 971 }, 972 /** @return May be null. */ 973 findSkin: function (skinName) { 974 var skins = this.skins; 975 for (var i = 0, n = skins.length; i < n; i++) 976 if (skins[i].name == skinName) return skins[i]; 977 return null; 978 }, 979 /** @return May be null. */ 980 findEvent: function (eventName) { 981 var events = this.events; 982 for (var i = 0, n = events.length; i < n; i++) 983 if (events[i].name == eventName) return events[i]; 984 return null; 985 }, 986 /** @return May be null. */ 987 findAnimation: function (animationName) { 988 var animations = this.animations; 989 for (var i = 0, n = animations.length; i < n; i++)
990 if (animations[i].name == animationName) return animations[i]; 991 return null; 992 }, 993 /** @return May be null. */ 994 findIkConstraint: function (ikConstraintName) { 995 var ikConstraints = this.ikConstraints; 996 for (var i = 0, n = ikConstraints.length; i < n; i++) 997 if (ikConstraints[i].name == ikConstraintName) return ikConstraints[i]; 998 return null; 999 } 1000}; 1001 1002spine.Skeleton = function (skeletonData) { 1003 this.data = skeletonData; 1004 1005 this.bones = []; 1006 for (var i = 0, n = skeletonData.bones.length; i < n; i++) { 1007 var boneData = skeletonData.bones[i]; 1008 var parent = !boneData.parent ? null : this.bones[skeletonData.bones.indexOf(boneData.parent)]; 1009 this.bones.push(new spine.Bone(boneData, this, parent)); 1010 } 1011 1012 this.slots = []; 1013 this.drawOrder = []; 1014 for (var i = 0, n = skeletonData.slots.length; i < n; i++) { 1015 var slotData = skeletonData.slots[i]; 1016 var bone = this.bones[skeletonData.bones.indexOf(slotData.boneData)]; 1017 var slot = new spine.Slot(slotData, bone); 1018 this.slots.push(slot); 1019 this.drawOrder.push(slot); 1020 } 1021 1022 this.ikConstraints = []; 1023 for (var i = 0, n = skeletonData.ikConstraints.length; i < n; i++) 1024 this.ikConstraints.push(new spine.IkConstraint(skeletonData.ikConstraints[i], this)); 1025 1026 this.boneCache = []; 1027 this.updateCache(); 1028}; 1029spine.Skeleton.prototype = { 1030 x: 0, y: 0, 1031 skin: null, 1032 r: 1, g: 1, b: 1, a: 1, 1033 time: 0, 1034 flipX: false, flipY: false, 1035 /** Caches information about bones and IK constraints. Must be called if bones or IK constraints are added or removed. */ 1036 updateCache: function () { 1037 var ikConstraints = this.ikConstraints; 1038 var ikConstraintsCount = ikConstraints.length; 1039 1040 var arrayCount = ikConstraintsCount + 1; 1041 var boneCache = this.boneCache; 1042 if (boneCache.length > arrayCount) boneCache.length = arrayCount; 1043 for (var i = 0, n = boneCache.length; i < n; i++) 1044 boneCache[i].length = 0; 1045 while (boneCache.length < arrayCount) 1046 boneCache[boneCache.length] = []; 1047 1048 var nonIkBones = boneCache[0]; 1049 var bones = this.bones; 1050 1051 outer: 1052 for (var i = 0, n = bones.length; i < n; i++) { 1053 var bone = bones[i]; 1054 var current = bone; 1055 do { 1056 for (var ii = 0; ii < ikConstraintsCount; ii++) { 1057 var ikConstraint = ikConstraints[ii]; 1058 var parent = ikConstraint.bones[0]; 1059 var child= ikConstraint.bones[ikConstraint.bones.length - 1]; 1060 while (true) { 1061 if (current == child) { 1062 boneCache[ii].push(bone); 1063 boneCache[ii + 1].push(bone); 1064 continue outer; 1065 } 1066 if (child == parent) break; 1067 child = child.parent; 1068 } 1069 } 1070 current = current.parent; 1071 } while (current); 1072 nonIkBones[nonIkBones.length] = bone; 1073 } 1074 }, 1075 /** Updates the world transform for each bone. */ 1076 updateWorldTransform: function () { 1077 var bones = this.bones; 1078 for (var i = 0, n = bones.length; i < n; i++) { 1079 var bone = bones[i]; 1080 bone.rotationIK = bone.rotation; 1081 } 1082 var i = 0, last = this.boneCache.length - 1; 1083 while (true) { 1084 var cacheBones = this.boneCache[i]; 1085 for (var ii = 0, nn = cacheBones.length; ii < nn; ii++) 1086 cacheBones[ii].updateWorldTransform(); 1087 if (i == last) break; 1088 this.ikConstraints[i].apply(); 1089 i++; 1090 } 1091 }, 1092 /** Sets the bones and slots to their setup pose values. */ 1093 setToSetupPose: function () { 1094 this.setBonesToSetupPose(); 1095 this.setSlotsToSetupPose(); 1096 }, 1097 setBonesToSetupPose: function () { 1098 var bones = this.bones; 1099 for (var i = 0, n = bones.length; i < n; i++) 1100 bones[i].setToSetupPose(); 1101 1102 var ikConstraints = this.ikConstraints; 1103 for (var i = 0, n = ikConstraints.length; i < n; i++) { 1104 var ikConstraint = ikConstraints[i]; 1105 ikConstraint.bendDirection = ikConstraint.data.bendDirection; 1106 ikConstraint.mix = ikConstraint.data.mix; 1107 } 1108 }, 1109 setSlotsToSetupPose: function () { 1110 var slots = this.slots; 1111 var drawOrder = this.drawOrder; 1112 for (var i = 0, n = slots.length; i < n; i++) { 1113 drawOrder[i] = slots[i]; 1114 slots[i].setToSetupPose(i); 1115 } 1116 }, 1117 /** @return May return null. */ 1118 getRootBone: function () { 1119 return this.bones.length ? this.bones[0] : null; 1120 }, 1121 /** @return May be null. */ 1122 findBone: function (boneName) { 1123 var bones = this.bones; 1124 for (var i = 0, n = bones.length; i < n; i++)
vendor: 17,944 bytes, lines 1125-1691
1125 if (bones[i].data.name == boneName) return bones[i]; 1126 return null; 1127 }, 1128 /** @return -1 if the bone was not found. */ 1129 findBoneIndex: function (boneName) { 1130 var bones = this.bones; 1131 for (var i = 0, n = bones.length; i < n; i++) 1132 if (bones[i].data.name == boneName) return i; 1133 return -1; 1134 }, 1135 /** @return May be null. */ 1136 findSlot: function (slotName) { 1137 var slots = this.slots; 1138 for (var i = 0, n = slots.length; i < n; i++) 1139 if (slots[i].data.name == slotName) return slots[i]; 1140 return null; 1141 }, 1142 /** @return -1 if the bone was not found. */ 1143 findSlotIndex: function (slotName) { 1144 var slots = this.slots; 1145 for (var i = 0, n = slots.length; i < n; i++) 1146 if (slots[i].data.name == slotName) return i; 1147 return -1; 1148 }, 1149 setSkinByName: function (skinName) { 1150 var skin = this.data.findSkin(skinName); 1151 if (!skin) throw "Skin not found: " + skinName; 1152 this.setSkin(skin); 1153 }, 1154 /** Sets the skin used to look up attachments before looking in the {@link SkeletonData#getDefaultSkin() default skin}. 1155 * Attachments from the new skin are attached if the corresponding attachment from the old skin was attached. If there was 1156 * no old skin, each slot's setup mode attachment is attached from the new skin. 1157 * @param newSkin May be null. */ 1158 setSkin: function (newSkin) { 1159 if (newSkin) { 1160 if (this.skin) 1161 newSkin._attachAll(this, this.skin); 1162 else { 1163 var slots = this.slots; 1164 for (var i = 0, n = slots.length; i < n; i++) { 1165 var slot = slots[i]; 1166 var name = slot.data.attachmentName; 1167 if (name) { 1168 var attachment = newSkin.getAttachment(i, name); 1169 if (attachment) slot.setAttachment(attachment); 1170 } 1171 } 1172 } 1173 } 1174 this.skin = newSkin; 1175 }, 1176 /** @return May be null. */ 1177 getAttachmentBySlotName: function (slotName, attachmentName) { 1178 return this.getAttachmentBySlotIndex(this.data.findSlotIndex(slotName), attachmentName); 1179 }, 1180 /** @return May be null. */ 1181 getAttachmentBySlotIndex: function (slotIndex, attachmentName) { 1182 if (this.skin) { 1183 var attachment = this.skin.getAttachment(slotIndex, attachmentName); 1184 if (attachment) return attachment; 1185 } 1186 if (this.data.defaultSkin) return this.data.defaultSkin.getAttachment(slotIndex, attachmentName); 1187 return null; 1188 }, 1189 /** @param attachmentName May be null. */ 1190 setAttachment: function (slotName, attachmentName) { 1191 var slots = this.slots; 1192 for (var i = 0, n = slots.length; i < n; i++) { 1193 var slot = slots[i]; 1194 if (slot.data.name == slotName) { 1195 var attachment = null; 1196 if (attachmentName) { 1197 attachment = this.getAttachmentBySlotIndex(i, attachmentName); 1198 if (!attachment) throw "Attachment not found: " + attachmentName + ", for slot: " + slotName; 1199 } 1200 slot.setAttachment(attachment); 1201 return; 1202 } 1203 } 1204 throw "Slot not found: " + slotName; 1205 }, 1206 /** @return May be null. */ 1207 findIkConstraint: function (ikConstraintName) { 1208 var ikConstraints = this.ikConstraints; 1209 for (var i = 0, n = ikConstraints.length; i < n; i++) 1210 if (ikConstraints[i].data.name == ikConstraintName) return ikConstraints[i]; 1211 return null; 1212 }, 1213 update: function (delta) { 1214 this.time += delta; 1215 } 1216}; 1217 1218spine.EventData = function (name) { 1219 this.name = name; 1220}; 1221spine.EventData.prototype = { 1222 intValue: 0, 1223 floatValue: 0, 1224 stringValue: null 1225}; 1226 1227spine.Event = function (data) { 1228 this.data = data; 1229}; 1230spine.Event.prototype = { 1231 intValue: 0, 1232 floatValue: 0, 1233 stringValue: null 1234}; 1235 1236spine.AttachmentType = { 1237 region: 0, 1238 boundingbox: 1, 1239 mesh: 2, 1240 skinnedmesh: 3 1241}; 1242 1243spine.RegionAttachment = function (name) { 1244 this.name = name; 1245 this.offset = []; 1246 this.offset.length = 8; 1247 this.uvs = []; 1248 this.uvs.length = 8; 1249}; 1250spine.RegionAttachment.prototype = { 1251 type: spine.AttachmentType.region, 1252 x: 0, y: 0, 1253 rotation: 0, 1254 scaleX: 1, scaleY: 1, 1255 width: 0, height: 0, 1256 r: 1, g: 1, b: 1, a: 1, 1257 path: null, 1258 rendererObject: null, 1259 regionOffsetX: 0, regionOffsetY: 0, 1260 regionWidth: 0, regionHeight: 0, 1261 regionOriginalWidth: 0, regionOriginalHeight: 0, 1262 setUVs: function (u, v, u2, v2, rotate) { 1263 var uvs = this.uvs; 1264 if (rotate) { 1265 uvs[2/*X2*/] = u; 1266 uvs[3/*Y2*/] = v2; 1267 uvs[4/*X3*/] = u; 1268 uvs[5/*Y3*/] = v; 1269 uvs[6/*X4*/] = u2; 1270 uvs[7/*Y4*/] = v; 1271 uvs[0/*X1*/] = u2; 1272 uvs[1/*Y1*/] = v2; 1273 } else { 1274 uvs[0/*X1*/] = u; 1275 uvs[1/*Y1*/] = v2; 1276 uvs[2/*X2*/] = u; 1277 uvs[3/*Y2*/] = v; 1278 uvs[4/*X3*/] = u2; 1279 uvs[5/*Y3*/] = v; 1280 uvs[6/*X4*/] = u2; 1281 uvs[7/*Y4*/] = v2; 1282 } 1283 }, 1284 updateOffset: function () { 1285 var regionScaleX = this.width / this.regionOriginalWidth * this.scaleX; 1286 var regionScaleY = this.height / this.regionOriginalHeight * this.scaleY; 1287 var localX = -this.width / 2 * this.scaleX + this.regionOffsetX * regionScaleX; 1288 var localY = -this.height / 2 * this.scaleY + this.regionOffsetY * regionScaleY; 1289 var localX2 = localX + this.regionWidth * regionScaleX; 1290 var localY2 = localY + this.regionHeight * regionScaleY; 1291 1292 var regionScaleX = 1; 1293 var regionScaleY = 1; 1294 var localX = 0; 1295 var localY = 0; 1296 var localX2 = 0; 1297 var localY2 = 0; 1298 1299 var radians = this.rotation * spine.degRad; 1300 var cos = Math.cos(radians); 1301 var sin = Math.sin(radians); 1302 var localXCos = localX * cos + this.x; 1303 var localXSin = localX * sin; 1304 var localYCos = localY * cos + this.y; 1305 var localYSin = localY * sin; 1306 var localX2Cos = localX2 * cos + this.x; 1307 var localX2Sin = localX2 * sin; 1308 var localY2Cos = localY2 * cos + this.y; 1309 var localY2Sin = localY2 * sin; 1310 var offset = this.offset; 1311 offset[0/*X1*/] = localXCos - localYSin; 1312 offset[1/*Y1*/] = localYCos + localXSin; 1313 offset[2/*X2*/] = localXCos - localY2Sin; 1314 offset[3/*Y2*/] = localY2Cos + localXSin; 1315 offset[4/*X3*/] = localX2Cos - localY2Sin; 1316 offset[5/*Y3*/] = localY2Cos + localX2Sin; 1317 offset[6/*X4*/] = localX2Cos - localYSin; 1318 offset[7/*Y4*/] = localYCos + localX2Sin; 1319 }, 1320 computeVertices: function (x, y, bone, vertices) { 1321 x += bone.worldX; 1322 y += bone.worldY; 1323 var m00 = bone.m00, m01 = bone.m01, m10 = bone.m10, m11 = bone.m11; 1324 var offset = this.offset; 1325 vertices[0/*X1*/] = offset[0/*X1*/] * m00 + offset[1/*Y1*/] * m01 + x; 1326 vertices[1/*Y1*/] = offset[0/*X1*/] * m10 + offset[1/*Y1*/] * m11 + y; 1327 vertices[2/*X2*/] = offset[2/*X2*/] * m00 + offset[3/*Y2*/] * m01 + x; 1328 vertices[3/*Y2*/] = offset[2/*X2*/] * m10 + offset[3/*Y2*/] * m11 + y; 1329 vertices[4/*X3*/] = offset[4/*X3*/] * m00 + offset[5/*X3*/] * m01 + x; 1330 vertices[5/*X3*/] = offset[4/*X3*/] * m10 + offset[5/*X3*/] * m11 + y; 1331 vertices[6/*X4*/] = offset[6/*X4*/] * m00 + offset[7/*Y4*/] * m01 + x; 1332 vertices[7/*Y4*/] = offset[6/*X4*/] * m10 + offset[7/*Y4*/] * m11 + y; 1333 } 1334}; 1335 1336spine.MeshAttachment = function (name) { 1337 this.name = name; 1338}; 1339spine.MeshAttachment.prototype = { 1340 type: spine.AttachmentType.mesh, 1341 vertices: null, 1342 uvs: null, 1343 regionUVs: null, 1344 triangles: null, 1345 hullLength: 0, 1346 r: 1, g: 1, b: 1, a: 1, 1347 path: null, 1348 rendererObject: null, 1349 regionU: 0, regionV: 0, regionU2: 0, regionV2: 0, regionRotate: false, 1350 regionOffsetX: 0, regionOffsetY: 0, 1351 regionWidth: 0, regionHeight: 0, 1352 regionOriginalWidth: 0, regionOriginalHeight: 0, 1353 edges: null, 1354 width: 0, height: 0, 1355 updateUVs: function () { 1356 var width = this.regionU2 - this.regionU, height = this.regionV2 - this.regionV; 1357 var n = this.regionUVs.length; 1358 if (!this.uvs || this.uvs.length != n) { 1359 this.uvs = new spine.Float32Array(n); 1360 } 1361 if (this.regionRotate) { 1362 for (var i = 0; i < n; i += 2) { 1363 this.uvs[i] = this.regionU + this.regionUVs[i + 1] * width; 1364 this.uvs[i + 1] = this.regionV + height - this.regionUVs[i] * height; 1365 } 1366 } else { 1367 for (var i = 0; i < n; i += 2) { 1368 this.uvs[i] = this.regionU + this.regionUVs[i] * width; 1369 this.uvs[i + 1] = this.regionV + this.regionUVs[i + 1] * height; 1370 } 1371 } 1372 }, 1373 computeWorldVertices: function (x, y, slot, worldVertices) { 1374 var bone = slot.bone; 1375 x += bone.worldX; 1376 y += bone.worldY; 1377 var m00 = bone.m00, m01 = bone.m01, m10 = bone.m10, m11 = bone.m11; 1378 var vertices = this.vertices; 1379 var verticesCount = vertices.length; 1380 if (slot.attachmentVertices.length == verticesCount) vertices = slot.attachmentVertices; 1381 for (var i = 0; i < verticesCount; i += 2) { 1382 var vx = vertices[i]; 1383 var vy = vertices[i + 1]; 1384 worldVertices[i] = vx * m00 + vy * m01 + x; 1385 worldVertices[i + 1] = vx * m10 + vy * m11 + y; 1386 } 1387 } 1388}; 1389 1390spine.SkinnedMeshAttachment = function (name) { 1391 this.name = name; 1392}; 1393spine.SkinnedMeshAttachment.prototype = { 1394 type: spine.AttachmentType.skinnedmesh, 1395 bones: null, 1396 weights: null, 1397 uvs: null, 1398 regionUVs: null, 1399 triangles: null, 1400 hullLength: 0, 1401 r: 1, g: 1, b: 1, a: 1, 1402 path: null, 1403 rendererObject: null, 1404 regionU: 0, regionV: 0, regionU2: 0, regionV2: 0, regionRotate: false, 1405 regionOffsetX: 0, regionOffsetY: 0, 1406 regionWidth: 0, regionHeight: 0, 1407 regionOriginalWidth: 0, regionOriginalHeight: 0, 1408 edges: null, 1409 width: 0, height: 0, 1410 updateUVs: function (u, v, u2, v2, rotate) { 1411 var width = this.regionU2 - this.regionU, height = this.regionV2 - this.regionV; 1412 var n = this.regionUVs.length; 1413 if (!this.uvs || this.uvs.length != n) { 1414 this.uvs = new spine.Float32Array(n); 1415 } 1416 if (this.regionRotate) { 1417 for (var i = 0; i < n; i += 2) { 1418 this.uvs[i] = this.regionU + this.regionUVs[i + 1] * width; 1419 this.uvs[i + 1] = this.regionV + height - this.regionUVs[i] * height; 1420 } 1421 } else { 1422 for (var i = 0; i < n; i += 2) { 1423 this.uvs[i] = this.regionU + this.regionUVs[i] * width; 1424 this.uvs[i + 1] = this.regionV + this.regionUVs[i + 1] * height; 1425 } 1426 } 1427 }, 1428 computeWorldVertices: function (x, y, slot, worldVertices) { 1429 var skeletonBones = slot.bone.skeleton.bones; 1430 var weights = this.weights; 1431 var bones = this.bones; 1432 1433 var w = 0, v = 0, b = 0, f = 0, n = bones.length, nn; 1434 var wx, wy, bone, vx, vy, weight; 1435 if (!slot.attachmentVertices.length) { 1436 for (; v < n; w += 2) { 1437 wx = 0; 1438 wy = 0; 1439 nn = bones[v++] + v; 1440 for (; v < nn; v++, b += 3) { 1441 bone = skeletonBones[bones[v]]; 1442 vx = weights[b]; 1443 vy = weights[b + 1]; 1444 weight = weights[b + 2]; 1445 wx += (vx * bone.m00 + vy * bone.m01 + bone.worldX) * weight; 1446 wy += (vx * bone.m10 + vy * bone.m11 + bone.worldY) * weight; 1447 } 1448 worldVertices[w] = wx + x; 1449 worldVertices[w + 1] = wy + y; 1450 } 1451 } else { 1452 var ffd = slot.attachmentVertices; 1453 for (; v < n; w += 2) { 1454 wx = 0; 1455 wy = 0; 1456 nn = bones[v++] + v; 1457 for (; v < nn; v++, b += 3, f += 2) { 1458 bone = skeletonBones[bones[v]]; 1459 vx = weights[b] + ffd[f]; 1460 vy = weights[b + 1] + ffd[f + 1]; 1461 weight = weights[b + 2]; 1462 wx += (vx * bone.m00 + vy * bone.m01 + bone.worldX) * weight; 1463 wy += (vx * bone.m10 + vy * bone.m11 + bone.worldY) * weight; 1464 } 1465 worldVertices[w] = wx + x; 1466 worldVertices[w + 1] = wy + y; 1467 } 1468 } 1469 } 1470}; 1471 1472spine.BoundingBoxAttachment = function (name) { 1473 this.name = name; 1474 this.vertices = []; 1475}; 1476spine.BoundingBoxAttachment.prototype = { 1477 type: spine.AttachmentType.boundingbox, 1478 computeWorldVertices: function (x, y, bone, worldVertices) { 1479 x += bone.worldX; 1480 y += bone.worldY; 1481 var m00 = bone.m00, m01 = bone.m01, m10 = bone.m10, m11 = bone.m11; 1482 var vertices = this.vertices; 1483 for (var i = 0, n = vertices.length; i < n; i += 2) { 1484 var px = vertices[i]; 1485 var py = vertices[i + 1]; 1486 worldVertices[i] = px * m00 + py * m01 + x; 1487 worldVertices[i + 1] = px * m10 + py * m11 + y; 1488 } 1489 } 1490}; 1491 1492spine.AnimationStateData = function (skeletonData) { 1493 this.skeletonData = skeletonData; 1494 this.animationToMixTime = {}; 1495}; 1496spine.AnimationStateData.prototype = { 1497 defaultMix: 0, 1498 setMixByName: function (fromName, toName, duration) { 1499 var from = this.skeletonData.findAnimation(fromName); 1500 if (!from) throw "Animation not found: " + fromName; 1501 var to = this.skeletonData.findAnimation(toName); 1502 if (!to) throw "Animation not found: " + toName; 1503 this.setMix(from, to, duration); 1504 }, 1505 setMix: function (from, to, duration) { 1506 this.animationToMixTime[from.name + ":" + to.name] = duration; 1507 }, 1508 getMix: function (from, to) { 1509 var key = from.name + ":" + to.name; 1510 return this.animationToMixTime.hasOwnProperty(key) ? this.animationToMixTime[key] : this.defaultMix; 1511 } 1512}; 1513 1514spine.TrackEntry = function () {}; 1515spine.TrackEntry.prototype = { 1516 next: null, previous: null, 1517 animation: null, 1518 loop: false, 1519 delay: 0, time: 0, lastTime: -1, endTime: 0, 1520 timeScale: 1, 1521 mixTime: 0, mixDuration: 0, mix: 1, 1522 onStart: null, onEnd: null, onComplete: null, onEvent: null 1523}; 1524 1525spine.AnimationState = function (stateData) { 1526 this.data = stateData; 1527 this.tracks = []; 1528 this.events = []; 1529}; 1530spine.AnimationState.prototype = { 1531 onStart: null, 1532 onEnd: null, 1533 onComplete: null, 1534 onEvent: null, 1535 timeScale: 1, 1536 update: function (delta) { 1537 delta *= this.timeScale; 1538 for (var i = 0; i < this.tracks.length; i++) { 1539 var current = this.tracks[i]; 1540 if (!current) continue; 1541 1542 current.time += delta * current.timeScale; 1543 if (current.previous) { 1544 var previousDelta = delta * current.previous.timeScale; 1545 current.previous.time += previousDelta; 1546 current.mixTime += previousDelta; 1547 } 1548 1549 var next = current.next; 1550 if (next) { 1551 next.time = current.lastTime - next.delay; 1552 if (next.time >= 0) this.setCurrent(i, next); 1553 } else { 1554 // End non-looping animation when it reaches its end time and there is no next entry. 1555 if (!current.loop && current.lastTime >= current.endTime) this.clearTrack(i); 1556 } 1557 } 1558 }, 1559 apply: function (skeleton) { 1560 for (var i = 0; i < this.tracks.length; i++) { 1561 var current = this.tracks[i]; 1562 if (!current) continue; 1563 1564 this.events.length = 0; 1565 1566 var time = current.time; 1567 var lastTime = current.lastTime; 1568 var endTime = current.endTime; 1569 var loop = current.loop; 1570 if (!loop && time > endTime) time = endTime; 1571 1572 var previous = current.previous; 1573 if (!previous) { 1574 if (current.mix == 1) 1575 current.animation.apply(skeleton, current.lastTime, time, loop, this.events); 1576 else 1577 current.animation.mix(skeleton, current.lastTime, time, loop, this.events, current.mix); 1578 } else { 1579 var previousTime = previous.time; 1580 if (!previous.loop && previousTime > previous.endTime) previousTime = previous.endTime; 1581 previous.animation.apply(skeleton, previousTime, previousTime, previous.loop, null); 1582 1583 var alpha = current.mixTime / current.mixDuration * current.mix; 1584 if (alpha >= 1) { 1585 alpha = 1; 1586 current.previous = null; 1587 } 1588 current.animation.mix(skeleton, current.lastTime, time, loop, this.events, alpha); 1589 } 1590 1591 for (var ii = 0, nn = this.events.length; ii < nn; ii++) { 1592 var event = this.events[ii]; 1593 if (current.onEvent) current.onEvent(i, event); 1594 if (this.onEvent) this.onEvent(i, event); 1595 } 1596 1597 // Check if completed the animation or a loop iteration. 1598 if (loop ? (lastTime % endTime > time % endTime) : (lastTime < endTime && time >= endTime)) { 1599 var count = Math.floor(time / endTime); 1600 if (current.onComplete) current.onComplete(i, count); 1601 if (this.onComplete) this.onComplete(i, count); 1602 } 1603 1604 current.lastTime = current.time; 1605 } 1606 }, 1607 clearTracks: function () { 1608 for (var i = 0, n = this.tracks.length; i < n; i++) 1609 this.clearTrack(i); 1610 this.tracks.length = 0; 1611 }, 1612 clearTrack: function (trackIndex) { 1613 if (trackIndex >= this.tracks.length) return; 1614 var current = this.tracks[trackIndex]; 1615 if (!current) return; 1616 1617 if (current.onEnd) current.onEnd(trackIndex); 1618 if (this.onEnd) this.onEnd(trackIndex); 1619 1620 this.tracks[trackIndex] = null; 1621 }, 1622 _expandToIndex: function (index) { 1623 if (index < this.tracks.length) return this.tracks[index]; 1624 while (index >= this.tracks.length) 1625 this.tracks.push(null); 1626 return null; 1627 }, 1628 setCurrent: function (index, entry) { 1629 var current = this._expandToIndex(index); 1630 if (current) { 1631 var previous = current.previous; 1632 current.previous = null; 1633 1634 if (current.onEnd) current.onEnd(index); 1635 if (this.onEnd) this.onEnd(index); 1636 1637 entry.mixDuration = this.data.getMix(current.animation, entry.animation); 1638 if (entry.mixDuration > 0) { 1639 entry.mixTime = 0; 1640 // If a mix is in progress, mix from the closest animation. 1641 if (previous && current.mixTime / current.mixDuration < 0.5) 1642 entry.previous = previous; 1643 else 1644 entry.previous = current; 1645 } 1646 } 1647 1648 this.tracks[index] = entry; 1649 1650 if (entry.onStart) entry.onStart(index); 1651 if (this.onStart) this.onStart(index); 1652 }, 1653 setAnimationByName: function (trackIndex, animationName, loop) { 1654 var animation = this.data.skeletonData.findAnimation(animationName); 1655 if (!animation) throw "Animation not found: " + animationName; 1656 return this.setAnimation(trackIndex, animation, loop); 1657 }, 1658 /** Set the current animation. Any queued animations are cleared. */ 1659 setAnimation: function (trackIndex, animation, loop) { 1660 var entry = new spine.TrackEntry(); 1661 entry.animation = animation; 1662 entry.loop = loop; 1663 entry.endTime = animation.duration; 1664 this.setCurrent(trackIndex, entry); 1665 return entry; 1666 }, 1667 addAnimationByName: function (trackIndex, animationName, loop, delay) { 1668 var animation = this.data.skeletonData.findAnimation(animationName); 1669 if (!animation) throw "Animation not found: " + animationName; 1670 return this.addAnimation(trackIndex, animation, loop, delay); 1671 }, 1672 /** Adds an animation to be played delay seconds after the current or last queued animation. 1673 * @param delay May be <= 0 to use duration of previous animation minus any mix duration plus the negative delay. */ 1674 addAnimation: function (trackIndex, animation, loop, delay) { 1675 var entry = new spine.TrackEntry(); 1676 entry.animation = animation; 1677 entry.loop = loop; 1678 entry.endTime = animation.duration; 1679 1680 var last = this._expandToIndex(trackIndex); 1681 if (last) { 1682 while (last.next) 1683 last = last.next; 1684 last.next = entry; 1685 } else 1686 this.tracks[trackIndex] = entry; 1687 1688 if (delay <= 0) { 1689 if (last) 1690 delay += last.endTime - this.data.getMix(last.animation, animation); 1691 else
1692 delay = 0; 1693 } 1694 entry.delay = delay; 1695 1696 return entry; 1697 }, 1698 /** May be null. */ 1699 getCurrent: function (trackIndex) { 1700 if (trackIndex >= this.tracks.length) return null; 1701 return this.tracks[trackIndex]; 1702 } 1703}; 1704 1705spine.SkeletonJson = function (attachmentLoader) { 1706 this.attachmentLoader = attachmentLoader; 1707}; 1708spine.SkeletonJson.prototype = { 1709 scale: 1, 1710 readSkeletonData: function (root, name) { 1711 var skeletonData = new spine.SkeletonData(); 1712 skeletonData.name = name; 1713 1714 // Skeleton. 1715 var skeletonMap = root["skeleton"]; 1716 if (skeletonMap) { 1717 skeletonData.hash = skeletonMap["hash"]; 1718 skeletonData.version = skeletonMap["spine"]; 1719 skeletonData.width = skeletonMap["width"] || 0; 1720 skeletonData.height = skeletonMap["height"] || 0; 1721 } 1722 1723 // Bones. 1724 var bones = root["bones"]; 1725 for (var i = 0, n = bones.length; i < n; i++) { 1726 var boneMap = bones[i]; 1727 var parent = null; 1728 if (boneMap["parent"]) { 1729 parent = skeletonData.findBone(boneMap["parent"]); 1730 if (!parent) throw "Parent bone not found: " + boneMap["parent"]; 1731 } 1732 var boneData = new spine.BoneData(boneMap["name"], parent); 1733 boneData.length = (boneMap["length"] || 0) * this.scale; 1734 boneData.x = (boneMap["x"] || 0) * this.scale; 1735 boneData.y = (boneMap["y"] || 0) * this.scale; 1736 boneData.rotation = (boneMap["rotation"] || 0); 1737 boneData.scaleX = boneMap.hasOwnProperty("scaleX") ? boneMap["scaleX"] : 1; 1738 boneData.scaleY = boneMap.hasOwnProperty("scaleY") ? boneMap["scaleY"] : 1; 1739 boneData.inheritScale = boneMap.hasOwnProperty("inheritScale") ? boneMap["inheritScale"] : true; 1740 boneData.inheritRotation = boneMap.hasOwnProperty("inheritRotation") ? boneMap["inheritRotation"] : true; 1741 skeletonData.bones.push(boneData); 1742 } 1743 1744 // IK constraints. 1745 var ik = root["ik"]; 1746 if (ik) { 1747 for (var i = 0, n = ik.length; i < n; i++) { 1748 var ikMap = ik[i]; 1749 var ikConstraintData = new spine.IkConstraintData(ikMap["name"]); 1750 1751 var bones = ikMap["bones"]; 1752 for (var ii = 0, nn = bones.length; ii < nn; ii++) { 1753 var bone = skeletonData.findBone(bones[ii]); 1754 if (!bone) throw "IK bone not found: " + bones[ii]; 1755 ikConstraintData.bones.push(bone); 1756 } 1757 1758 ikConstraintData.target = skeletonData.findBone(ikMap["target"]); 1759 if (!ikConstraintData.target) throw "Target bone not found: " + ikMap["target"]; 1760 1761 ikConstraintData.bendDirection = (!ikMap.hasOwnProperty("bendPositive") || ikMap["bendPositive"]) ? 1 : -1; 1762 ikConstraintData.mix = ikMap.hasOwnProperty("mix") ? ikMap["mix"] : 1; 1763 1764 skeletonData.ikConstraints.push(ikConstraintData); 1765 } 1766 } 1767 1768 // Slots. 1769 var slots = root["slots"]; 1770 for (var i = 0, n = slots.length; i < n; i++) { 1771 var slotMap = slots[i]; 1772 var boneData = skeletonData.findBone(slotMap["bone"]); 1773 if (!boneData) throw "Slot bone not found: " + slotMap["bone"]; 1774 var slotData = new spine.SlotData(slotMap["name"], boneData); 1775 1776 var color = slotMap["color"]; 1777 if (color) { 1778 slotData.r = this.toColor(color, 0); 1779 slotData.g = this.toColor(color, 1); 1780 slotData.b = this.toColor(color, 2); 1781 slotData.a = this.toColor(color, 3); 1782 } 1783 1784 slotData.attachmentName = slotMap["attachment"]; 1785 slotData.blendMode = spine.BlendMode[slotMap["blend"] || "normal"]; 1786 1787 skeletonData.slots.push(slotData); 1788 } 1789 1790 // Skins. 1791 var skins = root["skins"]; 1792 for (var skinName in skins) { 1793 if (!skins.hasOwnProperty(skinName)) continue; 1794 var skinMap = skins[skinName]; 1795 var skin = new spine.Skin(skinName); 1796 for (var slotName in skinMap) { 1797 if (!skinMap.hasOwnProperty(slotName)) continue; 1798 var slotIndex = skeletonData.findSlotIndex(slotName); 1799 var slotEntry = skinMap[slotName]; 1800 for (var attachmentName in slotEntry) { 1801 if (!slotEntry.hasOwnProperty(attachmentName)) continue; 1802 var attachment = this.readAttachment(skin, attachmentName, slotEntry[attachmentName]); 1803 if (attachment) skin.addAttachment(slotIndex, attachmentName, attachment); 1804 } 1805 } 1806 skeletonData.skins.push(skin); 1807 if (skin.name == "default") skeletonData.defaultSkin = skin; 1808 } 1809 1810 // Events. 1811 var events = root["events"]; 1812 for (var eventName in events) { 1813 if (!events.hasOwnProperty(eventName)) continue; 1814 var eventMap = events[eventName]; 1815 var eventData = new spine.EventData(eventName); 1816 eventData.intValue = eventMap["int"] || 0; 1817 eventData.floatValue = eventMap["float"] || 0; 1818 eventData.stringValue = eventMap["string"] || null; 1819 skeletonData.events.push(eventData); 1820 } 1821 1822 // Animations. 1823 var animations = root["animations"]; 1824 for (var animationName in animations) { 1825 if (!animations.hasOwnProperty(animationName)) continue; 1826 this.readAnimation(animationName, animations[animationName], skeletonData); 1827 } 1828 1829 return skeletonData; 1830 }, 1831 readAttachment: function (skin, name, map) { 1832 name = map["name"] || name; 1833 1834 var type = spine.AttachmentType[map["type"] || "region"]; 1835 var path = map["path"] || name; 1836 1837 var scale = this.scale; 1838 if (type == spine.AttachmentType.region) { 1839 var region = this.attachmentLoader.newRegionAttachment(skin, name, path); 1840 if (!region) return null; 1841 region.path = path; 1842 region.x = (map["x"] || 0) * scale; 1843 region.y = (map["y"] || 0) * scale; 1844 region.scaleX = map.hasOwnProperty("scaleX") ? map["scaleX"] : 1; 1845 region.scaleY = map.hasOwnProperty("scaleY") ? map["scaleY"] : 1; 1846 region.rotation = map["rotation"] || 0; 1847 region.width = (map["width"] || 0) * scale; 1848 region.height = (map["height"] || 0) * scale; 1849 1850 var color = map["color"]; 1851 if (color) { 1852 region.r = this.toColor(color, 0); 1853 region.g = this.toColor(color, 1); 1854 region.b = this.toColor(color, 2); 1855 region.a = this.toColor(color, 3); 1856 } 1857 1858 region.updateOffset(); 1859 return region; 1860 } else if (type == spine.AttachmentType.mesh) { 1861 var mesh = this.attachmentLoader.newMeshAttachment(skin, name, path); 1862 if (!mesh) return null; 1863 mesh.path = path; 1864 mesh.vertices = this.getFloatArray(map, "vertices", scale); 1865 mesh.triangles = this.getIntArray(map, "triangles"); 1866 mesh.regionUVs = this.getFloatArray(map, "uvs", 1); 1867 mesh.updateUVs(); 1868 1869 color = map["color"]; 1870 if (color) { 1871 mesh.r = this.toColor(color, 0); 1872 mesh.g = this.toColor(color, 1); 1873 mesh.b = this.toColor(color, 2); 1874 mesh.a = this.toColor(color, 3); 1875 } 1876 1877 mesh.hullLength = (map["hull"] || 0) * 2; 1878 if (map["edges"]) mesh.edges = this.getIntArray(map, "edges"); 1879 mesh.width = (map["width"] || 0) * scale; 1880 mesh.height = (map["height"] || 0) * scale; 1881 return mesh; 1882 } else if (type == spine.AttachmentType.skinnedmesh) { 1883 var mesh = this.attachmentLoader.newSkinnedMeshAttachment(skin, name, path); 1884 if (!mesh) return null; 1885 mesh.path = path; 1886 1887 var uvs = this.getFloatArray(map, "uvs", 1); 1888 var vertices = this.getFloatArray(map, "vertices", 1); 1889 var weights = []; 1890 var bones = []; 1891 for (var i = 0, n = vertices.length; i < n; ) { 1892 var boneCount = vertices[i++] | 0; 1893 bones[bones.length] = boneCount; 1894 for (var nn = i + boneCount * 4; i < nn; ) { 1895 bones[bones.length] = vertices[i]; 1896 weights[weights.length] = vertices[i + 1] * scale; 1897 weights[weights.length] = vertices[i + 2] * scale; 1898 weights[weights.length] = vertices[i + 3]; 1899 i += 4; 1900 } 1901 } 1902 mesh.bones = bones; 1903 mesh.weights = weights; 1904 mesh.triangles = this.getIntArray(map, "triangles"); 1905 mesh.regionUVs = uvs; 1906 mesh.updateUVs(); 1907 1908 color = map["color"]; 1909 if (color) { 1910 mesh.r = this.toColor(color, 0); 1911 mesh.g = this.toColor(color, 1); 1912 mesh.b = this.toColor(color, 2); 1913 mesh.a = this.toColor(color, 3); 1914 } 1915 1916 mesh.hullLength = (map["hull"] || 0) * 2; 1917 if (map["edges"]) mesh.edges = this.getIntArray(map, "edges"); 1918 mesh.width = (map["width"] || 0) * scale; 1919 mesh.height = (map["height"] || 0) * scale; 1920 return mesh; 1921 } else if (type == spine.AttachmentType.boundingbox) { 1922 var attachment = this.attachmentLoader.newBoundingBoxAttachment(skin, name); 1923 var vertices = map["vertices"]; 1924 for (var i = 0, n = vertices.length; i < n; i++) 1925 attachment.vertices.push(vertices[i] * scale); 1926 return attachment; 1927 } 1928 throw "Unknown attachment type: " + type; 1929 }, 1930 readAnimation: function (name, map, skeletonData) { 1931 var timelines = []; 1932 var duration = 0; 1933 1934 var slots = map["slots"]; 1935 for (var slotName in slots) { 1936 if (!slots.hasOwnProperty(slotName)) continue; 1937 var slotMap = slots[slotName]; 1938 var slotIndex = skeletonData.findSlotIndex(slotName); 1939 1940 for (var timelineName in slotMap) { 1941 if (!slotMap.hasOwnProperty(timelineName)) continue; 1942 var values = slotMap[timelineName]; 1943 if (timelineName == "color") { 1944 var timeline = new spine.ColorTimeline(values.length); 1945 timeline.slotIndex = slotIndex; 1946 1947 var frameIndex = 0; 1948 for (var i = 0, n = values.length; i < n; i++) { 1949 var valueMap = values[i]; 1950 var color = valueMap["color"]; 1951 var r = this.toColor(color, 0); 1952 var g = this.toColor(color, 1); 1953 var b = this.toColor(color, 2); 1954 var a = this.toColor(color, 3);
1955 timeline.setFrame(frameIndex, valueMap["time"], r, g, b, a); 1956 this.readCurve(timeline, frameIndex, valueMap); 1957 frameIndex++; 1958 } 1959 timelines.push(timeline); 1960 duration = Math.max(duration, timeline.frames[timeline.getFrameCount() * 5 - 5]); 1961 1962 } else if (timelineName == "attachment") { 1963 var timeline = new spine.AttachmentTimeline(values.length); 1964 timeline.slotIndex = slotIndex; 1965 1966 var frameIndex = 0; 1967 for (var i = 0, n = values.length; i < n; i++) { 1968 var valueMap = values[i]; 1969 timeline.setFrame(frameIndex++, valueMap["time"], valueMap["name"]); 1970 } 1971 timelines.push(timeline); 1972 duration = Math.max(duration, timeline.frames[timeline.getFrameCount() - 1]); 1973 1974 } else 1975 throw "Invalid timeline type for a slot: " + timelineName + " (" + slotName + ")"; 1976 } 1977 } 1978 1979 var bones = map["bones"]; 1980 for (var boneName in bones) { 1981 if (!bones.hasOwnProperty(boneName)) continue; 1982 var boneIndex = skeletonData.findBoneIndex(boneName); 1983 if (boneIndex == -1) throw "Bone not found: " + boneName; 1984 var boneMap = bones[boneName]; 1985 1986 for (var timelineName in boneMap) { 1987 if (!boneMap.hasOwnProperty(timelineName)) continue; 1988 var values = boneMap[timelineName]; 1989 if (timelineName == "rotate") { 1990 var timeline = new spine.RotateTimeline(values.length); 1991 timeline.boneIndex = boneIndex; 1992 1993 var frameIndex = 0; 1994 for (var i = 0, n = values.length; i < n; i++) { 1995 var valueMap = values[i]; 1996 timeline.setFrame(frameIndex, valueMap["time"], valueMap["angle"]); 1997 this.readCurve(timeline, frameIndex, valueMap); 1998 frameIndex++; 1999 } 2000 timelines.push(timeline); 2001 duration = Math.max(duration, timeline.frames[timeline.getFrameCount() * 2 - 2]); 2002 2003 } else if (timelineName == "translate" || timelineName == "scale") { 2004 var timeline; 2005 var timelineScale = 1; 2006 if (timelineName == "scale") 2007 timeline = new spine.ScaleTimeline(values.length); 2008 else { 2009 timeline = new spine.TranslateTimeline(values.length); 2010 timelineScale = this.scale; 2011 } 2012 timeline.boneIndex = boneIndex; 2013 2014 var frameIndex = 0; 2015 for (var i = 0, n = values.length; i < n; i++) { 2016 var valueMap = values[i]; 2017 var x = (valueMap["x"] || 0) * timelineScale; 2018 var y = (valueMap["y"] || 0) * timelineScale; 2019 timeline.setFrame(frameIndex, valueMap["time"], x, y); 2020 this.readCurve(timeline, frameIndex, valueMap); 2021 frameIndex++; 2022 } 2023 timelines.push(timeline); 2024 duration = Math.max(duration, timeline.frames[timeline.getFrameCount() * 3 - 3]); 2025 2026 } else if (timelineName == "flipX" || timelineName == "flipY") { 2027 var x = timelineName == "flipX"; 2028 var timeline = x ? new spine.FlipXTimeline(values.length) : new spine.FlipYTimeline(values.length); 2029 timeline.boneIndex = boneIndex; 2030 2031 var field = x ? "x" : "y"; 2032 var frameIndex = 0; 2033 for (var i = 0, n = values.length; i < n; i++) { 2034 var valueMap = values[i]; 2035 timeline.setFrame(frameIndex, valueMap["time"], valueMap[field] || false); 2036 frameIndex++; 2037 } 2038 timelines.push(timeline); 2039 duration = Math.max(duration, timeline.frames[timeline.getFrameCount() * 2 - 2]); 2040 } else 2041 throw "Invalid timeline type for a bone: " + timelineName + " (" + boneName + ")"; 2042 } 2043 } 2044 2045 var ikMap = map["ik"]; 2046 for (var ikConstraintName in ikMap) { 2047 if (!ikMap.hasOwnProperty(ikConstraintName)) continue; 2048 var ikConstraint = skeletonData.findIkConstraint(ikConstraintName); 2049 var values = ikMap[ikConstraintName]; 2050 var timeline = new spine.IkConstraintTimeline(values.length); 2051 timeline.ikConstraintIndex = skeletonData.ikConstraints.indexOf(ikConstraint); 2052 var frameIndex = 0; 2053 for (var i = 0, n = values.length; i < n; i++) { 2054 var valueMap = values[i]; 2055 var mix = valueMap.hasOwnProperty("mix") ? valueMap["mix"] : 1; 2056 var bendDirection = (!valueMap.hasOwnProperty("bendPositive") || valueMap["bendPositive"]) ? 1 : -1; 2057 timeline.setFrame(frameIndex, valueMap["time"], mix, bendDirection); 2058 this.readCurve(timeline, frameIndex, valueMap); 2059 frameIndex++; 2060 } 2061 timelines.push(timeline); 2062 duration = Math.max(duration, timeline.frames[timeline.frameCount * 3 - 3]); 2063 } 2064 2065 var ffd = map["ffd"]; 2066 for (var skinName in ffd) { 2067 var skin = skeletonData.findSkin(skinName); 2068 var slotMap = ffd[skinName]; 2069 for (slotName in slotMap) { 2070 var slotIndex = skeletonData.findSlotIndex(slotName); 2071 var meshMap = slotMap[slotName]; 2072 for (var meshName in meshMap) { 2073 var values = meshMap[meshName]; 2074 var timeline = new spine.FfdTimeline(values.length); 2075 var attachment = skin.getAttachment(slotIndex, meshName); 2076 if (!attachment) throw "FFD attachment not found: " + meshName; 2077 timeline.slotIndex = slotIndex; 2078 timeline.attachment = attachment; 2079 2080 var isMesh = attachment.type == spine.AttachmentType.mesh; 2081 var vertexCount; 2082 if (isMesh) 2083 vertexCount = attachment.vertices.length; 2084 else 2085 vertexCount = attachment.weights.length / 3 * 2; 2086 2087 var frameIndex = 0; 2088 for (var i = 0, n = values.length; i < n; i++) { 2089 var valueMap = values[i]; 2090 var vertices; 2091 if (!valueMap["vertices"]) { 2092 if (isMesh) 2093 vertices = attachment.vertices; 2094 else { 2095 vertices = []; 2096 vertices.length = vertexCount; 2097 } 2098 } else { 2099 var verticesValue = valueMap["vertices"]; 2100 var vertices = []; 2101 vertices.length = vertexCount; 2102 var start = valueMap["offset"] || 0; 2103 var nn = verticesValue.length; 2104 if (this.scale == 1) { 2105 for (var ii = 0; ii < nn; ii++) 2106 vertices[ii + start] = verticesValue[ii]; 2107 } else { 2108 for (var ii = 0; ii < nn; ii++) 2109 vertices[ii + start] = verticesValue[ii] * this.scale; 2110 } 2111 if (isMesh) { 2112 var meshVertices = attachment.vertices; 2113 for (var ii = 0, nn = vertices.length; ii < nn; ii++) 2114 vertices[ii] += meshVertices[ii]; 2115 } 2116 } 2117
2118 timeline.setFrame(frameIndex, valueMap["time"], vertices); 2119 this.readCurve(timeline, frameIndex, valueMap); 2120 frameIndex++; 2121 } 2122 timelines[timelines.length] = timeline; 2123 duration = Math.max(duration, timeline.frames[timeline.frameCount - 1]); 2124 } 2125 } 2126 } 2127 2128 var drawOrderValues = map["drawOrder"]; 2129 if (!drawOrderValues) drawOrderValues = map["draworder"]; 2130 if (drawOrderValues) { 2131 var timeline = new spine.DrawOrderTimeline(drawOrderValues.length); 2132 var slotCount = skeletonData.slots.length; 2133 var frameIndex = 0; 2134 for (var i = 0, n = drawOrderValues.length; i < n; i++) { 2135 var drawOrderMap = drawOrderValues[i]; 2136 var drawOrder = null; 2137 if (drawOrderMap["offsets"]) { 2138 drawOrder = []; 2139 drawOrder.length = slotCount; 2140 for (var ii = slotCount - 1; ii >= 0; ii--) 2141 drawOrder[ii] = -1; 2142 var offsets = drawOrderMap["offsets"]; 2143 var unchanged = []; 2144 unchanged.length = slotCount - offsets.length; 2145 var originalIndex = 0, unchangedIndex = 0; 2146 for (var ii = 0, nn = offsets.length; ii < nn; ii++) { 2147 var offsetMap = offsets[ii]; 2148 var slotIndex = skeletonData.findSlotIndex(offsetMap["slot"]); 2149 if (slotIndex == -1) throw "Slot not found: " + offsetMap["slot"]; 2150 // Collect unchanged items. 2151 while (originalIndex != slotIndex) 2152 unchanged[unchangedIndex++] = originalIndex++; 2153 // Set changed items. 2154 drawOrder[originalIndex + offsetMap["offset"]] = originalIndex++; 2155 } 2156 // Collect remaining unchanged items. 2157 while (originalIndex < slotCount) 2158 unchanged[unchangedIndex++] = originalIndex++; 2159 // Fill in unchanged items. 2160 for (var ii = slotCount - 1; ii >= 0; ii--) 2161 if (drawOrder[ii] == -1) drawOrder[ii] = unchanged[--unchangedIndex]; 2162 } 2163 timeline.setFrame(frameIndex++, drawOrderMap["time"], drawOrder); 2164 } 2165 timelines.push(timeline); 2166 duration = Math.max(duration, timeline.frames[timeline.getFrameCount() - 1]); 2167 } 2168 2169 var events = map["events"]; 2170 if (events) { 2171 var timeline = new spine.EventTimeline(events.length); 2172 var frameIndex = 0; 2173 for (var i = 0, n = events.length; i < n; i++) { 2174 var eventMap = events[i]; 2175 var eventData = skeletonData.findEvent(eventMap["name"]); 2176 if (!eventData) throw "Event not found: " + eventMap["name"]; 2177 var event = new spine.Event(eventData); 2178 event.intValue = eventMap.hasOwnProperty("int") ? eventMap["int"] : eventData.intValue; 2179 event.floatValue = eventMap.hasOwnProperty("float") ? eventMap["float"] : eventData.floatValue; 2180 event.stringValue = eventMap.hasOwnProperty("string") ? eventMap["string"] : eventData.stringValue; 2181 timeline.setFrame(frameIndex++, eventMap["time"], event); 2182 } 2183 timelines.push(timeline); 2184 duration = Math.max(duration, timeline.frames[timeline.getFrameCount() - 1]); 2185 } 2186 2187 skeletonData.animations.push(new spine.Animation(name, timelines, duration)); 2188 }, 2189 readCurve: function (timeline, frameIndex, valueMap) { 2190 var curve = valueMap["curve"]; 2191 if (!curve) 2192 timeline.curves.setLinear(frameIndex); 2193 else if (curve == "stepped") 2194 timeline.curves.setStepped(frameIndex); 2195 else if (curve instanceof Array) 2196 timeline.curves.setCurve(frameIndex, curve[0], curve[1], curve[2], curve[3]); 2197 }, 2198 toColor: function (hexString, colorIndex) { 2199 if (hexString.length != 8) throw "Color hexidecimal length must be 8, recieved: " + hexString; 2200 return parseInt(hexString.substring(colorIndex * 2, (colorIndex * 2) + 2), 16) / 255; 2201 }, 2202 getFloatArray: function (map, name, scale) { 2203 var list = map[name]; 2204 var values = new spine.Float32Array(list.length); 2205 var i = 0, n = list.length; 2206 if (scale == 1) { 2207 for (; i < n; i++) 2208 values[i] = list[i]; 2209 } else { 2210 for (; i < n; i++) 2211 values[i] = list[i] * scale; 2212 } 2213 return values; 2214 }, 2215 getIntArray: function (map, name) { 2216 var list = map[name]; 2217 var values = new spine.Uint16Array(list.length); 2218 for (var i = 0, n = list.length; i < n; i++) 2219 values[i] = list[i] | 0; 2220 return values; 2221 } 2222}; 2223 2224spine.Atlas = function (atlasText, textureLoader) { 2225 this.textureLoader = textureLoader; 2226 this.pages = []; 2227 this.regions = []; 2228 2229 var reader = new spine.AtlasReader(atlasText); 2230 var tuple = []; 2231 tuple.length = 4; 2232 var page = null; 2233 while (true) { 2234 var line = reader.readLine(); 2235 if (line === null) break; 2236 line = reader.trim(line); 2237 if (!line.length) 2238 page = null; 2239 else if (!page) { 2240 page = new spine.AtlasPage(); 2241 page.name = line; 2242 2243 if (reader.readTuple(tuple) == 2) { // size is only optional for an atlas packed with an old TexturePacker. 2244 page.width = parseInt(tuple[0]); 2245 page.height = parseInt(tuple[1]); 2246 reader.readTuple(tuple); 2247 } 2248 page.format = spine.Atlas.Format[tuple[0]]; 2249 2250 reader.readTuple(tuple); 2251 page.minFilter = spine.Atlas.TextureFilter[tuple[0]]; 2252 page.magFilter = spine.Atlas.TextureFilter[tuple[1]]; 2253 2254 var direction = reader.readValue(); 2255 page.uWrap = spine.Atlas.TextureWrap.clampToEdge; 2256 page.vWrap = spine.Atlas.TextureWrap.clampToEdge; 2257 if (direction == "x") 2258 page.uWrap = spine.Atlas.TextureWrap.repeat; 2259 else if (direction == "y") 2260 page.vWrap = spine.Atlas.TextureWrap.repeat; 2261 else if (direction == "xy") 2262 page.uWrap = page.vWrap = spine.Atlas.TextureWrap.repeat; 2263 2264 textureLoader.load(page, line, this); 2265 2266 this.pages.push(page); 2267 2268 } else { 2269 var region = new spine.AtlasRegion(); 2270 region.name = line; 2271 region.page = page; 2272 2273 region.rotate = reader.readValue() == "true"; 2274 2275 reader.readTuple(tuple); 2276 var x = parseInt(tuple[0]); 2277 var y = parseInt(tuple[1]); 2278 2279 reader.readTuple(tuple); 2280 var width = parseInt(tuple[0]); 2281 var height = parseInt(tuple[1]); 2282 2283 region.u = x / page.width; 2284 region.v = y / page.height; 2285 if (region.rotate) { 2286 region.u2 = (x + height) / page.width; 2287 region.v2 = (y + width) / page.height; 2288 } else { 2289 region.u2 = (x + width) / page.width;
vendor: 9,474 bytes, lines 2290-2578
2290 region.v2 = (y + height) / page.height; 2291 } 2292 region.x = x; 2293 region.y = y; 2294 region.width = Math.abs(width); 2295 region.height = Math.abs(height); 2296 2297 if (reader.readTuple(tuple) == 4) { // split is optional 2298 region.splits = [parseInt(tuple[0]), parseInt(tuple[1]), parseInt(tuple[2]), parseInt(tuple[3])]; 2299 2300 if (reader.readTuple(tuple) == 4) { // pad is optional, but only present with splits 2301 region.pads = [parseInt(tuple[0]), parseInt(tuple[1]), parseInt(tuple[2]), parseInt(tuple[3])]; 2302 2303 reader.readTuple(tuple); 2304 } 2305 } 2306 2307 region.originalWidth = parseInt(tuple[0]); 2308 region.originalHeight = parseInt(tuple[1]); 2309 2310 reader.readTuple(tuple); 2311 region.offsetX = parseInt(tuple[0]); 2312 region.offsetY = parseInt(tuple[1]); 2313 2314 region.index = parseInt(reader.readValue()); 2315 2316 this.regions.push(region); 2317 } 2318 } 2319}; 2320spine.Atlas.prototype = { 2321 findRegion: function (name) { 2322 var regions = this.regions; 2323 for (var i = 0, n = regions.length; i < n; i++) 2324 if (regions[i].name == name) return regions[i]; 2325 return null; 2326 }, 2327 dispose: function () { 2328 var pages = this.pages; 2329 for (var i = 0, n = pages.length; i < n; i++) 2330 this.textureLoader.unload(pages[i].rendererObject); 2331 }, 2332 updateUVs: function (page) { 2333 var regions = this.regions; 2334 for (var i = 0, n = regions.length; i < n; i++) { 2335 var region = regions[i]; 2336 if (region.page != page) continue; 2337 region.u = region.x / page.width; 2338 region.v = region.y / page.height; 2339 if (region.rotate) { 2340 region.u2 = (region.x + region.height) / page.width; 2341 region.v2 = (region.y + region.width) / page.height; 2342 } else { 2343 region.u2 = (region.x + region.width) / page.width; 2344 region.v2 = (region.y + region.height) / page.height; 2345 } 2346 } 2347 } 2348}; 2349 2350spine.Atlas.Format = { 2351 alpha: 0, 2352 intensity: 1, 2353 luminanceAlpha: 2, 2354 rgb565: 3, 2355 rgba4444: 4, 2356 rgb888: 5, 2357 rgba8888: 6 2358}; 2359 2360spine.Atlas.TextureFilter = { 2361 nearest: 0, 2362 linear: 1, 2363 mipMap: 2, 2364 mipMapNearestNearest: 3, 2365 mipMapLinearNearest: 4, 2366 mipMapNearestLinear: 5, 2367 mipMapLinearLinear: 6 2368}; 2369 2370spine.Atlas.TextureWrap = { 2371 mirroredRepeat: 0, 2372 clampToEdge: 1, 2373 repeat: 2 2374}; 2375 2376spine.AtlasPage = function () {}; 2377spine.AtlasPage.prototype = { 2378 name: null, 2379 format: null, 2380 minFilter: null, 2381 magFilter: null, 2382 uWrap: null, 2383 vWrap: null, 2384 rendererObject: null, 2385 width: 0, 2386 height: 0 2387}; 2388 2389spine.AtlasRegion = function () {}; 2390spine.AtlasRegion.prototype = { 2391 page: null, 2392 name: null, 2393 x: 0, y: 0, 2394 width: 0, height: 0, 2395 u: 0, v: 0, u2: 0, v2: 0, 2396 offsetX: 0, offsetY: 0, 2397 originalWidth: 0, originalHeight: 0, 2398 index: 0, 2399 rotate: false, 2400 splits: null, 2401 pads: null 2402}; 2403 2404spine.AtlasReader = function (text) { 2405 this.lines = text.split(/\r\n|\r|\n/); 2406}; 2407spine.AtlasReader.prototype = { 2408 index: 0, 2409 trim: function (value) { 2410 return value.replace(/^\s+|\s+$/g, ""); 2411 }, 2412 readLine: function () { 2413 if (this.index >= this.lines.length) return null; 2414 return this.lines[this.index++]; 2415 }, 2416 readValue: function () { 2417 var line = this.readLine(); 2418 var colon = line.indexOf(":"); 2419 if (colon == -1) throw "Invalid line: " + line; 2420 return this.trim(line.substring(colon + 1)); 2421 }, 2422 /** Returns the number of tuple values read (1, 2 or 4). */ 2423 readTuple: function (tuple) { 2424 var line = this.readLine(); 2425 var colon = line.indexOf(":"); 2426 if (colon == -1) throw "Invalid line: " + line; 2427 var i = 0, lastMatch = colon + 1; 2428 for (; i < 3; i++) { 2429 var comma = line.indexOf(",", lastMatch); 2430 if (comma == -1) break; 2431 tuple[i] = this.trim(line.substr(lastMatch, comma - lastMatch)); 2432 lastMatch = comma + 1; 2433 } 2434 tuple[i] = this.trim(line.substring(lastMatch)); 2435 return i + 1; 2436 } 2437}; 2438 2439spine.AtlasAttachmentLoader = function (atlas) { 2440 this.atlas = atlas; 2441}; 2442spine.AtlasAttachmentLoader.prototype = { 2443 newRegionAttachment: function (skin, name, path) { 2444 var region = this.atlas.findRegion(path); 2445 if (!region) throw "Region not found in atlas: " + path + " (region attachment: " + name + ")"; 2446 var attachment = new spine.RegionAttachment(name); 2447 attachment.rendererObject = region; 2448 attachment.setUVs(region.u, region.v, region.u2, region.v2, region.rotate); 2449 attachment.regionOffsetX = region.offsetX; 2450 attachment.regionOffsetY = region.offsetY; 2451 attachment.regionWidth = region.width; 2452 attachment.regionHeight = region.height; 2453 attachment.regionOriginalWidth = region.originalWidth; 2454 attachment.regionOriginalHeight = region.originalHeight; 2455 return attachment; 2456 }, 2457 newMeshAttachment: function (skin, name, path) { 2458 var region = this.atlas.findRegion(path); 2459 if (!region) throw "Region not found in atlas: " + path + " (mesh attachment: " + name + ")"; 2460 var attachment = new spine.MeshAttachment(name); 2461 attachment.rendererObject = region; 2462 attachment.regionU = region.u; 2463 attachment.regionV = region.v; 2464 attachment.regionU2 = region.u2; 2465 attachment.regionV2 = region.v2; 2466 attachment.regionRotate = region.rotate; 2467 attachment.regionOffsetX = region.offsetX; 2468 attachment.regionOffsetY = region.offsetY; 2469 attachment.regionWidth = region.width; 2470 attachment.regionHeight = region.height; 2471 attachment.regionOriginalWidth = region.originalWidth; 2472 attachment.regionOriginalHeight = region.originalHeight; 2473 return attachment; 2474 }, 2475 newSkinnedMeshAttachment: function (skin, name, path) { 2476 var region = this.atlas.findRegion(path); 2477 if (!region) throw "Region not found in atlas: " + path + " (skinned mesh attachment: " + name + ")"; 2478 var attachment = new spine.SkinnedMeshAttachment(name); 2479 attachment.rendererObject = region; 2480 attachment.regionU = region.u; 2481 attachment.regionV = region.v; 2482 attachment.regionU2 = region.u2; 2483 attachment.regionV2 = region.v2; 2484 attachment.regionRotate = region.rotate; 2485 attachment.regionOffsetX = region.offsetX; 2486 attachment.regionOffsetY = region.offsetY; 2487 attachment.regionWidth = region.width; 2488 attachment.regionHeight = region.height; 2489 attachment.regionOriginalWidth = region.originalWidth; 2490 attachment.regionOriginalHeight = region.originalHeight; 2491 return attachment; 2492 }, 2493 newBoundingBoxAttachment: function (skin, name) { 2494 return new spine.BoundingBoxAttachment(name); 2495 } 2496}; 2497spine.SkeletonBounds = function () { 2498 this.polygonPool = []; 2499 this.polygons = []; 2500 this.boundingBoxes = []; 2501}; 2502spine.SkeletonBounds.prototype = { 2503 minX: 0, minY: 0, maxX: 0, maxY: 0, 2504 update: function (skeleton, updateAabb) { 2505 var slots = skeleton.slots; 2506 var slotCount = slots.length; 2507 var x = skeleton.x, y = skeleton.y; 2508 var boundingBoxes = this.boundingBoxes; 2509 var polygonPool = this.polygonPool; 2510 var polygons = this.polygons; 2511 2512 boundingBoxes.length = 0; 2513 for (var i = 0, n = polygons.length; i < n; i++) 2514 polygonPool.push(polygons[i]); 2515 polygons.length = 0; 2516 2517 for (var i = 0; i < slotCount; i++) { 2518 var slot = slots[i]; 2519 var boundingBox = slot.attachment; 2520 if (!boundingBox || boundingBox.type != spine.AttachmentType.boundingbox) continue; 2521 boundingBoxes.push(boundingBox); 2522 2523 var poolCount = polygonPool.length, polygon; 2524 if (poolCount > 0) { 2525 polygon = polygonPool[poolCount - 1]; 2526 polygonPool.splice(poolCount - 1, 1); 2527 } else 2528 polygon = []; 2529 polygons.push(polygon); 2530 2531 polygon.length = boundingBox.vertices.length; 2532 boundingBox.computeWorldVertices(x, y, slot.bone, polygon); 2533 } 2534 2535 if (updateAabb) this.aabbCompute(); 2536 }, 2537 aabbCompute: function () { 2538 var polygons = this.polygons; 2539 var minX = Number.MAX_VALUE, minY = Number.MAX_VALUE, maxX = Number.MIN_VALUE, maxY = Number.MIN_VALUE; 2540 for (var i = 0, n = polygons.length; i < n; i++) { 2541 var vertices = polygons[i]; 2542 for (var ii = 0, nn = vertices.length; ii < nn; ii += 2) { 2543 var x = vertices[ii]; 2544 var y = vertices[ii + 1]; 2545 minX = Math.min(minX, x); 2546 minY = Math.min(minY, y); 2547 maxX = Math.max(maxX, x); 2548 maxY = Math.max(maxY, y); 2549 } 2550 } 2551 this.minX = minX; 2552 this.minY = minY; 2553 this.maxX = maxX; 2554 this.maxY = maxY; 2555 }, 2556 /** Returns true if the axis aligned bounding box contains the point. */ 2557 aabbContainsPoint: function (x, y) { 2558 return x >= this.minX && x <= this.maxX && y >= this.minY && y <= this.maxY; 2559 }, 2560 /** Returns true if the axis aligned bounding box intersects the line segment. */ 2561 aabbIntersectsSegment: function (x1, y1, x2, y2) { 2562 var minX = this.minX, minY = this.minY, maxX = this.maxX, maxY = this.maxY; 2563 if ((x1 <= minX && x2 <= minX) || (y1 <= minY && y2 <= minY) || (x1 >= maxX && x2 >= maxX) || (y1 >= maxY && y2 >= maxY)) 2564 return false; 2565 var m = (y2 - y1) / (x2 - x1); 2566 var y = m * (minX - x1) + y1; 2567 if (y > minY && y < maxY) return true; 2568 y = m * (maxX - x1) + y1; 2569 if (y > minY && y < maxY) return true; 2570 var x = (minY - y1) / m + x1; 2571 if (x > minX && x < maxX) return true; 2572 x = (maxY - y1) / m + x1; 2573 if (x > minX && x < maxX) return true; 2574 return false; 2575 }, 2576 /** Returns true if the axis aligned bounding box intersects the axis aligned bounding box of the specified bounds. */ 2577 aabbIntersectsSkeleton: function (bounds) { 2578 return this.minX < bounds.maxX && this.maxX > bounds.minX && this.minY < bounds.maxY && this.maxY >
2578 bounds.minY; 2579 }, 2580 /** Returns the first bounding box attachment that contains the point, or null. When doing many checks, it is usually more 2581 * efficient to only call this method if {@link #aabbContainsPoint(float, float)} returns true. */ 2582 containsPoint: function (x, y) { 2583 var polygons = this.polygons; 2584 for (var i = 0, n = polygons.length; i < n; i++) 2585 if (this.polygonContainsPoint(polygons[i], x, y)) return this.boundingBoxes[i]; 2586 return null; 2587 }, 2588 /** Returns the first bounding box attachment that contains the line segment, or null. When doing many checks, it is usually 2589 * more efficient to only call this method if {@link #aabbIntersectsSegment(float, float, float, float)} returns true. */ 2590 intersectsSegment: function (x1, y1, x2, y2) { 2591 var polygons = this.polygons; 2592 for (var i = 0, n = polygons.length; i < n; i++) 2593 if (polygons[i].intersectsSegment(x1, y1, x2, y2)) return this.boundingBoxes[i]; 2594 return null; 2595 }, 2596 /** Returns true if the polygon contains the point. */ 2597 polygonContainsPoint: function (polygon, x, y) { 2598 var nn = polygon.length; 2599 var prevIndex = nn - 2; 2600 var inside = false;
vendor: 8,151 bytes, lines 2601-2786
2601 for (var ii = 0; ii < nn; ii += 2) { 2602 var vertexY = polygon[ii + 1]; 2603 var prevY = polygon[prevIndex + 1]; 2604 if ((vertexY < y && prevY >= y) || (prevY < y && vertexY >= y)) { 2605 var vertexX = polygon[ii]; 2606 if (vertexX + (y - vertexY) / (prevY - vertexY) * (polygon[prevIndex] - vertexX) < x) inside = !inside; 2607 } 2608 prevIndex = ii; 2609 } 2610 return inside; 2611 }, 2612 /** Returns true if the polygon contains the line segment. */ 2613 polygonIntersectsSegment: function (polygon, x1, y1, x2, y2) { 2614 var nn = polygon.length; 2615 var width12 = x1 - x2, height12 = y1 - y2; 2616 var det1 = x1 * y2 - y1 * x2; 2617 var x3 = polygon[nn - 2], y3 = polygon[nn - 1]; 2618 for (var ii = 0; ii < nn; ii += 2) { 2619 var x4 = polygon[ii], y4 = polygon[ii + 1]; 2620 var det2 = x3 * y4 - y3 * x4; 2621 var width34 = x3 - x4, height34 = y3 - y4; 2622 var det3 = width12 * height34 - height12 * width34; 2623 var x = (det1 * width34 - width12 * det2) / det3; 2624 if (((x >= x3 && x <= x4) || (x >= x4 && x <= x3)) && ((x >= x1 && x <= x2) || (x >= x2 && x <= x1))) { 2625 var y = (det1 * height34 - height12 * det2) / det3; 2626 if (((y >= y3 && y <= y4) || (y >= y4 && y <= y3)) && ((y >= y1 && y <= y2) || (y >= y2 && y <= y1))) return true; 2627 } 2628 x3 = x4; 2629 y3 = y4; 2630 } 2631 return false; 2632 }, 2633 getPolygon: function (attachment) { 2634 var index = this.boundingBoxes.indexOf(attachment); 2635 return index == -1 ? null : this.polygons[index]; 2636 }, 2637 getWidth: function () { 2638 return this.maxX - this.minX; 2639 }, 2640 getHeight: function () { 2641 return this.maxY - this.minY; 2642 } 2643}; 2644 2645spine.SkeletonImageBounds = function () { 2646 this.polygonPool = []; 2647 this.polygons = []; 2648}; 2649spine.SkeletonImageBounds.prototype = { 2650 minX: 0, minY: 0, maxX: 0, maxY: 0, 2651 update: function (skeleton, updateAabb) { 2652 var slots = skeleton.slots; 2653 var slotCount = slots.length; 2654 var x = skeleton.x, y = skeleton.y; 2655 var polygonPool = this.polygonPool; 2656 var polygons = this.polygons; 2657 2658 for (var i = 0, n = polygons.length; i < n; i++) 2659 polygonPool.push(polygons[i]); 2660 polygons.length = 0; 2661 2662 for (var i = 0; i < slotCount; i++) { 2663 var slot = slots[i]; 2664 var regionAttachment = slot.attachment; 2665 if (!regionAttachment || regionAttachment.type != spine.AttachmentType.region) continue; 2666 var poolCount = polygonPool.length, polygon; 2667 if (poolCount > 0) { 2668 polygon = polygonPool[poolCount - 1]; 2669 polygonPool.splice(poolCount - 1, 1); 2670 } else 2671 polygon = []; 2672 polygons.push(polygon); 2673 polygon.length = 8; 2674// regionAttachment.updateOffset(); 2675 regionAttachment.computeVertices(x, y, slot.bone, polygon); 2676 } 2677 2678 if (updateAabb) this.aabbCompute(); 2679 }, 2680 aabbCompute: function () { 2681 var polygons = this.polygons; 2682 var minX = Number.MAX_VALUE, minY = Number.MAX_VALUE, maxX = Number.MIN_VALUE, maxY = Number.MIN_VALUE; 2683 for (var i = 0, n = polygons.length; i < n; i++) { 2684 var vertices = polygons[i]; 2685 for (var ii = 0, nn = vertices.length; ii < nn; ii += 2) { 2686 var x = vertices[ii]; 2687 var y = vertices[ii + 1]; 2688 minX = Math.min(minX, x); 2689 minY = Math.min(minY, y); 2690 maxX = Math.max(maxX, x); 2691 maxY = Math.max(maxY, y); 2692 } 2693 } 2694 this.minX = minX; 2695 this.minY = minY; 2696 this.maxX = maxX; 2697 this.maxY = maxY; 2698 }, 2699 /** Returns true if the axis aligned bounding box contains the point. */ 2700 aabbContainsPoint: function (x, y) { 2701 return x >= this.minX && x <= this.maxX && y >= this.minY && y <= this.maxY; 2702 }, 2703 /** Returns true if the axis aligned bounding box intersects the line segment. */ 2704 aabbIntersectsSegment: function (x1, y1, x2, y2) { 2705 var minX = this.minX, minY = this.minY, maxX = this.maxX, maxY = this.maxY; 2706 if ((x1 <= minX && x2 <= minX) || (y1 <= minY && y2 <= minY) || (x1 >= maxX && x2 >= maxX) || (y1 >= maxY && y2 >= maxY)) 2707 return false; 2708 var m = (y2 - y1) / (x2 - x1); 2709 var y = m * (minX - x1) + y1; 2710 if (y > minY && y < maxY) return true; 2711 y = m * (maxX - x1) + y1; 2712 if (y > minY && y < maxY) return true; 2713 var x = (minY - y1) / m + x1; 2714 if (x > minX && x < maxX) return true; 2715 x = (maxY - y1) / m + x1; 2716 if (x > minX && x < maxX) return true; 2717 return false; 2718 }, 2719 /** Returns true if the axis aligned bounding box intersects the axis aligned bounding box of the specified bounds. */ 2720 aabbIntersectsSkeleton: function (bounds) { 2721 return this.minX < bounds.maxX && this.maxX > bounds.minX && this.minY < bounds.maxY && this.maxY > bounds.minY; 2722 }, 2723 /** Returns the first bounding box attachment that contains the point, or null. When doing many checks, it is usually more 2724 * efficient to only call this method if {@link #aabbContainsPoint(float, float)} returns true. */ 2725 containsPoint: function (x, y) { 2726 var polygons = this.polygons; 2727 for (var i = 0, n = polygons.length; i < n; i++) 2728 if (this.polygonContainsPoint(polygons[i], x, y)) return this.boundingBoxes[i]; 2729 return null; 2730 }, 2731 /** Returns the first bounding box attachment that contains the line segment, or null. When doing many checks, it is usually 2732 * more efficient to only call this method if {@link #aabbIntersectsSegment(float, float, float, float)} returns true. */ 2733 intersectsSegment: function (x1, y1, x2, y2) { 2734 var polygons = this.polygons; 2735 for (var i = 0, n = polygons.length; i < n; i++) 2736 if (polygons[i].intersectsSegment(x1, y1, x2, y2)) return this.boundingBoxes[i]; 2737 return null; 2738 }, 2739 /** Returns true if the polygon contains the point. */ 2740 polygonContainsPoint: function (polygon, x, y) { 2741 var nn = polygon.length; 2742 var prevIndex = nn - 2; 2743 var inside = false; 2744 for (var ii = 0; ii < nn; ii += 2) { 2745 var vertexY = polygon[ii + 1]; 2746 var prevY = polygon[prevIndex + 1]; 2747 if ((vertexY < y && prevY >= y) || (prevY < y && vertexY >= y)) { 2748 var vertexX = polygon[ii]; 2749 if (vertexX + (y - vertexY) / (prevY - vertexY) * (polygon[prevIndex] - vertexX) < x) inside = !inside; 2750 } 2751 prevIndex = ii; 2752 } 2753 return inside; 2754 }, 2755 /** Returns true if the polygon contains the line segment. */ 2756 polygonIntersectsSegment: function (polygon, x1, y1, x2, y2) { 2757 var nn = polygon.length; 2758 var width12 = x1 - x2, height12 = y1 - y2; 2759 var det1 = x1 * y2 - y1 * x2; 2760 var x3 = polygon[nn - 2], y3 = polygon[nn - 1]; 2761 for (var ii = 0; ii < nn; ii += 2) { 2762 var x4 = polygon[ii], y4 = polygon[ii + 1]; 2763 var det2 = x3 * y4 - y3 * x4; 2764 var width34 = x3 - x4, height34 = y3 - y4; 2765 var det3 = width12 * height34 - height12 * width34; 2766 var x = (det1 * width34 - width12 * det2) / det3; 2767 if (((x >= x3 && x <= x4) || (x >= x4 && x <= x3)) && ((x >= x1 && x <= x2) || (x >= x2 && x <= x1))) { 2768 var y = (det1 * height34 - height12 * det2) / det3; 2769 if (((y >= y3 && y <= y4) || (y >= y4 && y <= y3)) && ((y >= y1 && y <= y2) || (y >= y2 && y <= y1))) return true; 2770 } 2771 x3 = x4; 2772 y3 = y4; 2773 } 2774 return false; 2775 }, 2776 getPolygon: function (attachment) { 2777 var index = this.boundingBoxes.indexOf(attachment); 2778 return index == -1 ? null : this.polygons[index]; 2779 }, 2780 getWidth: function () { 2781 return this.maxX - this.minX; 2782 }, 2783 getHeight: function () { 2784 return this.maxY - this.minY; 2785 } 2786};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.