spine.js 93 KB

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