From e2120ca07bfe220d47c5ae121d24e208f3438d04 Mon Sep 17 00:00:00 2001 From: NathanSweet Date: Wed, 20 Feb 2013 01:13:59 +0100 Subject: [PATCH] Initial Corona runtime. --- .gitignore | 2 + LICENSE | 22 ++ spine-corona/build.settings | 12 + spine-corona/config.lua | 8 + spine-corona/data/eyes-closed.png | Bin 0 -> 3296 bytes spine-corona/data/eyes.png | Bin 0 -> 3454 bytes spine-corona/data/head.png | Bin 0 -> 24498 bytes spine-corona/data/left-ankle.png | Bin 0 -> 1570 bytes spine-corona/data/left-arm.png | Bin 0 -> 3546 bytes spine-corona/data/left-foot.png | Bin 0 -> 5349 bytes spine-corona/data/left-hand.png | Bin 0 -> 4802 bytes spine-corona/data/left-lower-leg.png | Bin 0 -> 6146 bytes spine-corona/data/left-pant-bottom.png | Bin 0 -> 2456 bytes spine-corona/data/left-shoulder.png | Bin 0 -> 3867 bytes spine-corona/data/left-upper-leg.png | Bin 0 -> 4456 bytes spine-corona/data/neck.png | Bin 0 -> 2868 bytes spine-corona/data/pelvis.png | Bin 0 -> 5861 bytes spine-corona/data/right-ankle.png | Bin 0 -> 1530 bytes spine-corona/data/right-arm.png | Bin 0 -> 3173 bytes spine-corona/data/right-foot-idle.png | Bin 0 -> 4555 bytes spine-corona/data/right-foot.png | Bin 0 -> 5402 bytes spine-corona/data/right-hand.png | Bin 0 -> 3744 bytes spine-corona/data/right-lower-leg.png | Bin 0 -> 6174 bytes spine-corona/data/right-pant-bottom.png | Bin 0 -> 2068 bytes spine-corona/data/right-shoulder.png | Bin 0 -> 4847 bytes spine-corona/data/right-upper-leg.png | Bin 0 -> 5550 bytes spine-corona/data/spineboy-skeleton.json | 101 ++++++ spine-corona/data/spineboy-walk.json | 278 +++++++++++++++ spine-corona/data/torso.png | Bin 0 -> 8987 bytes spine-corona/main.lua | 36 ++ spine-corona/spine/Animation.lua | 397 ++++++++++++++++++++++ spine-corona/spine/AttachmentResolver.lua | 30 ++ spine-corona/spine/Bone.lua | 54 +++ spine-corona/spine/BoneData.lua | 13 + spine-corona/spine/RegionAttachment.lua | 12 + spine-corona/spine/Skeleton.lua | 172 ++++++++++ spine-corona/spine/SkeletonData.lua | 55 +++ spine-corona/spine/SkeletonJson.lua | 255 ++++++++++++++ spine-corona/spine/Skin.lua | 39 +++ spine-corona/spine/Slot.lua | 54 +++ spine-corona/spine/SlotData.lua | 23 ++ spine-corona/spine/spine.lua | 17 + spine-corona/spine/utils.lua | 59 ++++ 43 files changed, 1639 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 spine-corona/build.settings create mode 100644 spine-corona/config.lua create mode 100644 spine-corona/data/eyes-closed.png create mode 100644 spine-corona/data/eyes.png create mode 100644 spine-corona/data/head.png create mode 100644 spine-corona/data/left-ankle.png create mode 100644 spine-corona/data/left-arm.png create mode 100644 spine-corona/data/left-foot.png create mode 100644 spine-corona/data/left-hand.png create mode 100644 spine-corona/data/left-lower-leg.png create mode 100644 spine-corona/data/left-pant-bottom.png create mode 100644 spine-corona/data/left-shoulder.png create mode 100644 spine-corona/data/left-upper-leg.png create mode 100644 spine-corona/data/neck.png create mode 100644 spine-corona/data/pelvis.png create mode 100644 spine-corona/data/right-ankle.png create mode 100644 spine-corona/data/right-arm.png create mode 100644 spine-corona/data/right-foot-idle.png create mode 100644 spine-corona/data/right-foot.png create mode 100644 spine-corona/data/right-hand.png create mode 100644 spine-corona/data/right-lower-leg.png create mode 100644 spine-corona/data/right-pant-bottom.png create mode 100644 spine-corona/data/right-shoulder.png create mode 100644 spine-corona/data/right-upper-leg.png create mode 100644 spine-corona/data/spineboy-skeleton.json create mode 100644 spine-corona/data/spineboy-walk.json create mode 100644 spine-corona/data/torso.png create mode 100644 spine-corona/main.lua create mode 100644 spine-corona/spine/Animation.lua create mode 100644 spine-corona/spine/AttachmentResolver.lua create mode 100644 spine-corona/spine/Bone.lua create mode 100644 spine-corona/spine/BoneData.lua create mode 100644 spine-corona/spine/RegionAttachment.lua create mode 100644 spine-corona/spine/Skeleton.lua create mode 100644 spine-corona/spine/SkeletonData.lua create mode 100644 spine-corona/spine/SkeletonJson.lua create mode 100644 spine-corona/spine/Skin.lua create mode 100644 spine-corona/spine/Slot.lua create mode 100644 spine-corona/spine/SlotData.lua create mode 100644 spine-corona/spine/spine.lua create mode 100644 spine-corona/spine/utils.lua diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..4478e9e1f --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +spine-cpp/Debug/* +spine-libgdx/bin/* diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000..1750d7973 --- /dev/null +++ b/LICENSE @@ -0,0 +1,22 @@ +Copyright (c) 2013, Esoteric Software +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/spine-corona/build.settings b/spine-corona/build.settings new file mode 100644 index 000000000..a55b73421 --- /dev/null +++ b/spine-corona/build.settings @@ -0,0 +1,12 @@ +settings = { + orientation = { + default = "portrait", + supported = { "portrait", } + }, + iphone = { + plist = { + UIStatusBarHidden = false, + UIPrerenderedIcon = true, -- set to false for "shine" overlay + } + }, +} diff --git a/spine-corona/config.lua b/spine-corona/config.lua new file mode 100644 index 000000000..643443087 --- /dev/null +++ b/spine-corona/config.lua @@ -0,0 +1,8 @@ +application = { + content = { + width = 320, + height = 480, + scale = "letterBox", + fps = 60, + }, +} diff --git a/spine-corona/data/eyes-closed.png b/spine-corona/data/eyes-closed.png new file mode 100644 index 0000000000000000000000000000000000000000..60718e1018e5ef7c0da2d0d573c48e866cead791 GIT binary patch literal 3296 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 literal 0 HcmV?d00001 diff --git a/spine-corona/data/eyes.png b/spine-corona/data/eyes.png new file mode 100644 index 0000000000000000000000000000000000000000..707c91b72cbc6235787757e4e6db3a64f2d2eb36 GIT binary patch literal 3454 zcmbVPX*`r`A0CmdK|*GfjIm~$jag(cW+)Y9iBV)`%wUdYhMAGEHKAyFOO{e1OQ()x z>4*@rWG`F$MkHH{O3BW=qf_U7Kb+tD;eCG3^Ly_5e*V|>zy8~YN3_>#nHWmU_s00lF*w_g|sR1DjK7_^yVzTkj&$SIu2$PP7dRw`` zT|$YBVCIe}F2f_r)iWR}BmhT;+Sx*E1lAG)7K2ZP2v~>MJZk|S`h(Y6vR*xgK_Nd( z_#t@cU!uq^dm%&)mjSV|K$!=?5eNtxZGo_~LZcC85F{Ldgux{@+8kkNZH2Z*Vjw>+ zsKgtW9%$`Oa{B2@vcp4z`TS687%U>=1msptdBH4VZz?{v~ z`^7+F@B+BZP(G8xhO9DDX`FCA9x74#R|u?77ni?@*}R{LlB5hKpoYQ_7H}AgwHntC zYaZX7@gEugXwCDC3}wLF89YunH$YO4K)qjJN$&o)qg6wR8tXk=rlcs;LnKZ>IE%sN zJCpEG$rlSclWy%m!VusX1dfPCIyfQ`2!aE`lH@?dVNqB|329?j@dU802 zes#d!U=E+d3+9AEh#qK&u{V=V=S1+fu9oMoXh{q%^Du+%#O1IcKk{qM{0IL8ECOpu z!Xhjs3RdIBp-BWRnux`qP;e`P69)PdOaFgz29t<^tv1JhHOsFfNe8Yj|89NB=I`NQ zuq6}2T^$YY*iisLq12f~@D#kH#Z=!qBc*5(H+SpA$)3#{A;e5k>Xh<2({;@^{2Rda zLV;b9g0Y|~;;Eu+Wt9p@Ik%x(@Ua6d>y&cXDKJAU7B6RhpY3g!j>tWN0?4e_d%Rl{ zk}OUAW7C4=j?hyCp!GEP+pVC=!r(dep;=Op zqmVV?6|wO98&hKN2dzZCSOuV1Ox$ep*{_#EFP&X8qAxTwbdvq!d<3ZO>~oN-4!)2B2O&fAVrbSLHUW`^(*9W@atrPp1o`+kuS;LJ_d`sB(85^5K{hCn@Jhi8C zR;;NxL=}7=HIi0S>+{MB5iTz&c(rtyhbE1FZV&@|Ukj-hs`&VX$;_6OUYgyZh%Dnb<$+1Z4L0ZcfwiXOdOVwb_!A^6t5uQYkUAw$3D8Ozn}u_lW|3F zls!x#3Fp3QUptX1r5y?w&5VmPYiw<6ET(SmSfi24n;lJ}7i7Nxrsg;Sk(ZZ%{=y}i zG0-xI52kRGGzAWnKkJ=php7Q`#G%jvqZ39oQ3>e4EEJ#bMd9vVo(r;}O8-yS) zo!e3yhek(_R|7$*r|Rwk#c^CnZp_@5R9%DqgsG+X?|^4=?yQKHU#ZA$tj4T}d1I+= zE4gp(x8&&?bcKFw^GN(e4oR#!RR`R>rY`-c;#b0Zb^T+Y*TRK+L-_?A9qsqqzs!F2 zKc+imEbXLSegc?KP`f*$U|YhB3Pmw6fHK!<4*K;ZhS_2%Y- zXS#0`(T$o+<4w++>7MJ?{OD`&|#He)#l4?T45cwNBuIaz?j*+iq_J}ko? zJgCve)TpT5G5)Y4-gessJW1p7CbIZR zz1`qZIkUL_gPuFtp%Z)!Cw!BUW8u9+gkj=s5Q@$2sL%@QL&N0Qmg9H*qwfC+@3cDA zZvFu;a?{z1xN+04I40*eEm8!Y8u`ZpO@>`wGpC@>f?gtf0ODwp5}`5 zHViEL%2X^L6b^s-Vyq?ds+_;nF}Cl@L%X4Gkbqk|AGtbF$)BI@zw0v8vFuq^ zU{bjOyjJ_p9yoky%QM-75X98l)D+EI%07d-7v~pM1`W5#ZBcSy%+X`7NyW9v5@#m) zIX4{}@6w*8EOtDvwskKde-i0mthL?U1I)n<#MRVv`NA7#!gI=cd?Knj%X3 zM!T|f#iHLcuFt!=xv5S^t158to0R8j^z&o-v8^fXd1PZPeLa!POJ&Q1st+>L-h1lv z8g&m)RFAFfy@T1$N+(cL&Ym5~HXjG(RL2(jsraP_=Z|zX06W+ncd(sGMV(NU)T+`+q5Q;xf&GVlnvcA| ziMcb`D{_PP8{fMtLKy3)XY4wi;(6V*N$0~QA_ zFs9@#Yx)YPv}(#kzlHui5HMSB6FhjH$;_X`72s_Lw;DX|eB1(yd^DE*Ic9vhel{|9 z9Csi*j7bLVLFO<>V5=dn%uodRkTFHHaN>Mqw%OeMWR| z=uwuJf`;-YA;WBgZ9}icU6+l)AzyTFU3AQTMlYY&L9OrI-EDN}bL+l>b#Kzj|tfFsA@;hyT?%mtm2!EY_0Y| z>?x1!Diros24#UwTz~SyhDrIR=A0A9LjEkW66`7jS_;1pjP`f5hVcq5ZL=INR_v$G z-p@Vqud=ML>DW;D=$FJq>V_`pDUop{DPC1L%tyw5l{ZTOh5LzT9q$#vYnS!d{*W|R z!>LyjXPbWWt9#NKo}*eb8TR6|w)}8@G^*>|dUJzI_PV>I5bsjVyo$H3H8b$AB(#2& zdH;T|kDt;$w|j$yqi^~HG4kem3+^5%&t4$metlL}C&SAjH>7(HB316cJ2WNhZwTT} zE$qAE{p{Ks*Jdq^^e$R5d&lT5l21$78JB+h?N_u}vsI9+ZqQCW&@-P}>GArH1=Fwp zxE7_PsWG$9{`J@*G$)mU&_r**^^&PJWe?8S9QUP3Wj?oD^Ll6YeAs5A=%jmxUp^RW zuZ4YTDqUQPDU0X368#$G2tHR$6dH}rs}5$?23IhbAU|obK_pTXr2O4nf3i zsFN9KRh?F}YpXV_b}MKpDl)Cu$(~kD&M;6_PI@pfa5}YcZH(}pi9_~VKDqF)S$oEGIOC@Xr8dR02YqyMxhhuA(U zdcjo+gyQk|;CKBZhL*OAsk+koh&`Nxp3}q6??1Y2m@+`F(%!Cu|GqSL?#&Z_ixruq zC!)g4NVC4kbHg`m()3p3Zcmu{>Y%mSU*!J7?Fyy zV*JMO60f$j3$3mr;R;}LyTz4MO^Ar%_o@9A z8XTSe*!BucZnQcFKafn`8HWxSO*Dc!zm=9b^+F1&5O!iX>`yGkiMkBgInrK_=XS4(dG1!;=SLg8Ffx_vdfz6Z3^bMZDjaL7xRv%6G@jio ahOfxLR32^R)ZP2>N9642N-A}r#Qz(?!`O@f literal 0 HcmV?d00001 diff --git a/spine-corona/data/head.png b/spine-corona/data/head.png new file mode 100644 index 0000000000000000000000000000000000000000..5a98aa37a930d57ed3704b1ab4236b19fc966021 GIT binary patch literal 24498 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

;9!VleC^Uj=<*i%p5o3-2BrmMA11tFV^ z=$^P8bVjWjp$ZXydfO%+fA778=R9lvHS^8ltsnXLJ(No!(PcWf|APbh$&MNpNHe!k zByK>j;Cop3<5ZhJ?u=qOqu4DpZC|gg{XPM&R#M=5igLkcsS&Z%h+LwWQ+1M@>^`dw zNQF`gl{d0HPv8m5G!<-)BzK;ga?jZ|NoH?5(2CxE>|pK7TkSE^IHObyp7<5*pDM^# zlm!cc^u$Me_{iS7ahxW%eEOdFl_yr(uShko5JH5df}&BBM1iDKP#6nIW=JzjoEcJW z8B7f0#GVU%`8&-@@Vi2Ydl#A!N(zjDX_8$y_4*V%&v;NgQg&>)qu`4>mYeEV3qBM> zAx~|Z@;LLFVKHp=QWi(!q++d&1q?x*^*nj9RTJ5~5NKmiN)jhdMp6p(w0)NUKL9{f Vl4EJFkXQf!002ovPDHLkV1i{X`&$42 literal 0 HcmV?d00001 diff --git a/spine-corona/data/left-ankle.png b/spine-corona/data/left-ankle.png new file mode 100644 index 0000000000000000000000000000000000000000..fcf9a28135d9fe02913d70dd9abb349fabb951ba GIT binary patch literal 1570 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 literal 0 HcmV?d00001 diff --git a/spine-corona/data/left-pant-bottom.png b/spine-corona/data/left-pant-bottom.png new file mode 100644 index 0000000000000000000000000000000000000000..29a05bc4f9ed7a5091aecd88802654bb0bb76877 GIT binary patch literal 2456 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 literal 0 HcmV?d00001 diff --git a/spine-corona/data/left-upper-leg.png b/spine-corona/data/left-upper-leg.png new file mode 100644 index 0000000000000000000000000000000000000000..f076d5c91f60e67c25032c2587da3328bc77da8d GIT binary patch literal 4456 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 cbGvvd3%nKFIn+a literal 0 HcmV?d00001 diff --git a/spine-corona/data/right-arm.png b/spine-corona/data/right-arm.png new file mode 100644 index 0000000000000000000000000000000000000000..cac970f4bd83cb182559c04dde52f1bc12fe40ee GIT binary patch literal 3173 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 D=$40U literal 0 HcmV?d00001 diff --git a/spine-corona/data/right-foot-idle.png b/spine-corona/data/right-foot-idle.png new file mode 100644 index 0000000000000000000000000000000000000000..aaf609f4e447c10ed31925835e30779bf3cb075c GIT binary patch literal 4555 zcmbVQX*^W@+dsDKktJklsBB>t%P?^dX6#E7BTL9IV=0Vfm`V0MTSRV4vPH?hl)ngB zBD)A7*|*A;rDS=g?z{VWUfiGmi|6+_=W~A7?_A&SwVxN~4#rrAo#hM*008WIx@Z&X zQ;~WLF`WPan&+Aw{8T}Jq-8-eB|4JGI4=UAfhXD%KzeRCCxQt9hri|dhM)=nbdD}q z3zCJAA;N*^CWrf}BS&%bprQdl6-n{HIou?WK=uSD7k4$W_4+0;kPBW-%v{k3V&s7$ zIJ@Zjc@a$gjIj=WHyu>)V#q&0suTp3z>Pq{fhcaS?%oKBn%FO11a<%O7%T?*r9!%? zCia(87DgBlis(fEDay&qIzXUMkdl%dR6$Wm2`U4EL7*@&gnB8-LKP5-N(dMn^!E~@ zTJyp?B23WQf7_x;YGTeLk_Q3|CX>l>WO+HFmlGJOqN4JX0|t|&YRG!uawp*^vhLpJ zelws6-VRzB4S$%OE~Zv3mZH};kX0c=9>Ci-|eQ0w7%?l+j4yZ>(Jry|uG#APoRYEf{mXrhCU z8^N8VhgK7#zLCSb;1QZ=xCR6cRY57iG__z*sD>s~0j-HrQI=QMg2Q2`-yHvjg`>1I z;AjX$5u$*CLbYHjC^T9brmUif(uTmbp$fmTdhXsNoVx?zw_O*i-CtOgw)TI;B2Zog z9Es?KB@$hKcL2tjNFsVW6FopEQzek3xr;lVNcNWcS)RY5MH9SSdJ0d2bNruX`F%v~ zz@OWHTAwQXGdu)$>cn_aN8_?8_AGT=f9Rn#u#|Ct1jHWG__#U)hX+4^y}fV1X?{Ln za(ohTOkE;EXFBL;*w?Rz_fG`wOtMyA3R_d;;kB+35g2Ue0(1nnPgt z-7r8;M*}dOI03LT(*pFn-wuJ(0_*_y>C?a|-ZKCV4FGI?-3G?SJ_58Dh1beVt?HcC z6FQ0PvPdSdE_3#rnVz0rQU;5RXiP9?r#hFI&Lr-Il(zip@q>P$#4U;S*duwF*UH## z)u^j_rQ~askqe$p!(YBynb-%7wJHm@kF(kQXd%a?C5B{jB`j6sZa9{VFr+cGuoduT zEJnuB2GTOQN-zZ=LXlB_itNvx*^-HDJ?a@@VPP{L z%fZLT2M6t)%kFMZB|19-H^Bqg#K(!Rnu3Bto~t`+bJ8R3N2Ev0v@Ts=1ZbW-3e5@+ z0qsBMVd06#V9snZ4(rZ_gri>y7%6*gh_sm`Q$ zz>_~a`c5_8A}W{_Ded4edG@0Ue*AL$ck^t8B-r(X5WV}i3#@H3B4~S%_}6TcAJyIn z*Ty*B&H5_xX}k>0!)P_kT> zs;6yZ!?vmH2M9hCdBrOB-dASBEaA1^eRabpxXL$XqK!r98_@7*Xx65n!;xs&k3-b? zBI%038wgH477>XJCsvtThN7H3D7<9?_{jUs2?;ez1z1YS7IG(rq#|JG@Dz2Y*lKf8 zswet!t#2t}dF`z8opdGaYIRC-Mb7RtWQ4%B6@yJ3+p|8H| zKk?*d$4c2xi)v}%TsVuF_Trc1+c$g1>H0#x?<{l6mMhUO*RLaETQ?nqlRr*OCFW2V z(pXRWH#J?R$+MB_H+_@IJ$IqVLpznhXQtTj+j)VQLx0kEVZ`^h?y2FK6y&hTnrp7b ztU2A z4DoGjZ8&wyry3rYc3fiXQ)E&)^kgqt$nZt9M-^iji1P-&3=`uq#@!m8RVww4Wpr3C z*)}^qm}bX{U;L)y6m)IW{OPc(QX)&lTz5h23^*g0Ed1z_-^oj+qrIMzyo;QGdC8@r z==I3&=7Daj`0tJmkB`1H7B)ny-XtQj%0|@I_1~Y@e|RLqczL6t3m0`f(8H5K(ZA1z z7Ch0}mQ|#%=p-cMRQF)#3`pRKf2`@g;Oa?P)BNs>T0!*F)mDBP(RmvJ>Ar}eQBn?F zP0C~Rs~l#2E?>DeG?$Te9n3SgsV#fDuVRyNnU?Pi!v}sYhWI>ty6`q2U|`(%+IaeN zdEx%LTDySf=`|~c{c3ylALkA<1M(EVv@DsXUE$eM!8~(UHN8C1VvT*wUKB>x>tn^O zSiLxXav|~^(`>JpExTosLBYMG;T=gXDf+c0=b%uv)u@=Dsc%(j-3vsE!XhX;!l)%X zi&sNmG)W=EVn6Zgtha+yH87-7TaBCS+8{Hj&9897-$c0c=)Q)sQDq~ zX4`uz)1!+dSE6GECF&ZZ!sGfhVol<$dg(2hHOtHTlKYx{f)^kWCiR(9PM5DcZi|2o z4IiL(Z;jE)ofZ}p!JQdL>b@GqbFEC;^(uZ5|HwOH#~4~q65?BQbiz6Mv7|n1un>xN zA%|z0gG0tYL~ZZ9>e_mm8U0-}Zew|qzBNGkbQFi6VB+LdXs}FfypHZz3wX==ys##~@P}+N!F+F$tu1LGBZIEw2 z-8PSA0j5PPF6Gn?LLT6u8+{;?e}6`vXS4pt1zy1od#^j1e`MD$?9|Mr5?Tj3C0*A) zYx1LE~#ek z!xN;?+1Qrp4M~5$ri7BO(0yi2KD5I4g+=3nmKgF2%_W2BkcbtF4&9`*_l0jQ{re(Z zrw~I0C+g2GXE=$MXo>E){n;MH!JyC0OE?*C$-@xm_C@PxFYm|s8-cd6N;eeTYSp(J ziz8_Ks3WPOEUt##xnHP|Vaw7E<1dhoXJA$M zu_>wC4pF;aIjgO2-BEuip}x?dh8y5$2D@a`JL%RoKzlFC%k;!Wg)21~PJS30{@8 zkFWqq$BY-oNG4~HKp~yRt`eS~_g^|8`@XN$SK1^#m8+OJ@&mcPfHr_fsLR5y1jt=ROkbqEpk~bt7Y38~q!={(tVXZ1}(X`5_!Jhg~ zw+H)nQZQQuGKJ!q%swq5yNvtXF6zmxrLWQ=ar2EYeLD{n9%W~EnXoDHiiRdX@?K0Y zvpMSn0kJwkwwxj33|@6Djt+yyb@RK3sPZ+%i9d-StdleErNF_q%GV|Fqs+$KHoK1u zuO!b>YCJWLj&3eh@9bnF*K!+U+Ie*CB^idL6fq(%q%wP5Dyw&1;=4#0j^l|F$wDP-j=~QoyKFFk$!s%qj&W}d4Sy*w|qO@`+`H;+ULFwU;JJU zTBS)BT=)_JGnLZ)vMnGLY|b=iJc*%Wr`2c4OBYM(u?&xs=8d%*!A?rh`MgCmuPr)> zVlthqQtw+_J=JS=2{eJX79PMbmjsW>*$sSO=`)M&qJ9Uwn;0q`9>$L-dsLAlTOnWP zo_&I^?kv`|e}7Pd-LkTOw`wVs;`A*0#q!0}fywQ-o}6+>wv>&6FS%gKxijnsN63+E zj*j_YI8%0Rm(hz3%@lXbZPCn&(G!L$j_k77lk+(=%{mS9b=CcyTV3~L%oYmD@E?3Iye6^IcwOe|g0A;W8tPL44u=Cr!BOman7>8ctplMdwYe}qD- zGHx5i88Wg68MpMXUtkh8K1gNbw{+|)jEa=7cU^psMmmZnl+iq?RF~fvzowjgFEV{? z?%7*W@!nkxQ1!w#f&P${1)T-w7cCx!7}~0>?tBFQIZy);XNm&tR0U@YR){LU!%Jp& zcarL!oDg_#nqDY4GY@bFS7))atbTuEYLghC7m^iOH!KBz_G;rn5z;Z|fjUz&X zYR`90V$=49Q=!lD^>k^9NteX@DIJTkw^PNarkeZK9gmIN1L<`yAN=|G+}3}}4$g9X zvaX$|E#<2YuEWntChFBKRSWDrkAh1K`d7!^=PfF`S~G&`uh_~NF@BmfTW*!w>WO^&S3wQX%B2~reea{3V#p0=^f3Dlz>awg(fZx z@mY%}0JlUET~u{hkNhkd{v0&oS5*OF&FckLQb_{@T}d5_{;*fNscFZ?{+IZlZjOLI z1z%yiGw0)riN!y-me1@iM0ic#owBKmPw?w!n`{VqKUJ0=6d=X(HfXlkZOJCu@W;7T zXQtlT0Hi-Ffx_JD*ELx+4_W2eX%x#ea6wARTm+@bz<@dV(3t*^Qw8U*N{CnrYgx4# zrN))M4x+Cc+GE^Ti{eN{)ajLD=hRv~_`hZ#UUJBfuRJm*TklPP_yb!U-WBPJWB1bR zE6GBYNmsU2IoGw6ub~98MK4bj3`+W(tCVN)Jnyg-%?)F1o=1&VeXIwPComJW6%(hs vzC=H`2&0J^M>;%}68Ai18!Qh}{d$(Og7@AVlZNjPkgbvcHih%@(5=s)PbdV;!DF}ul#X=EKnsfxE zOIK+YK#CMWDGFTt&i9>rf1Kz1xbw_Bv-iwf)>?b*`7!Zkrh2SQ=a~Qi0IPw%j>YL+ z`}7iGpaTG?0J9kbrxQLh+Kz1LfP$ea$KN>KY>?uN)6zECD1ju@l z#Qssx!I4~ucyBV^%Mq!oKq7RZFbG=dAFhEXiHz}d!TsZlKlS~ai}OV8DNxDJH{7mxt}I1CMRP*wr&ofEfyTwnOKd9p27Q%8K}S5*9PBITpUkCqKc(cYO4#*L$O{c++^k_2tP8XXj3kgmhF?BE zSa|N;3Ozdh;bdq?^HokarY)=$&aefes=#8f2m6a_VX6E9jraH-s5K35{rGS>=CYR) zOj1T4UR@12aeG!@iwW@FR5u&ch#3~vfOwN?;K2ung5_KEU9nXxEC8x<(WrcyNKoA5 z1_VwcQIJOCY-LOnQ7mMTh*S@k35^b0a$4^Qn2jK4yD9zYQlhHUwZyQ6qy(+0)HbJO|sq8`5u= zJMYFJRA%O`V8DRcFE2(R?9m^?NbX~G2Ip^?8PS%AGT9^qh{b))N?BlztN(OAU~SE+ zd@iWrCP$);>~n`Cf{W>zI65tonwhy7zO$(@U(-@yLQ|L$tR8#(f!^a5g9Idf&`i=8 zRRB$;#AX>T9yaa-%z4<~W1%{s;UKC8Y;HSWTkh{?E~^nh7}nCZ*0yxSij{5eRm$fW zC!`oB<%^4REFPdAa?z$sc8tKjw(gF2C_s_LgmmitXRcSG8J<6NLsrlbC1gQOsgt|= z<)Jpc9?+Dhm7N#a#%YSPdTxewAAztw9A}o)q;55(V^iN?=l9H|hYLfzI(!Anr4*KW zd_(S)9>`2VSY~GZ8vgN-;SJ;GP z8PaCWUb%)@2%vZJtkxAQTiMy@(M5ME35T=33*f(OSr_{;^w&yBp?Gh0D092ryXOd2 zJW2N}|p$euCn$^f1{(Y+GpcVQp2QQkoIAkPpuKzb3)3pF8W!raOXOtgL z+c%4Uo19pBMLL$EMq?th433qSm6lbP&plHqD-*dy9XI46f8Qka2ztoJaA!;rf7O!f z^>>nVyqHu%;*tZkIeAhjFY$%7l0>Xq5k*RE89$oPAul`qf}8GR&MhBkb1{DP{)xTe zD{gQ{3KtufRG`h1ulG!18d@iHo;;5aP(O*awG>H+Za(|X`;}~)gvj>JIWT3l>G-Rm zRs%2)8A@=&k0O$yAJeQpkmcl(rLVN*cI(B)Ej_mu*gLx&=q3F5O|&wmbMH##tbowP zx9lz8TQ6^~4kj(e_RdE(UodiXYjbNHqkYIhlO`(`Dv{9bV$KOl>)6qUi#O(-`nq0@<+#HQ$YDq1)1JP^cKnDuE!WR}jiFb0 zt7>;R&Re^umV2OBO?9}~w_J9=_r84y)yW`Hb+#Q{klkS199a!)O|e3l?_~L3do^dR z)NV2Ha{E|&FT+y$UH^~s(loTN?1D?S#QW;`Gd4{0IlY;SRQBD@=p7n7G3VZG!}MUO z>xNdVd-T&6m5ub<9t_6ptz^|ZI@Wi;n?F;1O}2%QX}+7>`(Qhf@+|+E!HwL9>?Jk` zZu=5d1R5k_?c5PbX>V%Iri6FLP}=F@X{!r3RoL;g@l53xl1EFe@R6VOaud~DZv8$# z)B^V@)KaC%E)s`R+BVgP)Ru$$nr-JFR*q$_C+cvrS)VV+d-;su|E2M~^aM@tFpBFt z-zci-YP}4V-ncu5Ol7xxg`J#+6E&SDo7!d?^6S_XzvENcFr~DU05U}u9(8VJYtZ{k zOHpqy6%;-TX0wOpXo)S%VXNF16CEl7WrU`{Clu7Zq|y+|@5!0VK2&NZP%gmx=hdKQRBPcdIgk)>_IzcPE|-b)#}wVF z{JLfezjC6V*7Xbbq0dRU0H8XA0#3!`lF3$GDz_iV-*_luM*oH-)}4_l(d1n}EQgwI4wZ*V>_lu#W}$k)e{}0OBZkFL~A$9e_ti@M**Qd(|f_yM|zD0f) zVC;;k-ot5<$`&)9RMBn4QbvY0)Mt-d6W&f~JSWEc>+0v;)oCoN#vzxUeo0DO77tUao)3TL zq+=kX-;l≧zByOFhXCmug)f>Ra{C^d2u$+bi?aEz*SamKKIQU3<$`p=IIS4fOqa zU=sf6X$A5zEFp9mu?)*!F?M7wLF+TVrBB$8+(w(kiR&Iwx$mN`wSO&EUAVl!rvEA9 z@-gjP0}U`qRGbKe(HMO&D6@Q@GZZo;F!g?3$<39WA)fA{QsKa&%KY5?`1dQNOiC^n~yY1aW>v!lO`LD=kT;yux@+q ztJ{z7ylfEG(fT$$a4R*w7scGWfV`_29V!}Qx0=cAk$hzyQlVUDLOWHnsbot6zGF_Y znYuG*vu6D|)=865<4M?d&4f`9G)FO~U~J{Vbnwd^?)0E&c$&v`DdBXQP)Be|=M!DW_Yz%P`kQyy8dQaPer%+%H-8v+s+F*Nqx)W7VX+7T6)|c9tznPjh793`^ zdOZ9F!jiW?Rqza6zHvY}Yj@^#p+Vii3Zu2;P&s29VCo0@9n*~c7ww`DPl)+rS9y_v z!NG8E9?hzuM~?M|Wg8lHayWry!2*xP5(%-&QLQTB5WbkV24i2rhYuJ9!z~A~5A&42 zCFgywRJ)Z$t?bIUb(iarxrX7bC<#y!t5iyZ$26bPpbxxKs1;zc{^IOm;_Wv6K?#Am zY=;k$Pn^}q?&s%Rd1|$`Y;GZ3=quANkgR!Ji;Y`^-C63HAJ}x#>HT3{^&#!SD_b@Ki0iV8R`EWAv&D$HHb1`JFZZ^{2D887%kyK~*3w?%uU6VX} z1Zn~%xh{WpXgPR+9|iLFk;uOah%Oh)&ZI6e?!WgjDnm1Vr)4j^Q~KV-kv(If`N4o8 za&l^7b1F0|y9=SCX2Jzo0oq^2uJ2+&(&^_Di7^Jin&f^anmki@oE!t2@0TC;)^qM$ zLRoA5@7fQ5+53<~pJhCNZ%x8pxP}JxqDgTuv@YB#c+PXLl^~xRL9NS_Z4pZ6PKtP-oEj8`z5uKFWZI))(| zSVN6`Rnmlm=o8$|<+q*{kP+Cdq<)#afpI2A(i$6Zm*W6 z-gd?Vh8S`LisIrIk2ryu#%}2xR-LlNq=dI2IA>gFy_L<)EV@*e`956!<*jYjn09Qr zq(?|o&5Iw@8!k&VsoqBs?V+z%pDl55jv^;(nL?nc0E7tJTUFW#(;VAbJ6mo|N(UVJ zTWD$vl^6eNAtr~N$#Y24{*1genzu;DjUB_%d8gN^PV5pow6vM@@Gf@~h;mP1l zdpq_j9o`+XV&G#NnbnPN_bqyhH$)iosw5aVv_QHE7xpCEQ_-;X6~o5(b%jp`)&f_# zn2|)oinpAZfv`uA-pR1Eb5oyGQ%4m($LZ&#h?0;`&F?U`l#2URu!Nj`i@Cb^x3K&3 z`S~%@#%*Vo&W@MdIX6*Qase8RtUQvq_$lsc@`ERAb;W3@1DifDBN!rS+Wii3pniZh zRsWehBW5I(y?|EG?7jl@Ry*k-;W^=1)PD&ovr*$u%$L6@QmX^N<*L zb!(&iY^omF)Kaa?a(_19t*u@6u(mGNz2&Pp@mMl;0+;n!jKY(DFYRc-tI zIZ5=fb`_I~H*94V3BE^5+W59c#?6@rR}bJ@i1Q^Qs_86mT48e9&v2#2XI+DujrNQv zM{idJH-G-p^PbO%uF#`z(vD1cxB<6t=(-qR%q?A}F!I92)FbmC19h#F)jYDwUEWEG z>P9rLi@QOhljP?NgkrVq;%&bm6$Y4wtH;in^pKDnqu;z|hTU$wEOL`F%khk@$*K8l zw_JMV*Of!@u7x+B=kqfVx=^Ovl-$w#U$4E+kUowq# S-P)hOl?G^2ol33ik^ciwMXJ95 literal 0 HcmV?d00001 diff --git a/spine-corona/data/right-hand.png b/spine-corona/data/right-hand.png new file mode 100644 index 0000000000000000000000000000000000000000..17c62bf4a0ac6922265bdfaf9c8201d7c027f78d GIT binary patch literal 3744 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 NXpXbO-p9Cx{|C;PpdJ7K literal 0 HcmV?d00001 diff --git a/spine-corona/data/right-lower-leg.png b/spine-corona/data/right-lower-leg.png new file mode 100644 index 0000000000000000000000000000000000000000..1f00e8ec993465be3ce6cb227811e0d7e87f0f1e GIT binary patch literal 6174 zcmbVQWmr`0x*lL8q&q|yKssmW&XEuh0SUM!G}kkQR^-q@+bqK{};F zQaTjm;J3eTpYvm1`^Q<=TGx8tcRlxgKlx`x>glSJ-e$TD002leHPrNP-l8{;5+ObS zfYU({FnY6L#6V3j1}Fr^3x>_1xC*+EDMV7wqsXR0LfuxZU~&=7#Ila?BwDugOz9hi&y4m{pVPi9rTw8#!;UAUrw3m z=z&yGXgEk*NL0{P1PlgANC<(dxa0w9P87$Pikb4v(<#bm@KWFV5Dzc2P1HMAW< zMqlmz-&!|2d3Fa3##KgG*vrdH$V*fRg|-(4OG``t;ebE{Z!84eyFef#Xt%oz* z1*54Z&wleo$PQ^IqoO9MEFuY(R+WILKp|kTvImCeDG5>ihvPqCr6klO zpvo$u;v!k)%r#%0PRt=6udcy7QqfySFzw#@C z{15sPD&i7gaS3GzR9xh*xW%MYpvqFxqN2*u5)e^Q_P?=q|DT)*-#8=ur#b#lv;1>( z(}91M|8D)8&A*2S?s79R=$p}Kp$aVp0BCeI)szjfGum+viG%ehdN$-!wN*w2wq7Tm z-Yqc5Za#C{9^?F;bj%tRv1KzNNb>DCXsx4*q~+3c%1%zDYAG*XDh_5uDuVx!C*qxo zxCOlep(>ZJt~yXN$=YzBtG$ri0!6+bN@Z7f>_0%1QC{1#ZD$u)$&5Ye6rWZw{Pv;L)0yjN5`GU0C3mk z1uG%m+&2b=fU6mvdpsuOXB-?9wKX+Y)CgN!;EXZBS#DM^?$mpG)cm#o@u9dV@kcAr z{>io^zJjgeA7k~XafFU#txHvfPzE6lpJ!R{Z6_K#G1Uo<6ou%hO zSo07bpgXS)e@qJF`&;<4q^Vb1UenVp!lt|zKQ5rG+Ji0nKMW26D3oG89^4{l0b%MI zZ7HbfeqV2&q3p_vl$g5<3iIRgH^*nalvNIIt21)b7mp0JGGLQ~79`po z0Bf6#RRjPg#G(-H|2+Qp%T0PgU73Z_}{@1qM!Nbk~8A3IY zVCsyZhP1)wL%ED5LO97EpU3C^mYtaf2X?Ul10$oBWJTssa()B*hZl8Ltn=^R!eMav zTetVj8uvus`29SuG1t@yS^9iIOrjXzw*lmO&H6o`Xe_XcfKW+&dZ(Tg=yr+n-Sv|S z2RtQbj-Ub-82Zi4YRS6--nQkHm%ImZ$A#S~QBd~A4aMT>h4AS;2~~rZ1#5+5Mi}*K zsg11wPZwD*J-jmk5Nw$b`ih{Ms!;cN|V%$ptB+SpdGfA`G4T86X~*`T`{X z?OG3MS$`TZ(~hme`6#9X<;uQqJhzxWZ2`k-G=O|Gu*18o;#wOPT8R;-p*@sHG|Xtt z@b+H80kEJrtPQo0{*yKIZnN(%Yg0Nuw+O|#dZXS?n@ABlmmn90j-nY$;9*6t{g%NV z@%CGrY$ie8+$@Ifm0`*u-Y$-|jF(Fl(*{qPaEwO;7uP%>v5Qts!Rr@IjhvHprp3TR zo8MU1%)GA3Y?z}xeV9$8v(viLDLL8xPQSrDylo9`U~fCwVINeAyXditkKkA|1Iuox z{s4(ZGVimiM@mIL;UjKKq-=J*pY({vHSi%JQUX&`=PxW)=H7K$5~2#{M})x4ro85C8gCDY)VXoWi@yUs}$xefOjr5sKqaUWL`F26YBGez#@O zD+GUcIQkJ;P)ZS)qG!qknRWu^V)G#nSboDyzXK8Teo^)HxV!d(J@?u0;7AH_B*%Ud z4?Z}eHWljJo!FhmoY2E7muYolVBko$ z(dBv6t)nRrMuFaF-?5cTOJEp1ie5zbCn)>YvJGEoF+1)?l)^A2eW1=$O1f&a_p{WU+B@94*km zU#KWw@jBc{6KFyZh3lvGzz_RFL5%0rAml6BTaJW_=`(x9BO9NcybECevsFBq);A(& zK3G?ZIjOI%9(uV{sqiq))m||B`=*x#fpDoXzO6i?t%NDv81cq>g<9Di?TKw~($QhG z^CRCF45IK%pFDY_JE*iUF}!A>ol8cx=Exng-&A<_Qid_!3o~z8byz!z+YM0I}%GwOn}OeA{6gQHt>Q7u8e(_`j+_! z@72((c9-<`S1h?I!q+_bH8z&>H;d77h@`H4bm)~Vc1Fr_`B)WAscRof zIcZV(w~?BIl0;SD4(0|moEEbadL7G-`oVK}v&qM@~3ur2KM>I{wTe(0Zfg zZDz&Nu*mtmyWa_$Al+bz39fwM%d?={*08IeUvj^uOyp^hXq=0t^XgEFyQ=v~(reIb zCFpadTe38lAnHuye$Tt|9M=kvSW~BL)s-_nWl`{4)llE7aaONpkRXW^VPvEWX!Tc5 zP-g9T<7jytGgbcFwkq2Wy~aF^Em2MK42?&778I6C(K03yKD6g56xov)Kb8?#S>lhi zOb6XwctHoucS-nyQ zpX&j?RW;56CO;X&I4gUmlSjrILzQu&sfT$gaP#v!e+quB(rXG7ek#KeLD~Gx~KO2c-&w1o715Q@lRe$qzJ=_sP?Dnz=gfYKpQnfR;e`SW1y(=mB2 z$gyLcUQcscd3T(F`#H4Gyi7=r#P;b+E|bx1EeJ33GGoAY@W)AM)7#F?+Q?@iy`O78 zG*CyTPLJA8txjot0+20da%m;U^nRGk=#1W7lDQ0vicO$}Xnul4NR_PX@=*$o9;M8i z=YN!ADGKXCSHD?_Jnwrb{27cx`q;g!PtMZn!Sv$SP3~B6g+uMGs0q<6Qc2*z%t$Vj|1WL->(ta}c%{Mbf=)jems-?|sV|J~G zGo^A^@SZ7ZNT{BVzon4?!%Z((tH+~(g3f1!mq^RXy1x*jZpB?Ypc0Tg;?-|a`tIdqYjD;{&-<4fDtml|znQNdi|FuQ1N1?T>*PvVeCvim@5n0Rq1Wxp2rR@Gbl$#o?<^=5mcoI%e z86qBCYMbTiZR%^UUmX?O)rz*wa0b@EWW`_YTrRBFgnDhMmkp29mn2sXAePGl zx;s+H3@%>K_X3q<{kQe>Kq}^UfuTL@QHDfp=hRZ5(4H~^DHUZ0Y=H)YB zE{lNsLVylqSpho^?~ZD_9A@al@36#?+dZ79aY&H6TD*{Wa%C_9#cucZK2`lNmh;}H z0q>`$zjD<{Rh$J_Y(CZEBKm3hmq12cmUS(ut>-u@Xs;8Xmg$3sR%Lw=ovl^hCg;Zd ztos%hIhdc!HI}!61i4qA+7oA)*$>9E2(1#Ig$M6W2Sc|~PPUu3j6!AAm~Z*g<-i+`ReNF9qgj3pY_4@Gtrmg>G` z8=#3EjSnuoJ6GeMklxk-xdq4UEy7Igp;pe=2uOm;a2+~YsVt2SOAYrNx z%StKEY!%PWeAur|I_L5@*oJA*smtZNW5MFHf_1 zD)$Jw2=8;H1GOVv60;}tspFxR6Ga+@jHa82(>&WMsZQ+#q&;Fy)f-_E522$p;u!u; z%qI4sp&`)RW{XM$W)!Yet7NrKb`-kr&6 zw{z$)CIF#*Pq2gJB91tEYD~?hX3{-O#Vf#SL4|zD^!eQ-V))aVN64_#d*e?=j$XGB zy)G?$JKc)DpbA)5dor3N7gN=yV^U$PJ<1Y2BsV@Ya{t+?Rvh=MH}^ze(n`5%y6S1Ef!bPR`q}#@mpmIbxfC}k@!DP&?DEl;#O-+4+VEwK*n_Xr zota>|iGA5rE(a!{D4CwXK(|C3Z(J=!6F=LwF1&m@;=UBd1AX}R{k-K<6gdTIJF_z& zb1~J2mbXTeop$ca?onbsyu%3r6&egyKsG;CQ zL{=SZ!&Tu}o5op^k6|9oIW+y5;bh7sMMy!h*BtG&NN8pz{ z5PaEIAn+h3{{TkGYTo9R|snC;WtBC{atx4P%Gph#1R-#>t^BCGfM zdg5s86(1MRYPL|9)8ITEY?*Zb!Xuh(OzT^lQ%c5Ed}71B$J$(}Qljg~ZrTmImD=XVgPJgO5HNl(#r?1Xz*q}4~u zC#*1dK6`#n&HXS}q1kam*Nr6MQ@+kJ)y^w3?q^K2mPK(^r*<{kv9!=ENMf{iMs8&E z7wqjX(lKcwjFI?#Ttcj;Sh`X(uf)2Zt2ZY!sm`j;{?!Jjvw z#30J%7sJ3= zptAy9>=(aolF{`y^r_yV@q~hyspypz-$5&eD<9Qsz)2T}XJ)7{ZS97i6o{Zq?=)FL(lmKlJz={v!3q8=IciB;)B~h_uZmf4yJ9K3MdGn%Z%c7pPk- zZeq+$8oc$!0Y6KDfS8_G;2jw0FhfM>!JOFHmD490GmucN(EN@;G~?6fl6!7X3b>_n znaRRb^c_I};i;bP9?SVv8I&d}cFfzk6B-zn{Q%Arl(kH;4kFul+N;3Td@8 z|D0kS>usqQDd05r?tyikq0AMGhXL({@g$mG+z|c3MdaAR9JR=uWkzWjJ7tdR=A1y3 z-{g&`d?z7xr7e_x1-uIU=BrEL)S_>mbcUO+%4r@Rb({%9?qNA&=>EGYF?FGkDf?QNM1`WqRlS<{IS=B L>Z(<#SO@bDk>3J-Yxd%IcRmu!v|J(>qdM43bPXhcmMG8kDW7f=DXkA-|yc0 zyZ1Y@FLixF0O4%{0005fL{S>{CS%V+A3Oly((yNoFe3~RXCdi&B~m0a!T?{P&xJv$ zR;Gf}V41>F&;!Q;fTvQEk%eR>CvoL^Em`LFA)B=Z3=IIWJhMS2&w~*#7glL>am0r$ ztwd0xh$Ch)lc~uDA*|LU?l8jXJJx5&cjU=q6hz({FxJe)2(&OF1I^leor!CXBfjM2 zVr%y{g$TZMLGt2=uae42P6dT}BMdUh^k_L1f~0+Fc{t=3)F zOK%gB2LCsWH+q{gEC!g82AlMSMmg3GW%wKz)9#N0xgD`=xG6>r))ZO3NG~tc!a77M ziX&oQ$O?^uD-f~yR5lbNWYGj-8U*nL5JMyo#&GByF`G>j&T+g6%V%&H60t}~XNc$! zB&P9cdW zYP|szrnA7POpQ*VFEXukx93&0BG{t2i)YVBS!%2%vt~ zNIh?UdYhN}#o>9~Kg>KIOp#Rlgrex;Y4jQIod(H*g=f(~pk%-^RGf1F!0qWP0f#+0 z^6I{bcxwx;vw`e)WH=nGhUF5S12`jn+_;OY4{+b$F<$k}aj66CN?6riGP$OR56bnpHM4JBa6f+&-4F z9BLef^5+Mws01b;sls{S4+_d5};HV0V@0n_U&i>xvaGZ2XD_sLA z%1#u$#R{>2?$i4)ag)w

CPkk8cd2VWFVB^hk&wc3h^Fy``o5hFu z8KTh7l{RNs6laN}J>&t8Xe%5IjLP!Oy%m@>;k*0e?PHnOCUL*`96Mmh@?o() zxE|GZ6xz9?rH5O2Blv2aq@!i;yA`DCmYQAkN?P*cf+Qdr#DC!YcKnd0c%yyh(quFK zplw%q)WE#A-rcQU7dFc1*XC@*GnTrNgN7#8Zo2OzHxh+3^KiQM$i2fo#8H!TpC44R z;=$6yuSLIKKF&{#p-0{zG_3AauiqpRC!8HTE_7b&Th{nx)!+D`X-K(bYw=a}`@vhb zW_M?0bk%=z=HA4r`aNf*QddPwR^ro?zhB0i54N0J-6JQhvW#A+zH;eCk!frReP;hp z5#`77>#P4V#ZheY94w60HEtsqqW#BnC$2Zx8~(iMLG+bPr;kgGa&t&pe(0Hv@A=NF z8JN$nmh8;FTKCQP=fR5;wk&lWD|9TYK6)V!Y}v#7Du+I~u9*{Dz-zd@Cw6GT_?p(9 zr)6)S6w6iLF_?~>#m=i~nXNqaWZ literal 0 HcmV?d00001 diff --git a/spine-corona/data/right-shoulder.png b/spine-corona/data/right-shoulder.png new file mode 100644 index 0000000000000000000000000000000000000000..23e9a2fd1baa81a4138da7f8fabbf2d8ecd8d67a GIT binary patch literal 4847 zcmbVQX*`r|-yUn$jO^LQ*oj#%7zSfdqbwl}MFxWrMvT4e+sK`rRI)G0K9waIA|%Bi zNu?wtC1l^`)&1N(@B88TJs;ldcU`~hJkRTY9LInCa#5@;Px5jd=K=r#yx3DFHivJ` z!$*UI9ROge4;O!SxDg|p;>fln4{``TfB-;wo7g~1`v!yBOn(?n_^kZ^6#KNt8= zEx_FaX=7sckJjN11@a1MR~62@o4XASo!o?XVsmvVXvbx%=-zzYPz)L0Sb64~v5LF(J7H z`4ardSQ8ZZ@Qb=T(H&`QqK$@X!*nqSxUnf5216UeG);^#x;h#bgw@i3 zYigNjp|zlz7#PeHu496MqK%DBHB7WMwRFsM{$R0wfn>a&8{v;G@lf|4tnPosA~693 zJed?=MTgl5}6d}Me+w>Y!M)(^F%*)Qb?fk@ACXBS`$J5F__?P7C`a^{hePV z@jvJzjI|IjEd&~Fss;T!ZcQCyQ?!n*h6Y*}0oTv~|ATe^|KtpE=nUj{bNruX`EzvG zfxnmkZvDf}zlVq5cQ`Qthof;~>!CFOz$cA0LED8+x;|)Xay2><#W-LaJ@fV0M_LqP zsHbPGu%KYyusjR;Gicfb49&j6r5w{OM<-CwY8)eD;kjcnl-=TwJ!dZ?D|Gc@u;o z?h2c6a&poPqYivx9oT?IsT1w1yPH1+g~@1L-Bt#~x!uJm1JJh0pn47gUokd+ehf|r z4R`ySx>VLL4X!DLq_ZZl_Z#w%K6Vh?-%jRlFn;DW^Kfsp1Gr=NSVp?wzFh|FEDphm z8bi{sSY~@1PSi)x2!Ib#7cQ!+t`46$*xv;`65}?=DVjKIYs-=(Xve~F=V=Ay5*E9_ z0`+&n4|VeJ__;?*Jb6VkxVl4=8(Qza7bw!n3=&V*Y7bveSy^9vlbZTV+*~yHyIylE zb?jYI28I6^TcIKByJ6U0_>bHk{_xP{Pcbm-U#$!V1H%k{{^5FYYyS^Mp&>(b>V3!a zhPfWSL_(icj4zO%pNXFOb?FEP$Q6^ubkjIHX3WX@P6M!XdVZ*o5f&DPrt>}Gs8>k8 z*Gb+gjEjq#UYY5G;yo0u9*;&d3KJ3%rs<_8`)$rQdNU(sCCaAX)L-K11hI=pvku@I zS}&QJCNPyT3C4B;jLtW4nhFdnGlYbMqPb*RrE)pb@9go{993A}_^`{!;w}*tJTP$e zGB_xh7J-Vz*dPXpmuQiMt&JbI0s7rncMjsFmt(`(gNR4jE#-aLW$$h(9RLV&E}5>Z zvzpKw%^HN32akR+Hk*wqp|H3a80*I7lhI@GdH(cx&?GlPDW;rv9kUm+2;FO z$;3T*MKOc+ux9}C%S9$!a7jTW=-}!XnTCra{2ngMy?wijd7{RiQrkl>dtY&Ip5iy+i|#9H zzqE*Ed9FtX$b>ewZ(U@&wyYv;KIiz7xDSG;>!CpXuw`lBd+8!6R(#cy1>Y2wuIZs~ z`aCk|v08%4rCX`vWz>$L5DPl44M_vq9NX$3O+^%LA{+2W9L`9I`d!E^Ut@C-8>)y% z+z1xth#Zt5y+d3wcb+@C9my5xfZzSb2n<&mR~O{^ZZB`5&&?T;_PMQ;lqc19MG(dF zR5948`JFW?w~o<0$5h=l=nhZ071}GB+*irRQJ>#o3qw0RCvSmG}(R#R3k6Mu;O4@JlqLg2v z9_gZPlDA~>sqwE<#c^MvHoWHS6K8Igl=Yc}!tc6Kj4CF;nmEefFesbhArP%3{_1Uz>TG z!~^WJ=Xx8vzwA-5w z)Lh?t=eTt1i+bj)ujJGS!+a!4-N${Sym=}5s<(w^iM6SR=W1){%?cOQ`EN%Qf}=VBHdbD+gLY1JN5&0;_x|ZyN(3{vRfaD-8 zO){Y%B11eGy3;tv5RiBD!!B-HYg++4x>C%riNps&r5oSi8T6HJ8Ir*$J*tvyJyNL981BO*>4GM3&-XN_6yZ`al4 zy?#Qx->2oY`I$KPfEE#~*Lv#!dSd?0Y+*iWu5f$q

  • +p4@ArDQ5azEo%1~izOlP zRPGu1X_=qhg914g*ax3vXv&6xlpP!s_eJ=mqm~Ws1}g`yy`N5$%ZpPsQ%C5(HvBj-b&MER4!4 zn5Oovt_C1YhniU>+oGhja|Z?nLSrfCSSRl^o%kzrGd|cc4LTg>L2YGc;qy6avmqse z5^w1sj`Q33fMxk?!gSaSfE;BNO_SkN2Tpj&x{bY``iW#T)>lIdQSIs@BX*{wqKc#T z(v|IY>x>-EpoGQuA@k&8CM&wQ*Wx>7%4t)<;L9PSH?5wIJ~J9P*4Ge-kgki@bIR+K z;EKkIBos??r)L#BWV(HPx7f4fQdOCVv>r!*!tvN>N__5CL+ZskT_)6KeV0|e^y+}> zG`W?H>%o2T?9*3(S=rW2MVXJiPTl4a5qCUgEb5-ACFti=?WK2)ySc4Cx)0yiq>AQI z8_Sc3y^**NMJ{E_$jRS37oEu_t*k;uaSC8<0GhmxA+CAGzv=&sv=}e#RfHQXZIscsRr}o`9QJkxpE*`FDtvh z0VvZWmUeO}^ZtIIH5PX!edgJ+l7##1z9T(y^amGfSn{+%TI1)@piOxuV!)P9*S5J4m4f7z3sB zv&V6y2K{I|s8L%S8h>aoo8VTlQ_}{=!-+$}X$T#3^y8Z2GUv>06ZjB?RNIMuTbTww8!m*aG zzHKdWK!htHfH_XaiN;sj)IO5|$gbUnbc!csuno|?IWMSbP19AS(oRO%xd_sD-ULtR z;$|4^N*7jX@lQ;F>UpZ?i(h}fhyTjUdqf9gYv+~yY%{|a+a5f&*AU}EFD#*j)wi`d zLOfZEcWj;@m;v)_h|bO7hE;UO3w8P)aJ!LhPsb@f-;Iq9a5E5Z58@!bleko;Mh4^Tr{h`yLr-3RLgm!o!Qbf9Ð?cbXTg*3w&c> z*L8uf2?}S>0=;cr>8_JntEE8ED9T&E~Oz4jSB)bcw7NQxpc#) z;zsLI(jFIwb_{>?S)v+ZCN$DXMcCR+AuAFk`i=h*RIaXirD<>>JBM5Gc@1aFS){yT z{m$(DOOAj+bt{XIuX;BPyM{H^z|Urx6%8;!0!Th;@t$r8UR%C$cj*yTdrw`EqPZ2v zbj994X8jd$b@lXV!V2}5{G>o`sFlcEr#hBx-<7Ri-0D(ZoaYDlI|o$(MY|9Di98UV zyWwV!^Fr*dV?de!9RTRv#JqAko8fty7d@)buCG#b9eUL1PF2n;2RJFw=OXQlx09{> zuw?o{gVlq<=*W}-&RZ;`iFe8iMOJk?Pn$M-J|2^VzPO`UfQwcR8SXn8E!B1#S>E2; zFguvS>(v=?JLP5UWW~ArOR4Dh{Yg3&a=VL8h<8J$3-3{DovFCqT!-??7pe=PIuR;1 zp9I;pd5d+-kdyNC!fa_s&*?;)pmXc0R6`fzOV1^UY zloKVM?t(d6AhPzU_k;CvvLB4%sr&Q>BKBFJs<64zuq>tMd}c>{ov&9#=3@fy2Px`u zul$IZW&a2fam6l2hUbHghO+Fr8I{2K-CpqRA1h?&@+V)-3hu@&1hb2m@=>AL;=z{! z;772L@QQN=dtZj@@--Br9(lfDUs(JrT70Ps2>qZZe%2PhbG`LlxuhAB;`9ldXqsFevN@blk##Bos~fa2V08gOYw@04 zZ5^SHs~q3Tg0Kp)X3knY{U|?&Gg7~JeSlO;Y#kBG77n4B(TA8DgyM|IDBhm&etBjY ztK~g#{75T)!#_;I@nG-7_pyxvz40fu+NI`KwMqWX8ssVKBzsm@c%J##Om0)myOGZp zFX*GrtzSEo^H7qmri->IY$}a$cjv5lajEA}F%RR`f&e3Wj{9Y;O-=1;8D|Q%_wA@- z_Jab{$e#3Zp65#+k<34L5SEcX=sf z*G)RrVepowR#N$_{rAb*DWeCEAst1JD%jt`@?Ut!X*{p{qI6Dz=~IM$bI#MRRYT4Z z&JOi=8vQ^82CLsDx0{OU%#1U1gthxitA@Bi1>p)cD$U7y+1dNFoiZBamxlx8`!08B zKsF}7!eJRT+BiWBeV^R-X00cSS2t9Ssp#Db;|-tBO--)o9hZzVzG^VyZPoANZ?hC9 z``%cJDOSWpu0-qyy#1gm*=4ZYJ?7hdtI(3SOs}TjPHK(dd&hHYl({=(Rx8t0KP%Mw ajUi(SmeChky8inY6xP(zq|VqS_J06QRDcNp literal 0 HcmV?d00001 diff --git a/spine-corona/data/right-upper-leg.png b/spine-corona/data/right-upper-leg.png new file mode 100644 index 0000000000000000000000000000000000000000..df0b1166136cf5f616feaa7f6b6df4b0502f1517 GIT binary patch literal 5550 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 E1DezV?f?J) literal 0 HcmV?d00001 diff --git a/spine-corona/data/spineboy-skeleton.json b/spine-corona/data/spineboy-skeleton.json new file mode 100644 index 000000000..a51a9feeb --- /dev/null +++ b/spine-corona/data/spineboy-skeleton.json @@ -0,0 +1,101 @@ +{ +"bones": [ + { "name": "root", "length": 0 }, + { "name": "hip", "parent": "root", "length": 0, "x": 0.64, "y": 114.41 }, + { "name": "left upper leg", "parent": "hip", "length": 50.39, "x": 14.45, "y": 2.81, "rotation": -89.09 }, + { "name": "left lower leg", "parent": "left upper leg", "length": 56.45, "x": 51.78, "y": 3.46, "rotation": -16.65 }, + { "name": "left foot", "parent": "left lower leg", "length": 46.5, "x": 64.02, "y": -8.67, "rotation": 102.43 }, + { "name": "right upper leg", "parent": "hip", "length": 45.76, "x": -18.27, "rotation": -101.13 }, + { "name": "right lower leg", "parent": "right upper leg", "length": 58.52, "x": 50.21, "y": 0.6, "rotation": -10.7 }, + { "name": "right foot", "parent": "right lower leg", "length": 45.45, "x": 64.88, "y": 0.04, "rotation": 110.3 }, + { "name": "torso", "parent": "hip", "length": 85.82, "x": -6.42, "y": 1.97, "rotation": 94.95 }, + { "name": "neck", "parent": "torso", "length": 18.38, "x": 83.64, "y": -1.78, "rotation": 0.9 }, + { "name": "head", "parent": "neck", "length": 68.28, "x": 19.09, "y": 6.97, "rotation": -8.94 }, + { "name": "right shoulder", "parent": "torso", "length": 49.95, "x": 81.9, "y": 6.79, "rotation": 130.6 }, + { "name": "right arm", "parent": "right shoulder", "length": 36.74, "x": 49.95, "y": -0.12, "rotation": 40.12 }, + { "name": "right hand", "parent": "right arm", "length": 15.32, "x": 36.9, "y": 0.34, "rotation": 2.35 }, + { "name": "left shoulder", "parent": "torso", "length": 44.19, "x": 78.96, "y": -15.75, "rotation": -156.96 }, + { "name": "left arm", "parent": "left shoulder", "length": 35.62, "x": 44.19, "y": -0.01, "rotation": 28.16 }, + { "name": "left hand", "parent": "left arm", "length": 11.52, "x": 35.62, "y": 0.07, "rotation": 2.7 }, + { "name": "pelvis", "parent": "hip", "length": 0, "x": 1.41, "y": -6.57 } +], +"slots": [ + { "name": "template", "bone": "root", "color": "ff898c86" }, + { "name": "left shoulder", "bone": "left shoulder", "attachment": "left-shoulder" }, + { "name": "left arm", "bone": "left arm", "attachment": "left-arm" }, + { "name": "left hand", "bone": "left hand", "attachment": "left-hand" }, + { "name": "left foot", "bone": "left foot", "attachment": "left-foot" }, + { "name": "left lower leg", "bone": "left lower leg", "attachment": "left-lower-leg" }, + { "name": "left upper leg", "bone": "left upper leg", "attachment": "left-upper-leg" }, + { "name": "pelvis", "bone": "pelvis", "attachment": "pelvis" }, + { "name": "right foot", "bone": "right foot", "attachment": "right-foot" }, + { "name": "right lower leg", "bone": "right lower leg", "attachment": "right-lower-leg" }, + { "name": "right upper leg", "bone": "right upper leg", "attachment": "right-upper-leg" }, + { "name": "torso", "bone": "torso", "attachment": "torso" }, + { "name": "neck", "bone": "neck", "attachment": "neck" }, + { "name": "head", "bone": "head", "attachment": "head" }, + { "name": "eyes", "bone": "head", "attachment": "eyes" }, + { "name": "right shoulder", "bone": "right shoulder", "attachment": "right-shoulder" }, + { "name": "right arm", "bone": "right arm", "attachment": "right-arm" }, + { "name": "right hand", "bone": "right hand", "attachment": "right-hand" } +], +"skins": { + "default": { + "template": { + "spineboy": { "y": 167.82, "width": 145, "height": 341 } + }, + "left shoulder": { + "left-shoulder": { "x": 23.74, "y": 0.11, "rotation": 62.01, "width": 34, "height": 53 } + }, + "left arm": { + "left-arm": { "x": 15.11, "y": -0.44, "rotation": 33.84, "width": 35, "height": 29 } + }, + "left hand": { + "left-hand": { "x": 0.75, "y": 1.86, "rotation": 31.14, "width": 35, "height": 38 } + }, + "left foot": { + "left-foot": { "x": 24.35, "y": 8.88, "rotation": 3.32, "width": 65, "height": 30 } + }, + "left lower leg": { + "left-lower-leg": { "x": 24.55, "y": -1.92, "rotation": 105.75, "width": 49, "height": 64 } + }, + "left upper leg": { + "left-upper-leg": { "x": 26.12, "y": -1.85, "rotation": 89.09, "width": 33, "height": 67 } + }, + "pelvis": { + "pelvis": { "x": -4.83, "y": 10.62, "width": 63, "height": 47 } + }, + "right foot": { + "right-foot": { "x": 19.02, "y": 8.47, "rotation": 1.52, "width": 67, "height": 30 } + }, + "right lower leg": { + "right-lower-leg": { "x": 23.28, "y": -2.59, "rotation": 111.83, "width": 51, "height": 64 } + }, + "right upper leg": { + "right-upper-leg": { "x": 23.03, "y": 0.25, "rotation": 101.13, "width": 44, "height": 70 } + }, + "torso": { + "torso": { "x": 44.57, "y": -7.08, "rotation": -94.95, "width": 68, "height": 92 } + }, + "neck": { + "neck": { "x": 9.42, "y": -3.66, "rotation": -100.15, "width": 34, "height": 28 } + }, + "head": { + "head": { "x": 53.94, "y": -5.75, "rotation": -86.9, "width": 121, "height": 132 } + }, + "eyes": { + "eyes": { "x": 28.94, "y": -32.92, "rotation": -86.9, "width": 34, "height": 27 }, + "eyes-closed": { "x": 28.77, "y": -32.86, "rotation": -86.9, "width": 34, "height": 27 } + }, + "right shoulder": { + "right-shoulder": { "x": 25.86, "y": 0.03, "rotation": 134.44, "width": 52, "height": 51 } + }, + "right arm": { + "right-arm": { "x": 18.34, "y": -2.64, "rotation": 94.32, "width": 21, "height": 45 } + }, + "right hand": { + "right-hand": { "x": 6.82, "y": 1.25, "rotation": 91.96, "width": 32, "height": 32 } + } + } +} +} \ No newline at end of file diff --git a/spine-corona/data/spineboy-walk.json b/spine-corona/data/spineboy-walk.json new file mode 100644 index 000000000..b40e53a95 --- /dev/null +++ b/spine-corona/data/spineboy-walk.json @@ -0,0 +1,278 @@ +{ +"bones": { + "left upper leg": { + "rotate": [ + { "time": 0, "angle": -26.55 }, + { "time": 0.1333, "angle": -8.78 }, + { "time": 0.2666, "angle": 9.51 }, + { "time": 0.4, "angle": 30.74 }, + { "time": 0.5333, "angle": 25.33 }, + { "time": 0.6666, "angle": 26.11 }, + { "time": 0.8, "angle": -7.7 }, + { "time": 0.9333, "angle": -21.19 }, + { "time": 1.0666, "angle": -26.55 } + ], + "translate": [ + { "time": 0, "x": -3, "y": -2.25 }, + { "time": 0.4, "x": -2.18, "y": -2.25 }, + { "time": 1.0666, "x": -3, "y": -2.25 } + ] + }, + "right upper leg": { + "rotate": [ + { "time": 0, "angle": 42.45 }, + { "time": 0.1333, "angle": 52.1 }, + { "time": 0.2666, "angle": 5.96 }, + { "time": 0.5333, "angle": -16.93 }, + { "time": 0.6666, "angle": 1.89 }, + { + "time": 0.8, + "angle": 28.06, + "curve": [ 0.462, 0.11, 1, 1 ] + }, + { + "time": 0.9333, + "angle": 58.68, + "curve": [ 0.5, 0.02, 1, 1 ] + }, + { "time": 1.0666, "angle": 42.45 } + ], + "translate": [ + { "time": 0, "x": 8.11, "y": -2.36 }, + { "time": 0.1333, "x": 10.03, "y": -2.56 }, + { "time": 0.4, "x": 2.76, "y": -2.97 }, + { "time": 0.5333, "x": 2.76, "y": -2.81 }, + { "time": 0.9333, "x": 8.67, "y": -2.54 }, + { "time": 1.0666, "x": 8.11, "y": -2.36 } + ] + }, + "left lower leg": { + "rotate": [ + { "time": 0, "angle": -10.21 }, + { "time": 0.1333, "angle": -55.64 }, + { "time": 0.2666, "angle": -68.12 }, + { "time": 0.5333, "angle": 5.11 }, + { "time": 0.6666, "angle": -28.29 }, + { "time": 0.8, "angle": 4.08 }, + { "time": 0.9333, "angle": 3.53 }, + { "time": 1.0666, "angle": -10.21 } + ] + }, + "left foot": { + "rotate": [ + { "time": 0, "angle": -3.69 }, + { "time": 0.1333, "angle": -10.42 }, + { "time": 0.2666, "angle": -17.14 }, + { "time": 0.4, "angle": -2.83 }, + { "time": 0.5333, "angle": -3.87 }, + { "time": 0.6666, "angle": 2.78 }, + { "time": 0.8, "angle": 1.68 }, + { "time": 0.9333, "angle": -8.54 }, + { "time": 1.0666, "angle": -3.69 } + ] + }, + "right shoulder": { + "rotate": [ + { + "time": 0, + "angle": 20.89, + "curve": [ 0.264, 0, 0.75, 1 ] + }, + { + "time": 0.1333, + "angle": 3.72, + "curve": [ 0.272, 0, 0.841, 1 ] + }, + { "time": 0.6666, "angle": -278.28 }, + { "time": 1.0666, "angle": 20.89 } + ], + "translate": [ + { "time": 0, "x": -7.84, "y": 7.19 }, + { "time": 0.1333, "x": -6.36, "y": 6.42 }, + { "time": 0.6666, "x": -11.07, "y": 5.25 }, + { "time": 1.0666, "x": -7.84, "y": 7.19 } + ] + }, + "right arm": { + "rotate": [ + { + "time": 0, + "angle": -4.02, + "curve": [ 0.267, 0, 0.804, 0.99 ] + }, + { + "time": 0.1333, + "angle": -13.99, + "curve": [ 0.341, 0, 1, 1 ] + }, + { + "time": 0.6666, + "angle": 36.54, + "curve": [ 0.307, 0, 0.787, 0.99 ] + }, + { "time": 1.0666, "angle": -4.02 } + ] + }, + "right hand": { + "rotate": [ + { "time": 0, "angle": 22.92 }, + { "time": 0.4, "angle": -8.97 }, + { "time": 0.6666, "angle": 0.51 }, + { "time": 1.0666, "angle": 22.92 } + ] + }, + "left shoulder": { + "rotate": [ + { "time": 0, "angle": -1.47 }, + { "time": 0.1333, "angle": 13.6 }, + { "time": 0.6666, "angle": 280.74 }, + { "time": 1.0666, "angle": -1.47 } + ], + "translate": [ + { "time": 0, "x": -1.76, "y": 0.56 }, + { "time": 0.6666, "x": -2.47, "y": 8.14 }, + { "time": 1.0666, "x": -1.76, "y": 0.56 } + ] + }, + "left hand": { + "rotate": [ + { + "time": 0, + "angle": 11.58, + "curve": [ 0.169, 0.37, 0.632, 1.55 ] + }, + { + "time": 0.1333, + "angle": 28.13, + "curve": [ 0.692, 0, 0.692, 0.99 ] + }, + { + "time": 0.6666, + "angle": -27.42, + "curve": [ 0.117, 0.41, 0.738, 1.76 ] + }, + { "time": 0.8, "angle": -36.32 }, + { "time": 1.0666, "angle": 11.58 } + ] + }, + "left arm": { + "rotate": [ + { "time": 0, "angle": -8.27 }, + { "time": 0.1333, "angle": 18.43 }, + { "time": 0.6666, "angle": 0.88 }, + { "time": 1.0666, "angle": -8.27 } + ] + }, + "torso": { + "rotate": [ + { "time": 0, "angle": -10.28 }, + { + "time": 0.1333, + "angle": -15.38, + "curve": [ 0.545, 0, 1, 1 ] + }, + { + "time": 0.4, + "angle": -9.78, + "curve": [ 0.58, 0.17, 1, 1 ] + }, + { "time": 0.6666, "angle": -15.75 }, + { "time": 0.9333, "angle": -7.06 }, + { "time": 1.0666, "angle": -10.28 } + ], + "translate": [ + { "time": 0, "x": -3.67, "y": 1.68 }, + { "time": 0.1333, "x": -3.67, "y": 0.68 }, + { "time": 0.4, "x": -3.67, "y": 1.97 }, + { "time": 0.6666, "x": -3.67, "y": -0.14 }, + { "time": 1.0666, "x": -3.67, "y": 1.68 } + ] + }, + "right foot": { + "rotate": [ + { "time": 0, "angle": -5.25 }, + { "time": 0.2666, "angle": -4.08 }, + { "time": 0.4, "angle": -6.45 }, + { "time": 0.5333, "angle": -5.39 }, + { "time": 0.8, "angle": -11.68 }, + { "time": 0.9333, "angle": 0.46 }, + { "time": 1.0666, "angle": -5.25 } + ] + }, + "right lower leg": { + "rotate": [ + { "time": 0, "angle": -3.39 }, + { "time": 0.1333, "angle": -45.53 }, + { "time": 0.2666, "angle": -2.59 }, + { "time": 0.5333, "angle": -19.53 }, + { "time": 0.6666, "angle": -64.8 }, + { + "time": 0.8, + "angle": -82.56, + "curve": [ 0.557, 0.18, 1, 1 ] + }, + { "time": 1.0666, "angle": -3.39 } + ] + }, + "hip": { + "rotate": [ + { "time": 0, "angle": 0, "curve": "stepped" }, + { "time": 1.0666, "angle": 0 } + ], + "translate": [ + { "time": 0, "x": 0, "y": 0 }, + { + "time": 0.1333, + "x": 0, + "y": -7.61, + "curve": [ 0.272, 0.86, 1, 1 ] + }, + { "time": 0.4, "x": 0, "y": 8.7 }, + { "time": 0.5333, "x": 0, "y": -0.41 }, + { + "time": 0.6666, + "x": 0, + "y": -7.05, + "curve": [ 0.235, 0.89, 1, 1 ] + }, + { "time": 0.8, "x": 0, "y": 2.92 }, + { "time": 0.9333, "x": 0, "y": 6.78 }, + { "time": 1.0666, "x": 0, "y": 0 } + ] + }, + "neck": { + "rotate": [ + { "time": 0, "angle": 3.6 }, + { "time": 0.1333, "angle": 17.49 }, + { "time": 0.2666, "angle": 6.1 }, + { "time": 0.4, "angle": 3.45 }, + { "time": 0.5333, "angle": 5.17 }, + { "time": 0.6666, "angle": 18.36 }, + { "time": 0.8, "angle": 6.09 }, + { "time": 0.9333, "angle": 2.28 }, + { "time": 1.0666, "angle": 3.6 } + ] + }, + "head": { + "rotate": [ + { + "time": 0, + "angle": 3.6, + "curve": [ 0, 0, 0.704, 1.61 ] + }, + { "time": 0.1666, "angle": -0.2 }, + { "time": 0.2666, "angle": 6.1 }, + { "time": 0.4, "angle": 3.45 }, + { + "time": 0.5333, + "angle": 5.17, + "curve": [ 0, 0, 0.704, 1.61 ] + }, + { "time": 0.7, "angle": 1.1 }, + { "time": 0.8, "angle": 6.09 }, + { "time": 0.9333, "angle": 2.28 }, + { "time": 1.0666, "angle": 3.6 } + ] + } +} +} \ No newline at end of file diff --git a/spine-corona/data/torso.png b/spine-corona/data/torso.png new file mode 100644 index 0000000000000000000000000000000000000000..d5a318e7289f8269067bd87a67bb93480340c9dc GIT binary patch literal 8987 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 W2|_EnhyMPqq9pfDwp!XO target) then return i end + end + return -1 +end + +Animation.CurveTimeline = {} +function Animation.CurveTimeline.new () + local LINEAR = 0 + local STEPPED = -1 + local BEZIER_SEGMENTS = 10 + + local self = { + curves = {} + } + + function self:setLinear (keyframeIndex) + self.curves[keyframeIndex * 6] = LINEAR + end + + function self:setStepped (keyframeIndex) + self.curves[keyframeIndex * 6] = STEPPED + end + + function self:setCurve (keyframeIndex, cx1, cy1, cx2, cy2) + local subdiv_step = 1 / BEZIER_SEGMENTS + local subdiv_step2 = subdiv_step * subdiv_step + local subdiv_step3 = subdiv_step2 * subdiv_step + local pre1 = 3 * subdiv_step + local pre2 = 3 * subdiv_step2 + local pre4 = 6 * subdiv_step2 + local pre5 = 6 * subdiv_step3 + local tmp1x = -cx1 * 2 + cx2 + local tmp1y = -cy1 * 2 + cy2 + local tmp2x = (cx1 - cx2) * 3 + 1 + local tmp2y = (cy1 - cy2) * 3 + 1 + local i = keyframeIndex * 6 + local curves = self.curves + curves[i] = cx1 * pre1 + tmp1x * pre2 + tmp2x * subdiv_step3 + curves[i + 1] = cy1 * pre1 + tmp1y * pre2 + tmp2y * subdiv_step3 + curves[i + 2] = tmp1x * pre4 + tmp2x * pre5 + curves[i + 3] = tmp1y * pre4 + tmp2y * pre5 + curves[i + 4] = tmp2x * pre5 + curves[i + 5] = tmp2y * pre5 + end + + function self:getCurvePercent (keyframeIndex, percent) + local curveIndex = keyframeIndex * 6 + local curves = self.curves + local dfx = curves[curveIndex] + if not dfx then return percent end -- linear + if dfx == STEPPED then return 0 end + local dfy = curves[curveIndex + 1] + local ddfx = curves[curveIndex + 2] + local ddfy = curves[curveIndex + 3] + local dddfx = curves[curveIndex + 4] + local dddfy = curves[curveIndex + 5] + local x = dfx + local y = dfy + local i = BEZIER_SEGMENTS - 2 + while true do + if x >= percent then + local lastX = x - dfx + local lastY = y - dfy + return lastY + (y - lastY) * (percent - lastX) / (x - lastX) + end + if i == 0 then break end + i = i - 1 + dfx = dfx + ddfx + dfy = dfy + ddfy + ddfx = ddfx + dddfx + ddfy = ddfy + dddfy + x = x + dfx + y = y + dfy + end + return y + (1 - y) * (percent - x) / (1 - x) -- Last point is 1,1. + end + + return self +end + +Animation.RotateTimeline = {} +function Animation.RotateTimeline.new () + local LAST_FRAME_TIME = -2 + local FRAME_VALUE = 1 + + local self = Animation.CurveTimeline.new() + self.frames = {} + + function self:getDuration () + return self.frames[#self.frames - 1] + end + + function self:getKeyframeCount () + return (#self.frames + 1) / 2 + end + + function self:setKeyframe (keyframeIndex, time, value) + keyframeIndex = keyframeIndex * 2 + self.frames[keyframeIndex] = time + self.frames[keyframeIndex + 1] = value + end + + function self:apply (skeleton, time, alpha) + local frames = self.frames + if time < frames[0] then return end -- Time is before first frame. + + local bone = skeleton.bones[self.boneIndex] + + if time >= frames[#frames - 1] then -- Time is after last frame. + local amount = bone.data.rotation + frames[#frames] - bone.rotation + while amount > 180 do + amount = amount - 360 + end + while amount < -180 do + amount = amount + 360 + end + bone.rotation = bone.rotation + amount * alpha + return + end + + -- Interpolate between the last frame and the current frame. + local frameIndex = binarySearch(frames, time, 2) + local lastFrameValue = frames[frameIndex - 1] + local frameTime = frames[frameIndex] + local percent = 1 - (time - frameTime) / (frames[frameIndex + LAST_FRAME_TIME] - frameTime) + if percent < 0 then percent = 0 elseif percent > 1 then percent = 1 end + percent = self:getCurvePercent(frameIndex / 2 - 1, percent) + + local amount = frames[frameIndex + FRAME_VALUE] - lastFrameValue + while amount > 180 do + amount = amount - 360 + end + while amount < -180 do + amount = amount + 360 + end + amount = bone.data.rotation + (lastFrameValue + amount * percent) - bone.rotation + while amount > 180 do + amount = amount - 360 + end + while amount < -180 do + amount = amount + 360 + end + bone.rotation = bone.rotation + amount * alpha + end + + return self +end + +Animation.TranslateTimeline = {} +function Animation.TranslateTimeline.new () + local LAST_FRAME_TIME = -3 + local FRAME_X = 1 + local FRAME_Y = 2 + + local self = Animation.CurveTimeline.new() + self.frames = {} + + function self:getDuration () + return self.frames[#self.frames - 2] + end + + function self:getKeyframeCount () + return (#self.frames + 1) / 3 + end + + function self:setKeyframe (keyframeIndex, time, x, y) + keyframeIndex = keyframeIndex * 3 + self.frames[keyframeIndex] = time + self.frames[keyframeIndex + 1] = x + self.frames[keyframeIndex + 2] = y + end + + function self:apply (skeleton, time, alpha) + local frames = self.frames + if time < frames[0] then return end -- Time is before first frame. + + local bone = skeleton.bones[self.boneIndex] + + if time >= frames[#frames - 2] then -- Time is after last frame. + bone.x = bone.x + (bone.data.x + frames[#frames - 1] - bone.x) * alpha + bone.y = bone.y + (bone.data.y + frames[#frames] - bone.y) * alpha + return + end + + -- Interpolate between the last frame and the current frame. + local frameIndex = binarySearch(frames, time, 3) + local lastFrameX = frames[frameIndex - 2] + local lastFrameY = frames[frameIndex - 1] + local frameTime = frames[frameIndex] + local percent = 1 - (time - frameTime) / (frames[frameIndex + LAST_FRAME_TIME] - frameTime) + if percent < 0 then percent = 0 elseif percent > 1 then percent = 1 end + percent = self:getCurvePercent(frameIndex / 3 - 1, percent) + + bone.x = bone.x + (bone.data.x + lastFrameX + (frames[frameIndex + FRAME_X] - lastFrameX) * percent - bone.x) * alpha + bone.y = bone.y + (bone.data.y + lastFrameY + (frames[frameIndex + FRAME_Y] - lastFrameY) * percent - bone.y) * alpha + end + + return self +end + +Animation.ScaleTimeline = {} +function Animation.ScaleTimeline.new () + local LAST_FRAME_TIME = -3 + local FRAME_X = 1 + local FRAME_Y = 2 + + local self = Animation.TranslateTimeline.new() + + function self:apply (skeleton, time, alpha) + local frames = self.frames + if time < frames[0] then return end -- Time is before first frame. + + local bone = skeleton.bones[self.boneIndex] + + if time >= frames[#frames - 2] then -- Time is after last frame. + bone.scaleX = bone.scaleX + (bone.data.scaleX - 1 + frames[#frames - 1] - bone.scaleX) * alpha + bone.scaleY = bone.scaleY + (bone.data.scaleY - 1 + frames[#frames] - bone.scaleY) * alpha + return + end + + -- Interpolate between the last frame and the current frame. + local frameIndex = binarySearch(frames, time, 3) + local lastFrameX = frames[frameIndex - 2] + local lastFrameY = frames[frameIndex - 1] + local frameTime = frames[frameIndex] + local percent = 1 - (time - frameTime) / (frames[frameIndex + LAST_FRAME_TIME] - frameTime) + if percent < 0 then percent = 0 elseif percent > 1 then percent = 1 end + percent = self:getCurvePercent(frameIndex / 3 - 1, percent) + + bone.scaleX = bone.scaleX + (bone.data.scaleX - 1 + lastFrameX + (frames[frameIndex + FRAME_X] - lastFrameX) * percent - bone.scaleX) * alpha + bone.scaleY = bone.scaleY + (bone.data.scaleY - 1 + lastFrameY + (frames[frameIndex + FRAME_Y] - lastFrameY) * percent - bone.scaleY) * alpha + end + + return self +end + +Animation.ColorTimeline = {} +function Animation.ColorTimeline.new () + local LAST_FRAME_TIME = -5 + local FRAME_R = 1 + local FRAME_G = 2 + local FRAME_B = 3 + local FRAME_A = 4 + + local self = Animation.CurveTimeline.new() + self.frames = {} + + function self:getDuration () + return self.frames[#self.frames - 4] + end + + function self:getKeyframeCount () + return (#self.frames + 1) / 5 + end + + function self:setKeyframe (keyframeIndex, time, r, g, b, a) + keyframeIndex = keyframeIndex * 5 + self.frames[keyframeIndex] = time + self.frames[keyframeIndex + 1] = r + self.frames[keyframeIndex + 2] = g + self.frames[keyframeIndex + 3] = b + self.frames[keyframeIndex + 4] = a + end + + function self:apply (skeleton, time, alpha) + local frames = self.frames + if time < frames[0] then return end -- Time is before first frame. + + local slot = skeleton.slots[self.slotIndex] + + if time >= frames[#frames - 4] then -- Time is after last frame. + local r = frames[#frames - 3] + local g = frames[#frames - 2] + local b = frames[#frames - 1] + local a = frames[#frames] + slot:setColor(r, g, b, a) + return + end + + -- Interpolate between the last frame and the current frame. + local frameIndex = binarySearch(frames, time, 5) + local lastFrameR = frames[frameIndex - 4] + local lastFrameG = frames[frameIndex - 3] + local lastFrameB = frames[frameIndex - 2] + local lastFrameA = frames[frameIndex - 1] + local frameTime = frames[frameIndex] + local percent = 1 - (time - frameTime) / (frames[frameIndex + LAST_FRAME_TIME] - frameTime) + if percent < 0 then percent = 0 elseif percent > 255 then percent = 255 end + percent = self:getCurvePercent(frameIndex / 5 - 1, percent) + + local r = lastFrameR + (frames[frameIndex + FRAME_R] - lastFrameR) * percent + local g = lastFrameG + (frames[frameIndex + FRAME_G] - lastFrameG) * percent + local b = lastFrameB + (frames[frameIndex + FRAME_B] - lastFrameB) * percent + local a = lastFrameA + (frames[frameIndex + FRAME_A] - lastFrameA) * percent + if alpha < 1 then + slot:setColor(slot.r + (r - color.r) * alpha, slot.g + (g - color.g) * alpha, slot.b + (b - color.b) * alpha, slot.a + (a - color.a) * alpha) + else + slot:setColor(r, g, b, a) + end + end + + return self +end + +Animation.AttachmentTimeline = {} +function Animation.AttachmentTimeline.new () + local self = Animation.CurveTimeline.new() + self.frames = {} + self.attachmentNames = {} + + function self:getDuration () + return self.frames[#self.frames] + end + + function self:getKeyframeCount () + return #self.frames + 1 + end + + function self:setKeyframe (keyframeIndex, time, attachmentName) + self.frames[keyframeIndex] = time + self.attachmentNames[keyframeIndex] = attachmentName + end + + function self:apply (skeleton, time, alpha) + local frames = self.frames + if time < frames[0] then return end -- Time is before first frame. + + local frameIndex + if time >= frames[#frames] then -- Time is after last frame. + frameIndex = #frames + else + frameIndex = binarySearch(frames, time, 1) - 1 + end + + local attachmentName = self.attachmentNames[frameIndex] + local attachment + if attachmentName then attachment = skeleton:getAttachment(self.slotName, attachmentName) end + skeleton:findSlot(self.slotName):setAttachment(attachment) + end + + return self +end + +return Animation diff --git a/spine-corona/spine/AttachmentResolver.lua b/spine-corona/spine/AttachmentResolver.lua new file mode 100644 index 000000000..73c953544 --- /dev/null +++ b/spine-corona/spine/AttachmentResolver.lua @@ -0,0 +1,30 @@ + +local AttachmentResolver = { + failed = {} +} +function AttachmentResolver.new () + local self = { + images = {} + } + + function self:resolve (skeleton, attachment) + local image = self:createImage(attachment) + if image then + image:setReferencePoint(display.CenterReferencePoint); + image.width = attachment.width + image.height = attachment.height + else + print("Error creating image: " .. attachment.name) + image = AttachmentResolver.failed + end + skeleton.images[attachment] = image + return image + end + + function self:createImage (attachment) + return display.newImage(attachment.name .. ".png") + end + + return self +end +return AttachmentResolver diff --git a/spine-corona/spine/Bone.lua b/spine-corona/spine/Bone.lua new file mode 100644 index 000000000..f22591324 --- /dev/null +++ b/spine-corona/spine/Bone.lua @@ -0,0 +1,54 @@ + +local Bone = {} +function Bone.new (data, parent) + if not data then error("data cannot be nil", 2) end + + local self = { + data = data, + parent = parent + } + + function self:updateWorldTransform (flipX, flipY) + local parent = self.parent + if parent then + self.worldX = self.x * parent.m00 + self.y * parent.m01 + parent.worldX + self.worldY = self.x * parent.m10 + self.y * parent.m11 + parent.worldY + self.worldScaleX = parent.worldScaleX * self.scaleX + self.worldScaleY = parent.worldScaleY * self.scaleY + self.worldRotation = parent.worldRotation + self.rotation + else + self.worldX = self.x + self.worldY = self.y + self.worldScaleX = self.scaleX + self.worldScaleY = self.scaleY + self.worldRotation = self.rotation + end + local radians = math.rad(self.worldRotation) + local cos = math.cos(radians) + local sin = math.sin(radians) + self.m00 = cos * self.worldScaleX + self.m10 = sin * self.worldScaleX + self.m01 = -sin * self.worldScaleY + self.m11 = cos * self.worldScaleY + if flipX then + self.m00 = -self.m00 + self.m01 = -self.m01 + end + if flipY then + self.m10 = -self.m10 + self.m11 = -self.m11 + end + end + + function self:setToBindPose () + local data = self.data + self.x = data.x + self.y = data.y + self.rotation = data.rotation + self.scaleX = data.scaleX + self.scaleY = data.scaleY + end + + return self +end +return Bone diff --git a/spine-corona/spine/BoneData.lua b/spine-corona/spine/BoneData.lua new file mode 100644 index 000000000..9b3edc330 --- /dev/null +++ b/spine-corona/spine/BoneData.lua @@ -0,0 +1,13 @@ + +local BoneData = {} +function BoneData.new (name, parent) + if not name then error("name cannot be nil", 2) end + + local self = { + name = name, + parent = parent + } + + return self +end +return BoneData diff --git a/spine-corona/spine/RegionAttachment.lua b/spine-corona/spine/RegionAttachment.lua new file mode 100644 index 000000000..20c8d6599 --- /dev/null +++ b/spine-corona/spine/RegionAttachment.lua @@ -0,0 +1,12 @@ + +local RegionAttachment = {} +function RegionAttachment.new (name) + if not name then error("name cannot be nil", 2) end + + local self = { + name = name + } + + return self +end +return RegionAttachment diff --git a/spine-corona/spine/Skeleton.lua b/spine-corona/spine/Skeleton.lua new file mode 100644 index 000000000..0dbe95ec4 --- /dev/null +++ b/spine-corona/spine/Skeleton.lua @@ -0,0 +1,172 @@ + +local utils = require "spine.utils" +local Bone = require "spine.Bone" +local Slot = require "spine.Slot" +local AttachmentResolver = require "spine.AttachmentResolver" + +local Skeleton = {} +function Skeleton.new (skeletonData, group) + if not skeletonData then error("skeletonData cannot be nil", 2) end + + local self = group or display.newGroup() + self.data = skeletonData + self.bones = {} + self.slots = {} + self.drawOrder = {} + self.images = {} + + for i,boneData in ipairs(skeletonData.bones) do + local parent + if boneData.parent then parent = self.bones[utils.indexOf(skeletonData.bones, boneData.parent)] end + table.insert(self.bones, Bone.new(boneData, parent)) + end + + for i,slotData in ipairs(skeletonData.slots) do + local bone = self.bones[utils.indexOf(skeletonData.bones, slotData.boneData)] + local slot = Slot.new(slotData, self, bone) + table.insert(self.slots, slot) + table.insert(self.drawOrder, slot) + end + + function self:updateWorldTransform () + for i,bone in ipairs(self.bones) do + bone:updateWorldTransform(self.flipX, self.flipY) + end + + for i,slot in ipairs(self.drawOrder) do + if slot.attachment then + local image = self.images[slot.attachment] + if not image then image = self.data.attachmentResolver:resolve(self, slot.attachment) end + if image ~= AttachmentResolver.failed then + image.x = slot.bone.worldX + slot.attachment.x * slot.bone.m00 + slot.attachment.y * slot.bone.m01 + image.y = -(slot.bone.worldY + slot.attachment.x * slot.bone.m10 + slot.attachment.y * slot.bone.m11) + image.rotation = -(slot.bone.worldRotation + slot.attachment.rotation) + image.xScale = slot.bone.worldScaleX + slot.attachment.scaleX - 1 + image.yScale = slot.bone.worldScaleY + slot.attachment.scaleY - 1 + if self.flipX then + image.xScale = -image.xScale + image.rotation = -image.rotation + end + if self.flipY then + image.yScale = -image.yScale + image.rotation = -image.rotation + end + image:setFillColor(slot.r, slot.g, slot.b, slot.a) + self:insert(image) + end + end + end + + if self.debug then + for i,bone in ipairs(self.bones) do + if not bone.line then bone.line = display.newLine(0, 0, bone.data.length, 0) end + bone.line.x = bone.worldX + bone.line.y = -bone.worldY + bone.line.rotation = -bone.worldRotation + if self.flipX then + bone.line.xScale = -1 + bone.line.rotation = -bone.line.rotation + else + bone.line.xScale = 1 + end + if self.flipY then + bone.line.yScale = -1 + bone.line.rotation = -bone.line.rotation + else + bone.line.yScale = 1 + end + bone.line:setColor(255, 0, 0) + self:insert(bone.line) + + if not bone.circle then bone.circle = display.newCircle(0, 0, 3) end + bone.circle.x = bone.worldX + bone.circle.y = -bone.worldY + bone.circle:setFillColor(0, 255, 0) + self:insert(bone.circle) + end + end + end + + function self:setToBindPose () + self:setBonesToBindPose() + self:setSlotsToBindPose() + end + + function self:setBonesToBindPose () + for i,bone in ipairs(self.bones) do + bone:setToBindPose() + end + end + + function self:setSlotsToBindPose () + for i,slot in ipairs(self.slots) do + slot:setToBindPose() + end + end + + function self:getRootBone () + return self.bones[1] + end + + function self:findSlot (slotName) + if not slotName then error("slotName cannot be nil.", 2) end + for i,slot in ipairs(self.slots) do + if slot.data.name == slotName then return slot end + end + return nil + end + + function self:setSkin (skinName) + local newSkin + if skinName then + newSkin = self.data:findSkin(skinName) + if not newSkin then error("Skin not found: " .. skinName, 2) end + if self.skin then + -- Attach all attachments from the new skin if the corresponding attachment from the old skin is currently attached. + for k,v in self.skin.attachments do + local attachment = v[3] + local slotIndex = v[1] + local slot = self.slots[slotIndex] + if slot.attachment == attachment then + local name = v[2] + local newAttachment = newSkin:getAttachment(slotIndex, name) + if newAttachment then slot:setAttachment(newAttachment) end + end + end + end + end + self.skin = newSkin + end + + function self:getAttachment (slotName, attachmentName) + if not slotName then error("slotName cannot be nil.", 2) end + if not attachmentName then error("attachmentName cannot be nil.", 2) end + local slotIndex = self.data:findSlotIndex(slotName) + if slotIndex == -1 then error("Slot not found: " .. slotName, 2) end + if self.data.defaultSkin then + local attachment = self.data.defaultSkin:getAttachment(slotIndex, attachmentName) + if attachment then return attachment end + end + if self.skin then return self.skin:getAttachment(slotIndex, attachmentName) end + return nil + end + + function self:setAttachment (slotName, attachmentName) + if not slotName then error("slotName cannot be nil.", 2) end + if not attachmentName then error("attachmentName cannot be nil.", 2) end + for i,slot in ipairs(self.slots) do + if slot.data.name == slotName then + slot:setAttachment(self:getAttachment(slotName, attachmentName)) + return + end + end + error("Slot not found: " + slotName, 2) + end + + function self:update (delta) + self.time = self.time + delta + end + + return self +end +return Skeleton diff --git a/spine-corona/spine/SkeletonData.lua b/spine-corona/spine/SkeletonData.lua new file mode 100644 index 000000000..1eb3001a5 --- /dev/null +++ b/spine-corona/spine/SkeletonData.lua @@ -0,0 +1,55 @@ + +local SkeletonData = {} +function SkeletonData.new (attachmentResolver) + if not attachmentResolver then error("attachmentResolver cannot be nil", 2) end + + local self = { + attachmentResolver = attachmentResolver, + bones = {}, + slots = {}, + skins = {} + } + + function self:findBone (boneName) + if not boneName then error("boneName cannot be nil.", 2) end + for i,bone in ipairs(self.bones) do + if bone.name == boneName then return bone end + end + return nil + end + + function self:findBoneIndex (boneName) + if not boneName then error("boneName cannot be nil.", 2) end + for i,bone in ipairs(self.bones) do + if bone.name == boneName then return i end + end + return -1 + end + + function self:findSlot (slotName) + if not slotName then error("slotName cannot be nil.", 2) end + for i,slot in ipairs(self.slots) do + if slot.name == slotName then return slot end + end + return nil + end + + function self:findSlotIndex (slotName) + if not slotName then error("slotName cannot be nil.", 2) end + for i,slot in ipairs(self.slots) do + if slot.name == slotName then return i end + end + return -1 + end + + function self:findSkin (skinName) + if not skinName then error("skinName cannot be nil.", 2) end + for i,skin in ipairs(self.skins) do + if skin.name == skinName then return skin end + end + return nil + end + + return self +end +return SkeletonData diff --git a/spine-corona/spine/SkeletonJson.lua b/spine-corona/spine/SkeletonJson.lua new file mode 100644 index 000000000..a6a5cdb5f --- /dev/null +++ b/spine-corona/spine/SkeletonJson.lua @@ -0,0 +1,255 @@ + +local utils = require "spine.utils" +local SkeletonData = require "spine.SkeletonData" +local BoneData = require "spine.BoneData" +local SlotData = require "spine.SlotData" +local Skin = require "spine.Skin" +local RegionAttachment = require "spine.RegionAttachment" +local AttachmentResolver = require "spine.AttachmentResolver" +local Animation = require "spine.Animation" +local json = require "json" + +local TIMELINE_SCALE = "scale" +local TIMELINE_ROTATE = "rotate" +local TIMELINE_TRANSLATE = "translate" +local TIMELINE_ATTACHMENT = "attachment" +local TIMELINE_COLOR = "color" + +local ATTACHMENT_REGION = "region" +local ATTACHMENT_ANIMATED_REGION = "animatedRegion" + +local SkeletonJson = {} +function SkeletonJson.new (attachmentResolver) + if not attachmentResolver then attachmentResolver = AttachmentResolver.new() end + + local self = { + attachmentResolver = attachmentResolver, + scale = 1 + } + + function self:readSkeletonDataFile (fileName, base) + return self:readSkeletonData(utils.readFile(fileName, base)) + end + + local readAttachment + + function self:readSkeletonData (jsonText) + local skeletonData = SkeletonData.new(self.attachmentResolver) + + local root = json.decode(jsonText) + if not root then error("Invalid JSON: " .. jsonText, 2) end + + -- Bones. + for i,boneMap in ipairs(root["bones"]) do + local boneName = boneMap["name"] + local parent = nil + local parentName = boneMap["parent"] + if parentName then + parent = skeletonData:findBone(parentName) + if not parent then error("Parent bone not found: " .. parentName) end + end + local boneData = BoneData.new(boneName, parent) + boneData.length = (boneMap["length"] or 0) * self.scale + boneData.x = (boneMap["x"] or 0) * self.scale + boneData.y = (boneMap["y"] or 0) * self.scale + boneData.rotation = (boneMap["rotation"] or 0) + boneData.scaleX = (boneMap["scaleX"] or 1) + boneData.scaleY = (boneMap["scaleY"] or 1) + table.insert(skeletonData.bones, boneData) + end + + -- Slots. + if root["slots"] then + for i,slotMap in ipairs(root["slots"]) do + local slotName = slotMap["name"] + local boneName = slotMap["bone"] + local boneData = skeletonData:findBone(boneName) + if not boneData then error("Slot bone not found: " .. boneName) end + local slotData = SlotData.new(slotName, boneData) + + local color = slotMap["color"] + if color then + slotData:setColor( + tonumber(color:sub(1, 2), 16), + tonumber(color:sub(3, 4), 16), + tonumber(color:sub(5, 6), 16), + tonumber(color:sub(7, 8), 16) + ) + end + + slotData.attachmentName = slotMap["attachment"] + + table.insert(skeletonData.slots, slotData) + end + end + + -- Skins. + map = root["skins"] + if map then + for skinName,skinMap in pairs(map) do + local skin = Skin.new(skinName) + for slotName,slotMap in pairs(skinMap) do + local slotIndex = skeletonData:findSlotIndex(slotName) + for attachmentName,attachmentMap in pairs(slotMap) do + local attachment = readAttachment(attachmentName, attachmentMap, self.scale) + skin:addAttachment(slotIndex, attachmentName, attachment) + end + end + if skin.name == "default" then + skeletonData.defaultSkin = skin + else + table.insert(skeletonData.skins, skin) + end + end + end + + return skeletonData + end + + readAttachment = function (name, map, scale) + name = map["name"] or name + local attachment + local type = map["type"] or ATTACHMENT_REGION + if type == ATTACHMENT_REGION then + attachment = RegionAttachment.new(name) + else + error("Unknown attachment type: " .. type .. " (" + name + ")") + end + + attachment.x = (map["x"] or 0) * scale + attachment.y = (map["y"] or 0) * scale + attachment.scaleX = (map["scaleX"] or 1) + attachment.scaleY = (map["scaleY"] or 1) + attachment.rotation = (map["rotation"] or 0) + attachment.width = map["width"] * scale + attachment.height = map["height"] * scale + return attachment + end + + function self:readAnimationFile (skeletonData, fileName, base) + return self:readAnimation(skeletonData, utils.readFile(fileName, base)) + end + + local readCurve + + function self:readAnimation (skeletonData, jsonText) + local timelines = {} + local duration = 0 + + local root = json.decode(jsonText) + if not root then error("Invalid JSON: " .. jsonText, 2) end + + local bonesMap = root["bones"] + for boneName,propertyMap in pairs(bonesMap) do + local boneIndex = skeletonData:findBoneIndex(boneName) + if boneIndex == -1 then error("Bone not found: " .. boneName) end + + for timelineType,values in pairs(propertyMap) do + if timelineType == TIMELINE_ROTATE then + local timeline = Animation.RotateTimeline.new() + timeline.boneIndex = boneIndex + + local keyframeIndex = 0 + for i,valueMap in ipairs(values) do + local time = valueMap["time"] + timeline:setKeyframe(keyframeIndex, time, valueMap["angle"]) + readCurve(timeline, keyframeIndex, valueMap) + keyframeIndex = keyframeIndex + 1 + end + table.insert(timelines, timeline) + duration = math.max(duration, timeline:getDuration()) + + elseif timelineType == TIMELINE_TRANSLATE or timelineType == TIMELINE_SCALE then + local timeline + local timelineScale = 1 + if timelineType == TIMELINE_SCALE then + timeline = Animation.ScaleTimeline.new() + else + timeline = Animation.TranslateTimeline.new() + timelineScale = self.scale + end + timeline.boneIndex = boneIndex + + local keyframeIndex = 0 + for i,valueMap in ipairs(values) do + local time = valueMap["time"] + local x = (valueMap["x"] or 0) * timelineScale + local y = (valueMap["y"] or 0) * timelineScale + timeline:setKeyframe(keyframeIndex, time, x, y) + readCurve(timeline, keyframeIndex, valueMap) + keyframeIndex = keyframeIndex + 1 + end + table.insert(timelines, timeline) + duration = math.max(duration, timeline:getDuration()) + + else + error("Invalid timeline type for a bone: " .. timelineType .. " (" .. boneName .. ")") + end + end + end + + local slotsMap = root["slots"] + if slotsMap then + for slotName,propertyMap in pairs(slotsMap) do + local slotIndex = skeletonData:findSlotIndex(slotName) + + for timelineType,values in pairs(propertyMap) do + if timelineType == TIMELINE_COLOR then + local timeline = Animation.ColorTimeline.new() + timeline.slotIndex = slotIndex + + local keyframeIndex = 0 + for i,valueMap in ipairs(values) do + local time = valueMap["time"] + local color = valueMap["color"] + timeline:setKeyframe( + keyframeIndex, time, + tonumber(color:sub(1, 2), 16), + tonumber(color:sub(3, 4), 16), + tonumber(color:sub(5, 6), 16), + tonumber(color:sub(7, 8), 16) + ) + readCurve(timeline, keyframeIndex, valueMap) + keyframeIndex = keyframeIndex + 1 + end + table.insert(timelines, timeline) + duration = math.max(duration, timeline:getDuration()) + + elseif timelineType == TIMELINE_ATTACHMENT then + local timeline = Animation.AttachmentTimeline.new() + timeline.slotName = slotName + + local keyframeIndex = 0 + for i,valueMap in ipairs(values) do + local time = valueMap["time"] + local attachmentName = valueMap["name"] + if attachmentName == json.null then attachmentName = nil end + timeline:setKeyframe(keyframeIndex, time, attachmentName) + keyframeIndex = keyframeIndex + 1 + end + table.insert(timelines, timeline) + duration = math.max(duration, timeline:getDuration()) + + else + error("Invalid frame type for a slot: " .. timelineType .. " (" .. slotName .. ")") + end + end + end + end + + return Animation.new(timelines, duration) + end + + readCurve = function (timeline, keyframeIndex, valueMap) + local curve = valueMap["curve"] + if not curve then return end + if curve == "stepped" then + timeline:setStepped(keyframeIndex) + else + timeline:setCurve(keyframeIndex, curve[1], curve[2], curve[3], curve[4]) + end + end + + return self +end +return SkeletonJson diff --git a/spine-corona/spine/Skin.lua b/spine-corona/spine/Skin.lua new file mode 100644 index 000000000..098b601d9 --- /dev/null +++ b/spine-corona/spine/Skin.lua @@ -0,0 +1,39 @@ + +local Skin = {} +function Skin.new (name) + if not name then error("name cannot be nil", 2) end + + local self = { + name = name, + attachments = {} + } + + function self:addAttachment (slotIndex, name, attachment) + if not name then error("name cannot be nil.", 2) end + self.attachments[slotIndex .. ":" .. name] = { slotIndex, name, attachment } + end + + function self:getAttachment (slotIndex, name) + if not name then error("name cannot be nil.", 2) end + local values = self.attachments[slotIndex .. ":" .. name] + if not values then return nil end + return values[3] + end + + function self:findNamesForSlot (slotIndex) + local names = {} + for k,v in self.attachments do + if v[1] == slotIndex then table.insert(names, v[2]) end + end + end + + function self:findAttachmentsForSlot (slotIndex) + local attachments = {} + for k,v in self.attachments do + if v[1] == slotIndex then table.insert(attachments, v[3]) end + end + end + + return self +end +return Skin diff --git a/spine-corona/spine/Slot.lua b/spine-corona/spine/Slot.lua new file mode 100644 index 000000000..64c712cb5 --- /dev/null +++ b/spine-corona/spine/Slot.lua @@ -0,0 +1,54 @@ + +local utils = require "spine.utils" + +local Slot = {} +function Slot.new (slotData, skeleton, bone) + if not slotData then error("slotData cannot be nil", 2) end + if not skeleton then error("skeleton cannot be nil", 2) end + if not bone then error("bone cannot be nil", 2) end + + local self = { + data = slotData, + skeleton = skeleton, + bone = bone + } + + function self:setColor (r, g, b, a) + self.r = r + self.g = g + self.b = b + self.a = a + end + + function self:setAttachment (attachment) + if self.attachment and self.attachment ~= attachment and self.skeleton.images[self.attachment] then + self.skeleton.images[self.attachment]:removeSelf() + self.skeleton.images[self.attachment] = nil + end + self.attachment = attachment + self.attachmentTime = self.skeleton.time + end + + function self:setAttachmentTime (time) + self.attachmentTime = self.skeleton.time - time + end + + function self:getAttachmentTime () + return self.skeleton.time - self.attachmentTime + end + + function self:setToBindPose () + local data = self.data + + self:setColor(data.r, data.g, data.b, data.a) + + local attachment + if data.attachmentName then attachment = self.skeleton:getAttachment(data.name, data.attachmentName) end + self:setAttachment(attachment) + end + + self:setColor(255, 255, 255, 255) + + return self +end +return Slot diff --git a/spine-corona/spine/SlotData.lua b/spine-corona/spine/SlotData.lua new file mode 100644 index 000000000..27c1f7ee9 --- /dev/null +++ b/spine-corona/spine/SlotData.lua @@ -0,0 +1,23 @@ + +local SlotData = {} +function SlotData.new (name, boneData) + if not name then error("name cannot be nil", 2) end + if not boneData then error("boneData cannot be nil", 2) end + + local self = { + name = name, + boneData = boneData + } + + function self:setColor (r, g, b, a) + self.r = r + self.g = g + self.b = b + self.a = a + end + + self:setColor(255, 255, 255, 255) + + return self; +end +return SlotData diff --git a/spine-corona/spine/spine.lua b/spine-corona/spine/spine.lua new file mode 100644 index 000000000..d2285beba --- /dev/null +++ b/spine-corona/spine/spine.lua @@ -0,0 +1,17 @@ + +local spine = {} + +spine.utils = require "spine.utils" +spine.SkeletonJson = require "spine.SkeletonJson" +spine.SkeletonData = require "spine.SkeletonData" +spine.BoneData = require "spine.BoneData" +spine.SlotData = require "spine.SlotData" +spine.Skin = require "spine.Skin" +spine.RegionAttachment = require "spine.RegionAttachment" +spine.Skeleton = require "spine.Skeleton" +spine.Bone = require "spine.Bone" +spine.Slot = require "spine.Slot" +spine.AttachmentResolver = require "spine.AttachmentResolver" +spine.Animation = require "spine.Animation" + +return spine diff --git a/spine-corona/spine/utils.lua b/spine-corona/spine/utils.lua new file mode 100644 index 000000000..868591584 --- /dev/null +++ b/spine-corona/spine/utils.lua @@ -0,0 +1,59 @@ + +local utils = {} + +utils.readFile = function (fileName, base) + if not base then base = system.ResourceDirectory; end + local path = system.pathForFile(fileName, base) + local file = io.open(path, "r") + if not file then return nil; end + local contents = file:read("*a") + io.close(file) + return contents +end + +function tablePrint (tt, indent, done) + done = done or {} + indent = indent or 0 + if type(tt) == "table" then + local sb = {} + for key, value in pairs (tt) do + table.insert(sb, string.rep (" ", indent)) -- indent it + if type (value) == "table" and not done [value] then + done [value] = true + table.insert(sb, "{\n"); + table.insert(sb, tablePrint (value, indent + 2, done)) + table.insert(sb, string.rep (" ", indent)) -- indent it + table.insert(sb, "}\n"); + elseif "number" == type(key) then + table.insert(sb, string.format("\"%s\"\n", tostring(value))) + else + table.insert(sb, string.format( + "%s = \"%s\"\n", tostring (key), tostring(value))) + end + end + return table.concat(sb) + else + return tt .. "\n" + end +end + +function utils.print (value) + if "nil" == type(value) then + print(tostring(nil)) + elseif "table" == type(value) then + print(tablePrint(value)) + elseif "string" == type(value) then + print(value) + else + print(tostring(value)) + end +end + +function utils.indexOf (haystack, needle) + for i,value in ipairs(haystack) do + if value == needle then return i end + end + return nil +end + +return utils