From afaf0c70a3adc39fac62f4043c438484e47218e2 Mon Sep 17 00:00:00 2001 From: huaqo-games Date: Tue, 18 Mar 2025 10:33:10 +0100 Subject: [PATCH] rest --- src/game/IDEAS.md => IDEAS.md | 0 bin/game | Bin 927144 -> 927496 bytes bin/game.dSYM/Contents/Resources/DWARF/game | Bin 261368 -> 264048 bytes include/raygui.h | 5928 +++++++++++++++++++ shaders/{vignette.fs => postfx.fs} | 0 src/engine/asset.h | 11 + src/engine/postfx.h | 46 + src/engine/shader.h | 40 - 8 files changed, 5985 insertions(+), 40 deletions(-) rename src/game/IDEAS.md => IDEAS.md (100%) create mode 100644 include/raygui.h rename shaders/{vignette.fs => postfx.fs} (100%) create mode 100644 src/engine/asset.h create mode 100644 src/engine/postfx.h delete mode 100644 src/engine/shader.h diff --git a/src/game/IDEAS.md b/IDEAS.md similarity index 100% rename from src/game/IDEAS.md rename to IDEAS.md diff --git a/bin/game b/bin/game index f7edb638613e2478763103d43e507919acf6de53..3607854c06efb53f80942964278afd554d7ff102 100755 GIT binary patch delta 238761 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®QxRMxP?qeon|^B($J? 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 QwR>s6;67z9yx#YJ0BlD>i~s-t delta 226332 zcmZU54_wV>`~UgeB`HEt6sJFu9E1=>bqcAFIh%unRGW5$5Mm)m2qE3wbWKP?h$SJi zM{8_tv#nX%+Saxl{IcHbngfnkX zD7fQ#Csw18G#br}yH5CDqq!5y??t!{&^as6%MJ=qGe9STr3lwMqg1fH3f0^hC2|1% z&4uT2ml8>>~S?TA@BFn?|l% zEpo6I%k7u5s)eG(KBjNg!XAqM^*vQexo)qhf2xa*>#F4{_D4GvyK1?}=@P+`R*9Qk z5?JXz;p&jc&YTh%4t{Z(9vaOUjmFYTCf(OVlLU(xKK8?(xu}Qc1RV7FR}amPgESgv zz@EaN{O>4a%YSR}xi@GEW$j&F{Hlk>SNzvuVy|N_y3WFRD5kaVzz#u2SL6wI<>S&{s2ApYcfuWl}y7YAH=)#+BhOLv?u%l{qjF18PH z^C)nX^d0iw8M}eMm2T7iX6b4%#9b4WgTlKOfRj(WCLSuEEgG)7CPMs;t{&Ie0UwRe zhiA4e`psL?)Vg02CH_&)AeVTw#?s_)O|t$*B?WzbG93_imyydFM96S}D zEsVc$RoonGbiaJnD(;r)+SzUMe+%rQseKtN0g6aFMP%7kkrkkbv{OVLxGL%b6p{8k z^Qv$dGPM^(+Vf{23vuXk#%>WUwsW4zp1LY3hRl?8ci|JRiYG%9-Cg+Lt0F$o$Xu_A zvcR~$Ks)f?YgFC``w@{S4HpG5VfGIEL5+wQYGfbPh@zp2psxHzjc6OH2*Ag2yJ&vYXdL;L8gWk-tyV3Le0hxs8fIkkYeeoa8&NkNRU=x4*@(LFpc)Y{ z+{nCYMD}nSkrTJ85lzEwL{9w2D?&TM$iBEDGDpN%)j9KqE23dUw40*c;><5y`6~+E z{!TMl=@pR{6l{M6)``-f8CJgTJnM>h6l7$XS46@{or}ueo%^8;mt7ILBaLkG7127< zW=s!0?1~5;WizG+?{`IHk2118S48tDqgAL2Z@Vl)Mu%B_cj2F27FnYazssU&w2i1I zKX+LK2iqj|v60GWa^HGTp{V$7~V{PhO`45+b-#8nQEC2kGNFQfppIj0Rcmt7LM;}Nz?qIJB@kG_1^ zB@sNqroAukcS&SVK-eyc<_R_v-FaKJ2nn?jx$}>!MNX)Zy;dz+LT!>f`1xuP6lRNv z2R~dbGQx~(SGBkurbOfpCK|r7TKG*=B;Cd%9!MZhE* zQGf0QNt2As1Ck~wE`i8XajAQ?VBtpg^+jO{R}6trPyWtDQ5kM!*Ld;Ti{deeu3Qv` z2rIkAOJT3LDDonVEa#%Q7hz@B4B%-OMM$Jg`v5-oqR5FfvZpVKmPnh41NqR4B1~^1 z8pz!*id?;s*DT%CimAE&>7CJv=5IIx{Y%dO>7NwHjmb|Ul5+tjBEuYO*2_F`}61vqIsH)XfPjnLHNZQ*{};DE7m4y zFqbZfmRK860B^4p0dYq5S*6I1vo&V`zf~!k;%r1icvYp)#v9quN|70_NUG9UhVYz9 z(HyT3RcSPVd}XC5`Xhiwb$1%YmQ{+Z>3(cxr6`#m=8VXIA&^H_GV<_un!|=yim(~; zdlfh?apLCot{qqt3mkuP5GQ6t1!7XFavZ8ILT0UFhf=pLN@nKRk>sMnME99K%)atc z(9G+M&3j3-%}QX?UJ_wXC9;t(iDDEUFNwz}{yZ;Cvpw1G=SAjho$Jr%)z!ruGOa@c zu@BFS>e=C4;lWUT{k(WId#WRB9m-FiXEZ*@VGcWSUKAVV%LF?9!g=x7AQM}3+d6!a**yFy$yVLGl5t_zekZ!}M=5UC5MIu>Xw zqxtj-MjIy}R?{kk)51hHu|lLRG%^1Q(SV{yh45QsVvo*>>_wjJ;aO3Xc z`|Nx$$ zp1^OO7R^f(^aOt4wD3zcvU8_JR%#+Uc3QNgn%J(>BIJ1!TYXv-qA;Bn?azBM<7we! z*0BWO%vv_%v@n{Lc!u)cr$w<@kr&FJl#BajBYRvfB9UUvVWfxZL6(*SR(oPlOiZXjwsUPLnlR6hLIgSDVj3mh$34~KPdv%C}@c%hq$pZzWG*K~``SdtPKtzeCid+KQGw#a z6T%_Wq`h&%YIQoSPW!)B*PamBnL2h644GPX;e@!IsVK4IYfcE)^@>!M@!w0uLyN6rI`apmB4R7js!~z3)yjv=o!MKO?v#qgtp@gPsqo7&v6@nmjpA6T zXhE^7RD^7^+0vcQDHVC!YzBAd(WRn!n~_D7ilFUUHnmhFY}dJmms(?%JLQHsPmNhr zsmR}+$cC4S_U#6(hm9g1T`6Z;hdF&pZJ6l2|iH>+o z)a&b*uDcEFj}no( z+r<7=B5tB+ED_o~6T4a>vhtJ=-qBck^X(;~F;9_sN277&t4oCE9;4ri5^K!YI%U&%DC=u;@l_C`;BboQSoqpB8xgI3pT1AAsRKN!hCG841B6J5rycCedgEJRPQy?hivw)!}lgcF8 zQqsjk6dv%i^7T{rdL0or4}_>7?3H9b1{V$**q?`m>0l!J_hE4z#e0W^XHg=%dRSx? z*_`jsw;vXbMKt)zAy;Fki2b{DgL^mSiuqt_xl zfGfS|uxKLmqQfHiMMFT0jiL?`tHJ5;S9nIr(f~IzYW>r}j|IY}7tx6hi}n|-od`R* zZ;M6nA)BS1{F7pleaIN_VX==cHoi{H65=Mi^qp-!S+&u zcA;3r6o>RvgNnnoYn;5`_nq;t1fl}Md&eS zR(43l9D50;mIc-QCa(d>E0Z{;rdIy^KXhVNY2V3lzyhkV5R)|&&d)b+MoTeoy5O# z({$|Wf`ixX$H&O~5pVwHi=ys$l)U}%<~1)0hceT!i!Z8;_P`ArK6E%7TCRSu^O$F> z-CwRcZiQKPs#&76tg9@{hc~_`D$BGkdibl+;1Cd9sO&}2Ql|3`M9S*;(g1FDkkpOk zT_0|Ck~&lu?ZluHQ@jc~cbE~9Vx{fa(;Og58a>3J6Fphsi7I?{qy8* z`=`E=M@7Acw-l*OZ4QX8ePC^yWS6K81+SNQlMP?3?~sKImF)OXIJq=Ns&ylFzzn$K zX!&5VXsnYeRN}Qo;_=xqwW??QOp%DFFtU?HqNpOm6E56wgcJ!}IY=pvK|@lFzT=G| z(Owa>1v08M^^B)m72C))z4aYe0W-(^kD*${&?=4Ij;H*czOTOHoJ=3`KlJWa`g%KV zw9?D+;Mg76vB=(1&TR$W*m9-a&FP<^xK!>r=0zKO{5I|3A(z6+mY#U<5&JqPRv zkq=-?Q8x!r$zF$e_QydH@=_XWIw;Csijc#M?%0LjI4Ig)GP2r(BDyk-?LR0gE3HTz z1ZN!-k1BDzcTgl;NMkb&it86_oDO{aLBXnwY|KGns!C(s4vL1VAXi)9ZSCZ7P&iz~ zJa$l|Tr@E4K~Zy2%laP_%>e%UfC#QONoMiWF)#Mc0Z~z{b&Eobe679u!~u5TzZ+kr zSpnVLd&=#<)t;Z(HsCiix_RNHeq9w^Tcd^dB_Da8;ls}y5HXjM<>Pl>&g?8rrw)kf zOQAB(mp^qtJiIj8A2>gr2f^|bQn78}Z)fcmTzg>Gt)ly8y-)?(i)okNl(+YOeDVQC zzYpmaD(|TZH1&S`t`MdxM%E}q^_5dlq#vXx>JTEOMpjfmh@TXqtVUL(_vfwRFGb%h z(AWN5(XTac%1r*8glM>`>|O`+aY8s!7IeO!*)E&fgMK@-473Zbi=FK@j96yt-0$gh=+ z*9_sG7K+B&(Zhfn!rg4f+a>;X_SV9`M~QcPYv`VD+{BX_4-s|!w6jItFXJ%mokB+5 zVNRh=3P2x-?k+-JHnP-0k^gdhEas>x$Gci?zHXhP-nZlCI;rEq&zfq-ckQapH>D0V z@SVOI5RI>=)6mr?B_;i}KfPoWuA(_KWt{jqKWf5z~;#_UspR z4e2aM-qt|2{XJVycwpFKxvI2FsC{`e}=wC;hLDsshMP1}N zJ^rbicNZT^)BSyy8XB`DX51%Y?ig6qK2dxp)V=`efcW^%I5u~maCtwGb>An_-$#q@ z6*u44G4Fk%9l#Iwii9Qudu6XEYf58p?iDT{7}%w~BISb+ma$h9f1qP&dqu+sTDEwv zxR2W0y~6dwJoemPQSzaI&Dtv-ewf3)*dsDON@1_<5iKar?GX{pDXeghC~J;pclU_< z&55jNkBIr$z_#uY#UH1!ygkC<69ZefN0>edaUQz|({3|5s!J4Yadq%z!}o}~Pu{0n zlcfH3-S;p$R&VDg-u*NHQTxJ=o1?8!8$F4eWBz9x#Q!a7>3@q_f)cg-jfh%5>`wPw zGPM{bwlPmse`a8*dBWlIh_1u1_AW!!t-7s`)Ze{yk}rVc^U{-l=SX&4cQTsp?l9Z#VJ^CYyTiC4foLQ- z*)=yY{6(utug5XZKrb~DRPa(X{qF8CaF8;o)_3Lq%(VvXiM}JS|NjtfO`(Y%4g;;T zgCqYSR}{Bt*$=tmdYj2^9h83Q;gHN0=8CLuQ|$!m=la2#Y<&2$pTlaFoGU86Gq4%C z;>mY@Zu6kV!ZacBYKg0S!(5R4-rvC&k0UIGr*ehqdz_s>G>W@BglD^fy|Y84x9iw{ zc8KEkM0R$Ecnsiy9U|d}G)Y6Y<8}-1;$XpVXD25r ztL!&+8XhQVI--$vL|aDkSGI|oU+2p=EnRsTLK41Bc>ea&$SO@zS3U*&a_gM2oBJE~ z5I@P=C0jCj9I$$MoT9^glOw`9(5~A=e#f{07>kbF&&pb1xA3>`=As{|c8f1N-hu3T zNB((^D*M4SdF}nbvhM;0*~l8Y@vS+c<*|X~<%po)!{x-Hn_^~aj>!D|CnOeMb>k~? zMEW1T_^fy0t~t0a!+e<|+Wwfmpg>da#Qosa?^~_fhUjb0Odfdc$df-kWY1t$l@d;5 zICzxO=kHNMWD%J#{*|+)Ly}J$5pp?d)1cnz{ z#qZ!3(jeAtD=|q*VRtQ*DoGJeNpe=CAHm2|=!Sg6TPN@Q^s3bvO_EZ9Q%a_MEEHo3I7P)rvogiW+ib{Ek7xP@A~ zz{t+w}l=$fG&Rv>AFffmb-z1`kF0N)>X=4(OXFC z2)&+LD96!emp+Jh*+RD+VVAUp{JKfOs$ca%{HttA><0Mf*;La_%3xL5q;u-z8_5r6 zQ-%}plufstAa`Xp1v#TMW>cXv?46%Y51rvhbT%b)M>#B;D&(?HHaYZwz04SVZ1QJY+z z-b4wmHoE#zyl@j0xq>c#6ScbnpSp<*Zm@UhCaQLWABIij(g)?lO_U~={+p!iBTB5F+4hdPv5M4#(r#{p$K+?^8V2>s4Y!Ek>GwT?1%oI2*3$Ir3s+MHN@3XczCb13uxr^1 z^bn=?_zP-Wl7pf=91`+K#jVx=wF}|AH;J13zY98d9t7vsKN)nq`yE8zVPw8 z4V39C8Rf0=kDB@k9Q4h;l5#?UF&)Y;ZXi!T#OS3Bl!4Mp7s{mG-r8N!jYTyXOXa z><{BzH&DP}xdU&Y;=yqIyY&X~^4t8ig-3+h^M?&`f zdh#1$GXmLI;(AIQ0wYZ8sSc%Tgg%^Ct|x6^CtW!AUQa23pz~T!*HK#OBKXSnZKan%9ImG`}J7E;}QL8^v(=Xvd61SMpVZinUp;grhl7B4~I&IA23?60* z5v5fg-Vm;(ps}4%?W#m|#ab#HD}{|wqw2_A)>@;Q^0%lusFw;}z%K<(?kY;c=(d*p z#v#0HEftMJc)wpmZQ~?Q=a1KbFjXNGKYZXj{5{l_FuO+8rbI;5CZ|T#CY40hnn5Gq zlfEm{cZONAi)E#2s651GJ`$$?tRaW-onh|Am#m@q@o+PF4V9s^hNm09vWD1%PC6$Z zu!dqLfX;6Xm7uiJIq}Rj^khP3b2#&k3`z*?Yz}AsRR-mUb~Z(DLqC?Wz8$8IR^H0zorw51N`T7GR4{8`f>dIbTxsiOQ(l%F!*vh8RM}|`)aD51$oleCvJOcdF!9N!KGf;Lp+GirLWh*Ep0sOmHP=j2qT0y#52;iC(ls5|jTeyPm%jMJ+6#W#+pcPc|6apB( zf*fWefa4&4HoDz^mQ&$u#Ob@`R5u%OyStoP<@%?~$;lw)vHQ!Z$N>8Hms6Vo^aabw z?`hz7EvJO1kyy=LPPd=#w0}Gwvz%O?ft@3lQ`$4I(+={UvElU-c>6L6m;-#$%9&X_UWE z3i5ta&g|CV=&IRzF!E|wZf?Ob7RD3qYv{9u(o=qa<#Rzy9=-*(Lu>P6sUt}Xn3B^y zk^ai*`rvVC8f7e!T9|tpB_vA4@|$k-n7;g-rRw}|E{~#FuB@;15olk&dMSA>hRYu= zrS!#8i3-QX{I;d!o+N42y55}!E~SVh(Ct}zwJ=EvkW|U_?!2E(az+##+v;GIjC=JP zW@<|YhtJZh5h;?pWL4?GFPbUwS)1s34{kJ5?z14QHB-y8SjSYG`*C@H8*ZkE=cLCf zZ)rb1!A#Lh&{Gr|yhHxvdCFcQxqB#eOMiandDTyAD6gJdB8{_Z#x-{1^VF7V)2#R8 zYn~_9=b^dzc}jg=dZJ3L_v9;{r*yN84)2p)pQj=-=+=SXEJdgm;)Swo;h(7#vQ)A? z@g1PRzD=dvrIOa;8#JiztNI(hpZF$f`uS>;wDvcAUe(jfOQq4)a17wrQ|ZxCblTIY zl#qtq!p_vIjcJImCw#&leIVbRs``{%7u6x(Rb5FXm*tYq^Df%fcI`6_G|8D*dT&N` zK#*a%6zrw&>j&~aR(>a3v?DHex%4mDf+|h@Kt4E?@>gJGRTXOattHg70*Q!H z$E)b7C8SMV3Fw35BeJ$bco3ze);HZLRm=4pxzWv(=M+S|z=$iqhlF^b%@VZ8I46R9BuO zrwp6HxT`9Aj*J(p;Oj!J%f_G;LAsg<$2Ddd@jZuU+JrK8lcXVqyZIWe{) z$rRgReiGZc4?CVhtyxmJY%0!<0{N*F%HODV*#Zr2ZsJp@W+P<1ltNCMq#Wh}{3fKw zpUkC-P3UERCX;Tnl&13IGDnv}C7ThlcarJRW=VO74mm@W?tCqog0dxpl~%`pNT$4O zwabG>r|gOIlBp#dS(jpuei+Yz{4EG=QZkiqk@DGyWD2oJ^1)W=FdhzpTP5Y{ZaDue zi88iILGC{%S-nk#r!DFWi>dReW~=lKxbO!0%Oon#QMl@d^UX=rmLmnR?~=%K8=Cg{ zB+A={sXj7^+P6vadqo@|>5?d9yWGo?D1SSUPZra|?b3gN#Ho>U5VuL~7dur-md_!d{p>08;l#!EOpI zPB4C7WHmq+M?ciCne5j^6u%Eg8LBY#DC5ILRJ{*9|KcJF$cK>fMUP?Nq&%*HLBV{|B5L0c{DehUV+tfDSsBOhv5UySG1L@6mNC3( zAr*1>+_sP!IHp&qLiQp+cH5JBR`lZ=8%n76Uy(HsN@iMZ#378ZO&HRO)`G&>qyXrPJm z0khIf;!oz&{UhN0c0NTMMIQU*e5yEVlVO>}$C${e1n{HtDYHcF9k3;w@0m~4CE(jR zpPY_$(uecU=2O}+HQ1nw;L|||JevTzQZ!P~e0g-GGuQdlD%U&aQS|Xn{s=yEK9wC; z0|Nd?UN?{K1JAC{qlhw_emtQ*G>@{%06#d7n#v?UdoyB0zm-XWYS{6xTK0C`JPJC2 zsYz*iysVx#kFrmI>zR4fj8cW;%ZF#?QOL>8CR4wRIA9(Xo|Mw9G>osAM^2|CPghx! zV{%-rxuKi#(A62dr;rKT&7%~Q_Gz*u1*fDWpLge4H->4k9m$n(H}G)mh9=NgtC2J} zWGPpBl}nD2I%+M9*MnR>z&AHc5wp^?6n9#3Q?=tnB5^LIp2pzFoJ&Qgr8X6glZn*1 zly}B9I4pMDc`j9-!Qe=rd)48rQ>m4|L;~L88EdMJ8(XSiYuY$KXa(PQk|<{Kv!iMT0e)37o;G$ZJ}F* zndea91<9}Ln}A7jW_3Xt+Vv}Jk~JE8`u2jfj`_{Gno@=IQ;zT*%~xG{pv@GADIzjM zOJ^^t5xyf|?=(C^4Hsd5>ofG|qSWT8FyWA*@fp?r0XzX^re->5=0J$U%j6jW;y zs_(%+Gf+mYO=x`&{-%NIY9aJB1G!&E%Ar`Qci{&Oly@C)ZlHVD)iGA3sdwR-1~R>@ zj`Avvz9&CmprV(ho6H~Ze@N{zf0d@RCm(Ad!wpq0n!6WonoUJF&~|OJso{p&c2)Q$ zHE)@1ZM!VAo$KU|D>LbKos{a74!Ck;gXwEF+*`%w-@(!`R`GDD! zUJtQjXH!YN^gV!h_w7HM3SX7>d4Rk(|MMxUf@~D)z{vt^1t zylEB{y$)dGENXupdF`25l-q!LIeQj8Y(UZj&OUtUEDC!AL`!B-;TxD_!)6hCQwnx< zlyeCAAT`%sIbWVOi(=lylodIPGTuZA5Cn~HV(9e;|69@s=PFyj{v&}h-oh@q-z;i; z3j}tv$nUlkz#0-L{x$^EB~a#V$&Y!>qT<_9oSe?|<*y`A+ij_snG-1YZ6pp86X?m? zN?wL{;sFU1^A1e(OQ4c>VB)Vc$>m)s*c&F^QB15+&+F|Iu&*vbI;e~5SlTMl$fqSQ zdz^vKr0jQL@wYSS;kz)Xc_zg)!r}s(#kC-4gvB4tq?Sey)X$`#_h9k1nPhwq7H^zM zIq$*ZPi9j2d(tA@zGBClf~6uHhTK6WU!bwL^N^Wjx&zbu&ZMS0i1N2HDB^v^1?+B{ zXHf3@aG_}iwZ0D*PS2o(CN;{c3ytb=_2n5<*aVg5XHZ=eY(6}Lf4 zNRq$BjxX@mOz)f_=!fCbOjbRe5}VNGb4d z)w}*YU^>NoA~(=nUI`;M7#!>JWn1Pf!_Vb^_QT7*b=fgN^{sPmQ zO6SEd$NgWSUai=`s!U$|jW|XtN7&xv;VJr(IEw$$CKd0{4RKWTC8Q?AQ9DXiD)#IC zf0Mf4E1Rj7fqYyXCET@{ioN#-u~c~1CRDHG^|91?7efCLOCk59I<_~K9^LDt*YfOG z3j3$@$VGL*TUi*xV=3Zm$>3ZX%MRc-9Qv4>V=1!UZZy5~wX}wwb+PMj?*o*m`cz9< z|B^<86ga-#jhhYDBjmgIcB;{?14qk$ojK)O>$W3g6YAvqs$HMniFSV-I0ago{+M=^ z-IwwtwtX7q{~HauavI(Hw^YUgr%~<$D%!Ye0Sh z%KHXXuf$NhT$aa>p-nj?s1N4_F;voqSnQ3VM{Php7el6RCHd=O`UpNFhAO`WGB$=B zzLVr{py2{b8$+qz0q7hB%d@yiUj#rk<_r_zq4nK*LyVNxvnVJfA4FO9?4ua8us z_~}%t_#S&Ljl8_*ajAv*pkXRK0?bK);SKkhsT9!;`3I*`5lR(~x7%5uli`_DDd7j~ zo>h7^g)qAbylub4u* zpJCS0DU|awhVlF<^zdit7a)=Q&74B*|4|k>i#`8#G6nyFMb2&trTl{N>pq2=e?eY^2Dni<;x3l zTI@8L5*}mvD2S$t$LJF4qsirW>{~0NDf4$|ITTH|e}|S$(G>9q>d!}0;UAKp>l#_6 zq`t}0<0Vm1G&TGo-D6)yQN@3isj=RH*G19&{~}!1qbTAD&Mx*w(e)?Fl&J5@*GCci z6Ua4DWcm~HWn2_B{0R$2MIF?!6y_0iFrQ_~P$!8Q*w`pal-NGGcd3c$dwO~#f$ox? zObq27J=HO$oKraROg%Z+F}$-3`&^I_K_uDUui2gZCO$g>Bm>K;MqJ=je90=(IzS9-8H z>`pkjyRfNv{)z{Hi(QzHPk{z$=_ldVY2YE=%K59uI#^8#9P#?^7^vi^BUufn1{XN> zbvWI3LEzHDDY_>DJ3E}pd$LrvE1X<+Iulxwdi?eH zZ$>yJ_GX?eHk`70vk~&#<-*^YM3ue4G%}o+s{%yY``si8ab=@rik|$)BuaOM+T)X` z$(3!DZR^RCCy~hwY_EacO_kM)Z=FQ<+*mZ@lPI7MS}$f2<@N#5=tpn!@mO2KA|7~Int>4WX()wh!S-4x<>RYw?E6rv!CfpX3nh1N!1skxnm5E3g;KLz-x^9f zAA~?3inlOuc>?%+5P}h*R4La7hf<3VLJ%BEslK2e7%GP#hn<^15q@yDZ~~RdAGzRaBx^?W*moz!*>+rUy^`WC)eqYp09-n{Z2JP0mZG2XvuI2_c_+)!vG|$pB zdHmJjK#UPq7eeJaSaddo9_tW@T_Kb`4D~f3)P&M=H}ZbmKG!ZSbE}oV;)I`tdO`j+ zPH_lD3}<0%PY7iVXMSvS2$c*+z`BJH8-eofI7%I%_M0kAeK-EjII0|hS@F$rgMi;Tj+{mUzjz#_%Vo?sY8uIuW!Q<28Aq<8Kr|A}qnP~j7T7pD zj-xsm_{&&wAI;xt5HXg?yF$zr?qex;ET~+^QtMdN zMi>6$7}Aad@VhaTIZk24oFTLJA4~VfDXf?;{yBzBA*!}s{DU!69D?NoT6*y=0(RRvAN6{l}Q*=pN^*7aAg&&@5^5sO^x9YUO$=wB9wI#HM_3SIWfC^AH=OS1<*FpBb{A*Emx-H&D^Z2l<9ovf(P_v2H*F&RkxC<>T@ z<*@fCDxU(0zlxiFp`R65JZHhKi@i% zT4F%Gc_al-Lzjfrp4>Q+a;E_}c_g(?Q{{T{ppg_13!rW!Wyh+NUfgaZHOasqgGd*L z&I_4dyg7(+<1jei4w9ps#}1($kFip(%(Vmf_8@AE2a_d;0;a=_*+Eo3-G;9pz$XP! z`*h$Z1X0Wkmgu7L4OE<15=7NASSI^%1nFjW@(kpkji8K~;Q4q2-JaRWqg8n9gD4~c zJo`sbWdat=a?m7zcIyc8n+5%b5mYv-Q`;_<`Y+k4%*n45#~sP97hH=f-d{JPn@M z;dtW!`xb-d=}ul>K72R@J;QKms;ptYy#H{@dIqxk4yUGPSct0{A3y%{FzZrWP1lb} z3G9bqls1Rq;!NT5<8KYa+XwKyJ`8Uk7=B|(X^%m?WEkNmUhpez3f&;Sr&CUx7?wJd zZ5T#Qa~XaoN}>1Xi-%Fl+)jJ^`HW#yITvzchmpfP7Gk9v%mao|%sjyThT)AwryYa& zA3AE6;lJr9W`3s~0sMU(70>UK8^G&ybbmhR&gm$^#BhnM=*PF>bd+OaxJ$)tsiuAi zcO6FeOsr6?;~Q?@>hMH@Wm@rpJWEGU7N~aJ(cnTd5b_p6uD_0o7TVyrkYqY)mf=r^ zQqUsSWR<7mu{v@}RPBO39shbL;ir(4xI*4AerG6^Cw9si#&cePjGks!Kv5 zkUErFlaOG17f4~rSYJK}q>^MLk4{6$AqDH+FM(uA!PxsGkQ(Lstw8d77Rlp#f$V@L z_OIlzF_4UavmXK}>sgzPxVnrBr0dVZ#;Jki`kW1p2j_zV$?zQD-hou{943)phLHOb zwT~hucz8a95|;q~`4FmE(#bcHUmrq`WO&UGN=OCY-XU~76^Y2UA>{cy?3_D<@}F1R z7IH@N$wR2=dC*4=A)UE1#-n)uA(UkX+yQtq3kz1;eiR=&#Muvy*$>o~?NsM`EmBH0IExap6vnTzD)I_N`uGQ zDFI|$26$osRW8GnJ0^g%%UM3tqP`rHc>7=qUV(P_=U^&cf%>Jvc-Wx&1-Zfe*kDRY z2mj&0bRDJK_K+LQR}Uu7m9pHyl(DjtehiNvOf@n*W-z&|V)74V)sNu=22=Vf0J{yQ zhEsg%ac?j1HqL2-s2*7S{gGw=;XAPqE4Qz>=-Hca+ zh7F>`7u0NN0{_g9%3e_In84rmqkAu?7KZXcgD5@=ZXfZZnk=?RUbI5_4}RpiQOy&= z_(y(}vym;4F=70=AGL2pldtuo#7&6OVn3?hq^x!LzTHkga@maj)apwao6-KS`BKYf zm;la+{Gl&tvz3(=FS|>9DKQ%^9Py=^Y$aX6^KN;`c*~dkwx|ngI5+uH<`z&HeW`H^ z9EF^4Ug1kY7KEZeKAr04OW77s^zo%;i%Jo}&At?}6`=q{q#`uXm&&)Qc0}^Ge5h@! z5(*qX)%uVwM+pT^oqGFHVGdS!w4B7Z`cO*_ByaYi;BAOYm8M?ecYLU5n;JRBYkcU* zHpB%O#t-{Y+IGZc4%oIME_xpd+My({I8-wGP~HwT`gZ(vZ@Rq$f~&pBFIR0JdtTyA zsks2|@uoTzh}*$hZ(=)DOS|y1-W0tP-Q4I+jdD50n@qcqC_#G{?&?iNyTI<^P3^m| zNPnrN^xdi_4*a$j&me$o(2`4@%HhCIX(=AU*l{ghKwz}2(~|ohEW2~HlrNW|T5{Nn z(J@I&se3VM25af2T)JpUyAS2B11W1C_He=A-v_#X4zhFg`X+F&jyAMp!5TX&cp$9 z?*Q8&_E-03?vS1-Vdg)`hW4s*>^qQ~1DwF{Ktw|iebyIv8bGK5L2bm|e90pyuC*CVy z?p5i+IrpT(BP_*5r3+Wa&1_F%M==kpG!gt^e~LNUDJz0E_ov*Wkk!ql+J zfh_GuX=Uhc+xtAqsJ$}G@u`4om3?<-nAdy zJPC<*{mAo_I`ty{0sO(8(#~QU zf8Cv$&#D~uyvm)l6+oVMr_2iMRtw}e2i%?7D_ER7J9bf8`Bis{J_puW?o@dWtf1<` z!`$i7Ik1MfQ^I+5)^^~1+$sM&fW6%5{&|%WPY(K0&`SV5=u5dTv8A$H^}7*n?)3O2 zmZm-4*Sc_`^^%L=bi%Aohp+XeoJ#lton85^zEoEUN!$C9`vrA|cjSqEDfI$?CLk}U zGrS|O>`U4zCjS71zMJy)WLRHHslv47)|XnU5V+6!Q1(UD!fw2w4;~vp#LYgWtyX|I zqp0XZsns|)fMy(6^r7l%Q0(kOPM6pU0C5)43>lZuaFKne{gNunnd|yc$YoFl^r8IA zN=R`Q;oOHDt|%eJ8HBuwP3%LaD+uXZZq#rEZT^y*wats+ejfhr&+H7rYi?wyfy85O zR8gaZ0%sQ4ZggJ;X1P(sRdk{lH)^`7+R%fKb|cSgK#p*ujBDtVPh9EYH5hu&l~QV< zt-;l*t;E{HBL33$g)6n!qKDPGQuK9In+t!@m9nox-~m@^z7Dg~fP5MGtdD#th$GWE zu9WvO@Uva%-phz?e^<)=hYgPt5qno^{0HzFR|>d+`9bCD$y<9<>J7kKdQ;tvPWoQF zrZ+j%0bbpk66;v1i%Q>13EdaHsi_V&EbC1XuXOVC=EmNX`wDmry{YvTmTuM2n~(2J z#(EZ`%8<`Z5dPoWr{|R+7|qi=!`{6&1;2{cjUEmk;yncR~C-n7N4UOkXm)048^ zWNDKn=#XD&B$r#eXli_CtoqsXH$Bt&3jp}-CiQ2purA>OAk-YxMctEMTUe;ya-oK|Sc-R*i?v;1;_*v!aUGg2nj5jQoUJLLW_MN2V0WvW`hNUN z&?}F%0NeG#U;8$@o|JPNlXH^`-M@`aeZz&q-o|oW>Oz%oqrS(5*gM$QkqZU91G=Ry zl=lwc&$v+QJD?lyLWXxy_j950cR?5ALbu;#CXf0as(t1x*oF%~*j6A(aWt`!jguSe zjz-^~AL>C_jR^9=9@Nyx{Ja!64v{v1SvEE)H%?)cbAg`ku}~|cCx5mF8Qufq;vQ7- zUMHg`kG3%;{>Aw3zZkvvh#sW71ID2}DCbTmqZjXPV+{F=@s&F)%BpbyAK!zV-dD%v z9SzQu{?(o0--n>P-Kne-t{=!>=}z}#_{-fXtV!)ppdZMoJLNP1F1k}o6Ej%lYI$0B z3i$x=)b5o3L8p8zpVFNgWw^dO1$@Xdtn}V|AM|~QM6GLga{37E(e6y?A9d>S=C_@x z<|FVmIFn0rryd`E)S1$n0YBtSH=8^4`0(}4#6AXmjWd}(?$qPU>z%3jV>Z;jVDVNz zvipR^u_4Zs@Ch`!I8(J;{^CULpRyFc&z-Ejz7j3{wPvKe5bNd4N#oDu1^J;96@!j- zccv$wqNn`oM1~ghoE9f)XhHpTC-VFZP4PbDXfoBF8Hjs6b5oz%4#1Lfy3)u?OiSxN zV?*RPRB7sc`8!T{bis`AN?q^Ar-M@I-`Ue@&8>ZuTUgEiqwL+|dc6Pt@w%?-m4s{| zWI`;2&?eJJG9e0~O(qpmAvDL3oN|sUbhlV&7Gfcr6hdf(Sk9*;=UB*LtG(rWe_q$C zcz@o%e|~?wZrAJad_GRk$Mbx8JjvxK!wbW8u7NCzt=S$6?yct8bs_DGN-cX^z~dI{ z*C-1l-J(|B7I=G$T6VNR*log}Ss?2+%Xcda6y4VCL_O@(9o6AqptnnVguAF8t0Sd= zZEsF>Sl=Pt-s+;B)W^I#(r{@l0TDR2I-Cm0YF6ru${w|gJ+Z;Ycgp16PTtq%4=EyCQ9F4|lp=Ovvx~FF{mHJ#AYYz8&%;Zt# zNT>=w`nlS}95+OGH*+}M*9#Hx?bU|nh`i76dgjQ#uNNXF)?R&94UP{O{1nCfro4wNtV^pwdc-0ysTzVGRmo|k_OFK2N2Kdh4Q7w4P;x%;58+N=|Fly&CeKNZHa`GsG2hmb23grNy*Qycs;6 zvhh4-hTx|RpJs-frwk7?gUvJ1Nt+?&8R4O3xbcj$s=8*d`iqmAnr3kQi*%-D@E35I z0n7ekr*zo>sYJ|{4Dc7=pUWP>}VCa^?~LHR16JqFz%@8wLAcbJ4xIV(dT) zIHbJ78Qu-!T1={`wieTX@u7?h@$oDRO*6%&o3c32_K5<=H`0Vwt4-V-)K7_{RXTwa z)wgUsoyYd$Lew~Va`WUqoaa0T9DgGXld@&lzGVSOkTL(QJ_d787s<$d%iNqN!|rcJ z4wDh{w?4LPqsGX{`&%0{A8n(4Df55^F+0cz{zqGc;Ob{B87U&Lx(um|J$QkHh%%jb zTeXIa%rbq<-A>JrP+msN-zE5z>uVV8RJt*XFK1w^gpzWSkCNd3FYSFm!m@v9#|aXO z|E1l&lXyIXb_|q|@*l$eB~<)}cB~=6`5p0P2|@29?=~i)G2y~y4e2ABa3VIIzM^Q8 z)#FSJssk6CJx$x-<~!QtkSUxinC!KtNT`rp>u3zP@;TSEiUD?8RQHl*nZo5g5eJ(h z@jYvgE~&j5ZHkBQSvz#X_Nt@lI(wP>DW>b9WS0gyRtL4(2XkNR=pbi3yK| zkl_duOp|2?Da`~)vg|L7HG!naK9Y|Kd=)vY#&9y!4zl`quBm;kujF9@YlG}88BE}9 zkR9ZA?@ckwAg`2P@=pyjI)vdUiWX(sxr!Q>8V z$bOR#PUbRA%K8YL%5xe8M!0h2Ad4{6P`NIKRg-JWhu@o~kE_<=#2>hcJ=HG`H{XIx$Wxl>)9Cnr^yVw8m(C@ft_`Kj#*i$Y`Dki3R36TlFKUvF2mdUtDTm4f_~(@fap9ldwd786**kjittGdX zU-Hk+TJrBwA7xE!nvHx_L|Dqby3z!D%qO=|LyCIq3 z3E`i`b>tDXbsBa@oOi5a;Hx_F7(Fmr51hfkv32EcM(*}%O$O|)OCDwaQp0*xirK3V z|E*FCBO^?`1$Y5NznsKi8(AQ_2tg)1vA`w2E+>B*d0?+S<}aB?@y5%ucX<;p;Ugb# ziN^e?ET&oiC%=+(7@KXFVUNm9(~sN8-Av`NJMu-?b9Yn|Q_nlZLm~cnyLs%eGJW zh@NMWnlzT1(vv2){##L#-i_tYs~Jh~Lu0vz9Lmu2#_}+Ef0-%j*s@yu#6Q!;pEdk* zQ~ZhKpYBcMX7U*R8P$ZCWXp3q`D2FLNw9Xoll9Lzt1n^U46{~Qs2 zI`B`M7V;vQ=K-;=1%>tEpGKe4)*@=+=kiJU(BG!$Y)`3c`DcT@E|upL2;H+M`&s<+ zbxU39C#oNz=`9)T%RlE^QmO<0^lU|8w*0eO{CWMBGFr=vn&iJV)mz7;9%Z57yh7{k zcDQLRlfxFwUeCSX;7DsSG9y`i2Ws?^WaAv<2TCheO3n4chPMcBBfIx{EVDQqYo~@d z8Vg=WE}%PoRPdZl%LGwX`$$)I8eG{>xDdv?c&RR`x0P#4>f3aiwz9LSROc;x+OavW zc!T72vXjVd-Ys&&opy3JivVr=lq*YbVDHF2A>|FC9A$q?Eu4!?qIzF_gJMTHSP$bd z7!j8F2LA2kC?lSQ76#(Aufo&AB8k^Q_R!^UajE7Tq;{a3vez){C_B{9lo8YDRL!Nb zwL_{~nXXd})$Wb47BH;RpPq&oshg z@bcG?zLf2(@Y?jh{OZNOhVz%Qy|n5z z{J)fArGc+e@+I-Vehv3d@_gy^E97({|2?nZ;LI;xAy#~&UZK=kc9+h*f^%nfr}JMS zzBB12yh3qjIZT@N3cg=as6_%3!Q&_UA3d^r9EG*|r)3aP; zA5&>mDXh9uIqy;gca@h(wMtRimBzaJ62aXFUw?_xZnC4)tQ2;xOze*@5#uU5igLi& zhLvi{vT^?ZrfJ*i#sRLb<`Oz5#c63;WI}j zb=3|p*)#a@QnyZ8SIv8Y zZF76{wlirmesIUA|2yUR3mcY+b7u-NyU4leUQf@Edc^Fb2E`duwQWB2s zM`P_Sfz)3X2Rls~s^d%G++Q9lUK4Dn)+wn98?iu=nwY7>=r6#lA=MZqWL z-qNGLu*^%2lK%J$7Tz4jtvGwCbaPm!<^88xdDvi7Wjmix zq{~8W`7DX;_ZB{h+`e+l9-*^>QDCI1Le&kGpy8a|3c0{&1zijeDjQ_ zZ#2vHqGTv}G{z#I>;Bw+XmO&zyJ>boa!^kk-1o5aaYCC)36{@xpe|fRdt|g~8!D(BiMWlG+e(oXHdgM)1al!yBsl01QpU>SavE3SL_nWMunJ+* zM+`f)(IZ5JP&e~O$PJMjE7Z*rPebHBd?xQYCvMXeeG=EK3wm-0X1ls-SdyxUo`+k( z#`#MOVeR-XehFnyQ}i%>e<*uJDd-`r$20T19wKbK>{;z8Mrer^n8H)iHz_5 z01lHloYCn%(}pSIA0U1bTiWUmAaP`;$3^P}r{X?bCd)oXIgQn}#GOps)Au1oum?!I zkBEpWIrN=!ADI!9v*gY|TdZ}RV%uH9_$VHe@gd+?kt+eqi`A$U6J zeeWS}dX+u&t6%-@!E6T8*Zdy*XUJhjyEIkhd&n2z?~C9tQ(mTrv-F-SLe@-%pD2QL zBz4S+(2tl)TT}Y>w zPkZ9d*7IhM=!Aw8;cXRc(p&5w z6e4UMmrdRlB7Pp}o)*%X2;qB$D4NHiQf48-=QE#vE<~>Qt|)~40@=@YYN2t$VD^o+ z@EFZ*^Dcj0UhlE55Qz&YJEV|jY$$7RA$%56_Vcrwpk%O7g1Kl9ZXw9 z*{|*(UcgW9AbSz(&9OW1iJ{DtJ4hAZHFsdKn6hWzG0L{qWzVDBLfJHBNdNc9yo33R zDSP4_6fLGKzdLYVLfND4AZZCl(AgtBYhf#XujGTedRQpzqbK%{_63y{2&vQHJj zc^PHyEkK<3CKRAVd>0hJb2-b~u>u4yr<`d8$XQOlfd#NxK{;Ush*?2+XaR1l;JCPM z0msFT-;{;Ke1qk_=FOy<1#n$Sfu;rUUrB*wx3O#`3y~uQtdzxBX0BoEx(&xz=Jt=b z5fdwWF_6m_^KRpY2n@dsr&XjFeH-zsIE*C4=W5T}#`;D%N6gKleFG#C^5Bl;Z&*aFiQd3f_qg^lGr0Wsd@#sw?#>>`LY>o9R!_#yhgWGN* zCth~2-gHwh3jx#kj~^PvTvjpC&*c*QnwpO*+|t|-9W`g_8Vt7Cl>w2fS=@{(zEMG z{z>+b9B-iHC$<$$#nKl~`~Gqro{6+(+;t=+%AR$!aGv&!yl%|EWj%5J0iD>4y$aZE}r)gWB~vN;Z+fSJ&aOS&osaT}R$#nOpuMp2vY-UjrZX;2HR92;Ndf z*G4^mjjl!*e&!m=x5#0ZI==oG>(*D`Hj z$hDyMzsQY^Noc3GxW)rKtX^){FzpxC*PN@!|AnUb^(vf`*`ED)71_z`C+1#-!#380 zAy<*GjeVgm$WiTn6-C>q)z??yvYm8wt|D=JWjxo&E3V+-cE*=qf$NUS)VQ@*uU$dZ z4u)U4!XrFP&CgfhpHfBFUX8tigAVF@vF=YIt{O*nsOP=sg%F_GJS|p-qp*n+|9bO;xfW_lYaVTWDD5qGVJ!ye$JN> zCB98A^K1^k=A_?C`?a`?#J$9?eHo>D*`DTIf$ zO?1vY11yF}{V&2ggPd>VV}1tBc{?9P8KOAm!!?uN-T6om-}U);o5}3Fm=D{7#9NY& zsDm`m5BbPHNc!2tKSX$JKH?71%=Y=nJw&tGlI{@ATqhsahY8onhx=g`@0R(Hhc=^Rvk3!k;J+@WDUfeuR7?|3u^w?s`Q0X}adfH5(i|B9D^7{)GKe*-znG zjP6i%z@K94!?W{tu{d+rL=AB;wtA)wxWdQV?nJB_GV{*623HQ5on)-KFI%J2F*bZ{ z{!I5cCa0N7J1(F+n~JQx0Po|nm$GLZTfI%kIa=<@nB$zI?J?nz>DCtzdxE{;9&uz^ zxq!SA%u;#_vOmc(d+$6FPO^6*W@k0~Jg%H%WY&2&=CI%DIrkK1uq@9+v!^2;x zX?d{DB~of0!gICxg&SRL<{?i6PR@h<8LgY<@#|rEh&;oN#|L!m!5;g1?JEcDsX{j`1Tw(v+4X`*Y!WQ*2%em_E6NFXj#CA9C6k_hlLydm;AueY6{5tS+ zHN@3SbIQMjmuAh~3UsIZ?q;IN_%Q2^GQyQjh=&ei?R~kaWOpik|9!bak|O`W{zueg z%pb6LEc;d4Nu!EZWZYx6BGvyu&SN=Lq|{U`&Vln2Cg@=fVxP##(yxSzImkSigK5R& zfE?r&bAqO4i>X!sSL8r?%8p$NGm+G>IdFeU9;0%Q@RXB49amDn%0Yz)|2zl2&$u{h zorAn*m04`Uv%M#IqJ#0zPtt{k9A%`F)q^KdD#FuG!n1@~bl@cB^V?jPr>Lh-8mn#j zH)VY!z1nVPzobpDOE}We72pMflaQV>V2R8WLN8<4KV1l2mz_l33s&y0Ps05rEoOfb z@h=HiKM9Lc!mm%jzf`ufGohTL##K=hPRE)Hxbl`W;ffPTDkWXc30S`(-QE*CD?)hf z2^0u;?g==(W}~tE1c&IR9~zC+69|4y>sk@-HK*8my3Ex3$Km~kRxCV@-w6h z>Bk|xW%$11@Ovw}8}X~DvBVSM%Z{VsZ54hsHIR6JGknBxr2S1f^Nz#eAL=vyIHLZc zeglr9RKPCB;ZY{r*?1f`U29@|wkRaEe?~}F%?y!VkK>qMCVT58$%HT9usOe+jRMk0 z*Rmm%v$DR*Mo>9<6=Y+7Ie8z;hQq&vcV#2$U#9&)w&~i!kJ5fK8)^UQX}(|*ZLUtv zhTVTy$wRUc`ybh-#$e)WCmP~>=dGDVMmv@w9nvH~a7t)_R{Z5 zrO4VDogs`5Wn74dM_Fj9tTm3QJ`9tK2pPPyQ6Sc6nAO%QA8?= zztr(4ZYZSt>?j-!8D5|Dt#fhU%3$@h|xSBJ(#Sz4tD_U_Pehu|~7K%jp zzgcjpUWH#n&Cf!7b%y6^T2SA^SxB*3%NC!4%;letx38%S+K4}xJFjGdo81(_lOJiuMWf4 zQaAJ-ljxeNdKd|oH1v+c$h9Qntiyb@hKvbU*ebTzURxP0bv{ft9kj0PVLnyEui-G= zbnyG^5L`Z0oTToD5&kK)e0>OcpOW~_A=p`w+2ccqwIY1+5Q?m*W!xdy)S*_(4#A@i z<5Lgui5k+4Is~h_#PdFc;JVa)<{^6BV7TKUJQU##DW@Ls?G7Qi9^qPtP+m`Qu5tDt z3s-?wxX}F#_YzMWgugWzWE@14H3jWGn4V&-)DjyeCbiTb42_>Id%k_{7dpW!xC^v6uN zG$QfBOvE-Kvz3`B7x0Wscz;GkJ7-eS5~HHEsc8Gm^t8{EPff*Wpq6T#iQL9ijD3-% z`dbDpZK>GV47l2o*WC=H*pe4vDmGv8%fS35)S*WP9*S?P40tx>w{`~oWl*O;hBu{7 z)*0|%;bLbe1mZ3vFiY`>=f;BPD@p^ zP74pfuDQ~;=ALn;ZPXOmWREy9H@&$sOd5Is`OOuv_+vuDVx;%! zC~2XHF=}*ewKyHlpEL4dI$}T9DLzq8rXyDb9!rOvy%H&{Nk^hR6B3yYsU^RG>3j!9 zaj3CBor+2xq6t~k@BYvl;|Ocb8R4Dx`%1p)@Mxuk)fo9v__zmsCC_x2wWdL;r^B^1 z3xjDo!dffheoXWy>XH2@YE9w0_QSMuhS(^Gga@#XY0)B^W2gO(C#{tT$4$2(K>vxoQVB}Z7!@DE%J?A&%ccfW<{f!Tv z@VoXmB#7^<-%#Pi4U#e>X}*;QY#aaPu20iA>vCmOd9O=sap3p zWPPcGOBMUz*hyI?o!y7bP70mI2z>5PrtgE~O#AHHN3RzOAEOcB+=`6bhjP$XO_96VMN_=io*4oEyf8tjszb=Zikxw1?7B#X}KZz89|D*hp)9xDWZ~ULcpEf$GY5H^q9?D)K*S91R|A8tt>3u$vKX+AP{@?;SGY&1WwMRBa1Zj_ zY4qqlunu3dMYJ0IyW0Nz^GGTT7UYO^(8{$x}FB(;l;IO6%U+jf&pNH1EcY7fo8={{Cg% zO-wQZa))OeXIMZ{t+JyQ(LRUye{-l#C$9Q$BV3tFP1{8K{4C-_^!Nk2)3f_1)~328 z3O`dnVWh}`z)V^q#cuiE7RAXsK9Fh@|+DOa&kksL#WUOw@JRRF# z=_@QqAx+eJseGhGDRI)^rcKq)Dv9kp|7W{5kYO4gx89EZiW^?c&K6YOTPfA~amy|1 zS3cIF*y^xbGj-Ij@EJh7@xLN@fZ{9)8|CVI!hL^DFCL&Y6r+QtcB;p(JY=DW;}qO& zd%6owgA||Ubib_kHAULd^DZH=b+pnDl1tZ4VkL#?*)~XND+U4Fw$N%-NF@W`!5JYbjWQa(e_uaj z|L}~Egz9BaWb>3t`RRj|77duF7V3~n3Xj2>wOg^$yc(>0DMmazrn-whRTOb5XY=Q3 z_g#D}MoTR>cJA+l_fV?v*G?o2RkWi@_UgYoQ9e|OlahBL)|Y)YQ`k~X*ojtQvshxMy0g5K~Xe;$r z3c`m`ZugzY9;S#x1Khm0o`NhtVz8TTtwyEbp&v08r@&>nBCdjRr9q5JMyJr>2?yw2 zDe0xdmFlMLdH8{DOHzzB&+qfUHfI=ZzFO>G{IvrPBgl3jxr|V3s)dNH1S-F21hbM_ zv{A3^K>i3St-Y{tWe0NoHI+=-sW)St8qcfez$rc!iUO{K6MST>SPv-b{^j8v?v znAQkTS~R8N?bPl&jOxXDm4&jZhglEG7)Q}z%%=eXN?)n@4kQF<1HtHaYP}uwd!ngO z*iNmp16Kky6?lOEz;;vwQiWsNc|JpN9O+KJn@#lUFOt&anBL}w6b#P@CCq%uFgL9} z?(rX+Z2A}*`^{|pza$--5v@6@#ATV$YwQPF+zC?Zb^crk8TO$Ks;v`iJ(y^NYKZvn zjLh7bKwU7}j8gt-Nvk`mQQP(82WGJ$a_v)=LO3A4QAUWbqiXVQZkOxZ;W=6nM>0&> zs{^*v>xyC{Wo}2#Xr)Vc7KirgS4IvY&V0MW*sE1iCo|66#ALE~ewJ;lrdMU$#_ez& zqXbKZ+mJj)A82<_^S7aR39%2t6`$1+Bb@*zH8UA5PJYW)%s1KfL;?IRq@{~@d$VI=TmsSR_khE;pb`buqo!L&*2 zwDi zw-J@*E9|VU+=`MPD(Sh{@3a-xQ%L{yRyvBQG~dy$H1jpviqt8r>4vSan#!I~SE`Fz z@-uv=D)xg}2QRQWVVz@fWSv_wL^opq%{F^07lwv>s7AqrKkmwdMEv0YszxG9($7!j zJk~*zw7H9V{%51@a%j6$kFqaG6%fU$^tPQ=mD+8E*>o28@ShPry;4KIck%7dNSn^` z+3ROm%}`vpi^D?4_bxgc`GweeWrWOclo2TU8Y8dsKc`2`ps8&%g*Iych0tCMF=@9mvlN3? zN-mf*?WX!9;l^w|moJz^cT@k~0%;C&*)IvcbM(q}LAAF~BHQKVb71vYc_(m@ToYo%lA7WmKAD;Krvt`6IRl(~8*BQ(O9xk@vC%_eRp zs>c?i>Y~NW>6gKRzo##o;Oa|FRP!dh1Zry1<(etIQ0vL5DpGx1J`|}-oHS^tOW6jL{ubQb1YirL_t_ypoUxnXzJPYg-AorctaZIN!(w4&t#gx9r_JzKSXt{fOKO+R za9vbM&&BY9O$c5@`bV3Pxu~+%Ma!C9&uv1*BG$USn-COJRi+g+VH1*L6#phmHhoB* zxv5)5h>JlRCmA(I^TkTDueBu7Me`&gYxe?$-D5mI*j@c#cM-4Q=(fk)#q0*(kHO!GuB^L0yA}+ z5m^(?_5PZh5WifnzpNBy>f%J?E@%BMO~k|HinF^`%}lDPlPZN2eeR zW89@gQKy5Y28qa7QCXd%tEr}muvp2&JpTz{D=WjfCVuxPq^?wKJXjZ2Yjxqr4|(D& zYjt7u$Ia`hx_VtGWZ54@Ju2&hfW2s_SiLSVZRYCZpWqS8y0GFWV`0hvuez{W^imgN zmFuFh(^jT85K-%;h!~K-b3;tTD#fQs&yN^rrHv;)#i*R6O(=)XtCePRH6~onZewH; zB1)TWUs2lhlx_KtvgHy}rVqMSf7}O~f32tPC{uHQe4<@G6uuax+82SQ<s+;6hSr7$$QowbztU>4X%ICUuqid-F8xXvnB~l@Rwyb&Me@o=6 z^;IRZmRg61T8SiLKz`4%?i=v%N0!Kg2_G0}B{EC?uM+ufg3_#sULq~kT}0N}Hj&KO z-j&G&5;%Q3l>o~PY=!qFAaAQuA2T;7!=?BHToHlu65z0rYaA;R;JuOES|5({`B+f; z#EnWvZH&PArKM_XDoYRKJin~zpQHlDt=O& z>QlcxVmWySKyLj4XZW1>m#w03ywoqVjO*!*NxNOohcaOL{_uY?l6{UB(draIu zQG5M}+)avajUMEr*)@{SiH4h6+glIMcx+tZ3XJh8)A-SgZ?pd+aqMR0zL+?Fs($$+ ze70~fPqCk>`RftCMG>BeO{~-->ru3YOD6}{!zD@SSeF=lqh|g8sQyf#*HL$^N5sz> zBey!L=X&h_S?MJ%_ta548)-Q9#isLo%HfOk@Y~7`)Ox+hf*|P~;PeaES8o7Wzi>5w z58#ljBundn{A8VFU3D>Fy-g|O%jcWxstcg2A>Pnw){YBVPK`3wkZLzWS$exeJAOI;*q#h32NdJuiG}@ z?Kg)*lKb;eC7_Ync>0avaHpj2eaKws_#0!Mx}IVvf70AN*1j%mRBeDDzDg0S*;$gL-B5EK4Trc z_po%1T8E@Pw428|Snnm=aUH_;Dt2wUk$!XKx~ECBPXOVj#+5jhu?u3#tbOmABYm$j zQ+mG^PHALNycRKOWO!~Z->4#dU@g4&DR!MttR(~E!e}cp3@L7;ZSX!|xSNr&Xd{fK zsA9ftpE5yOw-(mFiH2`2ru{~yoz^1vH||>ntVOX1ueTPSzcbuqEfRlcZdYFmi~WRO zuYv!5ZfWdWgZTZ5Lz|szjP@_>Ulv%*sZ&XRu6yt%cbe`YVKd`H87GR>$n)HHTEB)* zRxvf1YcM~Zf+ns(Q92p>t%36aDzIn`d=D_(WexTpVEE^2V39!u9M@o42H}Qlkek8H zqibBGG#)mRaq`P(>Lo?~9njW4dX4#v?5Vx?Nnyg~k5pqmXk$r@kj8tKF zl#)DEOgqX14^~kmU{@8+$B6fCH62GWMQ>Ik;h4h5{sbR4Yn9=p$GCZw$@pw){_|=+ zOvUet)v!OV@c8>`T~ki1wBzqhO{0B|vAB4>tH8e1NIXv2A*)ewoU#V5hR+Gg{(d#G zP7v%LmWhpPxbU4@dyW{q(Bq%u;6=F}3&TAFQ1^m@2c%P=wzhe<| znx=jpYc#bBP3=UJIvY)GqrcXCpYfrL6Q=$;fsYp5ibcg~B~iK`i^N~yw*GvsrCYOb%U2@)JR5EA zl_)vSro(Tf|@#JMFy2Wib%42u?nfiDsTyGQa@>0a#=9vsF{OD)u z;iV`R;VDbuUO@WIOOafl>q)xC>fEI$Dq#GqrEs}JJw2Bq`woYzI(=ic^HNBKjQ?UO z{0gMv*QHTh%T#AxHWrA?5Ypd-PwJwpJ{)w7!D73E~O(s#OeP|DvcmG3iBrvH6y6FXGcsjEGwV-{*{&vj{2Ax%VHlsL~F+*$_up zV3QXi>;+F=bYMiNcTYA?J$3J}trqd18s+`H5S}kJd2Y?s3k#9>k{Tagh_^49#48Ii ztyJ+*`mmMPP6HfXsGSCAP6tLxr!K3_RUTA~ue=o4j4m^jGJ#vwR^=Jt%C;&|hcV+7 z+p5ro=?SkWO?tWjrEi#uD+}Q9Rtc}>z=4SH<#Oz1qCquZz_7I0Z6_?xl-n{UeA_vG}XukJL}l({S1nq@3N_TP%QVZ$Az4hvxW z4>>emfNB5ecBc2P1;`bFrSoA|#>{yi{?t5}RZs`aLu`fOSc8>C-(vTb^(}Va zo@F}ER_c*?#>&O8K1-`A7cW_Ji`_@ZujOOJ=PuOld2o2oI(B9rJm0g94Vs7K_cX>= z^VV4yjLGG`)Yy6JJPo!|_Pljr1|OplTB~OB*5w$OmGfY0YOs@5&4atC!Pl5R2es`y zB$*l>I_Wl`AN^>fZdN>B{eL$F8K&Wxv{9EvBU3W?NO94ylnqY04VmSlKF*AWw`_2c zOy*&kY;e%yxG^Q-21g@XHaP0?xi1wTjdI!WP=~n#@T2Wi%V?w;4AvG4sBb{LAtNLcQ8RhiRkyLD`rBMsni+f@x6C!xyZBxip?U6A zuZxMHxx1jXG%n4wj`nelMx2=;NXnaww`P=?F&CcI3=z`CxqKmu@M7v>Zm_djL!Qyb zMo~0W`{%;L+`#t-wQ}dE)|rbqbK1Q2Tojudf{Z$~SBs+fau&nSMX0+mAg83{L)#t$VQv;tsnS+>5NmDW#4?m^M>$Blv zWuSlM+3>Y8cuJ+Skz~dAZL=ZOVSF6J>lnhM4YQFg;F#I4u4{0Xdd-G+U4w(vZ8jq7 zvQ{|FMuLDHW+SJrVZPL5HazPQzr}1M)+3xY3wGAb`yXc^Mtq}Zp;&y!&VqM+(jA(G z$oiB!c@}QeC*Ak6;Mjn2$IL=P1HuDmp`-!j)}96XhQzNn3qB1Eo+6KFdnfgiSx9bZ z2$xPo!rI2*E9wOEjGJUkdr~AKZ46qQvqwBBuqYC_#F6Gj!mg1aQW_kI#727A-y^*F zyGG(+BgVT#!u2ylj8r|6?_g2a7c=3|*x*`+yvgTF_2$gV^6(7?T;t22S7-7VpDvt? zI%&eqBH?JuOpcq0BwK^lNRqgd8a)#QwiGgZCY+n-tqf_LRlk{-)`a1{Gm+QCAch~j z*V17oY@0H$EhC#6hKa7Zv&Mb+Oumg}=uw+koz>?vD)oWu8rfUAH3N~&sCU5(6f`sV zNq@|MiygmvW+0wl+aHOqjU7Do+p%uOsmbIA6}UPBmd%+TD`p_PIqg4v2C|zoKcZ*A zu?69AGcdme^TS~VGFvb|>}KF$3$`ou$urcKWiJtV@jTL8dj_07H!PFd%s|%Xg{7#;C0(2%K!ZO_Po zQ}M99PT``qC+`jnY%>*+9Sq_=E${z`60J-{X$KaL)#CooqbYFjNUTd!kkHW(B^{qa zM?gB?uhlJ6;OE51pQiB1ED9Yzh2DS+j@8VWMsZPK;ui+(LBFo*+9}4;v&_A0yPw`_ zYginT?k1Mdv#Yvr3a)&?`o4Jz-hRQdWIqKyUoxe&reObnNhC~xbtlbW ze9+BOAn!3{T8b=MC@>7MTY+b=SVb&ktGuIiv4kkFZV z<@W$_?5w4I`;$J4H-0tFM33yACUBwK^){LWB|##7{nPLZoT~x z!I!nj>p}#qT?{=$RWnhGBH-_0uoeQQi9l*+sxFB@mJ55ksS$dO39#gHmxXvH)a0;O zq!hiKHB<0$Z)f!b+`pz}k|L1&HKnX1k8Xzg__V8GxHKsO;awRxoGNr>mp4{0{%Cb- zSp?p8WvkIK0%6^V_nAfSMgvnth%$S zI6WC2-C6yjCetSo=|d-@ygQry!INR_#%^K3Wca%={;SEza${H0oP4#e#Iq;2<~e%y z{m_-vnheJt>?*oWMr04tyqts^J;?LcBsjXWN4RfN7~Gn?_Dj0?%?iGNkD*-V*)#GY(B=1qdbH)J?|5~99gUs661 zQZHKe?nDHO@2QE%72n+x`PdgLv@!{P9#kx2BK;SUZtFx?_NHRLPDEsH!s{m@uQwI@ zb|TFB5P!f#IQ7x1u&MgpM8x!AM^bYl-u7Wr%lwzLI#(PHzrI?XJ1VK?!jaOKh52+i zBu{oB8^RIg$u1;73{m(LNK80#JQ+Vf9Jc)o^e?6jU1V+2zdIbu`ca*3;dtARYPTTc z{sz|uI<2DC4mVbXEKcU>3k(-Jaxz~d9OeD1I4SBpHUnRUBiM_aawZ_(iwQnG0Z!hm zlxY(XE4~{hpqO9Vg%fnkhlJ_RlvXzM-`}V}_5=hCAno)C$R0rB1WkbTKtq_txJsHV zB;28&B;N_RGLS~AHvyJ|XtY`r;4+AHT$%ts0hfjns3oduQHJKQkT? zK4iRqJaT*tVKt77H!8zy*6!A)ka93NhmJ?qU~&o^FZ_Wuf?L^ApFzbi!({0|7%co~7d@8@>iRH5 z`7wvrhS6aV%gc-~cnoK54h%!eaJ?j45HBoz9fs23#OoXe&+iRM()&=9d{4ZGq3{_| ziRWgf{uzpd5yU$eiqa8!K9k-|D>3Dv@b@>+Bb_#=(Vtzo9g2K^=KZ)(KDcF|YZaC- z(V&kTX=v=AAs(%!t_w95C2;{~mENX@Wb#s17yVM#-cY2CWI^d13d;aPP$OI7i)tU> z+V8NqutNt}hc(9Hwpf6nv7N4gx$0HPIIdS&tFHQfqiA;~haxw?;8)+o$SA~xOz2u& zFwtDA2O2sF6EbP$>h%yr1~SQ)Ly#Y6uxq3dt>1R@IG6&)j)nJFe!a&cjbFP?WA&T}^rQie9?J_wBVwX^ zEbliK&LPAfGZqOUEU*K|q9lYJ#usA|6eXBe2yY8U+&K2;`+|8mjm5DC z!$-51>oVTZPihs6nDM&R*x}aFtX3@;56A0P+as>N6pw-P1X}0e7{pG{twvl+HGK@| zhuT-#ItG5>hG1c3;#;bV#voUO&l>}~iJW9<;cm6nA*7$k@E&9EaH2sRVda)!t1)n$ z#K0C~=mW_h-f-f+;NPR^2#JCBN5gNjVY0ydL_Izl`6BShXgEY@f!z07H5y3~3|u}M z!$VjPr_r~Vwp($TP+Vu+O*k4D-QedKPX{yhrPR3U5>{HC&* zy*Ub*Q<-nsqhLFY$cdwnI*o(2iKF-&m?2miJqq#DIsPNpI%>~R$e&K)?xWx^gT`&a z$QcIB9bg?*9%ZcCHoY)-xz$yV1bx8T^dDj!41!CfKG>#3$B zolO?+0^u~r(4{U(tks)=RZ`1B9eZNH1g^+k4Mgr7y#uvY_Xffyie$eAA|lG5J!Gms zRB}HT8QzRs z=P|ryAj0R-VD$oVL%=4)pHI9a0SKONaIi}cFt&4k9%X?(yjkSSHc<>k_Un(l?Fv8| z@uaN*D45R?$gBW_EnqDe9e^D1^$LL9LVleC5VerQs3`$RSV;M;15mz@^6Cb_dlBU~ z4&W&!!sY?6jG_ELM#3Y8L!l!hjq<}NKZx>!jq-V8UCh>hV|*y%LYTLW{*szWyGHWC zFcz2jBjLT6g2#~b_JjVICg6Skd^?P?m-@qLIb}xp^X)Kx zhx?xl`8`XJksQ_0WHRA4^iLg(uVSyfjVTBCC%GE?@vE>Aq$`NMi8hXrju zir8I`5!U{=vXW|D9>D`VRO8$TxWrPe>=E!2aOMblJfd2wNAS5Zsxxy0BE&an1oFhU z-w3)jV%{tr0gu&8zUv4iuV!*vk3jiqCf{iUf>pweM<7$BoLk?cR3+a_-@`VJa!!8_ z*Eqt*zDHObYv!Bpksrs2x|?W)c`@gQ?_sruWix>BYq%1jg&%F8_W2%JBD~Z0uwKiW z-sXEmuC1bLs8;_TnQIwuApJVlxl6;5u&y$mw_uJ9$BlIc-%kz?H=0#+p$50ZYd*ehvoC~ZS4x9Bf zNZ;Y~X+#5jIUITGX^?Ki;qoKlR>c3226^O%oF8d`JANqrk?~f;;h#{YXd`vC9}*MD zca9(4Cg=vZAhvJD_`!1n!+rdaw1Ecb;|H^iT=}3r7lcp3mVR*G$oS@dNZ3dNln#U4 zPX^~YT0FOL?hLDHJTNke4ytYrO zTYBP~?z_{FElXR5!e%!Gtr$u-Lx!MgXIN^+aZBXtZVtj*4Ta|(*7-U^>0^k!=KUe? z+pBeE+@m``1W9|D)n|sFd@o1ZYla{(jpZ+L2&8>_kJm&UGX$Rdh!jZVeTGG%_tqaI zUNi(wzj0vm=@2CU#>pT@1x?km!6^TY*lz~I=XZVl&`dow7+JqF@b|&6-ftKq&hIo+ zG1ypWgFMlQ@0?3(2IIzlZ4|)0uL*eBFiO&OtmbN~!Eil5 zta^hHe}FBR|6o4&#fn;o(lcn13LhkA5WeICvrNVx_Cb*NCi@^ud{_Cv<{(?Doj#a< zkofUFxN?vscPQVJI>eIe;3r@gAHMHp5FRj&Hdo6B(N7SCza0ec!?eTo zLC8K#>+Kx``z)2Q6j#_2f{O(9oepd#_H#%KU1=qome1$ z3lCSIcp$Q~NxNwv?2a>i%LZcFaW+hA2BJv7Q3K(8g6Zux5aB17zD@&?aDwS|7>G;( z+YQ9S6C5DD9Dtyc)c*7UX`nuK_6igGkK>!2c9AvLAq~Q%pte0kApE??2v{#;@&NZ)0l0|2s7q2P@EI07_1a z-1LTbF10`6jig-iJmn3`GlchfBj^lM6XA`7Gt@rJ8#!l~nvvdkDBy3sVRe?NvG+#o zS*E7K3#Df{p=>Jpr=#}j6EC=&qplCU5O3-)=;=(S!*$g84j zsm}GHw;#sOBK>*pWa)IR)bqqU&zyAfg53og#>xvx7pQ+dFGznf%@zIOFTRiZBa>g- z3;m60=K~{6YMFGY%*pK;6|nSzQ$A^r_eWel)0)~J5A&J!^#1UCV_Mqvfg6-TGnLb>fwJ;>vaEd)pHZH>m$ZPsHCK{HG_1Zy20wul8hb!{_-zg82B1g8{o= zD2)_8ZsrN^n@r9ePlVrOa;ADB;U?!eH1!3Oqpj6Wp0Kz@wK{qt=oYi6F2&qp&#T3| zIjE(5VSStNC4CWon`$5Ki?_G+WRc!M-QE|j1&rU?7x4v5{_MUeFJSV&?~BMgm3X}4 z*1IncND!}QU)U6qk5ykJ6^bnF3+XPCThRyp;`^u%GWoT=(8rjie9Y~?vh;UmXjxsOy%El@(FSc*_ddvbz^>ru-td1|nWm#{)!5!hen|Xfy;1RyX%Fg+ zphuPQZtYaB-bi`G_`ba%J?1{HZu53(Q}TJt@XvZc+^Hk#sLv{BXv8=0~J>%Xr8X&y*=O4_j=ke<;dJ|6T4 zL>mqFK(>HAJYfA7ZDjC(_g}QhyIzR=i#96lg#-Z?_d?EJ)FtEp5%&IZJzoF+__M2A z*QE$W2&oW46hcUakZD`nY-?L+ueEAh+ibJVw!~g*TifE4+-Vjg|^z3@BLiY^BM2==Y6|<|9IZc^PKbebsmp%o!{qiCL^rg)KP)FSBJ^;3`E&8 zC!?C7l%4(BP;q%Of^JYpQzxVR2HP+K4;8~F!{sJ{hfd}J33H}7OgK;G3r|dRoQ#&6 ztZ_AyF!v7=W0?4H5=#DH=Ke`=Y2b1`Y5R+nlaSQF#O0Gv*1*=DwEe~Jli+iU0!B?j z?ky@SU=qAvLgCoLLL3W4ObZKjIuzwHzAqFWciRLyy&uYkquyvZu&U6(YtTDPFjnRo_!L$h zGni@2Sgi*=Uy%sRV@qQm^o$Qh#a)_WVrW)`%7c}mS$Pb)gn}=I@yiZDjGgMPj0?ql zJC)sW2&(N=uHlEkPf@vsAA)R!@na#VS5&Uyhrq{P_4WQR#43go(KM%->{_g1@O2J3 zaeX%ga|x%s9)cWu^7$%+#}8Cvk88LX7=j=Nb*ADLf(!?BhFo13AzCKf8#rwl#7)#| z6A;`+F}6xHyF8Xsg}B6G`3X}oo)qN>o2w5!JCuTnqU+E<6+hshKbyNeC`0*(3$jZ`dJbXJ*3;K8@ zcVgi>jYpk~|1%E3E-d`cahT_#`s&-pnc6|YZu>6S<)Xgk^cRzc%gYnq5ty*Y-XAZz zs-GM0Z6}R09?!~5zU)2jBRNsnPtTDv?aUceCm#_XZP#>Ax$iV+vNdj-P_PEd{LHhL zJ?*EDv)gv}@?!j82)xsd-X9@5G1}CYt?;A zNb8xr4RX%L#qY6Q)n0>4-E&XX2G~qMH|wf;0AB8Q%Tf%f*LuS6k10$i?)2W6|85w%s0t zMeh8Va)MAJ!w-Y#Y>442L0Hyx905?%&p+U>_6(MwHqbZgB(%xG>s*^Pm(H|5_mn&SAH;uy}CcZ^25Hz^m5MuWFH z!<>pMt4AZcj~Xd!(J}pc4|?sf&cpxU`QjvttR?qO2;^AfwpujTjN@V-)l;b)U8MF^ z6+5NhXgKy`c{`3qOg}YGDINvYN6l8&j6$xDI$zm03LgELzhxBW_E*2R3i9kIL=I4+ zT@67#>nY+JG_yK?ABdd;)L~xt#E8^Qv20=}W*qGXQVfStMScTSH+yAfAi@WeO=uvp z2di`!#POo6(0>kApOIfJ`(U~Q9f_DB{A$mRMBxy1o|(?Ov-u+t=*RTDkx2Jb7g^!Q ziPVvBAF9r@!i^W(Mq>U@vn3(D@nYIYlrUeJJQ6O$)CeVm^oLQ1UL&z}n93R52n6`E zoi32u_-967u0MfKjX=4-`i2}81dF^82oGRl<_P2jn2-}h$_UiR#CJy^aJXtriOm<} zH;zE=aFy;84M4-NcTiR=fBRkO4#W4%FdH)=a=0J6> zRTg{k@^H)>rN&rguou&Yqh^$vVa<0C-G^iTX!7bZ9F?P0dW|z=br81#=@ySAHbf^+|{ zJ^+3}s)yn@9Fak69F_ziKZxJPn*nehtHvpt12Ata&9)){@6e0mvAq zdMmF5pm3bJOc@=3$ni|?6M)?Dgi{0H7R>k`{zwca+`s-v4^{&`C?<`oiWUA=F{7s! z$47QFP9Jm#Ky9$fCmW4%s3sQq!*_zMig8;q(I06O)P=Ij=whlrTte8DlbSC2*r-XP zBu{Qa$|K5DrMExwL)1{YSkqQ`v)At6kH!#nJnuQtRo@^RPU7UIsU6I%t@-|l3{~YS zPKcwJ;g8%Xz<0uXeLw%?^N9H(*&BHJ=%mCw_-il$!4>Q1cgK+UMG=`}!Nt|}# znPGffiDrFr7#~+MYBe{r1`I>+Bx&nmSSG_+Bs__&aOYu&oUBH9-yLcl8>kV*34v3L zlaaDjpQEHi?OWLbUlN;4_;W+y9Zm(855>H2w%R9#qE^OBhazwao6GlxB54YT5^oGe z_7oa8aVSb;Ja#B9O;JmgSBD~RD(UzPg*uIRordz9f*NCg+0QPs_Z&AIpQcV!j`_h& z4g-t*Fjt1Tetdq3wW8Dyfzye!(T`^m)W8mWjg6V&{V#Gr?_$Ru4m?fhM-M;b z{g@w|A0Y1;eh7L%m7dhNgXigotq-VS$}@gwe1L+u_+jP@()@P_@@EiffFH_dF#VSy z@Qq~p!68VFWI>M);pqg%zZ=4*msrquhG5=<9AmyV#M&#xPHCDGO<7{5n7xvRgE7X8 zAHtIg6k_%e)IX>`CkN!tB5(+zA5yO~!n=nfhamD{)o`cRL7W(jjE7Y}<=SBEeVA-5 zL*N%hwv3m*sCr;^l=>g#?ZHqV;ny;IFcM`rWiTpa=r*_f zA=4&bBtJ=}fB5pLBP#roFUn=S#utrGva0ipR7bJh7ctRlo#T0qtt_)Uif?@p^^{7V zX)?|Y&?sLldx~mG^hMcIWU{~)0Z)?&vngT3K!nd`TW<)#4Oj1h z$e+!sG;1L0XOm9nfry+Vzoh|IO*!+Far!+?Eu^OQW${}Yh`n!va~i7^8Z`5(2;)rfn# zh|%P449k7PGVgxifrRH&R}+}mJ*)a7^*L&;zCQ||BU5_{5l5zs8=6}hN6o$4AI)*p z)U*8&^E|_d{@5!+|Niiar)2LlJ)R{P-5;g#MDEicE(s(yxIdB;81LF2l?jBa@_}Qb z>f5%$$JEFi9Pix56%Qq#is?1%YDl%byKNtAVMKe)V1y!3vE zdzp05kFO9hzNjC3ULjm)Kg7I3?T+b(v{%?mQk%yt+>^Fv{;O)B)Gp=eENc4NdOA8_ z`iN`i)qPR=sv7KUB6Jb5$uI8<$GPn0O{6a3a$iKuRg;v@`_iooCpadoo0#91Ze94X z&FhQE*VKGvTwgT5rUqM?xrzSwF*`ScGps&+k^MTyF}M4`{SAgE`yl%bc3vjIu3~o| z)V@K2JNf?LJT=A?ihI+c6zWPJs55Cf&u7KHS;opv5d5HwpWot~Ji*!)|*c_-(4ZZy)5mO%-?OgNC=&5-YsB zNb^SFd^v_qd{)yvBm*xDY3byk{;xNQhq zXV>%*e(l2zp0|_L4$2*`qO@c+$WEE(g|Y=K!W=KSrx-mf_Y6CGAw5O)lHF}j;pm0J z6hge@1;>RPf}HV0@_>(; zdwPowz4@*X6P-x$BNNh7{N{m(kD2(Z2Xa4F$H;Tso?^F$wYJoud9r<^veN@WX`FRc zd!Q_hy!U&+{S)$@>4A(-$a}m88fDnm1JR$V{<1^#60Xerl$1Mopzc$n6W}h@91lc& z#%gr67q)(;8f#hJqPQ2DKO^M!UWiIJA-#p>fs%AWF75^Q#j1Q{k+-B~^|A?;*|IrO zd8!vm7Mlot#HL>GUP6SCy|8GBIz~RZ+gE74_(Js!t)C0);}Yqh?(d#93i6po4}{#* z1}ibW5H8dhkKdUor=xTDMEh*{9JNPC@ql)gF>+z)N>A(+>Jek9;BZgmXQ;tJQ{^(j zM!sEq$yzV{xzQ@C-Tli1X0?UYA)B5Emh z8{89lOW8KQ-V;?zsnfrEASjE?ONcR)?IWstU|trLRn-F(S*%CJJrK5xZL5*bZM0=Q z=y8Ji89h+5OpWMf;`J3T^spAZo-^d+P(E>9I#qeT2hyNMIhn|PMQ{%;St`0add;vK zs|58x@N%|r9zC#md8-Kh#J}#STTT{D?g(2!5ze}!a7C*K{Y0@lnpa4Bx+5x^YfGjG zJ|f+{RRr7^%tk299WB|Ml@Nf&@ey;}5&bz4pK-_5&rL*HvA+ns4{?>o4f#Iqh*`<$ zjfvP_@N#d(N+SNz9X?;M4xH|eh*hdPR)3*BU;>2<5GCEYYfqpryK~oG4U&Z>*8w84 zyB#{T)gMz*x}z?K*zpE-lJZn{l&mtA=D1TcvO64C6WhN#Vpp51dILqr?#Pje?MQkx zHF3Th64w~xK5mj6?uN~4n0c@p)Le6g&sXGj!^~VJ<}fptyi&Wtc`YaKPjo}tTDF5T zx}jmML7v+qgS)|R9f1dQL+UyLHFt%wo~?a-S0u^sL|0U=r-6#PA|j9LG^e`K6$9(g z-mdWZQnj88P!@DW&6jGFD{Jd9y%#SmlQN8MjYKXa!KHou0=r`)qDq~z6&mGBG1!Z5VTp1aG%B*r*U_|(WO}7Wl-Ci zl;Vb*&1$a>OS~-Ig#4glQ?;hNE+}WBw!|x?oA{y&>Nk_p+g%X0gUvFID- zpXiM0Z(8XO6<>FT-_}<8L&b{Dn7@^9S)Eb2m3^v7f0%f+Gu*c^{iV*ByR8*|n3&ob zr80eFXS!5Sqn%86f6=|OUFP3WL2V7O{e@1jZwcl=u{_Oulk8VYtWHP3xO)mr7B(fTFG#I{RY8}(QhD6sqMOVmekb+ zVWnzx*IX;P_+=!;!@iP~JnXxzR2}JJ$}&>CVS@Kk*@@6MQ>{h*d7};ElkG5vd z4t&7CmmkE3yVWsLzbs3jnB0k{3aFRRPW02zia1L2wIMp+L!7lo9n;N393?umGUk-F zg-Z&vgH#@;?}X-iWJZhnj%FEWUz*;^f7JJ?m!fn+^!Ka}H65|}d)j}0N4V@|TeG1f zQui{R(h+rg*>b#L5eG;flan4!)P(KBN~37@S{2+Vjo+QZXHp!&z2uD zM*P_U%6{hG>VW9|Y*~Knz>^7V(oOs^VtWTTmNEaE4u~x?zbRIVAhEaua%K7_9nf6H zm3tFDNIcg85eJw)hxrFu;m3*z9Z)ON2X~GxBBnkIqoa)ku>sFaE4?MszvTzi`IZaudElt|7kbjCz^=mNUW+ znU%djE*C!PjPyfH4|V351}b&9vs7|dyn2{QbazJSVJhQhd-xu)A#pkJOnb~dLZnme zQGUb}mc%BA?d{=M!Srw1BesHgAGSwDg)N_M_+D=h=cCMjr9I+~(sGXz|ETTD<3i)` z_Ha4I{GsiUc+92*-Uw>n9{Do8ZF?ScprvoLL*j9>0izM@#KCqbJ#IEgtf_WldpkH* z5C2JIC+*N&$==trnIdA_Vde=N8D1fIupJ*fBAIc7 zJE4x$m+;K^m;`4ByxeT>jrX=X_ECDYL-I+ML}^Di5e%<7(M^OJ>wV10I*=;i2WdS# zZgjWS!{e8nP)<0-(hh!AtlQU|u&9dauW&-6j2Am0;*{#`vR~4fbnk=T=Y-@_YWMz2 z$zP?>nNhn)wSH;d_Sks6J1t^rWD_vI{o}RG0*m zwut_f1e$d#feI3+FbTBi$o`cCuIgz1l>|=eh^%cTkY^Go(J{Z41h(1;qx*5~wi=B@kB9&dFsBZJc5(B(9Ux_@C4;{SC#- zZKaicJQLZG8Q;!o4K9~igikcgy{tx!nr9QSg(8wzeAT4lga&g-N=`fs>y|kf)_qzs zAe>|%k8!&_YC|sL{Xu3(CQoPxxIzXKHDp{-qx}4AFzQs3!Dcd`?_oLuEpBCyV>0MW z;jU8m?QA$Xq)R+Wx1)xrtEBt4img|v>q{!sI%?&p3ZFXS98gVN$2*(wvY|MnBCd`& zg(}MGh_gn8`!(7tUq$LQ#cnQ9bl_dgHt@Y+VzxCfpKgPU8^j#b2I@_&=X7s_R2eooK>dTP z{&7Iu9~=z*=77C2tZ;xw1H&Q*%x_?OaKZt#4J>P^0|IZcZocP$q+1mA4F_c3Vi6J@ zP$J{84)TaY57^yShbrj~e3gpCCpsYGwi@N(=U}bK^m08Xh>FSyYrTr!%>l|C66ojv zzdJmG;o^XZJH-9h9{G33_=-JR?x@{4<(3UaoMKd^qxSG=lvcC15{?VwE4HTP4%zc$ z3<(t4qpVR{&7QtOC~2BKg8o!}`!BNM#7CO&Q-^0p4Y=^-T#H?QkN+|+A;Pre%ZIhc zl$Y&M`==V^8*O70#S%yWAF~8kjJM08=NV=0qja?6IUy}d`P+i6c8njlz(vub6+Rb~ zB*V29l*{l_3(p5>amoe@((MVKX+f<$$wXP;?m(&$7KA&H*8~gVWPFr`M}V|!=&R{X{%_fvIv9ZCi3IwZ>UAqj(vN z8%vIzmMN`H0xewT>0v3VRW(OD`xoz8a6{7`wtt*|ChFP{`_K62HC+pJvKV`{gM`k6 z-MaRey#xPrZEMR387$7VSnzCH=A7Z5S-mvwt+myr+izp6x1%=FN@1{AEwdd7w~~K~ ztT`N83=#90@Tbgqo_`*6GI2O+7$P2J!eS@pJj6ejTXRDEgdY?7w_{EZ{#npYd&%CJ ze{QtXR!D|K_7e{?A+x>qu$jPvf8YH}i1x(U!9P=+HGeDUPyr^q@64P`{yF1pmX5Lw z6G=?y-+?)a{Ij4#E6y-6jR`wt&Sd^^?Wj$b$CZfVFM9uLF=vJuVOX%qzL(uW_}i(j zSlLnQY2QPlb!?^MFPi^h={u56BmX?uNsCav>59)g*|b1UDc>{WOeaF@;vYl9(_EfSc@}4H2i(9I5+;an_+*B_5S59Hu9WNA7a9`F2vozKTd8Wzmk96akG)~tf@2mIsO)kdC&(4M`I{M`hSe~1uYb+wV_EO;CfZgeH?K>nH1jpW<&Pf<4;26Pye2_98O?8nDBg0<~Z@s z?w;Cs$&ff>L}QZ$S}*1_@DEKo$G)6@e(2T8Fh~?i5D$W^l^`Cr9QwLg%!IWv=Ux8! z+e3TXel!2P*_$8m3jR6NTU%+pe>0QO_dT`eTy?gydMA1h%vG&t$GYKfPc2l_t;=i^ zy|nw6*;@G8=>5xV6=ob8yfjaHIy5ahT=rotFmmWME9p1>{hR#esX4%u<7$qHTgySGBQF*2j^9E@?PSnmZV;RY#jd2pCy~pGx z1D-3lA2y777$V;zZU10wHDE1zwIGDM5++Hl9D7r&LXxQ--g$#taHhG-*Yp^nMdVGiBF)*&p^ zfje;Y)4Y3_g&HXGi7biFu9{{F!3Cr#e%cr-qOZuhgET)PiaV&ihv+L_w;^u6huC|l zHl~}&agdm01&FWU3zij=n&A1F!&K#|J3JQE%72guwvkD_N9NC=+Dpo?JBS;m#VTFz zpnRAXWR+*IxP2SW{*>qDZN&L&QL=u}I)lZ5+xP0ngqPaPP`Nr4Zhc|1mA|=2rb%*NPk+lkuidZ zmfNTsq50^J)Vo}4z>+PFQ^v7&B z)HmJ2X2K~4Zoy>~hXh-1A#Rj5SIN4CY8g+tMTae#xAN&NM2#j~%qSa2!Lp z!MBh+hVibqP&r2Pp5BN2EWY<@jkk;sG~;tvV~m^Z&gyt@KDYswWcr{6o}AJm zWc?ugFyTtVMzxmpgFZX(N*vEDb!b4{IMX`B9wvVK0}2Ll4=Ly<;D|~=>zzro{996=tr!Q)PBL<(;pS%#}_pjw6>-QaO2Q{q68bc3E+w8^qOrk|_G8z`T` z@nrT5C{s!0!5fI3szvn=x?ydCD*5_s1&zCGa_c;+FY^+ZE)D+jBKni*c>^s|HFw41 z2HdBSNLzB5#u|3J9u?DA6Pey1(@)eRDng4IR9bH(UQOavBouj%_y*=BFx_YrauwX2 zsmY~?)%B>4AdB33I8G<2&+3sloh;s}N9lAeNlB@P-vf-lP>)3quspu?eEp2$Vefie zdO-7V>MF_Bnle9_N|`&5*XhuO;mzN%Oopd_ zM}rLa{*K5f&8>$Vc^ea$dV6D{wexq1+GvWpK(q7ey^RURjH`a)u6Sm!32!QrK=R#F z+MxHh4v#tIT7hK3jZXXuKl`00t|-Q{zoYySvU}in_&myR(+41 zvh-~}->{mew?g^r`$P-Ut|9CR@}6)FxlgdF`Vz)GY|T6W?iBpey(NLp%uDbv3p3Q7 zyAJIrz>};;&estAB#AWDq2x&le6bGB(G;M=HTXp{eP12YqqQiHEp=Anz9jBLLiepV ztf)gvG=&v)@O_FjGwbN7hPcUf$a{)36L`$vDbie82luC$KCKS(pJw`qI#fKZxw+8r z1%~0n%^81>Iy64bLc7{{hI7Wxts$xKu5}1}hBTBqEPIADu3tsnGo;5{uRsxWNb1bU~5yN9CLFpCb#ggO3D`=MS1y>OLEbD6g6%@+w z;VW?Y55u4OX`Jy#n9oD4|6%iZK{v4br@nzb+&FISO?BGB!U)e!pEt z^>f-h<@?KsiX)wTrpqw%G8~_0`0i!IJ+JvFMZ|la{9n9``sYdi@yiH{r$%NIKA!RE zm!Tw3ZpX_AN+4Z@cnK`%pO?s=?>5PTzU)8&Zd}6F1TqY|4Btd;tAiXwXYvtTWyd8n zCu$L{SL`@E{I|P^&u?pvs$aFk<1c8BX;;`P7@OBGXrW#bt#xwVLP#06P0p(sH!pk- zd{OJ56kI9_dQl5@P^SHc`L9se5x=406)jx5Mv5o%L0nTsI$dwo9>4ipo;sVm%*EtaLR7Ljjr)M}Q0yf|HJ9W{qPXfoxf`IEOfYBmwai+#0x%8Q75 zYT+}#6){+>wIO=kLwt6AD`K!nuSMQ`BBs@%#fn%Ucj;cTAvQ)zj@-NMi?Q!$p^_s< z78AtGTBN>1#Hd=-yrTu0l5l%&SS>u>W%}S+%zIa(+a*J<7NORnOr|T$e~-g8vuJkW z^skuz9@EQyMdf?8D#Go#&A-AYnd$kzBAKBTUJ)t3((w$_U-}h+3phYC=_}&VUy;6m z=@0#iOA9nQ95Skoz3B5RqEeXN@mJ)hXntB9<(F=q&ZTJ6l$+<_yO5)vQ|FN`!_xC; zVCcR6ylLz?awX9^Xg)6sZrz#Nc^>l?5&oz1s9wa6V$XT_z0bP2_B?XmXFUBp8sFzo zCHp+w|4Xw`wtU^sqD96#orP}}EAghY zh|Hqwzn(#EmN_qR5+lz-S!T`yoJ8IkgfF97bI%}WnPzy!Y9|(+LA6YL?+gNn&pJ}r`ojFj1^jxB;+g} zID@0(k`uJ<{L7t~=@G;~`9Le*S)9}b4&4Z_roTEhz-DZQ?Oq$DRyzpto3Ay)-x03k@ z%!{v{)|8Orkh$s;_cl3`nwFBxD%$en(+FNgTP{3}#8tFquWF>PVo@GGjoMXI`4S6# zvaLUju+>!g66uT0?KDzXQ{^rcay4y9h>qfqpW(iSiPwL|+%?)u60)NhcN&-0Xk+C4 z;7(%m&(_&>^)yU4!PSfWpOKtvaM;sHwET>kTy4ArbrCP$2kP`HS598|*|e@$OY4%f zi`e-y>ef;V6Msg;I%<0G&&XTHc;}y?uBWE|J!RE&DYa7ae`wlIH>}%u3Tf-9>3SQy z-_%|4#F3hAIEC`{r1{G!zR*OK96W{OJjQcQp(c+!KRkt?FByON6tWrmK5nB?PM&4| z2hTFi;Q7!gcyA!jsW$ksDZAo{BY8e>3b7kVbJQv9-9Vn+r{K1cW^y`(z>S*kPfjH@b;T+ zdMJCU;FE6}+f{Tvh17gDi6I>H$y){=RG~bdrd?PC@2@nTpq1%7{Xe@3F<&wL=_(X{ zr6pS7JBzQX;QKYZ7!$6G=v9TpuL;+^3VRt^;kt;INNhw z4gPMzw+eonsgkWfA$>E|{`pU+lkxX|Lc|uT{e_>brmmq%s{e=Dml&<^GSyJ~e||#c z7OMSe8~n0xo^LSKKKm!Q6p-fhpD?$8Y7hJgWisCGC-{6ro_9|2%p=2^lc@QI>18Jo zyj8Pp?fRJvcArGtRx&6$X%)zi4C+h1sgaM`ynm7}PTADR>kPL~zc=H6} zwzrzAn>cy`xibCG2{dnSHCH#`eiBKAt>)@3K0SfWg@pU)1k@rMAG$L;OL|2%KD@~= z;{@`VuS`2(ew*EQu%|R_<}Oy8z}y`yuGa}v?x5ZrPr$F3;jK!f6>Bl0&Qw}e)Iysz z{~tDMG0#PuBwPYvjOx5dF|M(73u`*uiY|{|m>ND-iKr4S#%ZTDk0=-v%Lj+^DxvPA zEbmq#PKN)fMA=TtGNTgS-?9FTv=MWpM+S9TYmchS`X_twWu`2CmB{~&=Jm0`FO$Bb zrx~BEZzbwTOX*UHh+Q!F`Rj4i$#~UqIF>SAaU6lAY;6-O5nW37 zoa5MBYAXAfyzbF(9L~E4@D-KD?XEs@pUXJa-0o5 zi3>f%k?mi|F=Xr`?LicH9~I+v4B`73|NSWPWO(u@)H3qib(9Av8Ri{DX&G0QT8*We zJXRfL#qp(I3)X^jk856TV1lt~qmmgjB(u+t!sh^qrXEG=0Wy2_C|}f~m71mC0!(7Ys?LO?n0t`sJ98Av4pLptM^Vqv)D-WH#2)3-TQ;@w%E*ZdWc*0D zqZO!QXod3>eU2icycNz1q-Y|*s9j5HaqKa6}C zzjPQ?$EmzUle`^weSOJxTcR!*KhFblMz71<)T43{6`Ax?%14^13 zJNw(3Xhx5m5izukSV z8G@~GvNYJbn{gDJ(L9y4L=3#QVZQy2j$d&kqMt^D8$+mPj9Zn-9XLmZb6zBDt18iw>f; z*2v^tsFx1H_k!jnA^VDF57H|ZB`P~euUMS7k2nbTi=4iYX+Pn05YZR8vrEW+qRT;~ zT_ogNWOR{`mkuE6HxtrFoH&4t-?V|0mDhI;9B7p_vqMHNT=|W6t9%c_?Gn+JA3)kA z*0Q4q&~S<5N)90WGHcKD11P;rQ3DRZ`wGME2atM&wc|m;T_Ic$;jU`wirWEHU1i+v z0DS9+mr;h?I>NtQ2K5@l*=0z)rulXCG)8&-#e-$7!tkhGXy$_R)0F9DXuie~ngPRo z=+BAsJ8Nd2GL-+W1$Q%X2Z&qy@54TYn!!<5Qb`0t1NO_p@& zek9!_y!U>-7bbU&2zOK4%Ofs!XS5!Q!+w zE5%I=+lSoSG}6?4aK1yJ;rkGKhep}=1FG-P7+?K>;6^RhBjX3_7hD;_A#O<1?3mD9 zp1Nh%BJR^|`~jtntnMX0ApB3#SpNgE|Kzt3_5+^@<50m=&miIT1ET+;I(z+qt$z{z z_q_;evKfp1*-q`X8H*R&Vri_KkK0XEPV7Z>laypHf}8o7e6km%&8Cq!uox`n?S=X` zsm|Stn7;`Zu@`&)=DHBM9+R8k0ej*050#&^7xVt1bWiR@`9E5@12uUJH@n++Z$q}T z9W!Gtd!p)J&37`*P@w-YR>ap@&G2wL<6dBE>%x1161mk39y}o?<2Ez!Uf@A|@7=aD zo^0Xr^uOO1CAMfjcFOzTBjYY5NctX^?rQmp+xJ-+dbsl1_gU3?l+v;Xes+4Ia&ix{ z?Q~nEaunb1p+7C1@5${!fTCNq$)%u`dw6b+>C5+^Owl8)T6Pkz?16_p)1TRcdGul|grmv5vhlu!HVu z*1(ibB5oJLJLrB&@-8~c(i0ss32Y2`>NE4pBV=-5M?Fd^ohKe#3`6waML$_)QIE-Y zpp{*y>c}FsdA6$e>+3tDS)j5Thn&F+k&(@56l4_x&Q%GU3SmbvQeEeCyvhR)Q9 z+jj`>LY?f`2}d_Qyj_>?*q0ab)egQSn7QYTZg|~IAEvC{i99zNecn#Ebkzf8En>l3 z#j`tY-~1%(4%TKUvvwlCs~%tiSUQW~`v6|vM1Y{32<~RqcT(sqTy|nvH>&1t37_?{ zsm#(v{9XdT?o7W@g4FJ;??+2e*WIk|#4|ks>??t{yIJ3Ed4KZN61eoz1EnDe*G(w)DV6obnAuAYx59K6)y2r`WlBz%?gq@^V$`&z zS=^1Z(qg!I=st>j34%TJFe^>dllR7AqGZkKpy59U6`V=F^Q(mY$+xF>*YK(5@Jbp88`vSCP`w7$IHTftg;qbaP|r zCHC(?xfh|f?tr(qE)RO7^b%j}K%zGj({^C5w=O;ESm;%I2i*EFan=sL4#tmU?+)bj zVYQmE0}Xv>hCVwG)7N00;vqURv#(^n0}(!Y4|M9M`$;mr#ib&I_hZh9BINYbXYgiA zN^h~V$YvTiwr>-u6ctIdY0R{E3UM#9LS`lxp}|L&2VYV=jpDylgvkCzg2l@y;mjiB z_t)jc{1h({S%l{Prc%7cz#;?7b1Be z6ZaRQYM?IPUr6aAwiVjsoCK$7Y)V%bBGH$cKUs(xUn*mFAp!>JRm#VOa2(9|>xGCJ ztY<4ug=ikkx_x0g9d(h#5{spusMwCYA!Jd$9W6tcnY$gaenw_WKk?aik1e=_96YN9j;zPTCH)VZ`jYosWg-{u~pg_z0)%_k`T?lYK8NeOVu@ByET4 zuMd%&`-?%_5#+CXXdm(8)))Qle@(QP|Y{dF(9CD`Dv_iP2=`?M0kGC=(M zEgJk;KmYs|Q2{Jr?YGDa(1TkcuLbCyeMxG7*#50m4*J#`$jf88orS-)jvtfhfQ5ZA zbT}`7$A62|;rd8Ab+il=Q*0P)krL`Tt~h^}8Bg8SeS_rj?4yo-gG=MtN0~T744ggR@X;~dN1C;uH;pwbSpUgk z0|!s?h=6_WH|&S^*!RJ_3A*2ykK~vtl+NJ8tk3ctcMt6hQz{?)rbr2)4wa(?hz(b@8&g#PkBNG;@^k^_ zPo&K!7NBOL?(MvgLvJq&n_mu!9xH(JBt6L0EW4lRQ(&zM5fkyb&i#Vk1<0SI)4iLq zgzP6?Er82pJ-}23PX@c|0i)b z5;j~P>A+3zFl>24q3=m!y5uiPw^&8tQqa)h%va<6Ro43Gk3T?c8 z3%!9+AxpNPehNQ`*S7FL9OE%tP&ifR3gH%1Po+No*(~$BV#YLmx^iJNvZv|ul)}w$ ziO>UGOzu2BxY?!%c$CxO$g0iAXTD_0p;mx+Z!_v5SjM+EBW$`(Z>2JwCk>-o@h0NN zZg%q%$Za~Cyl$IO_JF=fxv~inGdRdI2@Mw~HX&mM2_4;px*4?6mzxk7$uNBrwnp0E zcsTLxO=ylJ+#8z^^&m?-eG|{Fu^vQj;@LHpYSbpom!an-K1#;0?Ir{~tjAjUj1Z^4 zM$W@}fRoQA4r{8yn&N5Up$9Z~toX~W8`?+deVopGZ5_`sYw-bXns1pkVRm&GPx}$4 z{@(el0_G(!ophQK=4R%6(xc7X(54MvqasS5uVj6Vh)1aV6moq;cUQjt8YPcV+Bsjt z{ZXbr@HLViWqRP(NPCoHYQL{h_^3YLsmFaH9Q}k2Fx9V-`k0>NVe9Rudrw)DHME#%`LMpjfBW~5QsUi%7hkLwxAbml!y9ryVP zF;CcZ%oCi>Um@=a>e%rsv^+suRp(>TleT=`McAKDFJjF9J|EuEv;p#Y)QohJ^U)B^ z(k;xV12O78F&~>{_((n+pJq5NA8}8cwkVJn_uJ*8@@YLlc`_gBGsJUd{xj4{(?*m$ zqq{p@*ht;Bm^Lz;jGoyDC5CD}xDm-QdX&dD0vIFjs*vJ@M)Qf`cjQU$t>MMzHljX; zM3-(vXqnC1Q1N>rj z>C%#?SLJt~w*lF)`g77<;V3bW;PSZeoU*W{*)Ac*UFnPsaDSG%#snF*)C@C@l>g|S%2ylscA0)jd1wRD zo?|t<@g?$}({mJ$4G52;?!IO`jt0K=C0w3o{OvC>_j$&5e2E$v5C0Ou@r-})CGz9h z!p)YWUS8IDmGBA7Z_2~m1a=)=zC?8b^=J7Keu;V-eM!lM68rD-c&Vem(q(9Z?Ca&l zal3wF_Sny=if6pH^*>)PKYm`bG+og`nhdya9MIzhy`O8mTsrxU#b0Kf*MDz^M_$l} z^kYYJv$gy+bm}AHw({rOHO;PI8eVm!-;d%KI0ZVKS5*Fj9-(NGt-de}J(6@!`S$2& zado}5`AZ9J`p9B7zCP_+U|c7t2yJ2?LboYHL_!`Clk^C`e+WN2EVL=MEVRkaGbQS= zJj+s9uq#$veuYcqAvL;vuROaRwMqI1953;7+NSkLdYKy9y&ijC){_2uI4Wr&DfkNml;Q6H~^@*2O|SJoj;hL5j9`Dzb}=Q_p*>yYs}zs|STq3m^? zYmQzPKXG&&8eiv}Bz7G<-q7QGPp`Gg6>G}%{}h%d>11ICuEXXx46%53r+F=p#!;+x z>ySQA_g?TU3l~2#R6bOHoUhFZPdiJ~fHsz<6l&L!;wSnsUp`|0G{ZS$G`o~WEDddX zit*Wd@BNob`F{kkj5P!}NMzQ1?O3sTEpp$a zWLwvw@l6i=X{@oL|5`LJZEFmwXsdC;Z7ovYq5@skqUJ5#O$j6LTgHf!{x7cN(jA*V zUOsj`joqeCvs8!wjSYll$o;=L!180h2MPk(`#~(J6{jS{Bpq*-<6V~Hyp)Tc zJbqsTzxVVY7b7km{;shV-f#(aY7O6b(}P|9WwJqLo=K*14WE1C>^PO=rITpgpEF_2 z!%8+-WUfI*GKaJ#*$HCN8dN1y`^jXtfb)5i{RHvk8q8n7^vBkqa)BPKJh}!hDSDxD zl6+J2Am#iTs0;On<>zJ*-fIxEPnR z2HuPGKsP_8b(OVo5%XCK?OakSv(_MKksj&5=E@j8JM39)S&CN%Ie4RGk?t(pyJPxx zXRiEMy+r-$iQez){sSdKYkQYOUr;h`Ywx^uuI=hga|$~ae`GFVe)c}wy!h2cIq$P; zSG-okJC$F5#%dnpV}mnqH5wUu%voja+UQeLdhd~qj=V6uh^2gM6&8J{r+RqGAu6@^ zU&6`~&Pn81RQe+bBg})V;Pa85CKo+!%BwTct5EWho^Il#3>716IN`*}FmdkYAns!u z&Yq#daTS_B*3(TImSN&z4l>eA8pq`In$jFAUl-D#j8e9ba}fNAo+@#USyG0HEWS4W ziSBN$tZ}d{8zbb=ZLRwprWtVT0{4G`^3Oqo1P+w&hX|NWDpT(&zAAP6SsH zT22DZpPLA6R}kTLHfF9cm(Y&Mk*7qskj>+K`ds&Kv#m8fkF}fwLR&3AoQ;5NQ_=#9 z=P2=WHuh#y(uLXZ{+tcW@odC?uE%;zv*G9SOWFKCzm(b8sQp~ekhQ+RGJBLrAguAF z@K)OF&65p{jL1gDN>hskmer%gglxLXGqqS?IX_Btx8bBo98-%ISD^BXR@p|2n=25T zqx-t3gpG|O9KG$xa(uG_IXO1C*`vj-74Ta{EkD9^8ID>3=hYneMXrGFYSY@3VYG-| zVU;tSwCE~GTCU#;R1ikiQpz=2_^&|B8m=vbuR!`5-Pk27kVBb+%Tc<94e|EnaLeU< zvwS&%a&0=;Ge(?PZl&!;+AgLJa+aemS6^n*=D;OyIi2p=big4*iVdfZ9;cfp8S+eD zj=*&`c~XMJhttC_t)=BpOZ&Exs&7wy!bsJ=}Y~RDH}&GuL3a}2;a>LAG?>W&!S09@uX+R{#IFz znhn&;%YgGn^1r?eb7gpP8LBpN+*)8snIOI+ve79-Ol?vKn6Jn6`FfdEutHO?j|r2& zmp+JQS59e~ zw+ud8IKEtzh3GAMxXWwI^OPq?SY&zHVnr6VZZYc>Wg9Ohkk=Mn9vS7}!Y>Ox1!U}- zh2#QrpcX9JWT9Lp+GWA}8!l#?T#D>(SR;01!DE-+8{N0+PRh}x@Y$+M2j#qS@as}O z1W4O_yp#_Cvd+A;lpX~2xh@YawaQXunqo*68nAQmtx+x`c)F4Er%}U zxi}*4&qURB0+nPUxR5~WmSSe1v2w_}3t5>+D`c&3SV|{?5?Z7wI$IW@K9BVH;yD4Ul8Om=I|Dhzd<27h6mc=bDgbBOvfWTf ze@h1PN(@D%DB}AJc@)>UDniu+Awa*S8~r}dIp+z z>eD2Sy^s`>GZ6V573GwH((h=O8zj1m({43`XWR@Rksm~1#(MSsuqFDQmXe|fxz8lHCrHWHw`+`Mxe$tsAmQrALK{e z@4oaoTw$A?6lQ$%d^szBk7?jG!doEwdlK8R1de-&v}uVcO>8Y|ayX~`Br3mr2&C<$ zzQq#M?$!IrA}Hc*!Lw~<4Q(UlEJ5@Sgm`8Nw*EkiP{WhDEk9T5WG*n!$kTP z3tEDp{rdPG{A@Mx^J1%coN1l_a}aiWF*5e+13A%1(Zm5OfMEb740nI$p__AyCA~iA zQl?jus6`h?7Nfq*{DgGz!eRs*&{vQH9V;!h5|~pJ%8xVDXkce8#-#&t;%Bk66#E3O6{8m;>_>y>p0=VY9jQMWMESbH-E>pzIXNVnZ4xa{M^L#zG{sST zk&eW265XC|O1i6DKWeULTAak%bSyj6x|Z!ELeo)wNMGh*F_vJRM52v)9I11zBm1b4 z>3s2!eS!gFX(w?!j@Xu3L(EO_JD(xu2*>^dh(9}UYLiboPo=T#GU>JxKYWJDBec=( z&){33^JNZW1lwLL`wXcS6n67xD6OPgPgmH4}Jo;@>b)~vN=&27z^8A+kR zo2PHlsx1&J0&VV`w}q4@^lB>B3U3~bj7`9rsbSsHq+>Ps@c1oM{IN>}KK#SS;aKJp zfe*j-xF+E9@ZdOu(*qE}(Z{KvSueog%b$Fls+v*2D~}7Z+q8mx`Oe4b&?h=>Y?`M& z4yQ96H@3hFb=>=ad#}XZ=W#mlsg4^v;kO^7^Pd8DR~2^;O8(46ydU>?oV;7~0^o!H z++&p6q89*%`~P`NBYp`AfG>|Ao*u)ii>~^^{q&Df&F8NAll$V6AETDf&DnkrA-^5{ zVIgjP6YJ5@k5SSW<}A~|$EfTJ^#0zD!Fvr0L|L!?{L*Gh{}T23!)Ds{r5+Ej^Ty3| zM#R6pnNm)hv${(7&S=Y$KDA9n+UWN4SiDznrqie4%&--SC75I(kwSxv<4vz@rt+`M zxe+3l7{%2 zs~x%rA@T@}AvafMzVyFikG&{tVkfYwGc3jvW??H?Z~}v{MhH9KOE`I%t{K1{1>JS&t@83+f&S1{})h0^+7M z`n!b9*lKWohxo!)n^R4*%Cs}> z<053-m+j*sW!$HTYj3-06zrk}8-cq&(!}uS2vBV|^u#&yGDQWb=*T@bk@tBlY`Siu zqVrfRsqu{+)y3Q8jkNPTrq*g49%gCSNO9j`p(XQr@uH2C_Z{-Sw~_XJr{_h(6%0MS zkv?gqMJ&>?H&Vsvunw#Xc6YsErj$K6CEZYEgJ+yl@zOfVc+CXB9&|eM1 zJ>})~nsBr5lGi|UFY7yq2ov+LVYucH^Dt4v;b6+-UeR2ILR!s{QpoUQ5i@~Z>*+u% zv}3^riulQ#Bhu;&27fN#53Hy1pUi=sGd8#ifm21M^CV#Cm7mPxOanI1t)H+bUl6T_ucgz3S{<}jdAt-~)}hNYy} zdOCF3e9hFbjt=~a#u2xk0qIEVWy^ z{wP&mHE+UP%ifv015mC3F>YPURIMc+JxY;n<}F}yS7(0uQ99IS=72uinZNO<23-Z{ z^AdXXqg4DK6*{a7-~1@u_>Y+*tGx@K{U|OORI~2t!ZY-&FechB$gJ#9%J@yqdbSJi z{3td5re+Nb;Fs4@={1QbfS*`Prr#x=0KR9fMgp3j9h_yM(&w+G{lA+xq13YheEC|+ zxNZ&+yBb~92D@@C6<>$7x6Xj$Bcs<++jS^=!CHceqA#G}CnFRpc`cPY&0FG8)!n$e zR)_;bnfY$J3gT3)YV5{es-*NAz}9gsRowtK%%Hlf?e)7#I(`G3VLH>DAE>1KKg`0T z7QQr-E2;7iWI0qxEq|z4DgxDJ$}7qHPY?j8Aa1YJRP?|-2tXVNKv_ZDqZ0mxz~-nV z>rH9(4dP*yRD2T+_gx?nO5lLF^@jU;C9dp4!+pLIZwsK|R#noHTjopf!UzlIb!)Uz zD{VBhh9!z-iWyxn&sjrzZ=?A(tii>7>ZA~EI1|@wZ)WNWD1^6FP=Jxe1uDRx7Fi^l ztI#>o^o(n8KOfs9>ke+U3c*-4`WnmuVr~5vYx6Zkw!Wa!2+sxJlD~qTSfCntKW?1z#@#+-6%_lsqg~EE$EXN zOR)W?Hc#7XDl)U>7#_biv*CifFx4wy*lLPnOnss>j9)FM1&sXy!GwkLE9JC#4YmYi zZH4oya@wmfxI&fFErrE-??P8%Fhr9dk9oC!GV`O){F#r* zxQZ_Lvu1xOx=7yP5v>K4+vwXznUyYeX8xK0Bl)$J_nAixD1#cNj5!2rNMxRL_9q9UfOq|M?xXeHg~$^uOj zR#HGWmZeo}G!I=#MXqo~H1D{Q_IG1(rj;w{OgFYn6;2S!=*|)c)R}*SNbTQ^Jz7Oi?KJsrYE$Wq`e_4aZ+2`XiWQe*kP<&B>N_2ZV)=}?v-VX;SBiFP+YgS{AQtKWpz_Egv)Lw($G$_Qf_ zF%oZId69<>8)~Z`31O(PK8AWL;?Me5-`WvCZ-=p-LS4WfE>nZfdw}II*2}#v+>k(B z!&w;ml+9 zZ*?_`1zK3wfn4Z-)Dv`HgII`oyC!fsU5H@&P4ge7njS32H2q<^&;#{-KT7F|Z=Z*0 zFTTAyKdf~FG3W+Tu-&B{{jUTozDO%Uyd&49p5gH`Yrqafig{s&hwx@P{6v+E_?x=|hy?+oj8ieDp)Kzqd=P5_#G~aOBkUVZ$csAhGbq?=3)tRo@73*OtLh( z%*7JmQh2X2%I+gE11^R8mAP0#`T%Y$lPq0cMoE38C;&Hrw=8q<1h`cG&N9iHO-06qpFf{PG~4fRzvf`FjuI9av0eK+!<{ z#)IUY#PR~`9+Y^`4!7OBILaohY7OCy5!P2haT1#$a1Y|EAEfh1689iJ??H;|2i%Sa z;UUVb?ha5!Pe-#sl3T-IKIlQZ+)siJ=FtyQdVhciJcx@8S=L}PD#_d{9Jd!~O|DZE zcfd73RGzEJozlX3lRJPWhtVlYt`eSUWgR_yE1K6oNc&q^pY3sqh2|%-!|(+*Wbl`l zYQxiE8x46}NvAs~DnCi-4m_tJ9pU$vkl#QSY1+Jm(g$MfuUtaK0})@mlnxDK+k`&Led*~-3{O_q zeQBl5gIGWsB-mvB1`^aet?&+NrzOB$5=5t^hII*|(~1(i(P18DTtGc4#bV0HU}dJK7vr8omanO;kuP3MfkRMt^B2>SA*{wlkcf!1v0;)FhN(oYR+)(b zxa?IcT0dkZDo&85ld@MM11SFpEVB6@}4v5#7iFsmm5o?tPdZWG}+=uuS!vH}T{} zq}zA`k<6imbm$EhOy0v;pnEjfrar@2aKz^e4NqdYypFn4H?U9W?n%&kv1wkk zh)Rbuaj8m$8_!utdxv9~Zdgby!p69U}pbmVD z7Jv3WjBx|ett1-N2|nKZe)7e&)309~V4!c!mM#)2E(IFAfLcd^j!7yVzjXo@GrvzK zAru3e?+TXeQDNri=2QL{bxj5%dDDE{z{oOTQiomq@O(+}IUk$zEV5LxissYv>Bblq zjU|RbQ76eq=Tlq`OA$3zM~)me3hN6P#y8EULpkWP0B7N4^T~58h^d-SDPx(qK&8UM zbLUgdSXnO2-1F(QfS5X;lyR(3IQVzuL0b72@3YauQJ5I-7{>wxMlY_+r-S1FA2FXU zj6*L3crSiw9&UM*WqR|Ld9;2!ATH0NgX3AE;K*Ag`2BerS3_*-gU+ANCsVGvEIRAW zKbS|?a@i!@&%O?=5T04;h4VLai&fU>#gu4!tzwo_6cZ(o#xZt3Fs2; zn@8IwLb2oK(S?a@4hV&X?Yp^@J4t07rnTm|R5J;Lw$7#FlT=o0zWlYh6qu*70>gIg zT-@jgh=YL4gZ};lEahP=0j^GbF(4;PT%EXmE?(aScnu(i5l5y-a?{GL?NPitEff%q7o!CU$iy zI`ii>P&-Veg{QHBpu@()kE1z6S$EWM~V5<481aJ1TEUTIimYVY=lJ>$H z7j6Jgrwg=?HD5idG``pfuKfy5I2JayN;$J zi2vpwrO=fg%)fWwNnmukA3JDoAxrU-;t1x49eR~e!5+^X(;)|C6tQfX4y#JFo?bww z78{c^F^2F;2elM|%$*MMoTak^`$?e#cRI2x^4-BaJYY7-L3y(PR}A=BtVN0lXPBnx zcw=nUzdoHP@xpN8e1LAu*6D`btN% zIku0pgmiev>ti&-tyJ*<)+ka9!gOto`SuA`Vv&1D4|TqKVvrj&WIJ^#uy^9Q%SQ?sbG zOouZh@_Dmxm8M=^MIxU%i&i`Y{F7!;^Fum*OiAKqQRKsVzKSFsGK)$d2L9w(wDVz| zKP(Spkbk)j2baAQMRXY9Zc^9!@i&XKy6%nk#|@mq#;^oU`u+LyMU=flrv}b=+lr`W z1*lnFM3+~v;V^!ksy^7S@MMSU%0FM`!iO(;daC|Hq;? z53FP+qba?J4nBfDyH^n@tJn%bMxF5C`?Qd%R!K7I#7*5t3+ePKF#Ba8DdlXl=|UmZ zlq28Ah16P(33yQ<6|IK(Xk;PYWyWX+Bq=X9#%*N6~K@R%oXf60Wp9_ z77F92y0RO<-?h`JHEbw0Gq50i&8`hF*f_NBlLO3$c8aS+p)c8~vQjMsE7VFmwN$Do zusmICr@*x+WRsn;*Q$k7r16LBly8>`3`){?7dvf!RLuc*F?SUDsJi5Xzt+{66u3^N z4CH5LQo%Y%{==Dca2-s$$UBf9nn~A0TIEU=7%5ChgoPXa5=eb^)E=sM2N_ z!hbHHxJ@Ye%K}_#$wrD@uOVC*Pg@G;^d?s6E;K+G+uXk>&=y@gH?s(#Fm>j_9^A1W zrt#aiub2ym;24OiAa~|i`?avHFjYcf)RW)rG0d_0LoSbDj#XSho{ysf#uwm?Xtsi` zyp3VVVBm%VI`g=$Em(N|GJ|5afN2lFZDGYytKhu!-VAuU%BBJGjr@%nHgi>gHaC83Ie|S3G z5)eO5r?_f$(ShdxCrzi#)oR5xdhq+F)2V7eOb2AOtXfZ=JzbmtP&L|SW4o%#@VWW>G|H(_%g1VgPoteRfOrXzHSC*kvPj6{==#b#-mET3FZAav7#UPqQ%7cOc?v=xLXH%6D*4rdY!KtkcTJ^&S`hQrRH~|FB?7{mKRlIg)iU)!h7W&Ws@AB> zaUdfmlWsS-hnrSUr6tdzssZl9=TD^tyO_8(68rQP9o##U;-_H=_2n*g302|CZ%o0% z($Lm^Q>kb-sIpF_gS*jZ8m3a*9)y3ILX~@1gz5Jww0Dn6prI3AIfdF}0M0XxDU|UX zsI8bn3!YP#b=Zx+e+r#?P6fyAdg2rc{5v3aO~I9v&{ojo&%J^0@2dE*L4I>GwF-zX zfP9|)hNsmHow?f-JQeh{F_H%FRjI|gWA|jr-^;|!MU9>L6O%O|;6%!h6ma!#4Gt@e z$#h{a@YPJFfES<|fbYU*Os3Koq>Qn)m`n#>07MZWUtr&0CDRzd^E8ZwIDTTUks2I6 z8E&vDorbRb*F1`N32N&(netwO+HMthC zFT>y|;RCr1g}jW>TfztN_`G&%;f?-&YcUkBHji>&VM~k`>1cOLkSQaNtgS4DI{t(C zrkyarKKL2bTDKb-nQAvg$9%=5*039@VO_0ZH@ry3ol0lYZHCM8-dynyhPz~rOrkye zp*H&_(Y5`UJ4;G~c;O^C$6^S6dJ-Le73mu$;aW+y#8f(o*4H6CX%d~T1BX5G=vp0i zd@f9++}8mA;Y2$48Z1NZlgN4i2HRgJYUZm-X}%IJNymWW0LrS=(+<$BkAS0OA`N>T zd3Q~u{jZ~p$0m~L4YpI4!-$E(rWENeSflUXU{f@)2lERPXxKmXYQP@$ClhGfKT!=o zO`v1{#DrUlJB0sZ0>vD}NFbRE;ZIM%g^_@JV*=G4#E2o`tbES|vZiB5_SZu+2Xo2q z5WdgkQrRKE?aHN=LtuMTE+zeorKFw^lQG^CyKh>LRcPXlqIO%*#rQ8^bc-U!RS~9L z|6-j59ZmGszd*IC*gZ?PZvC8EHdVpOykJnVOus$3(R;QQF z_?mM}QDZ6l1a`a{FN$@26!#fRdrr9UM)5y$aK|I?Udo|i|7Lq?T3N9BZ#me$@SSar zqJ)#oeUPe)CGuFWSsgub^UpT5Te+iu*sc&-=dx(m$S^HB2`!8tE4IsHso^AhBCrM6 z8^bDc{}5lz=38N|$o)Nsia&t%OwFNVAFv3&&)cPkA^npax`yIzwYL|9p%l*&2AsEWw2;pNyf?A7ZrqeGKKELicta0DmD2-PYQsbZfNe2m`62JL^WBn^`FAp65_kdD`wnINVsUn~%DwbM+PFT38kfPGWe!QRMf9I(vk9!8(eHzrbu~ z_-NYv1-h#-qv*yLpg(mK<$Q_ZDhTv_iLmD=3OEh=za0f%Tgbg88!vaWBI~MbS$~Cj zm_X#<7intBZ4GCiwKc$&4l|6c;f-v%d`6uR!?sa6l2X2v_TM-@8978#c+qVd z4T;9~+=P*I`dhF(A)9V|E3?G&-XkgNtV%0v9Gyo})mc!0mpLw+Wm~|FErEYIf>xZ9 zD*fx8W-%@?JMSby#@oK9W@BI9t1xP%?pw&9e2 z2?)bbmzUTkRfA2x4inSJ#PqG^@ZNW(k5|#J%YOX-Tz#l4QGK%N#1zuUGI+&!k~^TnaNQH4F>S{ln;#D-7dJzhUI}GboH7hWj-!6UH!YA7B01;eY%lgi&1O5T?-wc~6t}UR|IdI05NYnYg`zhv@E>;|y+i^cFxP?Nt-%rPHxx_e- zmjdoKiwjt&v3SvPM`xcKN(*kYq`@zW6~Y=+eT?36v5JUO+u;>g%gxck`Y-{}*fS8P zt{yt2v}?6+JZQRqyGc1{nlN{tPqQOc z-DXOr7#>uDerQL~YkmJ83F>n{Z8Iqsv^pBZC*DVuZc3a|g0k&cUO{|^+*~A?Cf|pf zE0s7n#>WHsrCLI^wUu+cP zr6jqdXKj)WK+vNmVK;o=MhCr=ETPs-;#lMxHeKPSU8gJmWFh2CQo4EIu;X(!8s@F! z1w0FgFf^7I-DX@j;0VdCwcXyXve5x=MQwP%lEIhS$kRv3vdB_0xZP%`UY#(>G~Gt~ zd=#~j18xXUw2`+jmQxaL2oJMSuCJms9h-rB*{D`azaq{Q{yBus`=TPQ525rJ)M*!Z{Pu(k&AWw3BY!eG+hzKy%&a1il2@f#=R$pP^F(N8|iL*?GQTd2i%K> zkkwz$2NT|uA+*F_&j;(>&>?i#U(eU*&ifA`Q)kE}VThE=#m8`g0_1Y`6H`Oz5L(b# z$?m4o1-qU*V8l>-aUs@MaNVk2G+665VCTD(XcL?doU``0PQH z6{_cJ^yA|PQB^49GG>q_m$m4gg-FP-P5U`)vL^90i0aLlMA^zV{&78HUo7 zLDUwe%n%Tr`L_dw_nO|8I`dNlX=k{SDH6Nzw+GVsaAl|&*}L$U1{$hEvnQFJA4uyX zltKX!z<(b|mm`#93m^ixP>u3|6xTx*-<3}sNR>TQWZ0C?LP&Ndn!JrHwKb- zFXc1AZ8v@>omzWIM!NGC(6FqNLa8$}2J)PA z+Swa<>%=*ULFsh9H}WDSh)1VWTom&5N~iTvGH)ExY19@g^M>)-G|KIxtP`b&@tdi1rjH^F{Mc9jIh7*%%DmzH%T!v>R~g&| zDG~fcsx}RZf%$j=rXuR~8y=e?IJ5#AF4mAvn5quRe#z~Al_&i{YS4nGxnIjcm zl`48%{XRUE4#tDD`%>Xp2^`&1aYd&xrYmstj^tr!1! zfTTrS6n6FYYHt%Ru&5!(fm*fwI)l582&;ErKAAjxfH5OK`C3svT_9=L}XbCWerf& z^F6UD2Xj+s#Q-GSmqN`0&{6;$%VSe0G8IzZDsB!BOrg?LKm?@Fu~Z4shyR*P0cj`^ z5PkXA$yAgEh%b`qP#W|GIQsH`BnvB}`cPCHe>&MUB3BRj*BH|#K&C6XX&c3??Vo6C z>DsLAsxQu3;x4uJ_TB<5thco+gr&WA>Oi!!5YRVJX*G>aro2Izsih~=zCp^2UZ5h5 zU+pgoE<|jv3m8`Z zBKvYJtjivCVP9Zy7M3Dja;h3wviswfP|0ZmABXbpQ_4*1`@ta-G%xN)1@~iyII$l! zBWxX_(+V2xF*dyNB3J)zur3YmPgz63S5p$z4h3ItCTV=7gD1gTz#YC$C6RU59llN^ ziM5B-9rQO*(=a%Qhp98E1U@&3B8NjiA4sC|;TYJ|cr5vCNz^Rj`zBG$2xZtHNTkWU z3=&zP)%F@s?vN5_a;+h1Rf*g&3s%Z7y)pvVdAyrMr$#^*uO-rjx#$c~=;#_}+<>GFpen;@mfp zwvEQnEII1WZza&_(Mp-n!d4b!>Xt|g#watn#!;zSC}0b|c4z-bbMS0zyXSS80aH-Ywzg$M^EkZBwy>DB})9tQ^95~x{xFUC{G zc*K7cPkY4oU_5!|BK~jjv_yO>;^~a|&WXp3p7>_R)4>VQmA>&5GZA0kc&eR%MP99_s$icPcQC}%RlqvGhmWP}srC~ykG z-QuWxiefdz#Zm1P(0!vXT@&%=`r_GV#E*!h6;pxlXkR)#6&<^3k^HhRm0x9X1EC*v z<}NWf@v4b&ybn&is$!~h>4y|!oy$6emnrO4BmKHm!5ho@=oS3p=tjQMM&mXp9^K)! zGN7+E`rWWO&1>MHa@ycrgN4#`Gy`j2T0o0}UrL$*@%Qda>+$tNy*CL1 z#oK)}99GIW#!`enGznLfeSIjVK*{JK;Zpch8l3$Qx<42ljJu6|$eXvxVa=?5q9$3( zm%=Oi&`IQzVfdab>O+1rm8?LCcL1NE;VBeWtGzbonSauPnM%4r2OHDnoriSSnA@0j%)nOkrBdwlr?-BOFi$i&;||_v%Bnc8oIM5!V~WiYWsw z)lqp%=a*tBt`JrDLoBT?gp3+uskIQ}9e@Y&=VI}2v_vzIZ;PePMVPQk>TuE_R&3k% zrkh0yo*z)r;gw%R&H}p9SlkFIn;nCAwmr!mnS@8}U` zm}*#WjuBFaI?0*n0CisgUjCC~sj?Uib5jg0cmSI5U<@65017-N2Hu6Brh5#na6meS z7&_xX1N$MGvPBB7RjgwTf?1H0903cX%`%6W>136gLkI z(kGhsh;LgI1(V$l6{Z(6WeDT;Wfw>Bu=!k~!vdkyp9&41J= z&O_sEoQmd{DBQ)V6l6cw4o;Z44a;Fwyb8_p#E6xY>AY5do6h0dK`{vso*=lo*!c$X z6v39`5V$klcwtE~X-Z#edQkCLecYn~cQ50nEfX9-&HG9YgB4Lw zJM*;Ta26b3?=o2<4y~fj(3ru0iPT!fA;1Y=lsy`*z4ySi_pi9HL5oWc5vd}BMdh@P z3|y7KE)_beL*MF&j|Jkua|@Ef#2iVK(<`$cR?x*4-+VUkM3%foR`9WHP5;%Bt|9yt z9o06#i_UekMpxB6=&JfFT`F0K11|Ig2EIebwK+@5Y5hHLtXFaL{Htvrk&++--*^WJ z#g{4lJJ%U(M*ff&YqRsGeP?sTQlvopO>=n)u_*8YRTX5q+n!962T$_^{-_jeplm zQ==S^fa;>RE*q2m)GbbT-lQiE%cA!?dT0g1dUZrk5V<(sTUXM=!qS7kq9+K7(s6;- z6<_xeU0+13DolVI=0KP^sxYfxU6d6%Wzd z)pxfIt1d53KBIkxM93cRuBq(|@2mY+I}1d4cjH2wlyL{1t>Y3L1>olm99|q2PX8v|>f=-%hD66HxB80@JsXGuQ`BaSD?e1E z@ck3(_^;X{Zmq7`n7#US9o4D(a0xnYHRxrmH=&~v+5JqoHRm#V%w~<3mV5Bhat~e* zCwXD~DZNNs3#JZKCpBEBR9y7c|0sU{rB$bNvK78g%U^gh%V|F;WxN}4DqT1uq-xml zd(d_K9&{m2(xvc)I$g(b&#~HN9@3BFp`Bs@zENYn1-zx#4KJSI-LH zO0_!5H0q?c=U+$Z75AVHaVm8<;#IBVD$69FPu!BasH3+Juhip38Jw~zl{6fYwE6Od zdO}MU{Ysu=X3s^0Dr-Qhedm6Y9EkEYs)Tpf-L1Od9#kPt%FLJFuNRUJI8il?Z?lA1 zlIBi4seLMHN7ZXgj{mEaoO_glI9W<39@ZX@=!J(F>8Hue8hdwd3%4;@wjcM>^N4C2 zh8j(H64k~K8z!o4e^!GdpKd*>^maqFQCKYtuU_?pzov73{B(q-SScV)jArf)EJ3Ei z8h)aE>N&wS^3%w5N&w~rFp&RKPZx#5sWyH%R)G_Jjlrw;AVm=10A6)YjJdAfHHq#? z?E(U|3bEcpRMvZl3UOe2tFXdv&`S=Kbc;2viW6&Dh@Xacv?K+><8_G+=La}coG>o{ zu6iX;7Lx+tf|sif17oXs4P`_sDWPf_Z1~xFn&1$t-%`M2KVzg1oSq|njF{Z71AxjX z)bH7HHY^fxi?leq2^T^kgJ|(ajN-xnbDK)`q4faPXEht|W4e>si3D1>noSD56z;+( zBAvK_ydliP&=3=XJL^vw=yo`ImHvxO0bRr?`HJSS_DD|I=twy34d30}Gfa?T(MjimEPK#fC+do{Gh}sxEcW zNZz5AmEUd+1em~qm_DS+7Y^KsbUZUvE`{*cy??IxNNgJF~AprYkn{&e@jo~T- zh3;jE!Y%=Ny7SI@rpuJ^xFW9n!FfbexO%`)Gz0(z@~dH*RNzEw{uqaRw*HKU@Y3T- z0GPs-#~D4n%to);F;zsaApW5qE0m`Un+7(c+lYXFBQ{Jl4H3H^iz48(C1c0iloPsJ zPeZ)@a61o)T!T`i=OvLTbcG3`5;R0JjDbQt(!Tk?kgclghbZCrQ zPR~y@xI!Trm~8A;X=ROm@ivtn5Q>cMP24r&fj^}O=@eIDO$X5?U+}cL<8IrH(%krc zD5Y;x5{*qXZ<`WqIuI&74$4EN$HAOX>2Z)9Dm@P3L#4+-K&bRMxM`Ih2j_7GLI=f4 zi?%DHP48Rj@OELa3#BvLVJ~>zO2cYkf7ocHLp87)EJP-PoneVpcp4O#@~y(jpum&` zOW0HR##n`GL6PZNi0~>1qL3YMG598gigzd@bL-3vu;yJhNZUTgJ&$d01k#^JzGe`Q zliab$peI$s`YQegEDPuv?E$8SLO)YOk+-Q~qul@NvJ-Yba1gmuIcC}!LajTMJn!NV ztuoNll{Az0I9M6RgwWo+5{t!&Vo&n6sU^*ba zuLhH~7Lo}Fp^REcW=k;bt%YP31ykU&NS_o;>z{=LrUcUk@wFlUE_|Z^C%(SH9BV3_C2#;trHrF!H}DGZneN;VZ5`dQmrWsNPj!ye*ij_JDvDK{&<%!&yNP6+H(= zGJ~i^e0v7roCX-27DNaB4ind~Ao6@3j6d=gZX{PWsfIOo0|*kgXRPkzGSLY0j6+o5 z?pW@)W|WmIOl>#dS^kN~fe{6@Z6gW}w>fU%va^EPW^?F~HuKCgh`ZJ1FyZZM4aR}> zl1LY@=Fo2egLJH&ke=kQy4U|jNxH?E{;DN@CNw9+NzK6BhaFdcU(wtN>r5-6xq=DC&WELC9e!8&Z72`$tw%eml2rgP!7 zOy~SI{Hl!3`B-1>f)U7$`Rp!CKkS&#?lQXZ)%KnElj+Xwwc_i+?R&)6liT--ZwGGQ zC%$HG-!Hxjw;vE+3l~pw?8@xO?T5tIi;D+ic4hi-@mS2ROkZxta%0y~KW@iTX4g@F zE?xxMwWd3_H;Zo|x3`FI&}wc!ZFF9B^V+xgjM2F$k2lw)yx5jtGC1M3$bImAHPgT^ z;~28pYs_O}3Fi&YfBD4yfET3i6?(hvL!@~D7WbYxy#f0RYHCcunYJ;gIg#dFsK;sH zH3t4aB7V2{uEw9ETEsc+Yc%o?1VFfvtH?8r{1t?~3bpSV?YrB^UlwpjjcTD@P#3*W zuX7TnqtV1415C$o6aNW>iT_@iCjK-2kA@13UJXhmaue@3v$k1{L|jL3CgMA;(Gcv` zzDKq1Iqi!&w1hs}Y?*nuZ4~m20@tDt3uecq;+rYIN}(Gci7;E^#xH*Eo)m?*MslHd zqZ}|!I4)@O!&X(<{<@54#a!)f|5U`GM`#kyetz9u>k%$w(oYqNb@kn_n>AQNIR8L{ zEjf=l5>`IZ@bnx4LeN3fi5rbZ_N&f~{^W%vVaDFp;E!*UxKXnZa3)-u_zm)^`Ka!g`9yGiQ8`3pLAmEd9xrW0RJV*SUdsfGytWP5tBaEne<>2XSW z2J+O;Km(Rc;<5%4?CUQ9-T~Sf;6#T28k~ZLYTK4@YWM(yu`D-&FYQh#l}h}731fjS zj2_&slO_-rNgEj5PLR1s68-;3;~+MUY9Nsd_+F@&i&LJ$Vl;O_g+Q zrZZ-ffzJev7;fO3&|L$0nkpS!D797)k_SQnCoXr5;;ND8SZ|FfH>I%2i91}A{zDlAc>rWe1Y0jSjM0W~ja)Vy{#HG}v_LCr8w12{p= zAIPgxgFG&3kgpvz)jm%|(3UC8UkqIGkBlWBL=sUE$v5g$ z#(~OktX?CvOfi4Sq;3m2VgPe@lSG_ks5f8Mo}qnU=#s|J)w>zWNamlRhV7By2!Mj4 z4LV220N*4=@sF8f~S)wNMC_YdJfNn8{JxbAy zMH|sjb_u68RK&(jbCIE4=(xZ5fcKGcF;B|x*T=>VP)trq~3tP^{8~H{k zzffYqcB)`|Km3INZ19b=8bmh{0I?uWRXOByi353caa3CHNE`C%-B>J`X+<|8`srve zH13yx6E7b`y=C z9-hYfYvPRI$J;^M4}sllHfMOEiL*@_xBRc%eg$~PL2wIL!R@ADFXo1$gJvUN%#FbJ zoD9u2Yu zjOZ(dG-3(1+)AI)o6#OPa3yTVw3wJB$hZ zN4|86pwB*6x~;B=<@RR6qyjs?JE zAuKWOU@uIp>;YM_$5uUdUxW#t&~<^U_eh9eflq}vjyeJjf}ZeonGF$}G8=>zuR(jx zGFIdYE$#s={?`wvzvG}8@M`^mPFEWSt*$ogQ_=i9aEmI7fne2jf!cmeqMDrUs${3f z;@m^Yb~&=ti5CUuYjSaHgVea0Za<6{fQ7}?fOp&UwDXy?veF#YvEIzw^wvx9Un!}< zz!A>}>Ttp~BB}@n%!DGtXCi{eyuj2t0>%U$sY9;N>S)pTEFlba1Uw16bNf`(i*RC- z3h^k63gT|x9xA9Ik>Bp3X$5@K(C?@|VFDD_=F*VuZiy2l&P3j-0Tz~_&YPtSOA7GZ z_&My#WTW0;WktumoTa(_rQUBMUn!_8DR$L6{rWGrY(La;H_)lpp{V5?8$EFud}i9s zp{s=sxap~M4s$EDftK0o`z%+d@d@fYzRwOh1@BX@eZQ37Sf@#}-1=x#qTZK%^^~0Vpmvh@ zGF_+{5NaYW%9o~|!~s&6NxVo05UqE-6r6dgREa{Q*|Ra~iEoZN`q9E5mMq#Qu=nG` z^~^EAzT1;i@J6^b{%~Ch!1hB$Kc3t^JscK(-$y*dsqf3WvKspH2pvQSJ`h*ixpxSk zl8#8VHd-*!<=E=&*|vIdd2JZWY6$nrYA`{*lTJXsuqlZrZbUa9gFLF7!GufBU_@_C zs@82itEBl?^ygPQYr5tQ!nqfxra?-7yJRbwpV3m)syL0g`eIcs^)Kz%k-Mp0t{IG5 zBdmgqmyd!BPmlpPv39tEymKK-F-70xFC8#A~%IZQP9v#e4h&5t4J{m-O z3d=cipme?_xT5)WO(G?6(0zHl>DSKUkXhWw5yCz7A9&$VKPGq;XHxgIGacuT@9 zdP)oHrXzH;_QQyiE|lWhf=-<)nlFK7`$2*fw6&fC-MX;h{`XXDC+v=D$B@iNX)+e~ zOFZ)-%(%EvRdheyp;#$=fR^e&_hUe@k2c*VdOQV}3X8r+b{Q3T_fH2yI~3K33m~1M zbR3PPvA8@u{qCt4dJI{~1Gtw?zybk}o*b>?@2E^Qf3bmlzBO7??#^GTGcbVv?ysp3 zdK0x}d8Df$7~4`aFeq+XQh2cVAV2UJPXu5-q4 zT7E_e2tkWY=c_e1(Xt#VQYt%|A$DhHnrbqC*A(Qgr=rl2Y-B_PV-a5RcITwt?5pP)D@eaCG;q zlUzlMRkG~z;pw7JpE2zjjC_R(p0Gh4xbQkp{DjRK;3%yEd$l%aALQ3(L4AM&=8asK zG?vGviB(2LE?R9GMP2O>!T?;d9~rk%#?21>Oxxgux6EjDKLtF}fx9P)Qm@fXPj{0i z@zmDZDTzB^mNKgcI?}lVrm4TQ(92p_Z=o<**``r8Z#LF8aWVG;cG$MiZY`CE`u0 zv98Y=H$JaMq~i-)T_4!$=D}9i=P15=MA(DR+biHyYRfly$HZSSy;D?Qq*jYh#-${&~dLRy2>a9%*B+uesviLwrGP?nvvd zCCFc|d}iP!T6(Lmbp|tHCgs zkMYwQuvl=chm^3nKlwjONJ0@3M8rQJ?NTI`Y(_~C>1e4eNl=jbQQ-!zKv~4JnHG&U z3J3hx+B`$)>>*F3A0AZ!jxaH6L_U!p%9$38iyTXqfKvF)z;>PHxNNEi)r*C{8yu%i zX8-Ehl>vd7&e*#%dmuA|Md|E)9^J^d$k?Y_=et1|K)e9rJI09H3o1SP#N6y8Nw8O8 z5CsVrg>9rGmX$D1JCRm`c$K_@>e|PGf(kO7SG61tq=>WGR}gkU%+;w?=$0lk|NB(g zRSf2DAw}I#6tdd}7W1%yW!gC8&%_bOqLZdO-o1&Oe{N zO%Fp)R^S(c_>vk~;niXM{(z2%2-6i52~t7n%=hkrQ02v*W`Ek4WbRm9H<<-_W;%cK zy$f7Z$(kkR`@5aFJ5g80rXM=oAN#(RDxM4!*3I^M_zu!a5U=WCo1yyI#{!GmY|ek_ z2$3Wd@esnQLbMuWd%tYByS>Bt0At79l0lrTP7|*L4pn7aF}rWXHCbXYA1LK!;*0fE z(Oz58*Po}$Kd>O{d7HCLmlUD}G2+I8(})8>u64bb?;7xMrjF$_Xjuc-inFU(LQh$S z8y~EviZW`^MFT3EW9fa;;H+-^W<+pr0J!P|0K&&247U^r8#Il(Wg21i)*-Z116&Bq z=!zVey*bWMHg4|K<{j?*e|ps-4Z&W&uHBF`Suw=7oA-Lw-J?kg9mSF zpSs(~tGCwl50I>R@CH3mu(p?Oz3G-6R*yIrHwQ6vf(}~=w!g6fY>zZH(3NGLBf_@o zP~Zsmz6JvWM;M76>jg*RrqypSLHTC5o4(@o$4Rt!60Q_*Z> za~&-P)ywaq_O?nPri3akgPH%sg$t5d4=J?R>TSjdD>d%%93AMcV-|AT0|^|&MmZ#5 z^TK6vp4mP>dAF0{o=nXz-l$rYANfe2=3`%&`!!0BXnNh3Uh}{_z5=DafTn8?;p+hmeccCqQc+q^( zAY<>qdWKnxn2?$=V-bn!jO{Y8QQ=h<c|vWm5G&0!I7@dLoHi`T?0NWN8fnL> z$95Fc#{%(n4uVH}naw!{Rs<{rC}E+3nCb>qIy zwDksa_r3)PkrD~~jwQ6Nj8Yct#qc>YZg1Gsu!#(>rJLIJ#sFyv`Zn8Q!g&;T@hqk&d;W4(mU9g^?JyXZvt zflh40ym|r_$xA!oB__%A;wBwJvC*@m;r8S4inPljzZbu1(bR4mq^Up(;u6d-hCE@a zH5)4NZ<{k7;dvmtbOF?@98jXCiv-^&MD6K(03Z_D_jLZkVzmUWX^n1)G|%7D+{t`S zl}5eVb?gT!wVN}x(c&9QfA7UDw?~}%^OM|ld&_!{-I>M3kMF$ z{G5f-Q-3HEbHcqVn$L^Ep}a-VC{f!=7Zbnqo!f!v58V%-(K(f5lk65IA^vm3S)avP z@<^MSw#?*OH{ujr+@DI2J1$|(r!jvj6O1Xe`%fj+-Qdl;&^Lc7lZ~Ay`6ePNy!jQ} zx2D7!&9wWb($%<#>TfEuI-O87xq+IJY@2fkCEilHrU@cnhoA+K_8e%*RJr9~E;Om# z{*2t4BzlZY4l7}<&G{dAXbKr+(VAPztE+#Rh-74&J^dzmi5>}{g}`1V!14cUd^?DE zWc}bbiQ-A@{^(A(@7})MRirijd7C^nSt%evC|pT|LERHmK#FS0u&UuS!*~N1WJ5pb z)!Ryb7u3Y(;7&C|f(^CeJ8!pIayy_e!`(*d+aI!&2jYUud4Lkc?^~OH{S~+T>sm7T z7%itvwlMnEXc^oA*{>KX!l;MIGDijs;q-*bl@d;$m@MI?_=GpdS}eUZrYfRn zWk<^|8q#Q5=%sULi++>5EYBFF*9Wd%_{ftk2V273oA9*2o3nf@b|Vg;R>bgmo>XpC z;~Qh%{MFYo+XxU_EKT;a^u)i4SiJsbd0b@cLq7hNR1w#QM)_O*SH$(D`#P&|w!SpC zvkKSPm;UH%`4g#Oar8$Qi6xGD1X$h{IpXQN0LzO4OFTW%)$+86OQ85}mh1RuPoUWD zmLI!=VNZ==;S;B*K4(p4quZOYftG(7ea0`kNzeu>Dxk@D)JDGsso8fW&`-f?fri94 z{X--#6^XRcszx>@zWJQhGQ}8BC+?-IHOb0UUj*H0bAC^q!Ypv^a-;jgEF-$r87h)^ zv<9QVmjz|jfdcxfrzMaY!YrrU>#(IkPlQ`+_-E@!pM+aR;9p}u3XQNl4&QiNf4q&zax+?~m7gPkrAx zb?Vf)wY|sdW6BS0hu#==^Anp6Keqg@ZNm+n@mal~xaY4XW95i1h|1n~Ox)w`7sJ8l z0?j@C516^fn{np8cjEr2#C=ub9&ca-#S?YKgA%~7#6A9doH2T0;{K$>{VD2x+p*DK zk1sza>Q!C7v+d%!b+hZEfdk9CZ8~UR`N!u*PkgVuTlCoX%0CJRj?4@m#DBvwOBOVb z8ayyFa#&{Akj!w3!$%DsoEbQBP-e)G%m@|?95ib1(9EFWgEE7vb;*cPgNJ7Z4<2Sp z1`QrHctmDMb#=A`oROI!uqs-E2ag(3of$f4M3{l~*!18LqlUnXp|PQXgEKR)xU8;m zz><16h4SIh9HgBXGHle4!I|MBVsitBCYVF3iHsOB0xxBC=+IH{edKUuHHSNrNI0+> zjtmsj!-k9+G8Ce6KF9WOxJ-zxK!{?Whr{P#nSsL)KKPeI9|=o@Ko#R7QR9frz~RHH z8SjyCJVy@%Z)7l#CGa`7-9rJy2pr8thM`*q4vNN1M>pZ7*tBRo*>>F9VgzkYwmbjX-pCoRh$aQ6m_FI2&>zG;rXk5y~$+ zc8JM{5t+fmMr4o;xjG|96_3DI8r@WW@_{4KqT!i2bqnf84MI53XPZ90seDRVr|I+N zEUaI$q<#vse$mm8y%hmd@VsyVCmZpOs#+ySQvl zV|m%!(H+a?Z8@;4VM4dE`P;jfHFh|nY(blTWeevHD{JaLzN~rY%(6?nHk2)zds*4y z$G=~;WasT=OLwg=yR7BuvdgdAT()fdt7TVo|3%rAU+ylus`}lsUH}P#C50@WT zyanG9@(7GH4~s_ech`~8BL1#DBU+E&C0nL{7QMKod|M>yJo>AB_(YqUfT|;cmo6%jsiaY#1`UQTMwCVDBRQ@=cKN(-H^*Dg$ z3!^Lf`|$^(r}=y8_-G%0Z*GWsKY`yDwnXRi_tb6CE%;rs|B!z~KY0RP-gEdrVo$b5 zZ#{w9dOca*tz<~Ae?;GS65!e!6gVQf|6zbP11w&9XSDuFSgO4@`aOTQd=ee{L%2P$ z!xyok(aP;he+Wa95C0;%@rQ78*;UaiAQj(pd-MYl|Uz87Q<98IcBC4Z@1D^u+<!Smo0l({w(dqbIy7&8vzdG9bd^!FYz%%7tiYKg&o_+?I*Y}p__xN2pz4emtsr7W^$gjArupyCe{iJ9SfA2jtT94nQZ6+!1com_4ZZ7Xq+WpKN{ejOz|Fvn+>CcxRSJoeq zo`?bCgA1b}METxpqyGS>-EFvEwmK?)5%=40zimx43ip+54i19ZcPrf$ z(Nj+{wO@q&(I|iXzGyu;OK=~oRh*T&O)r*rYPS~UGaiZ#+ya}sc)vb69ru-8yJ7s@ zr1-N{7T>=GHYcKd!Yk1W;GB3J?puGZIITy-d53|!V`f6d;hpa-`nTd+OKxjZvhIkA zo|y?9gSUV8pF2Pqg4Y(>_%Nz^3H5x6`-z_^8&jjLPs8_XUMlZ$a{ul@Ft;e~+poss zKE7<*{k!Mco(=AjLzG_sxSum!+vlJpw7{m|JCw^=`9_A2y4$uH` zsi4?$fa!Zw0>^E9i37x|@DhE6hFK3u@Hrs37_c2co_h5K&(TNyCIU=ip96yD7)aKvKU)0e!&}`f>fnfx`+I5IkXk^&9=e3+M~J-6XN9-x%ms zzyNVRDdGTb<4cmP52OmbYNP_|DH2@ti*^0Rfxb}g>@gs?F#s+vae$AYPhW7+5A7`G zBjht6xEQeY`HUZcSB)bAf@}RSz_1iw(gHrCz7PuTa)3DVMDW-+eu({kxX;=TGl4zQ z2|*0lEhNslOmN)BmsBtSk}raS$NFIa2P^}}6)+&UIAA+?d;xvIsgL}F14YUMX~7_f zzCIM(IH1%`hzCQ?hB!aMfKwP17s2L$)&bGQ{; zn>RUfg0dev2MQ8=&vA`1;M5mf9I&6Vv9Uh#uSUAS8mkon3n#&?5T67CoC{p~f*XBs zc}b3p!+lrgzso>O0B#Ie4)6rT=YZfQ0+#*+=!d=}A%VCtfO}rjg41zdiq~#Ogw6rR zr>OI->M65FTHs+!m@EcB<|P$O!9CY~E(3!5^m{{J8i3pQ%GyW#k3o@(FclaLxEv7N zXQ02w0QHIc^hde%!+-`za2Yrcn6Cwb z`}Exn!2C}Gz7`Na5ieH=1$Q}c0d$>R$oXFgE&~_BfG+}q`}AEAK>lR{8t_GcxTg-R zoBtSw*~vx-E(0@Rz!xFGefoJ3LjA@=8t`Q?ao=MoxX%IRQ8I$8KgR(Qs%5?=h)eo- z7Vdo!5ZvVeaVr9G{W%r*B0vMa93egquVf1$=GZ5mbx_rxLzo7FD+yUa175xgh`S;< z8(2;R!xEI>k`N0a>tQ~gI*{mbg!;a5L~yYm7AyNX4va>bD*`ld8eXml2rd<*+2?$s z?d$lXAQ^#63sgYd72KU}Y&vvJMLFY9Vo7k`k}MD~@2i|4;Fd z1YZSn!~kYbds)p2h`S#qY=70~MQ~+-VjtH>-^IO0Q zNN}}aE-+t~3+{>_acn-&0LT8Hgy}IM{d|DyPf~$f1 zLP(suFxOK-oP%Pz1DM8d2Z2ksbb`Wb3*cN=xb*LYeV(=%Jeh=?#_s~5Z<2s}UXp~w zod%$P5AdGgn+js>tUhs$xhpA2`PiA3iG`=lGMs|C(2`qR#-C zKKvFB{tWD=k2882C&4$+Yy{rNQvq=_5O7HsJ`X%+pb}iR@h`XtdfI*qczO%e zI)k{ci~bWhPh90Gk=3=C|4HEdZV2L`c3=naj!7K%yrhN1xq24;7_{(|$tyem(*Q#( z2IQ?5so>YZ8A5~W8j^VT1g>G@AocCpkH^S41Wp!Gfo)(n4Agk=eZadVa0#(E_-Ej> zpCiXvt(QzC0C@@FV@pBg?GFAY;By6KEwPL};)es51~S5|-w@j3zgL_E*<>+6T;dRM z-(>SPD(D5iR1hmC^edr14sybNT)(M+1m9#tye`*3T!%Q=7r5^!A)fn~tNM)tM}m;^ zoW|y}5g45c=RN49#-p|HEi*OtWzV!fcz6F;EVNL{yb2@f)!STSW68dHvFCiqs zH{BBVRWJy+cM%GFG#t=Ls^gCWaexLmpSxN}d_e*HGT^QV49;;7^S@l;00~SI*JDJS zC+{u?i8mI&jf0&3bnG!+y< zz$Fnp4LCQO`}I(5+dm!na^Ty|+xXPRB?d@%46>;pMsx9vD04-C`hPE=UjnDi+xXhP zao`LXnB_4*+_&T+ez(U#;=4KjxLQcUK97Mjf#Wm6*%0gLQz9t1%Rcd*od0|TCYcZC zP;L4+#etlm+{%%&*Z}6g%Ro%?`>9LSkYtrnaO2l$k@1|s5D0e2-S z@G!uizi|@IDNq6NZ+Kcr{B$pl_~XCfI~|w;1BZB8IQ47bJOgs&(9{qHPW2IhKLp$r z!WqDi_Bgl*_&|^Skc1OG1mZlBb+v%_1s;3}@Lp~_3`p<|rI!Og00vx1whXv02Z$e* zbRZ{*G5@m*x+Dp>=OqIPaeng6L?FjNCRkBGpSV+>^Z!jCaBt>n;cDRHk`CaWmpDj# zB4k&N5RZVH22dFn^^yOXfP@=Rpa}U#r^J1e5%K#9=sPAW)UO?Q3U|I1>@0u}@i=fZ z92}d9>-nFAsi_3Dy(XSLM9Pm4ao_Iu4&bR>Ec^dELGbl4@w9hFBnOD!Wg3vbq9T5i z!Lto8`+pLCXb9;B9yEB?K+=KdfxEhp_Mgkgv-^J%ewR-$Sx(&7$9Dlg%Q%?d0ODf| zE)58?ZxE1>Jwg#eE69%|-a#iqk@SN$|ia-_Y^C{ByP5s6J zi=h3_wvhOXSp)xLydU(hHu{+V<&qHQ67um$Fu><{LY(FK>;CpT#Er8=I7<0~cZ3l>tu^eFi#(~E`UL^DE48=#>tr-|{Gj@G1=WTKpPtU&M%e z_4!!&LPi5V2VV!?2$x-5_8-7~k7YiNG61mEOCoLehbgovL|06#W?o1Kx&{~ck#_nZ=+00XY4 zpc`;zxj1Ml(0fDT$rTW&@nz=!?jUezH3l?6l8|`6ByK{erq?5Zb5ZHiCr$^&o|bX` zAFt`~9XM8n$3Y>P^>&{UXHrRpTHRDI7C4vPg4_BNf%oP5R|vKN5(c8sm2|{&mQ+?m zCIR;yOcL+Q{5KU?2Bv`E%L(E`pzq2F;?q6&xxm9p4`D6{%xdEx?s-Wc60e4AaH|3H zfOA|iIF)gUKJYMiCu13?hk;}cDD|v?8-U}Vj({A+R0lVqkjW;OR4C=y^#bFMO9(&6 zF_?+5Bz`;aktlGrhH?2+$h z!1*?wG>GyshM%(k|0M`HOD>Rki2>rA3tTzy8{j$PLad$DC*Di+Ise-u6A3j!aNzTS zON((EU*aJ3eUIgD6AmK(@*N-{=PeVf0^;YQ%oPFR+$kBnNEr|Z-v!Rc6FBof|D^K+ z5XykKMz%i}z&{4=8`%B|d;{#~eT-i`{5uHWiV13V!)<&CUIg!Qo^uOt1Dr#*@Y_M| z1zB~O3{;t*LkNIx4k==F&;c^XY`Me$%TGd~tIsQdGo&hFQbBca1jOKI>tDCG88b#N@oFB0nsgHqn?aDX_UnjCu}o>T&390pnLa*%plV7R)d zA8;nA3-1p+BRDhw02hmLNywz!<@Y2e!t8;SB6+BkoSJt=qP#7I8> zXFCjzbQom0%RyG?TNQr;c(%(k%zt%>$D={u*l)LR49Ypc$R&I!cR6%6^oB!8_|qWs zoKcS(rv4nlq%1+|Gx)hV4rcQ38NiQ1soj9{P|l}CF69vB|Jniu>rxG7f|=T&GE^O0 z0-3oam$X>QO@uTd#yS6!Fb;*b$1LZ{MXsblmK%dsl2UI3aAhwe>L!BtgL0;e5&wL` zd=M5v&7MpaqMWmuT;kBBD92cy*8rAZDP;Uk@>z}su>Ui7sVhm~b8AP01}_vcekb`X zcSVGHd_40bqWAxcK{(71vIEOCC?A7zxunADa`+j6jYHQ1PfNm8wmsSZ-vl7>SmYTb z?t3bJ06g1(e1}#8Pje`|4FJbvxuk_sZbGUFNt|!D+g(IG9#qJcs+!v9xz_Ss_CiT-Om!xL>CTpK9VDLHMX-V{>gu$e} zmr?FZYT%(atG5<#=#?CYGORnkq)YxCIFmcK&#Qy~Ksmdd>(BTSg>3-RLWaKy5zk_Z zosHOUQSNIYao=P6yAT9lAHEGdE#&W@JbyOJ1n(8Fx7V_#&;P1}KRFD3i1KDM+YaGJ zC{LRUK0$d}1dH$#50>!Zw~lxiv;oiy1*`S4xkQtsONbwmRfzeNTZOL`lKkZCXYa0Q zZ#MMz$NG5w(<;2ss*v)2`7C!zg;xMKyItJ#5{KHNLau;P8_4;egzO$LE4x}q{+Tc+ zBc04&qJvz$sPiZC(&vDN#K*2|1Jl91VYM%2<`wL`Ut-S z!Pkes0`AKJ;sx|W=R1=e7ihre;ID!Ea$py5Uk>cz{)5|PR~P&q27CvJ?*r$M>Uv7{ z1Lr_f8-Kw;{wJ;WbEG3d`b-pDYeM{?s>DHJ2Ab*;{V##@{R3B0{u4NdUU5jD|H+u1 z34|a9MRqwR^;_D+}mfY&4p z;5NR*LE;lp;!48)z;m9Wgg){=6AS>Mo5uig&UVs5t#2Z9oTmcXC(a0_ILPr&5yqtx z44yp;&Y(4g#igmBC>KB7cF^E@|9^&)fae7cP6X~7$tD5!jfBKg^=1E0!cd?@ttL? ze~#<=|IZwF4Gp*e4RCcK@i~bG=KcSF5^^G7J(l3`R=YP4x!}nnzXZLHh@Xx@rEy!On5$AO6a)7vW5%MqHz-1l-9~W@&6W}?Mm2ROl zka!vRB^9>0T0V{%SkzmR}J^$M|(9RIl^lIbnfpefT72uwi zw6Fv4o{)WbydH4v|7pNC(h<)IvDL!P1@Hqj?%e+$2tw+LMSq~M3vgcxi5JpG1Ks<7 z8t}DnFmRnj2y}i94fz`QbngFMNi+fmIG?-vka*5GV0FPafX8P%jxV<(K8yM9s(^$> z;4TM=4@l};4x9oU|D5(u0~q=i93=4M)8!!X>`0ftyFDGa&pz-lSm~+Yi~XB%Evr`4J#~v%&KnBz|`R{9QL51~l-WhLG>TRN%fA5cf5JxVr(E|4F#VIFR2$ z;y)~ae^vm0&)`-AIsZ>X1->LBeuFWP?;!D4J$Nl}*GP)|&jfWI0`Zx^eY4#x;5|JK z5O>T49RD%_378C=BOP&93#dQ80N&`t_58m81c!&QgA0NCT1dQ*erf|{|4#$H7JeW2 z(Qw7JIVC>SgKq{tAQ9nW-19Q~|K~yAn@}>@2tigfF9GKfi{Mn|mBcTG?8BRYTLV${ z{r^``L63Zbserg|Rs1S&Ul$Qio+F|vT*yCZ0SUeeUMqmV4&1l@C*B)Xng|rB`i%o` zg5cZV6Yp*eSOW>30^-wvySjillQfB={n-fo1OzUdg<$8vHsFI2ICXhR1b+&gT_E}~ zn84oxZY6PCzcE09FN@y+&Vk5P!S8{O^x*#uJo(;m-2e1aTJR?jxMFctK-{P|M z7+?t53R%v#Qsj~frQB8F!O-KzB)!5+aA>kV{uwJ}xH<;XDx?C-T^06B8cf(@d73>b zr#-|!{}T{>p*YUd0^+_tZUg*8kN(lX^+?J7&)}sl32_w&z9j2sJ7DSe{~EZ;2|fSY z4phTHawN3zfxvy6&!NDFK*{wO57W5$Gk$gjBS1I}g{~wT1DsET;PwGU4RFpCE_^I- zM!jqt=5}=gA|I2HE)smQ;NbE~;>-b`KJYN`8Q|W|XMng%e>xiA>muUS z%zxKNMgk`jAAX7lzX1Boa?^k!2)HCd#H*P9k|e4nG9KWsYk|Po%H;s@cwEqLF5CLw zETB(3^clDa1TIKS3rZm1k`@T=>VgH(=bF;h0N|nb%jal-2a%G+telrPun@TKjmzeO zIO3n24wdo4Tyuwfggl2R|J-ag$Vzj@vxAGE8xHwPYa0W zw9v}(Yk+g0azr2uNZ@>L2$q3s{RRT!KK)yP^OKUsKJIy`E($XN30#vIg5|(%z;jv{ ztBZk5K>SFL{_Q?}?*B>f8F&D=ZzLn0eG2l|jKuSIKB@u8|4i^;feMKGDj?1-a6P7v z0(Z=&9RD%_3BH3y;&q-1)&n120A~*5JE-UXM_`~|DnZSD4*~bBieCrrJ7^@n6!uMy z;hxtX+5eO9Jrv{-^l>}!SAgfYKsiW!M*;ngMfv(>|Nmnc@Qrjo1@0T^-U9A>N*s80 z|L-7}vHt%Lj{H*tK@j{BE#PC~>H^|C0rBBu3*b2sLU(ZeVOsbrRNxsZ1LEu=;{Xld zlF8=R1@wvABPHuM2KIvBJAfeWo6m`#0DHzk8pkCL61PU$xPC+U69_pWQu;Y~&PZrQ zU|#`!;<+QOs^3&l(uu>7v><;dB|h5V`A4zDvk^+y&pGPV_2)QHV=72DP;c;b2ePN- z`TA|F2IhVKj|5)}iJ$6mfcWtSPj}!VgJX9~{w-;MwcWZ%_FH*l30aOlr7c)or+ z*w1Jj`Ik=cMSuo;5g>ki0S9yhnE&|^paEY5i2EWy+!ulNz*Pj|`9D7bB={mg+!q1j z$9p0`JdS|t{eKdC5g_i10C8UgIsj(`^!xw$5g@@A0ph+05I^1%0pf^&`}_Y%@I`?5 zWu}7s93t+EKpF5}oPS*d4GF#o5a(I1PyY;q=Q~LKG0cCTfy7XmH%`!iZ=^gD_%LHX z-vQ#GFN7pK=P__BaL)Ix^8w;KA#t4#0LS@H0R!jx4aEQN-{$~7LE&c&5+nf^TNNeYi+5eMpa*|L40hf$~mlbe;xX%INDG|u-|4FDtg|>%D z2j&;RrzLT#0aw8Oxk()N@%~#XAVIH60pt%fR{RljlIP8i^9We9Qg*%lC|1Fi}LH~N-?>!4ptef^ox zxc^y)gouR2kc|O?xRUr<$i_g7X7M+mpM6Uwzl(?`$C13x|C4Yaj2Z{57W_MKPF4oD z93VaeWiAJabKjtG9e)%^3rX-f@MZ!0XTWoE#Bz{$XOyW1VE(t?`TRKuJq;m0gv7H3 z^7Xd^&v^8S8~u3yZ-sa_2uH$zL_}oQ`~Sqpg6|6XyTFfiIE46Tg1157{OmGN1b2N& zMLd~Q#jwRo8bI99rR;x%5CmUR5$6{bxEv(TV>KV1?tq^EOWYpD4z>keg*#W)6F z`MYW2sqcWu{7(XBFINkQa~bZ#TReCf^f~m}`ey#G0KwNn;_)h3MlKlRC4F28-1pQF z=T^>gAUpq);9MpnM>-b3I~BmY0?&4lJl4oRX#ojc;GyZ`BDOD!9|YXD!XcjX6j=HP z1Fwd?oCq-g#Q_p{w3S!{giQEU>qR97lH1AM<1=JILo9?6^f@M z>!nRx(k|k&AsfG9G#9_igZG0zMkxDD_H61n2*v^8%x&|jJIev$Qw!jW^YBFK41j^N zKybB?_%#Lam-8yfMu_@(crtYcf-uTsfHVMzsDOBO%E-4rqch?^$PQ#h;7I3kfH=o;G1vfkCS=ER9T4Yq>%&*_ z=)^@>0RtHr$bB5E1D3NZWbtdj z=St0XkmdMiF0m)&ISz8MEQG6}#ZPXuMq3}K=-IxN{{cFvxpiyVA*PpJ1qB~}2$tnE zB0E+IE+$_qz!%)+n>M2^T-jCH>jex7E(S%m44O8-QNW(UF-nL*QE(Z269(}wZ;|v< z6dn{eM*R?bQob^dC>}iP!TA~VdT^8yg}4B+QP4&O{|OWZqRcg)y#<_up$p#u{2U8s z{l)6Vna^-0S8mCX7x!H1SX%1MKiIZBHG z%EueII`|7@{4hNpdh%-cje3{1?+tiYJwOP1((533m6n! z?1}8M7ycCnIX2l#|1VIEf94W{Qf`ve%IYtn#IZ~GA{)N8sPQoPClt7d5rw})9st>u z#U)sFb5CLqjx0|bz1yLj6J)wQtkOux8q9#IE^(+ka7H5CKqkn=<*BJQ?VI120zu_(gSyofjv^r%&8CfcyA8pT4>a*b!V9tkB1FCAtfecn$E@ z=$f}Gx|NbXBUfz76~ALdewrhGkX^PJ9WF$7NAJRR$ajS4t4$x0$d*39H|T7UPX^d{ zwYB$1;vCrart61sI+7simR3RbZR_kozEr^W_#6~G-9ZdIBzQbDxXVH6`y6CP_rfbR zf*g2+knW+veGXFJ7eV4od9x7La|I)ary>)BP7f2f%Rw6VIVgBa1l7WW1eb?&klX)( zc$p&r{k%vH2yR*kF0Ulc?PI>a-X78b2`&Si89AmovN(R=i2L+YBNXb#j1`bz3=~1Y zB`x4M&)F}C)F5s@C42&WIM;z`cqkRn`!s^!Jb(B)xGP7vj!esB&)p2WphZHg#|axZU99Uj4$#1{1q={(MTF5j*rPAF z(O2!yMt}q^Or_eG5Q zDG>`zNJfF+OQNyBxsq*lL`?AAf`iLT93;;9B{yQoKbznR8Aq{sc)1)9+~olAD{Kdt z|KflUTn?N9F6ZnPX`%I)3hvTB6}onWS-){W2(F|f&KwbkMK&Xy9qYE2N)4?i0eB(x~+}~37)kVw?Eea7a&Q4luZk)7Sdo1US=G?J+Gv` z9r7HU_4}T4R*($2$gYqRXUNSGE5+enz-3?y?U9cLj>XHgs0acsY0+u8_k~#SY=~p^ z9Q{Ou!}$ACd?BX68oZ1{%3h8^Ux=yijxgqb5=!w(wve(b#N_)zOgtH4JHo_|#Vc-5 zeDG+6n1_nJ@p3)qg1esc$M|y|17jeHWHF8 z7TMKe;=UFWS1rz+zRmnkg0IC)y6j;z1bs=1&xPzuTEVTP&CdVl!2lN!uB;cFS(}!$ z#FKM@$gYSHAIAK54VCAEz>vBe65MK$$$<+B=*M`R|1w(@K?9eB^dj6JjF-y+!Ces{ zUTN8*Y$AgCSbt81%mH78#C;WVui(=so`_gne~tqg5F`Q@9R?i zfut_6Ka1_>mf7X;EMUZ4Ehc_q0e#|$7DLK5a2DIo7Wf<>ZXB?3WG*n@V<))Ffv^Dv zhIkwh+&BO(F9{*>ekrm^GHU@sK2KWpQ-^OBun6-3`W`#MT`g)Xpf9-653?T#kQOz; zfG_C;cSVGF^05=yL?qdToc~GiJ$8coD)c>e)VCfxl&CI5{wW7Cx`1*s?tKxs6u9rP zW71XO<$5fa06QKpBt7##{{%z`t`-ybJ$8b-a)h{g>h%0?AHfL0I8X!)T#_TpaL)e6r*coMVE|0l`H-upHp=e7-*NPbv_? zcI!+>@FQTLGhVI;2yXPjjaELbBjr0RexX;>?}^= zbRug20xrS3;GPjIgc}ES{W%5(z<~WOR`PZHR|WR|juBt9_(e_8i2ons@m%gCr55S%%{!A#+t|Ml3M zB=iJfwS0U8_q+tB@wfunh*%ZyjcnpF`^o!=qR*Mt;K}{J5a=DV+!(+;FTpubF^s{T z<@k}`0KrWJtOgR#;Kc?a|6l+DFR6ed8Q*GiRY06;xI(xzpqN}-N&Dxs;7)7)7eWS@ z&jI2-2Lu-f>;}@dil8n(kDaQ#$v3qFs;XgHjvl$Ng9|9e6Ghq;`Z)3sgI>R@?U?PJFSIFVZaO| zxaXBLz!i?dvmeh(;>&lg^@~0rsPDu!!cf74*P8=L%PZ zW1Qo^s}D&SNCV;k?sq6=~x{&#=9PssFFR(aWx*{aFYp5p9DLFp^dj2QjKtsrn0P&G{ z`5YkbbD#!zo&%wt?^yu{3Rf5O0mgyI<$&NW2Z(3w%m1s#{3~NI30!pe92i@`0pdOf zCK&t10sO}U9RWHp)DZH!fc;0@6#>CrPYLnSc;!AN$Ukv_gj4X!>m%(TajuAb4iNV_ zZ~^cf2blj!2kIfa9AN*m4_yu%4XjX(Oa>?U7_)xk0F&@Ei$J{NAhpq`#69=#EpkFq zLNp&Y4JgXRdE^!!bY}JA`b`Bw5D#VJAP%tdu6Vf|5ZpMR>NobOo7(_Ye;&aYuv&0X zo&i;ZI7pl$sWd>L*$8o_%xOSqg-{4$z>Wa%_~G{t2*DW8 z5g4Fzfa7>uyi68bIKx{A=c-soIQz}QQUSg58K8sA6VpYw=Oy~Ysc&%0L3R(Hl4bG6 z1@pgbJj4KJt0N5|9p_lD45Z^{dT>r;#(up2*Et{#kdRiv>ADN}2(c9_t*w{f3@=Ah zA3j9m$p35$k_JeyTPQe}Q{3IUDj+`iYv8cY=P%!Z{wQS>TorH>pb2?NC>0RziI*LrBz_EVJ3>i(AoqW+ z7O(=g(tgV%X<$SF2gZ6F;1kk~`R{TdCIH7{f}h!^L>wUQivV$71c--hq0a$d1Zcn) z0ph+0V2n{;594xxgV2F^nJy@TfJ-94^&oMVK5-7`l7zU8FVP>#{`X}uhhgF_2Sx$o zlN z|1xpwNJ#Y%_({Mr4g*ApANMuz6#LBoOfU{VnFFpC66cg$2v4a1TA5%xe)dS!*ZcpI z0rpBIsG*lQ#{!oFg4=sPdCZ8{;FUL7g?c(Afn8v70QbC-2F`)(bAY(df%Aad4ur`H zW`W>yfC~44V; z;cEpOH*didfs9LVc6SGk|1JZHfcI$h*e&nliGe<`0k^)v9r{O7pZV`{ASM7e-&tg} zfV&u91Oyj-y8%2e2z>@fAT9=qEeDP%;DF$wZ##gEO6Y9?2r)iarccWO;>-hA1i2CM zHLxH1p9Fjo2|w{ps8sCP^_X$o_cnx9L5s|ceAbt&;WERgx4||NGzPIAD@GQn@?0Ex&Zl?iH}wJsf1Jy zfe!=5;n#%^{~CBEU7z`%iI-p9(+LLWe&6K)mv71Q0QpFV4AsQ>DCb8|&;KNh#miLz z6VMj{;u()VSJ9~vmieEHOwNEV2Z;N|3F15#a_Nr&c1Q{yN{HBcUl(wV=W}2ja30yX z91z@kOhYptbB)%=V}L6pUj>4jfyR1D_z33fBmX18sB;>J>%b4V@ zZ=TZxW8fsE;N%M~6^iWoUbk_vJtUdS0Y%8RKxCJ}@dX?dTpWyLCb`StBpBoxPZZ9C zoD3;t9>WQK7GzE&BA*MH&%ERVZsSYv(}Bl}Ohw3kecDU_Of(@jKpvEk=R@Y4EjVQ+ zp2&@mla5?!$(KXcjNS9p$W8F0r=* z?=?K@ni)er&JKzC!VzbzOgSKGFA;V4v>(nKx9`1 z#LrAL-~-6Xp_^Tlnq%@E)SrRi>%+eRcl9A7NIdDV$S#LJ*Y?7+q@Y0(k_JWg8RR-& zy72D>93~F?*>5-211u7t(Y=FqQ4M6^h$0TrhB=Q%KvjasYU>BwKq5gvi z?Xdpp3H|MQd1j9j?bC4Pzf{;EjgY{*1LqQ1_#!tuzIFRh@GBF1k&}GZZwwv=1xETlj{VLU3}W(J1U8hlJ!>yM*-+a%lZ-r`lH-8yAk)zZiBSG*b_PHVBG#} zi%CeXY(&l~C=Zhc$D&B)2D<^(u*U-o7d|}H9-5>n%B^5D@WCjO3dca^0%f%f&5E9b zC%c4v%DGvewHK1WC6ah(XD#ts;QKula_f|Ikh1+@!z8{GxNdOvLqSc6$Yx~*RCS3%rva}(k@7hE=|{oO0p7#l_$+{>PrP#yPj)fq z|0y8!OcE>u#JSay7HHUnocLJUl2F$mEhNtKe3t{n&n|#F9N_bp z33k9ha%2pq03?77sj}r|8XB*(qa;pqr_+641;Iad>=wD6I)V0#GaII z*ZTy$pbGZL{7*tDbdm~`jY3hb!H>ZoOWZNp{0%tQ3t~@XV^5h2%>JMIEKG1lL1bG& z3=&W7|3&^E^25N@$22$r4!OFZ18|<{xFSHDCt5E3QsC2g$mTLo2?9^9eK?nF5)tw# zyCOiGC#gyPc;^5ANCA9T#17OIxEv-vl=Vr@Ag5Tr@u&+3rzQymaf!#od7xkn#Aq&l z_1DJZk(Bkz=zioLea|V9$2M zIkful>wvFTBcYBz3X%?duYiFpp6(!VR~OL1(Z)Xh28|+SldwMsJdhBFM0P!iM4po^DHv?5rj}1^9kXg^pTsW)zFod#%&u@8D&%D1Y9aCD{4R2S3(H{zAL9a_S#LMc%>So@z=KHFb2|xm zuY>{I#+S6{Ea2=C`>&*2i1JaI%U{CR<@g&^_L4|%r%4!>P`DT}hfXmdvP+-%Sc`v7 zLaqaTyl?)W0|L(jToGvi?u*DW;6pt6R{|f+{C8Eb9E3F<{A%D#TJyCkxaTDix(@hV zkX`n#1s+ZZL6U;Xyu<(rjDQQj0r+jeT@|bb&QCaa@G#yucnCqQ$G|NG9EgDXcFR#$ z#6P)Rrh;#~OuQc)l8D%kE%Eb!yT%FP+$l+fqfi&P1_~Vqy^xwzEgQsSquVK^TTY=Nz%v~Iq@HapeQ6`B@AOtZe zvU$#nl*uH{By&|5p~AM=3a$FE{}+N7yi+TPL3@RC4{*+623P)=7TyaydF&=~vz|LN zUGX{p-wy?zeu=>x0`LcbXACZps*cM!LiGawdAxC{zfPX~H*Ym#= z_!NdDDj=V-i+>gH-U+_Qd3@RblfXkHX(4XoOIk#neKtZpHkv27kO>60`R2XlqFj5+ zVUI^Lp{h^}RR^K2NYS$)mGZn6=;`_zttSnzyXbo0$sEulXZHM`g#M^C*P%?na&E&_ z%c_ITkU2!lB`ub6mxC`rPqLmlr)1=xOJNHXlAn0^5#&Cob+uy+NSs|L4v8#7tv%8b zAISVSA=6Dt8aNGQ`#lwowJN0SnoC&WG~mhEmi6a&d?{pK3+GvU%Dxu*8u)4#tiRYN zCIVKLvQLxCa!}(-BJ?;$9sUm&)uQ~Z9C7AUvc)uz)rWiRQ=fsH{W`UAWeupgz^Bhc zET;pU|Hl|YehZ#1&_d$A783V0FeJg(LgJk5TrGSCxUUO{yB$RTli>4^ICnylBe;z( z=>par)eI7m69 zf-#7DUPAZ`1kAurgM!<9pFPec2?yE!Y>R1-grq^rE`xsqpQm66gE{sD7kiZXMrKw< z{fvNXt3(CjSp_A#c1mA>&m3?$B)Hi7g7ZHWTrH#m$8ME$5~=Ed<@_*;T*ja-H%Y1q zNqjQO#GZcsl|jC7AXid><;Gxk(@rb67tml*g6AWt;KAq^Xc+d<#AS?vnEJCx#q zj`P3X3K;_=WZ%Qd#}5L|h`2^d;zxS$ZV3mF|M?Y=;B%mR0SAct95@s>2QoB(&p#Zn zx}YZr>{HW13qQI5-oF4o2)J5t>G|L80us^}3_P{U1Ve#yH)|ZkJuk@-;vBeK_%Prc zh@9vDr-6_Y0b0i;6`TPa|C|*}{2DmzhsHxI#FGjbAfDr(r9Tb0?qgKbIhddiE~EkH zDt(;)%e&E_@k$bWAFG*RJD}8!KJmj)=CXfYtdIQj5qt(Nh5;VGx%6v+=j4bLp*rHs ze`CNRTvDI{;=T&z6u=vShrSk&;HzLk0en#beDOip|M?sM!Rx@X0{9icefF<72=Vu| z@ah5v!U7JgD1hHY13i;DfO}r@6x;-y8wZmkF`C712A;OA7k%QrJ^CRD*~uh-<3PM0 z47g@H;>q=a_Rlon7U1~jYCsr}kQ^vfMY7V##5g15a)A1LOkMZ`z}@LTLbb>W=6G{cPXvgMGh6A+)^NmAmyJor}Nc}dLt7Y9g4 zIU>oyvq!c0IYNDQL2e7P_Fn~VCn@VU6_AjcrTRS{;=Uw(4Y)5!-^j<~`i%o5oa|`< zalUWoYT-|S9}V0!RR0_}7p+-b)o&d5B?$QEd0ab5ranFId?@44d1wh#g?$uZ)| z91HE84++zt;2H;r*A~F9DS+Rc#q;<7tYCm4fopd4hBPmrMGHgo#2(!9M|BR{)>t!T$z*$r0pV22^#4 z10*Dq#Eua0X;5+H2=Uqi_%#Y={^xfA4J48zuZxKLa^!R1(>x9kUmD|%{XYrWB*}M> zxGzVJ#F82m=VN#ja8B3G{XYrp0@rg)oNr3Gx`6n+0{ErCLth2H2(W@%Jrx`S+!ujk zfuD~0oh=}Nvzg05;SsGCPfJmVR?S0FUXqF+iamM0&MOoD#Qr;txh;+P?G$Dlu^Qc;4%(!czQL*B zXwPFVg<7p(*YI45LR8U+0KArlY->aS7)oB5_-7FOB#pUh0rPo2^5hq3@HWCb3I8Sq z*6DsgBhvl%DR>;T6}m}gXwn_C>=N&-92|Cyo?dw>Uu9(27qKMkXb1&GmMX~;w( z$D|<@3lTlq;+2Vi;sdEE%((VUbihK?eu4{Mq41Mk`0nUz>Q73+qiysAQ(%0p(7&gp zF;_LQqZXp0zL^GZ1Dw~S`V?l|Wtn@~`s(=1jg@Bj1J{BSg{Yz#rn%+gRTKZj$|;4Z zvO$~X9*|c}{4)r?m7*Z&)r|05pMpo*P<6Dk35~uf4X(Hpo^ch+t0w*#1h=O$7lC9q7ZFcj0UV(ga+(Mfn$5Y{mP!b*7(4s z(4wDcdkFZ{sqk$*-%AyG%xE9K5!5-zTmH1HOjqdPQpo5w=mmv|_3C!@_sF^&~o)9N`JSOo3&gM{+l+S3tF|jU&}!}5~B;|CKk^FkcyH`L_DqEb>YvZ_u(DGoY_!H6%d4 zvGSR%Wsi2M%pm2K;ni9k1h+&7tf>5EachrF%_}N@SrmTRDJVLkb5K-+*Clve+c{`| zSLdL^HvHZRIdeczbP`^3@wyhThw*B~>sNUF6|e3G21O(AnvU08yl%m3^MOHoeA81= zhc3{^>lD0dy9Dj=$^G_s;PqF$hG3?>_~MH-B8&QwcJ>F(4ptlFPvS! zXlnhkB}*682NzFls++BaXwQw6qoe0lZB!dbJ7G{kjU}D_Js?uz}@xe6isbvYFsj}IapcJCfM=oz9`*!3zp5rb(fzu3+=eKq^Ws!)8z}P zycU$}KEa2IO6D!Do7q?&e7|H-u)bvJf(2KcQ$H)%3V3sD_k$aq_FHpGUwYDhSaQ7kjx#i|VicVe@+|f2DURWQjZo7EN^m+A{2lupX z6MX(KecyF`-=b3%H7%G_zo2Q+6~QI|n^&_r`&)V!jjz9?ZfWC^U^~=R8(wNVWeFSi zs}RK2*tNRZ!5`bsnjd`LHYll^iJrWs?Y!WTwoSpmK)LM=cJ``&(c-TA@J^uW?EBj- zYMQgCe(_@V^ds$H>dsOyHmo9VOB~J*_S3!F;`_%DY!%wywqxz@wrdjxJJ2yfTa|A= zZWl-T=k4g_lv#D){IVUQ{a!mshR;yRsx{qUa>u6!;pe*5-HPMN+fQE96g<%$dHLU6 zQ2zNJQB~Vni<%l6C&zjDYCCkv7wsD7@sWC_ee=A93vu&$*nUaflBKc#KY{Y*+dDvc z+x-XN=f?dRc*_p`ZimwrHZNVm+nYMT_K(^P1zP`0X)0{bI$Xm3MAz^ znq9Ri9+q3<`zQIc<<(=`j1SEqd1uAsrp5E(@$$ZkDb4luvxA2!rq?65^Ojr@JO)EM z-a8hpn|lR@`^CXi6>7+S7r>YI(uXZA@$mmBf3`%7>G=A^OE?&YUw12O}+zp2wf3F|i`iM{F=6^B5+ixzy&v5Tb zc-lti-~$~`#bgz%>o~D#PE+t?$4T`Imj)Xe}pQZu43e3H#RBe zON#kwr=W7|?AaquEHpg|`({Wy~yW@hoc?*NTcU%;&A%dvWQWd-(cS4Y&2X3$Y zS@>niZEg3rdGmnRj(fAmsspyST~WHKbY;orvM&$WbMS^9ttV{hxTE`P)sJ_)uIjZ; zd&*l6+Hv@v!-oXHFl@p*7BRp@0e%G&w7mZsB~RD#^1GEhOUrv+D31A;YB}6JxFjxE zp$nFcQSvG+w=7ZeU0SZ#+%D!nrsZ}0+Q;%1EjNCzLoC0p-k_mvz5 zT`N?<=bEthP$ie+8ZO1D4a4iQ_NKoWp1e`^NVtcb4Nw_HZ5~U zMR`*!W6j1b5exo{1=!~DJq60|XqlTt%I|5pMazHDGWUqY`8AQ$->v1Zw2UN)aeikZ z@r;%`Q4Ud1qYJueLamm2YI%j0kI{0AmIrFNRm=SHwb%hIkJB=DNOW+bmbpWsJPmS4 z1#Xd8aFH0$@*FMKU`Ir}S(DE!T^Mr)>6{4@@yG38iTSQ;U zVektvfD;cI;M>8m16uBbxBe*egoOBXE%Stg@^`h&6B5dswagO|%6mj#%cWRx#tn#N z^nXuXz#|eW4AnA^NGR89nI|NaLouM`dqf{69>kv(eJ#H!`dWTR^eJ=C_*XH26Av1w z#O5Q8fR>NfGEYc|Pt)>#EjMbJCnUtbEBab~Q1rF@g6KmIsqmH>mmRD=}yIOA1@_ky~ zpyije+^XdrS`N4Cf)8}TZY_7g=YZ+Jek~uXM$2opT&?97wOpg+Ur-KF;bdL#Crzl; za(PeXP_vc?YI%j0Cun)KmS<_XMa!XT(rU|>X{97&W*Yd|& z4w_U1N;AsA&RWiBIiuy_TCUdenOd&Va(#yLKO>+EmTN+-mT%Q^vzFIud4-m@YI(Jm zcWSvs%YV`G1}%5(r5tY6a{peTD%h?I#%aQCEuXLD{aU_M%K_eaC<^e0kG0%c%j>nA z(eh8VT&?B(TCUM@`w#~faRhY15tMPdRjcJ=w7f#ggSFhE<#AeW)$&9w^PP_(I5=JS zc%y=Hlkl}1ep?stoeUE0&@$h-p!}qk`Njj~ZCb9;@=h)DeFNg}X?cZ~zYzIqg?H(r z8ptzc@WbF}DfqS`j23yNlFx>W^WdQ6CMC0y+5Dle1;A&EfZyM@nzq>VA*r?VJ)-tp!iY#o(4p6|YtEwp{_F7+$svZJQ%7wRG z^Y)kM_P!o9kSFEB+ogE}wY^>Nk31Nlc&Q@R}^-i-E7$6sS%HRxbaP-V*J$X_tJUQ*)=?9y#|C(qYc~UMsIR)XV2zkrzj;hupG*T|S z&1LFz7qbz-!SJSi8R9Lw;S zh7Rs|A*y-|JSi96Vg1!<%!%6GVf~{9@}yjNa;n2)9@^VII9gAhlnYNzdwBXo-m)># zKJuhoc-tncdMD_5w@r?!9tTg#g}3Zt#rwJB>cvq5c~UMsIaT5*6YFhR60Ijs%7r%p zNzeOtw7m)6kM@x#<-%M3vf_QFb9(v9QPmURNxAR>9Od(VE`G4y;Ez!QczvW?cr$RK z&HMW`4|4R_6G#LBgt%?8B0eICFge=Ciltn5kAI|i*J|G5A4OG9qGBl*-h}RLqe^c#HUce9=UF0 zw2wR~7v7c$idU!YZJ7{NZ2(Wog|}gn;w{v?4U?h<@}yjN$2_Qbtdp-}9*owLC*{JE z^G=?Bl2@@g+DD$03va?tmA%0zAaBA?qpGLClXBt7c`46N$y?ViY9LR_h1cd3b*@^B z0`l6N60Ijs%7u5~YQ^iSc^9sZ_JP+&%7wQAe>;`;{J(>=2RZ8ZGzN14gxJ5EB2Lpp z$kBWf1rTD_K8pBr9cjqXV<7exK!`&|DB?3ZWrmE1_C1ZJNV)Jf&Q`pR+Th07QPnfx zNxAUkh?z&uY)a$zq6YB#NV)JvtXB4Zi~{l?NBtf`O9T+&1Wm-*c}#>H%_mU+Ax_oA ziSjVf;=^dN077im#0Pa#npZ~+8_^Ug7oMDs^Rzs6ab2_?ygpJcyzRxMaqqo{0`ed$ z4+Rk7E=~NFt{8IE?^!fO03j~xqAcF1iIAiDAodnOh&%cz;%z8k)jRq{>z_qaq+EE7 zBNVTfj!h$anLH^MUW?|{w^R07MnqN5fhXm{+jgR|_XEw_c4E{(o|Fr3=Shn9u;%SN zDOyjSlnZa}c*VP3^X86^_K_#$!dr5R;_cVGC8tDHo4}KD;cYxs@wRE+##5sP@}yjN zEoUg+0L^PTBU(?MlnZb4WW_7iywQ^tPs)Y2bE@KX)4ZKiqpHnF87UWDoAVWKx}G2) zNAn*;2MZv?H|rGf7)^Y$E?Q56QZBqz^@{gj7)6)}kfZs}z@Pv^oYAO=O`15PF{*kV zEtYcOwJcUVtkYwIEsLWD@}yjNbC)R|GBxJST^6k;Ps)Y2d6nYL)(zRbD%wY$lnbx9 zMe#z-Yi^0EUI0(Zg}3vE+CRr(*qIrF{M(fFwa^cndLhDc&?~Z{_cz2J)m_cx!em-mJDNert9|>&cUH z;m!Vw;%(ISX8$GHN1l`mZ^GXc52rzKe@ysWRJ8>>DHq;`FBGp@*Sq11r~$k_QZBrp zs4O1b#%mtr=&>yrvjh<0)OL!P(L~76`y>h=#5L^|akcgka`gU-APOMF<((AqQ*9A) zH2)=8Bm2vL-B z;q5wH@djvvyAF@mlPBfETYHq^P1p9;9u@5)Ps)Y2_XNcordzW2gsAFe@T6RL8_rO? zHrn2XGol9aq+EETrz+km%^N*6T2G#o3$Nl_#lyNV&YFsIqkZH_x$st9pm=LFZ`B1+ zRV#Q>F1+rwiua=Cb+3&Y$dhv6wbUuzw=}N>!y9>0F1($WDBiWwahF8<$dhv6?O3dM zf7JGNERL$SBCDlbcq2l^!~1J-dm%^jv3s5=fDretQpAI_L6M2~#j6#^!n`P-i62Rv z2U+VLQ~IX?=eWG?v1lJ0>MiBeBX7^siZ@F0_B$kMN?*ijp|><+BX@Yy%@dwJ6&6Dk3lC z)FV$m;=s>5kk_>$s(KAPDHoo6^no9RAaC!XQ3H5=q+EFNkqCZ7f;`C4`&{G+AVm4B z1V1}LBIJ0z8VbMe`f^zaR6h|SNwfZv<{0s%<6&4o8KsOeLNY=UQhAb*y;t_E5Fwk2jARrUAxem{A`Kb!eLRlm^Zh=Zzka{Z zv9%blI;MWs46!`T74h4Qa$_SJw@EZ_F6!;AYBntcn1QG>)0|JQx zzaC}iP~g`SI28Ex1P%p${T3s5i2}a?fkc7d0F@-5M1kJ`WhhbLH$WLm6!`ThLx%#t zp1`5NuP1OQ@aypmUVkW2;5Q(UDDWE)NEG-D2qX&p1_TlXem%<2p}?=dxYeeD4h3ZR zYbNk3FLWp%mqG^T$3ck#4!~bCffJxa0hv&ufJ`V+KqizZATOa(1#~Fz>rp2HIu!Wz zC_{$=zaB8&`hXGzegkv@lqm2U5J(jG4G1I({00OP1%5rs(4oMuCvYh6>j@kR{CWq} z`hXGzegguD0>1%)M1kLcK%&5JKp;`z*AqAt`1Po=038ZG&|P*#89Ee@eVvf4PdSt* z;6OAw0ZJ5*2_*{1rRZ@eQ9ve?C?NNs$Du<3nb4ttyo4Ty4h3W!f+_`2qJRVRC_{+? z@_v+|L;+bGWhhZVRzVp`6p-~%h7JW}OO&BQ0ofI0=ukjLe9-|YQNV#{l%YfcISXYd zQ9v$58A=q88&QT51>_!-p+f^vtZs3a!G@%osQ654$3+1mUm!b?M3b?)zWnq+iP=*c# zJU)&xbSNM%p$r@f@ckbQ;814)N)(U@B?`#<(c@5}fJ`V+KvqGI@8sG#u8%TwDENpR z3dp|b@k3n5)`To{07?{aLLsT4h5e5w~j-H0?)x)3>^yaD*opq zX{m>X8Nupj@CucV1YF3WSFGS2if62zBZ4wkaex<)a6We72roP#V;7u8C}VY~3n*h1 z5SJ}Ra9Ba`HZ}ph1czlCxFJ@p$v_z^lvSXN6{cVT5zfa7hr=jig-O`yhR3l6_YXXS zHv!fjgiRJW0c)kAY;uT*yMqXHFscB1v1u4fxQ#RSjz;q8zEzDMyPbq z!EeHt%KUJP6O;C zAaDTdAACnA{71IfwzUA07GO^X&c}K&u++nNI05YZqKzRf*CXK*`HDs(&4I0S^ zegNwr!&X0>fVKExpARzD--G=;$XFi_HaH+-eGS;hfQ+>-VCMxg)^ULr2xQFuXxj!} ze>l+Cx^;mM+gOmX?iJK1AY=LjY-B>l8kn%9k6(|r_@M>^8Pi{&o&p)uQea;MGS&}~ zM9=}ugHc8q^GRTn2`<2TORzHw8SBWx4lHD>^9nn>`1xqZ7q*%qV=ZRrk3hz}5d>Ne zZ~&7VU=JHI*1LxNI>=a`4$2Pr>_$Pxx=^s|1R3i#!LAl$ted5QXQ1nW4={|c!NKEL=?!-M@bl%s z|E>d0fK^5~fK?HpjRzUC@L;SORwQghx#0@< z{DW~E?BBr&Sl8@a3d3FsusN`~Pg0PQ)cd{FI1aBry!r>?8S_qze9nFo2U1J~fCJy}{&_+SS4-oMo zA_m>zf1dCeBDN#q8-xu1%7+mS0L~y{&~*Ig1ocGRM#TL@JVV5r1PsrQW1{@`1gu0X zNW^kPtU<&^M0|;e-T%w@^W*&fI{=>#E{TZm5pgvUzaZjaBAy{)&<;R9qg&_4;XtvG z@NWSP5wjC9EKU;6mm^|rA~qvpSB$aq`(Ok3KR*r^LB!y<(f&E%Ln5vx;&vh)A>z*{ zW9P^HCYnGE%BA2>2)=e~eee>oBoV6;u|5&sBI2|yM*eexGNK7DhxlR{5w{cZYa$*b;<11D6b?7}&j1cL zOT^1Wyhg;^LA#Ie6Hk@YG!A|sU?&>pOCtFQzJ=?7pGl)Y+&~V41c5|?$bvY51c3N} zFo3v#*n(UJVFuv@5dd)qF#tIL!VBU7avLNVmJ zh!O}Jh!99BNE(PJxXB0Z6nJ0=;tjG7WIsqENCHSaNH&N#hz1C}M1YqCnjl6XaUkF} zHMkUzbdV&FYamxZ96{JYGC+=j#DGMAIDni7i3U-Fe+q688IVknJs?&f79esUk|5?F zdqK28TtQBQ$b*~!F#$OWava1A#1iBjh&4zoNFay;h!%(r2ouOI5IzuiJ%liVfAN4E z1mOTN2007D0^$jx2yy|06+{>WUIh7pTmtb0@dEk(@*eUB^Xx!;Ko~&K_Y(5Id^7zY z-b>*1|KGit{txdZ`1=3P-b`Sx|G)1gMDUOCH`%~H!r%1+{|MgrBZ+T;=HSt-8*XgP*?PP+YwI!o1|b$(_u|-^ zv-Nmu&emf%r&@P`MsjCT<9C{!Nq4`~+)COLLBoDnix%R1jXFr82b5@cc7p)}%?!vlaQBv~MK*!GC>CyrA=4Nf_ieIt{YMAI%L_vNNFUr1nUR;`!xG^cw6S?grgA+K@DnI>Na|eX3kD9uW z?qnnVYHqlTNv|J?=Pd=v;GdN~rW6Nd7FOj|Ckq{XI=@>-8?!nI-CjTqtcSf(*Fghsg zcW2JJo|%7z-CfQ*xTfZ%$;TYtLq>U_2As(rfz?h$SFLDgOIq4ncw=iVy8V$eTIy~b z6CIm=Qo;{zi@GS+NLNmCXDu5iiZUMP@p2uZelktxAxcu2dXHn@4V^}9tz>83M;~eg zN^Rtotv=d)71uQn&svh;UFN6lBO zeBe)@tX4TXYin4*R4G=ue5^Dz90|MNV=*W{F{5-Tnb~>ptTXl1Vil4CM1h}tBaQvg zl8>R>POGY1@sj~dl272UXvm@tlfaLC&zD6T?V+t_= z$`51%4o68+8d)og!Hsw5G~caP3RW{M@gjcwR-Oi+w zu81&apO+FhyKp4;^G&Nxl?w9X8pyp99*(q4MP-W9>SS_7oM{7k)pC^T=3?S6e>QY5 z4vkD2d;g`BmEO5FsN<9@yYS@8ar1|L=4Ty#P$m`y=KX#xy;JI!&TX@hpD(z&oYJzV zBGTNQ|D=WGl8F6zZZ0j*vKc785iNg}%jA_kay~SZR{zzdjMD+*VB>saZ+_IId!?U$eVCNp!Qh#+b!55cousFlPulscAFhvGqCMmSSXnI3IND{5 zUVcC^hbzw?laD|G&}P4Wiq<>$;jLA46qIN?^huH3&Co^rU#**j6+<^nZ5 zeM@9@a&8)YdFbljU^MY5nDZ>lUgHRL&9R2GojR%lXCwVGedTOrC^UfRVhcP>+8 z;ZVoam-<4hkddCz^geqF8``AE4_D;1!=w)gMEzNvsb>7ssm6K2{o(W|7u|8>`rafn!QN}@ODeK2CL%I*qjCCNpZe{#B#CwG!gu}UuA-$ts$%FZe zjBfEf@11uSbF#aC>;qbG>pQhP}+&(>_th(GRn{Oy~!$$CyP*1pmfP&rE)knUbXMnSd9kSuq| z>d>x!uU=$>oLZ~%nrBg@?fLP#Cu}~{<&)GS7kv7dLv_eJI;RHgcttPMm55(DDwR)V z|9%i>`F=h>d}!Dv;NYc-p=)AK+#c73}>( z4wj`TZ7)q)-8~{@efFr5%oFpKu7|2gZNXG}U3FAij0nS~YzF6;xNbt6DPnTpx+e zhjUgc8E3siuF2Dry>%+7ZT6VWndHCxrlnGSQJ|)?ao9D@x!}T3Y`EZYZJKW0>m5$9 zj*WVxC0{RlI=js3_7w!{>@^9Admwq=$R2U|eS3iP${rzwGB?rb)T&|}RI6?J#yt(xHJ^;**_xz+hhJBpjx+4s z$jmA`t6+Vb?XBkavXG#Jhq1V9^}CnZu84LSv)_Hw+&=dDTfnM@2lZ6G<9ow6E2j(Z zz9z;-j=6W{UcILRe8%RZzUklc5K_I@t~S>` zQa{ERQKiA~_pg=NparX5=z@t=n`X~0U%QTP@9nxze(4!{k0>U)Cu=y>jrXeEx;51; zUFX9<-CJ#aYw1U{bG-GHKSNQI*@J)ga-_se1q(M`+_C97JzT;;d269aW1q3(y}%DV z2|N3S%V?;rdDUmn{lBLa)~b((q}0kAk@JeT>z+=x zFBw;pq?b&oR`PDNpaI9+^5ru9rO6F{yO4&;ppkL)!QDFDPC-Qhc6~G#=R+UAYprWLheHQ zNA1C1i<-sv#z;F-Nq4j?4dq&su=Tqsc>A42DoSY24uiXcR`L7s>>Z1~@@geb*0c3` z!KjZ>kJjS8eb4w}J|lw^>p1sp1wABo-?1RxMtg;+9fy6~JJxmUuW5g#oz<}oX>_rj zAN0`gwi$TDc}Hz9kzWImV-FEIRJ3xCy0yyXbFTJtXZ`gfT(U~HN3R;#35RD=<{6S6 ze*4!|p`29E!Cy%Dlhac{sUL|?_n!Q|n^T}`o@DBjVdEg3LauTsQZOab8x$_7TrFkp zB=p2re<6hLQ!4YD^CKP(^t&X<$Q#Ux`3wrPH_pB67B_aJmvhS!{TiOr)W5=fpR0BF ztL3J9afD=ZgT7|NIqB4=#m9y&Ygt?UaJN6&D!hAHqOsJWHT4dyRR51l!!KT6_uicu zThU6DlcCg^>NxBhYj6pfE@^NZrZsxTU0cc&VJM|!d->q6nN6{e;bWD#lZNXTL{3ev z2QOSPUtd<2NulvHIXHSKazDqgEBDN>zH$&PwX99RjvJAzrQ44RP7R86-S43sI8__r zd~D`fT2JQOQ+kqfyZre#MLs(84LQ)Kq6R+=qh z>2ElsE0)b`FHn2?@zo|S?|1f#)S^^#SHEeioys?q@E|2qk)>e9tvl9Zf7LY`wp--t zzN;2R0T!=Lw%4%-C2FxzA~ku@UMX+8KG(%>e=tNhf%Bfz)-9ppcN?!twGA!&>q5`c zHnMx;eTsY()kf2RH0zBIp?9b9?_S>g`!bQOJ}mP}!ZERTcCzW$`s5`RV_N;rYy`Y) ze9L~y+P1OT(s(Ec#a`qDl5D{gDst`*YywOk~K_hmZ2s5xUXf#t$t+ z4viP$BFgG{#pm1=GwzrlbJ2O>I`gb{sq}R)@A{2xb37|Ffj(7cdk-tBA3LKfBmJO9 zOm5ojxPV>YP)TZqc>quUF7`&GWz3$Yl6^ZEK~jZbLy=9`)JFq;&*(yJR+?o)DB zdiGfi@NWp}o}CYgzSifoD|1k;f0B&!%%|a(DYrLj=QX;W3QiS#x=EU4I(8G;_T%hM z(eQ!(u{)9UMJ1oab>7r`xGE+W-uNuzwvX4wW?fL+Do=`*uoZ1IcYQqb+DYE%;RuPj z!WX%%Y8|sv-sgg@?3T2S=$zJ#DT!}m-FQI8$&J>~Ca5vk}e_uvLGks$V z2+7v4LE>enaQrt;ial{U@3{)At4~*5Zu)!ech-{UbuBR%v}#Jw=uNDtMXb68 zSDa+0$+gwFgB+yS-u7`)K25Ltyyr~F&iea~$6MlUB_8$fIa3$?HGTU`7R6i3!z-pL zB7GJsVQmrlq@QAH(wF1D9-a0Y6tuk7WGTRM?4H;Omkaxh#_oM;Ws_;lI?{UlqJ?Jc zddmD|zxzgxuf81R(<6%*u2fz*85LS(h?ENbx;yx+~*9+Zg{%o3YSOWU3B=la>7KEJdk80jmv zht_1r+sR8y75P#{`KjV|>{n$u{rUFF)8;wlL7T@4&63<%oa^BN%6a2KO#}4)^LK{6 z`Sd782)OvPb(quKw&lI6+uF@NsHZ{unR$Z=`75O&XmNw3G3p@s+6T&Ban_tM@%r?J zbCj+YKXdqIJJ)wnu;oY8y^`K5cU|?1&gryIXYYkD>pif^zqh>LJJ8gkcHr(sAE)bk zJR{SO$XJF^p1MYH|4zmdZ`Luo&R;soI+1%vwffY|<8P+=xOQ9l6epTG505f){T>nB zl|NjK(5odoB({prPWc|550iIv zxv&=Qc$|WS?J#vM=dIBYsy{qwU?#83{o;cT#59f~^Nk>vssn<){kxbGOCZvKb=f%z)%8CVr=~9*D-x}JJ zf6mv*)7M>LI4t$ddu1{60k2w7lI%=f^21p~isO>NaXpRN+8^x&ZpssVmW{WC=n`+) zAK4N5^Ici-zSmWxf^pY!~|w?DZ$`wFil zzhdtZY@Nxwg?JqKG?wJ!(yKP?aDajA+UC^l#vzibO_7k)XKNy?MQ5I}>UmX+%X&p; z{??Ij|1GD_SV8r4=n?&>rq5WQidsya_cwiUCykBZ)47dzKfPBa+jI5wj)~pl;fnWL zd6D;w0zdSB?%AQZIjgpt(=ak-bn@@mTGs*kUOGn>tO znW@j!i+$fil#s{=$8PHEBr`22WauOR{IJ2_!7f1l`I957`sXJHWE1Sy^?h{rZC`Nt zLG|g&Wz(-0ziv2-<-GEHC6Sf3ci1>{xpC$$$;8Kn*PX#KXUjhMKX2LNlv$O?CUBsl z_QfY5F0PFOVlvP8B2!ae`|ioeZ7lWrOyXW;%AZLxv3iHn-Dxz+f&`{CsCHRd3p_EA-L`Z~J!I1Q;RvT(Pqm+!(|v1l-lK)CFRALH zDhp)p-Au7;Wv_Bbz}|wwzCU$hZ@{k8GByH(SK^4wuU0eSFOsnVcZ&q^Y}f)Q6f{ z;`wXx1L5b&51ij_a%k1iM>TSfn|yS3Mgu?VYbnaI5vd9OnGdG&ZoDikCt0*c{}fEG z%Boxs*U!pw_xHV=9dk1OYtVazZ_@?R5_)SU0b)!Hk5=`K^o#GD4a|DOtR_U(vRy`# zxl8TvaJ;kLh3}7Dn#p?9;^=%EWmPZHX2oUhzi+wwL8>5y)ABr}{7b&AntJEv+jJ8f zh4#OLHOE|xk1oI5+xxuzh2Y!nbDRUoenu{?%l(IL%}0N=+sEA{+Hh?C%zYMP(gq67 z;Nj5phhKA--Fe>r4j<0{v-bHUdCZ4j&o_PuPAeR`A*9u5Hw5BmSzMo2c?%zj)&0&pSxP>oc%^gTu<%Ux-;rX`6>b$9MVhu5#NFhQ zb?woqiiw$QI~gUN%^N7cYw{*Z?c1n7Z?hJ9;DRVG#NZ$<(m*BzmNR#jV~`hl+LQ| z;O%U7m}5mca!ezoPmu*Ip3WP6FKp0*JQqEEH)q1+Z(UJnqiVz(Y7*Y8l$2{MDn2`R zT$a8|F~|~Of2&WXYUor}uDYOc#l`^zY3;fc`<)_u^B>LJU$1jIk0&u&W%AvZRhJzU ze0Oba_P*T@`=0R0=M8%r&K&%+)5TwNI|HSM0oTR`pO)Yd-}K4;Xzq}VmyG$!wJLiM z?N4oXw1Q)gUdV*-OUMOTF7X5(O!r?wj^^!9JHS0{b%*clz@ZGUrY!yi-uUD4H!BKP)2S&a7PN1U3twR`@otTnU43EuDOoe#Q3 z>cepFJAQrqtk(0`M`e?)AR%|UrtLiq&jj+Eok~z?CDm%=y3u`y->%l%-|k~`Hu`F-1LVXQH9rMsE>@KTX0(E zHPv<}Jqa;O__@|Ybw2Uzw!g2230k>8<=*VC`eW*p<=vg>=%>!4-SnLAyUD>Wjq zj+CTlUsJEvnux2_T%_73;HLXU@&)tI2KU!SQS;5JRYu$au9!?Ok=74IbDY9yWt&D{ zIfif-X}k+7r@GuMgU|hWb@i6J+xPt=^LI2Fr7qNkwA5UUdK9K$+ZJOu`|w3^k0+_R zgIv^QpB_K835T~S7(!{TnXPf34$ zpmFZ1~vXIs;iU=Q%?TlkOv2YJxB A_y7O^ diff --git a/bin/game.dSYM/Contents/Resources/DWARF/game b/bin/game.dSYM/Contents/Resources/DWARF/game index bf36eb92363cc721a10ef7427b055c5cde1729a6..63028c3af1fe4797aaf932a31fb5a7597873acc3 100644 GIT binary patch delta 38675 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
&RmYR-(OM`d-e^bIMZ^q85WVaPg4 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

(Mf@5-T#0tPMFcS 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 aflt~Qc)?DgV%4Z5^8WuT&}*S09p^u_5EoGZ delta 36803 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 StatusBar, Panel +* - GroupBox --> Line +* - Line +* - Panel --> StatusBar +* - ScrollPanel --> StatusBar +* - TabBar --> Button +* +* # Basic Controls +* - Label +* - LabelButton --> Label +* - Button +* - Toggle +* - ToggleGroup --> Toggle +* - ToggleSlider +* - CheckBox +* - ComboBox +* - DropdownBox +* - TextBox +* - ValueBox --> TextBox +* - Spinner --> Button, ValueBox +* - Slider +* - SliderBar --> Slider +* - ProgressBar +* - StatusBar +* - DummyRec +* - Grid +* +* # Advance Controls +* - ListView +* - ColorPicker --> ColorPanel, ColorBarHue +* - MessageBox --> Window, Label, Button +* - TextInputBox --> Window, Label, TextBox, Button +* +* It also provides a set of functions for styling the controls based on its properties (size, color). +* +* +* RAYGUI STYLE (guiStyle): +* raygui uses a global data array for all gui style properties (allocated on data segment by default), +* when a new style is loaded, it is loaded over the global style... but a default gui style could always be +* recovered with GuiLoadStyleDefault() function, that overwrites the current style to the default one +* +* The global style array size is fixed and depends on the number of controls and properties: +* +* static unsigned int guiStyle[RAYGUI_MAX_CONTROLS*(RAYGUI_MAX_PROPS_BASE + RAYGUI_MAX_PROPS_EXTENDED)]; +* +* guiStyle size is by default: 16*(16 + 8) = 384*4 = 1536 bytes = 1.5 KB +* +* Note that the first set of BASE properties (by default guiStyle[0..15]) belong to the generic style +* used for all controls, when any of those base values is set, it is automatically populated to all +* controls, so, specific control values overwriting generic style should be set after base values. +* +* After the first BASE set we have the EXTENDED properties (by default guiStyle[16..23]), those +* properties are actually common to all controls and can not be overwritten individually (like BASE ones) +* Some of those properties are: TEXT_SIZE, TEXT_SPACING, LINE_COLOR, BACKGROUND_COLOR +* +* Custom control properties can be defined using the EXTENDED properties for each independent control. +* +* TOOL: rGuiStyler is a visual tool to customize raygui style: github.com/raysan5/rguistyler +* +* +* RAYGUI ICONS (guiIcons): +* raygui could use a global array containing icons data (allocated on data segment by default), +* a custom icons set could be loaded over this array using GuiLoadIcons(), but loaded icons set +* must be same RAYGUI_ICON_SIZE and no more than RAYGUI_ICON_MAX_ICONS will be loaded +* +* Every icon is codified in binary form, using 1 bit per pixel, so, every 16x16 icon +* requires 8 integers (16*16/32) to be stored in memory. +* +* When the icon is draw, actually one quad per pixel is drawn if the bit for that pixel is set. +* +* The global icons array size is fixed and depends on the number of icons and size: +* +* static unsigned int guiIcons[RAYGUI_ICON_MAX_ICONS*RAYGUI_ICON_DATA_ELEMENTS]; +* +* guiIcons size is by default: 256*(16*16/32) = 2048*4 = 8192 bytes = 8 KB +* +* TOOL: rGuiIcons is a visual tool to customize/create raygui icons: github.com/raysan5/rguiicons +* +* RAYGUI LAYOUT: +* raygui currently does not provide an auto-layout mechanism like other libraries, +* layouts must be defined manually on controls drawing, providing the right bounds Rectangle for it. +* +* TOOL: rGuiLayout is a visual tool to create raygui layouts: github.com/raysan5/rguilayout +* +* CONFIGURATION: +* #define RAYGUI_IMPLEMENTATION +* Generates the implementation of the library into the included file. +* If not defined, the library is in header only mode and can be included in other headers +* or source files without problems. But only ONE file should hold the implementation. +* +* #define RAYGUI_STANDALONE +* Avoid raylib.h header inclusion in this file. Data types defined on raylib are defined +* internally in the library and input management and drawing functions must be provided by +* the user (check library implementation for further details). +* +* #define RAYGUI_NO_ICONS +* Avoid including embedded ricons data (256 icons, 16x16 pixels, 1-bit per pixel, 2KB) +* +* #define RAYGUI_CUSTOM_ICONS +* Includes custom ricons.h header defining a set of custom icons, +* this file can be generated using rGuiIcons tool +* +* #define RAYGUI_DEBUG_RECS_BOUNDS +* Draw control bounds rectangles for debug +* +* #define RAYGUI_DEBUG_TEXT_BOUNDS +* Draw text bounds rectangles for debug +* +* VERSIONS HISTORY: +* 5.0-dev (2025) Current dev version... +* ADDED: guiControlExclusiveMode and guiControlExclusiveRec for exclusive modes +* ADDED: GuiValueBoxFloat() +* ADDED: GuiDropdonwBox() properties: DROPDOWN_ARROW_HIDDEN, DROPDOWN_ROLL_UP +* ADDED: GuiListView() property: LIST_ITEMS_BORDER_WIDTH +* ADDED: GuiLoadIconsFromMemory() +* ADDED: Multiple new icons +* REMOVED: GuiSpinner() from controls list, using BUTTON + VALUEBOX properties +* REVIEWED: Controls using text labels to use LABEL properties +* REVIEWED: Replaced sprintf() by snprintf() for more safety +* REVIEWED: GuiTabBar(), close tab with mouse middle button +* REVIEWED: GuiScrollPanel(), scroll speed proportional to content +* REVIEWED: GuiDropdownBox(), support roll up and hidden arrow +* REVIEWED: GuiTextBox(), cursor position initialization +* REVIEWED: GuiSliderPro(), control value change check +* REVIEWED: GuiGrid(), simplified implementation +* REVIEWED: GuiIconText(), increase buffer size and reviewed padding +* REVIEWED: GuiDrawText(), improved wrap mode drawing +* REVIEWED: GuiScrollBar(), minor tweaks +* REVIEWED: GuiProgressBar(), improved borders computing +* REVIEWED: GuiTextBox(), multiple improvements: autocursor and more +* REVIEWED: Functions descriptions, removed wrong return value reference +* REDESIGNED: GuiColorPanel(), improved HSV <-> RGBA convertion +* +* 4.0 (12-Sep-2023) ADDED: GuiToggleSlider() +* ADDED: GuiColorPickerHSV() and GuiColorPanelHSV() +* ADDED: Multiple new icons, mostly compiler related +* ADDED: New DEFAULT properties: TEXT_LINE_SPACING, TEXT_ALIGNMENT_VERTICAL, TEXT_WRAP_MODE +* ADDED: New enum values: GuiTextAlignment, GuiTextAlignmentVertical, GuiTextWrapMode +* ADDED: Support loading styles with custom font charset from external file +* REDESIGNED: GuiTextBox(), support mouse cursor positioning +* REDESIGNED: GuiDrawText(), support multiline and word-wrap modes (read only) +* REDESIGNED: GuiProgressBar() to be more visual, progress affects border color +* REDESIGNED: Global alpha consideration moved to GuiDrawRectangle() and GuiDrawText() +* REDESIGNED: GuiScrollPanel(), get parameters by reference and return result value +* REDESIGNED: GuiToggleGroup(), get parameters by reference and return result value +* REDESIGNED: GuiComboBox(), get parameters by reference and return result value +* REDESIGNED: GuiCheckBox(), get parameters by reference and return result value +* REDESIGNED: GuiSlider(), get parameters by reference and return result value +* REDESIGNED: GuiSliderBar(), get parameters by reference and return result value +* REDESIGNED: GuiProgressBar(), get parameters by reference and return result value +* REDESIGNED: GuiListView(), get parameters by reference and return result value +* REDESIGNED: GuiColorPicker(), get parameters by reference and return result value +* REDESIGNED: GuiColorPanel(), get parameters by reference and return result value +* REDESIGNED: GuiColorBarAlpha(), get parameters by reference and return result value +* REDESIGNED: GuiColorBarHue(), get parameters by reference and return result value +* REDESIGNED: GuiGrid(), get parameters by reference and return result value +* REDESIGNED: GuiGrid(), added extra parameter +* REDESIGNED: GuiListViewEx(), change parameters order +* REDESIGNED: All controls return result as int value +* REVIEWED: GuiScrollPanel() to avoid smallish scroll-bars +* REVIEWED: All examples and specially controls_test_suite +* RENAMED: gui_file_dialog module to gui_window_file_dialog +* UPDATED: All styles to include ISO-8859-15 charset (as much as possible) +* +* 3.6 (10-May-2023) ADDED: New icon: SAND_TIMER +* ADDED: GuiLoadStyleFromMemory() (binary only) +* REVIEWED: GuiScrollBar() horizontal movement key +* REVIEWED: GuiTextBox() crash on cursor movement +* REVIEWED: GuiTextBox(), additional inputs support +* REVIEWED: GuiLabelButton(), avoid text cut +* REVIEWED: GuiTextInputBox(), password input +* REVIEWED: Local GetCodepointNext(), aligned with raylib +* REDESIGNED: GuiSlider*()/GuiScrollBar() to support out-of-bounds +* +* 3.5 (20-Apr-2023) ADDED: GuiTabBar(), based on GuiToggle() +* ADDED: Helper functions to split text in separate lines +* ADDED: Multiple new icons, useful for code editing tools +* REMOVED: Unneeded icon editing functions +* REMOVED: GuiTextBoxMulti(), very limited and broken +* REMOVED: MeasureTextEx() dependency, logic directly implemented +* REMOVED: DrawTextEx() dependency, logic directly implemented +* REVIEWED: GuiScrollBar(), improve mouse-click behaviour +* REVIEWED: Library header info, more info, better organized +* REDESIGNED: GuiTextBox() to support cursor movement +* REDESIGNED: GuiDrawText() to divide drawing by lines +* +* 3.2 (22-May-2022) RENAMED: Some enum values, for unification, avoiding prefixes +* REMOVED: GuiScrollBar(), only internal +* REDESIGNED: GuiPanel() to support text parameter +* REDESIGNED: GuiScrollPanel() to support text parameter +* REDESIGNED: GuiColorPicker() to support text parameter +* REDESIGNED: GuiColorPanel() to support text parameter +* REDESIGNED: GuiColorBarAlpha() to support text parameter +* REDESIGNED: GuiColorBarHue() to support text parameter +* REDESIGNED: GuiTextInputBox() to support password +* +* 3.1 (12-Jan-2022) REVIEWED: Default style for consistency (aligned with rGuiLayout v2.5 tool) +* REVIEWED: GuiLoadStyle() to support compressed font atlas image data and unload previous textures +* REVIEWED: External icons usage logic +* REVIEWED: GuiLine() for centered alignment when including text +* RENAMED: Multiple controls properties definitions to prepend RAYGUI_ +* RENAMED: RICON_ references to RAYGUI_ICON_ for library consistency +* Projects updated and multiple tweaks +* +* 3.0 (04-Nov-2021) Integrated ricons data to avoid external file +* REDESIGNED: GuiTextBoxMulti() +* REMOVED: GuiImageButton*() +* Multiple minor tweaks and bugs corrected +* +* 2.9 (17-Mar-2021) REMOVED: Tooltip API +* 2.8 (03-May-2020) Centralized rectangles drawing to GuiDrawRectangle() +* 2.7 (20-Feb-2020) ADDED: Possible tooltips API +* 2.6 (09-Sep-2019) ADDED: GuiTextInputBox() +* REDESIGNED: GuiListView*(), GuiDropdownBox(), GuiSlider*(), GuiProgressBar(), GuiMessageBox() +* REVIEWED: GuiTextBox(), GuiSpinner(), GuiValueBox(), GuiLoadStyle() +* Replaced property INNER_PADDING by TEXT_PADDING, renamed some properties +* ADDED: 8 new custom styles ready to use +* Multiple minor tweaks and bugs corrected +* +* 2.5 (28-May-2019) Implemented extended GuiTextBox(), GuiValueBox(), GuiSpinner() +* 2.3 (29-Apr-2019) ADDED: rIcons auxiliar library and support for it, multiple controls reviewed +* Refactor all controls drawing mechanism to use control state +* 2.2 (05-Feb-2019) ADDED: GuiScrollBar(), GuiScrollPanel(), reviewed GuiListView(), removed Gui*Ex() controls +* 2.1 (26-Dec-2018) REDESIGNED: GuiCheckBox(), GuiComboBox(), GuiDropdownBox(), GuiToggleGroup() > Use combined text string +* REDESIGNED: Style system (breaking change) +* 2.0 (08-Nov-2018) ADDED: Support controls guiLock and custom fonts +* REVIEWED: GuiComboBox(), GuiListView()... +* 1.9 (09-Oct-2018) REVIEWED: GuiGrid(), GuiTextBox(), GuiTextBoxMulti(), GuiValueBox()... +* 1.8 (01-May-2018) Lot of rework and redesign to align with rGuiStyler and rGuiLayout +* 1.5 (21-Jun-2017) Working in an improved styles system +* 1.4 (15-Jun-2017) Rewritten all GUI functions (removed useless ones) +* 1.3 (12-Jun-2017) Complete redesign of style system +* 1.1 (01-Jun-2017) Complete review of the library +* 1.0 (07-Jun-2016) Converted to header-only by Ramon Santamaria. +* 0.9 (07-Mar-2016) Reviewed and tested by Albert Martos, Ian Eito, Sergio Martinez and Ramon Santamaria. +* 0.8 (27-Aug-2015) Initial release. Implemented by Kevin Gato, Daniel Nicolás and Ramon Santamaria. +* +* DEPENDENCIES: +* raylib 5.0 - Inputs reading (keyboard/mouse), shapes drawing, font loading and text drawing +* +* STANDALONE MODE: +* By default raygui depends on raylib mostly for the inputs and the drawing functionality but that dependency can be disabled +* with the config flag RAYGUI_STANDALONE. In that case is up to the user to provide another backend to cover library needs. +* +* The following functions should be redefined for a custom backend: +* +* - Vector2 GetMousePosition(void); +* - float GetMouseWheelMove(void); +* - bool IsMouseButtonDown(int button); +* - bool IsMouseButtonPressed(int button); +* - bool IsMouseButtonReleased(int button); +* - bool IsKeyDown(int key); +* - bool IsKeyPressed(int key); +* - int GetCharPressed(void); // -- GuiTextBox(), GuiValueBox() +* +* - void DrawRectangle(int x, int y, int width, int height, Color color); // -- GuiDrawRectangle() +* - void DrawRectangleGradientEx(Rectangle rec, Color col1, Color col2, Color col3, Color col4); // -- GuiColorPicker() +* +* - Font GetFontDefault(void); // -- GuiLoadStyleDefault() +* - Font LoadFontEx(const char *fileName, int fontSize, int *codepoints, int codepointCount); // -- GuiLoadStyle() +* - Texture2D LoadTextureFromImage(Image image); // -- GuiLoadStyle(), required to load texture from embedded font atlas image +* - void SetShapesTexture(Texture2D tex, Rectangle rec); // -- GuiLoadStyle(), required to set shapes rec to font white rec (optimization) +* - char *LoadFileText(const char *fileName); // -- GuiLoadStyle(), required to load charset data +* - void UnloadFileText(char *text); // -- GuiLoadStyle(), required to unload charset data +* - const char *GetDirectoryPath(const char *filePath); // -- GuiLoadStyle(), required to find charset/font file from text .rgs +* - int *LoadCodepoints(const char *text, int *count); // -- GuiLoadStyle(), required to load required font codepoints list +* - void UnloadCodepoints(int *codepoints); // -- GuiLoadStyle(), required to unload codepoints list +* - unsigned char *DecompressData(const unsigned char *compData, int compDataSize, int *dataSize); // -- GuiLoadStyle() +* +* CONTRIBUTORS: +* Ramon Santamaria: Supervision, review, redesign, update and maintenance +* Vlad Adrian: Complete rewrite of GuiTextBox() to support extended features (2019) +* Sergio Martinez: Review, testing (2015) and redesign of multiple controls (2018) +* Adria Arranz: Testing and implementation of additional controls (2018) +* Jordi Jorba: Testing and implementation of additional controls (2018) +* Albert Martos: Review and testing of the library (2015) +* Ian Eito: Review and testing of the library (2015) +* Kevin Gato: Initial implementation of basic components (2014) +* Daniel Nicolas: Initial implementation of basic components (2014) +* +* +* LICENSE: zlib/libpng +* +* Copyright (c) 2014-2025 Ramon Santamaria (@raysan5) +* +* This software is provided "as-is", without any express or implied warranty. In no event +* will the authors be held liable for any damages arising from the use of this software. +* +* Permission is granted to anyone to use this software for any purpose, including commercial +* applications, and to alter it and redistribute it freely, subject to the following restrictions: +* +* 1. The origin of this software must not be misrepresented; you must not claim that you +* wrote the original software. If you use this software in a product, an acknowledgment +* in the product documentation would be appreciated but is not required. +* +* 2. Altered source versions must be plainly marked as such, and must not be misrepresented +* as being the original software. +* +* 3. This notice may not be removed or altered from any source distribution. +* +**********************************************************************************************/ + +#ifndef RAYGUI_H +#define RAYGUI_H + +#define RAYGUI_VERSION_MAJOR 4 +#define RAYGUI_VERSION_MINOR 5 +#define RAYGUI_VERSION_PATCH 0 +#define RAYGUI_VERSION "5.0-dev" + +#if !defined(RAYGUI_STANDALONE) + #include "raylib.h" +#endif + +// Function specifiers in case library is build/used as a shared library (Windows) +// NOTE: Microsoft specifiers to tell compiler that symbols are imported/exported from a .dll +#if defined(_WIN32) + #if defined(BUILD_LIBTYPE_SHARED) + #define RAYGUIAPI __declspec(dllexport) // We are building the library as a Win32 shared library (.dll) + #elif defined(USE_LIBTYPE_SHARED) + #define RAYGUIAPI __declspec(dllimport) // We are using the library as a Win32 shared library (.dll) + #endif +#endif + +// Function specifiers definition +#ifndef RAYGUIAPI + #define RAYGUIAPI // Functions defined as 'extern' by default (implicit specifiers) +#endif + +//---------------------------------------------------------------------------------- +// Defines and Macros +//---------------------------------------------------------------------------------- +// Allow custom memory allocators +#ifndef RAYGUI_MALLOC + #define RAYGUI_MALLOC(sz) malloc(sz) +#endif +#ifndef RAYGUI_CALLOC + #define RAYGUI_CALLOC(n,sz) calloc(n,sz) +#endif +#ifndef RAYGUI_FREE + #define RAYGUI_FREE(p) free(p) +#endif + +// Simple log system to avoid printf() calls if required +// NOTE: Avoiding those calls, also avoids const strings memory usage +#define RAYGUI_SUPPORT_LOG_INFO +#if defined(RAYGUI_SUPPORT_LOG_INFO) + #define RAYGUI_LOG(...) printf(__VA_ARGS__) +#else + #define RAYGUI_LOG(...) +#endif + +//---------------------------------------------------------------------------------- +// Types and Structures Definition +// NOTE: Some types are required for RAYGUI_STANDALONE usage +//---------------------------------------------------------------------------------- +#if defined(RAYGUI_STANDALONE) + #ifndef __cplusplus + // Boolean type + #ifndef true + typedef enum { false, true } bool; + #endif + #endif + + // Vector2 type + typedef struct Vector2 { + float x; + float y; + } Vector2; + + // Vector3 type // -- ConvertHSVtoRGB(), ConvertRGBtoHSV() + typedef struct Vector3 { + float x; + float y; + float z; + } Vector3; + + // Color type, RGBA (32bit) + typedef struct Color { + unsigned char r; + unsigned char g; + unsigned char b; + unsigned char a; + } Color; + + // Rectangle type + typedef struct Rectangle { + float x; + float y; + float width; + float height; + } Rectangle; + + // TODO: Texture2D type is very coupled to raylib, required by Font type + // It should be redesigned to be provided by user + typedef struct Texture2D { + unsigned int id; // OpenGL texture id + int width; // Texture base width + int height; // Texture base height + int mipmaps; // Mipmap levels, 1 by default + int format; // Data format (PixelFormat type) + } Texture2D; + + // Image, pixel data stored in CPU memory (RAM) + typedef struct Image { + void *data; // Image raw data + int width; // Image base width + int height; // Image base height + int mipmaps; // Mipmap levels, 1 by default + int format; // Data format (PixelFormat type) + } Image; + + // GlyphInfo, font characters glyphs info + typedef struct GlyphInfo { + int value; // Character value (Unicode) + int offsetX; // Character offset X when drawing + int offsetY; // Character offset Y when drawing + int advanceX; // Character advance position X + Image image; // Character image data + } GlyphInfo; + + // TODO: Font type is very coupled to raylib, mostly required by GuiLoadStyle() + // It should be redesigned to be provided by user + typedef struct Font { + int baseSize; // Base size (default chars height) + int glyphCount; // Number of glyph characters + int glyphPadding; // Padding around the glyph characters + Texture2D texture; // Texture atlas containing the glyphs + Rectangle *recs; // Rectangles in texture for the glyphs + GlyphInfo *glyphs; // Glyphs info data + } Font; +#endif + +// Style property +// NOTE: Used when exporting style as code for convenience +typedef struct GuiStyleProp { + unsigned short controlId; // Control identifier + unsigned short propertyId; // Property identifier + int propertyValue; // Property value +} GuiStyleProp; + +/* +// Controls text style -NOT USED- +// NOTE: Text style is defined by control +typedef struct GuiTextStyle { + unsigned int size; + int charSpacing; + int lineSpacing; + int alignmentH; + int alignmentV; + int padding; +} GuiTextStyle; +*/ + +// Gui control state +typedef enum { + STATE_NORMAL = 0, + STATE_FOCUSED, + STATE_PRESSED, + STATE_DISABLED +} GuiState; + +// Gui control text alignment +typedef enum { + TEXT_ALIGN_LEFT = 0, + TEXT_ALIGN_CENTER, + TEXT_ALIGN_RIGHT +} GuiTextAlignment; + +// Gui control text alignment vertical +// NOTE: Text vertical position inside the text bounds +typedef enum { + TEXT_ALIGN_TOP = 0, + TEXT_ALIGN_MIDDLE, + TEXT_ALIGN_BOTTOM +} GuiTextAlignmentVertical; + +// Gui control text wrap mode +// NOTE: Useful for multiline text +typedef enum { + TEXT_WRAP_NONE = 0, + TEXT_WRAP_CHAR, + TEXT_WRAP_WORD +} GuiTextWrapMode; + +// Gui controls +typedef enum { + // Default -> populates to all controls when set + DEFAULT = 0, + + // Basic controls + LABEL, // Used also for: LABELBUTTON + BUTTON, + TOGGLE, // Used also for: TOGGLEGROUP + SLIDER, // Used also for: SLIDERBAR, TOGGLESLIDER + PROGRESSBAR, + CHECKBOX, + COMBOBOX, + DROPDOWNBOX, + TEXTBOX, // Used also for: TEXTBOXMULTI + VALUEBOX, + CONTROL11, + LISTVIEW, + COLORPICKER, + SCROLLBAR, + STATUSBAR +} GuiControl; + +// Gui base properties for every control +// NOTE: RAYGUI_MAX_PROPS_BASE properties (by default 16 properties) +typedef enum { + BORDER_COLOR_NORMAL = 0, // Control border color in STATE_NORMAL + BASE_COLOR_NORMAL, // Control base color in STATE_NORMAL + TEXT_COLOR_NORMAL, // Control text color in STATE_NORMAL + BORDER_COLOR_FOCUSED, // Control border color in STATE_FOCUSED + BASE_COLOR_FOCUSED, // Control base color in STATE_FOCUSED + TEXT_COLOR_FOCUSED, // Control text color in STATE_FOCUSED + BORDER_COLOR_PRESSED, // Control border color in STATE_PRESSED + BASE_COLOR_PRESSED, // Control base color in STATE_PRESSED + TEXT_COLOR_PRESSED, // Control text color in STATE_PRESSED + BORDER_COLOR_DISABLED, // Control border color in STATE_DISABLED + BASE_COLOR_DISABLED, // Control base color in STATE_DISABLED + TEXT_COLOR_DISABLED, // Control text color in STATE_DISABLED + BORDER_WIDTH = 12, // Control border size, 0 for no border + //TEXT_SIZE, // Control text size (glyphs max height) -> GLOBAL for all controls + //TEXT_SPACING, // Control text spacing between glyphs -> GLOBAL for all controls + //TEXT_LINE_SPACING, // Control text spacing between lines -> GLOBAL for all controls + TEXT_PADDING = 13, // Control text padding, not considering border + TEXT_ALIGNMENT = 14, // Control text horizontal alignment inside control text bound (after border and padding) + //TEXT_WRAP_MODE // Control text wrap-mode inside text bounds -> GLOBAL for all controls +} GuiControlProperty; + +// TODO: Which text styling properties should be global or per-control? +// At this moment TEXT_PADDING and TEXT_ALIGNMENT is configured and saved per control while +// TEXT_SIZE, TEXT_SPACING, TEXT_LINE_SPACING, TEXT_ALIGNMENT_VERTICAL, TEXT_WRAP_MODE are global and +// should be configured by user as needed while defining the UI layout + +// Gui extended properties depend on control +// NOTE: RAYGUI_MAX_PROPS_EXTENDED properties (by default, max 8 properties) +//---------------------------------------------------------------------------------- +// DEFAULT extended properties +// NOTE: Those properties are common to all controls or global +// WARNING: We only have 8 slots for those properties by default!!! -> New global control: TEXT? +typedef enum { + TEXT_SIZE = 16, // Text size (glyphs max height) + TEXT_SPACING, // Text spacing between glyphs + LINE_COLOR, // Line control color + BACKGROUND_COLOR, // Background color + TEXT_LINE_SPACING, // Text spacing between lines + TEXT_ALIGNMENT_VERTICAL, // Text vertical alignment inside text bounds (after border and padding) + TEXT_WRAP_MODE // Text wrap-mode inside text bounds + //TEXT_DECORATION // Text decoration: 0-None, 1-Underline, 2-Line-through, 3-Overline + //TEXT_DECORATION_THICK // Text decoration line thickness +} GuiDefaultProperty; + +// Other possible text properties: +// TEXT_WEIGHT // Normal, Italic, Bold -> Requires specific font change +// TEXT_INDENT // Text indentation -> Now using TEXT_PADDING... + +// Label +//typedef enum { } GuiLabelProperty; + +// Button/Spinner +//typedef enum { } GuiButtonProperty; + +// Toggle/ToggleGroup +typedef enum { + GROUP_PADDING = 16, // ToggleGroup separation between toggles +} GuiToggleProperty; + +// Slider/SliderBar +typedef enum { + SLIDER_WIDTH = 16, // Slider size of internal bar + SLIDER_PADDING // Slider/SliderBar internal bar padding +} GuiSliderProperty; + +// ProgressBar +typedef enum { + PROGRESS_PADDING = 16, // ProgressBar internal padding +} GuiProgressBarProperty; + +// ScrollBar +typedef enum { + ARROWS_SIZE = 16, // ScrollBar arrows size + ARROWS_VISIBLE, // ScrollBar arrows visible + SCROLL_SLIDER_PADDING, // ScrollBar slider internal padding + SCROLL_SLIDER_SIZE, // ScrollBar slider size + SCROLL_PADDING, // ScrollBar scroll padding from arrows + SCROLL_SPEED, // ScrollBar scrolling speed +} GuiScrollBarProperty; + +// CheckBox +typedef enum { + CHECK_PADDING = 16 // CheckBox internal check padding +} GuiCheckBoxProperty; + +// ComboBox +typedef enum { + COMBO_BUTTON_WIDTH = 16, // ComboBox right button width + COMBO_BUTTON_SPACING // ComboBox button separation +} GuiComboBoxProperty; + +// DropdownBox +typedef enum { + ARROW_PADDING = 16, // DropdownBox arrow separation from border and items + DROPDOWN_ITEMS_SPACING, // DropdownBox items separation + DROPDOWN_ARROW_HIDDEN, // DropdownBox arrow hidden + DROPDOWN_ROLL_UP // DropdownBox roll up flag (default rolls down) +} GuiDropdownBoxProperty; + +// TextBox/TextBoxMulti/ValueBox/Spinner +typedef enum { + TEXT_READONLY = 16, // TextBox in read-only mode: 0-text editable, 1-text no-editable +} GuiTextBoxProperty; + +// ValueBox/Spinner +typedef enum { + SPINNER_BUTTON_WIDTH = 16, // Spinner left/right buttons width + SPINNER_BUTTON_SPACING, // Spinner buttons separation +} GuiValueBoxProperty; + +// Control11 +//typedef enum { } GuiControl11Property; + +// ListView +typedef enum { + LIST_ITEMS_HEIGHT = 16, // ListView items height + LIST_ITEMS_SPACING, // ListView items separation + SCROLLBAR_WIDTH, // ListView scrollbar size (usually width) + SCROLLBAR_SIDE, // ListView scrollbar side (0-SCROLLBAR_LEFT_SIDE, 1-SCROLLBAR_RIGHT_SIDE) + LIST_ITEMS_BORDER_NORMAL, // ListView items border enabled in normal state + LIST_ITEMS_BORDER_WIDTH // ListView items border width +} GuiListViewProperty; + +// ColorPicker +typedef enum { + COLOR_SELECTOR_SIZE = 16, + HUEBAR_WIDTH, // ColorPicker right hue bar width + HUEBAR_PADDING, // ColorPicker right hue bar separation from panel + HUEBAR_SELECTOR_HEIGHT, // ColorPicker right hue bar selector height + HUEBAR_SELECTOR_OVERFLOW // ColorPicker right hue bar selector overflow +} GuiColorPickerProperty; + +#define SCROLLBAR_LEFT_SIDE 0 +#define SCROLLBAR_RIGHT_SIDE 1 + +//---------------------------------------------------------------------------------- +// Global Variables Definition +//---------------------------------------------------------------------------------- +// ... + +//---------------------------------------------------------------------------------- +// Module Functions Declaration +//---------------------------------------------------------------------------------- + +#if defined(__cplusplus) +extern "C" { // Prevents name mangling of functions +#endif + +// Global gui state control functions +RAYGUIAPI void GuiEnable(void); // Enable gui controls (global state) +RAYGUIAPI void GuiDisable(void); // Disable gui controls (global state) +RAYGUIAPI void GuiLock(void); // Lock gui controls (global state) +RAYGUIAPI void GuiUnlock(void); // Unlock gui controls (global state) +RAYGUIAPI bool GuiIsLocked(void); // Check if gui is locked (global state) +RAYGUIAPI void GuiSetAlpha(float alpha); // Set gui controls alpha (global state), alpha goes from 0.0f to 1.0f +RAYGUIAPI void GuiSetState(int state); // Set gui state (global state) +RAYGUIAPI int GuiGetState(void); // Get gui state (global state) + +// Font set/get functions +RAYGUIAPI void GuiSetFont(Font font); // Set gui custom font (global state) +RAYGUIAPI Font GuiGetFont(void); // Get gui custom font (global state) + +// Style set/get functions +RAYGUIAPI void GuiSetStyle(int control, int property, int value); // Set one style property +RAYGUIAPI int GuiGetStyle(int control, int property); // Get one style property + +// Styles loading functions +RAYGUIAPI void GuiLoadStyle(const char *fileName); // Load style file over global style variable (.rgs) +RAYGUIAPI void GuiLoadStyleDefault(void); // Load style default over global style + +// Tooltips management functions +RAYGUIAPI void GuiEnableTooltip(void); // Enable gui tooltips (global state) +RAYGUIAPI void GuiDisableTooltip(void); // Disable gui tooltips (global state) +RAYGUIAPI void GuiSetTooltip(const char *tooltip); // Set tooltip string + +// Icons functionality +RAYGUIAPI const char *GuiIconText(int iconId, const char *text); // Get text with icon id prepended (if supported) +#if !defined(RAYGUI_NO_ICONS) +RAYGUIAPI void GuiSetIconScale(int scale); // Set default icon drawing size +RAYGUIAPI unsigned int *GuiGetIcons(void); // Get raygui icons data pointer +RAYGUIAPI char **GuiLoadIcons(const char *fileName, bool loadIconsName); // Load raygui icons file (.rgi) into internal icons data +RAYGUIAPI void GuiDrawIcon(int iconId, int posX, int posY, int pixelSize, Color color); // Draw icon using pixel size at specified position +#endif + +// Controls +//---------------------------------------------------------------------------------------------------------- +// Container/separator controls, useful for controls organization +RAYGUIAPI int GuiWindowBox(Rectangle bounds, const char *title); // Window Box control, shows a window that can be closed +RAYGUIAPI int GuiGroupBox(Rectangle bounds, const char *text); // Group Box control with text name +RAYGUIAPI int GuiLine(Rectangle bounds, const char *text); // Line separator control, could contain text +RAYGUIAPI int GuiPanel(Rectangle bounds, const char *text); // Panel control, useful to group controls +RAYGUIAPI int GuiTabBar(Rectangle bounds, const char **text, int count, int *active); // Tab Bar control, returns TAB to be closed or -1 +RAYGUIAPI int GuiScrollPanel(Rectangle bounds, const char *text, Rectangle content, Vector2 *scroll, Rectangle *view); // Scroll Panel control + +// Basic controls set +RAYGUIAPI int GuiLabel(Rectangle bounds, const char *text); // Label control +RAYGUIAPI int GuiButton(Rectangle bounds, const char *text); // Button control, returns true when clicked +RAYGUIAPI int GuiLabelButton(Rectangle bounds, const char *text); // Label button control, returns true when clicked +RAYGUIAPI int GuiToggle(Rectangle bounds, const char *text, bool *active); // Toggle Button control +RAYGUIAPI int GuiToggleGroup(Rectangle bounds, const char *text, int *active); // Toggle Group control +RAYGUIAPI int GuiToggleSlider(Rectangle bounds, const char *text, int *active); // Toggle Slider control +RAYGUIAPI int GuiCheckBox(Rectangle bounds, const char *text, bool *checked); // Check Box control, returns true when active +RAYGUIAPI int GuiComboBox(Rectangle bounds, const char *text, int *active); // Combo Box control + +RAYGUIAPI int GuiDropdownBox(Rectangle bounds, const char *text, int *active, bool editMode); // Dropdown Box control +RAYGUIAPI int GuiSpinner(Rectangle bounds, const char *text, int *value, int minValue, int maxValue, bool editMode); // Spinner control +RAYGUIAPI int GuiValueBox(Rectangle bounds, const char *text, int *value, int minValue, int maxValue, bool editMode); // Value Box control, updates input text with numbers +RAYGUIAPI int GuiValueBoxFloat(Rectangle bounds, const char *text, char *textValue, float *value, bool editMode); // Value box control for float values +RAYGUIAPI int GuiTextBox(Rectangle bounds, char *text, int textSize, bool editMode); // Text Box control, updates input text + +RAYGUIAPI int GuiSlider(Rectangle bounds, const char *textLeft, const char *textRight, float *value, float minValue, float maxValue); // Slider control +RAYGUIAPI int GuiSliderPro(Rectangle bounds, const char *textLeft, const char *textRight, float *value, float minValue, float maxValue, int sliderWidth); // Slider control with extended parameters +RAYGUIAPI int GuiSliderBar(Rectangle bounds, const char *textLeft, const char *textRight, float *value, float minValue, float maxValue); // Slider Bar control +RAYGUIAPI int GuiProgressBar(Rectangle bounds, const char *textLeft, const char *textRight, float *value, float minValue, float maxValue); // Progress Bar control +RAYGUIAPI int GuiStatusBar(Rectangle bounds, const char *text); // Status Bar control, shows info text +RAYGUIAPI int GuiDummyRec(Rectangle bounds, const char *text); // Dummy control for placeholders +RAYGUIAPI int GuiGrid(Rectangle bounds, const char *text, float spacing, int subdivs, Vector2 *mouseCell); // Grid control + +// Advance controls set +RAYGUIAPI int GuiListView(Rectangle bounds, const char *text, int *scrollIndex, int *active); // List View control +RAYGUIAPI int GuiListViewEx(Rectangle bounds, const char **text, int count, int *scrollIndex, int *active, int *focus); // List View with extended parameters +RAYGUIAPI int GuiMessageBox(Rectangle bounds, const char *title, const char *message, const char *buttons); // Message Box control, displays a message +RAYGUIAPI int GuiTextInputBox(Rectangle bounds, const char *title, const char *message, const char *buttons, char *text, int textMaxSize, bool *secretViewActive); // Text Input Box control, ask for text, supports secret +RAYGUIAPI int GuiColorPicker(Rectangle bounds, const char *text, Color *color); // Color Picker control (multiple color controls) +RAYGUIAPI int GuiColorPanel(Rectangle bounds, const char *text, Color *color); // Color Panel control +RAYGUIAPI int GuiColorBarAlpha(Rectangle bounds, const char *text, float *alpha); // Color Bar Alpha control +RAYGUIAPI int GuiColorBarHue(Rectangle bounds, const char *text, float *value); // Color Bar Hue control +RAYGUIAPI int GuiColorPickerHSV(Rectangle bounds, const char *text, Vector3 *colorHsv); // Color Picker control that avoids conversion to RGB on each call (multiple color controls) +RAYGUIAPI int GuiColorPanelHSV(Rectangle bounds, const char *text, Vector3 *colorHsv); // Color Panel control that updates Hue-Saturation-Value color value, used by GuiColorPickerHSV() +//---------------------------------------------------------------------------------------------------------- + +#if !defined(RAYGUI_NO_ICONS) + +#if !defined(RAYGUI_CUSTOM_ICONS) +//---------------------------------------------------------------------------------- +// Icons enumeration +//---------------------------------------------------------------------------------- +typedef enum { + ICON_NONE = 0, + ICON_FOLDER_FILE_OPEN = 1, + ICON_FILE_SAVE_CLASSIC = 2, + ICON_FOLDER_OPEN = 3, + ICON_FOLDER_SAVE = 4, + ICON_FILE_OPEN = 5, + ICON_FILE_SAVE = 6, + ICON_FILE_EXPORT = 7, + ICON_FILE_ADD = 8, + ICON_FILE_DELETE = 9, + ICON_FILETYPE_TEXT = 10, + ICON_FILETYPE_AUDIO = 11, + ICON_FILETYPE_IMAGE = 12, + ICON_FILETYPE_PLAY = 13, + ICON_FILETYPE_VIDEO = 14, + ICON_FILETYPE_INFO = 15, + ICON_FILE_COPY = 16, + ICON_FILE_CUT = 17, + ICON_FILE_PASTE = 18, + ICON_CURSOR_HAND = 19, + ICON_CURSOR_POINTER = 20, + ICON_CURSOR_CLASSIC = 21, + ICON_PENCIL = 22, + ICON_PENCIL_BIG = 23, + ICON_BRUSH_CLASSIC = 24, + ICON_BRUSH_PAINTER = 25, + ICON_WATER_DROP = 26, + ICON_COLOR_PICKER = 27, + ICON_RUBBER = 28, + ICON_COLOR_BUCKET = 29, + ICON_TEXT_T = 30, + ICON_TEXT_A = 31, + ICON_SCALE = 32, + ICON_RESIZE = 33, + ICON_FILTER_POINT = 34, + ICON_FILTER_BILINEAR = 35, + ICON_CROP = 36, + ICON_CROP_ALPHA = 37, + ICON_SQUARE_TOGGLE = 38, + ICON_SYMMETRY = 39, + ICON_SYMMETRY_HORIZONTAL = 40, + ICON_SYMMETRY_VERTICAL = 41, + ICON_LENS = 42, + ICON_LENS_BIG = 43, + ICON_EYE_ON = 44, + ICON_EYE_OFF = 45, + ICON_FILTER_TOP = 46, + ICON_FILTER = 47, + ICON_TARGET_POINT = 48, + ICON_TARGET_SMALL = 49, + ICON_TARGET_BIG = 50, + ICON_TARGET_MOVE = 51, + ICON_CURSOR_MOVE = 52, + ICON_CURSOR_SCALE = 53, + ICON_CURSOR_SCALE_RIGHT = 54, + ICON_CURSOR_SCALE_LEFT = 55, + ICON_UNDO = 56, + ICON_REDO = 57, + ICON_REREDO = 58, + ICON_MUTATE = 59, + ICON_ROTATE = 60, + ICON_REPEAT = 61, + ICON_SHUFFLE = 62, + ICON_EMPTYBOX = 63, + ICON_TARGET = 64, + ICON_TARGET_SMALL_FILL = 65, + ICON_TARGET_BIG_FILL = 66, + ICON_TARGET_MOVE_FILL = 67, + ICON_CURSOR_MOVE_FILL = 68, + ICON_CURSOR_SCALE_FILL = 69, + ICON_CURSOR_SCALE_RIGHT_FILL = 70, + ICON_CURSOR_SCALE_LEFT_FILL = 71, + ICON_UNDO_FILL = 72, + ICON_REDO_FILL = 73, + ICON_REREDO_FILL = 74, + ICON_MUTATE_FILL = 75, + ICON_ROTATE_FILL = 76, + ICON_REPEAT_FILL = 77, + ICON_SHUFFLE_FILL = 78, + ICON_EMPTYBOX_SMALL = 79, + ICON_BOX = 80, + ICON_BOX_TOP = 81, + ICON_BOX_TOP_RIGHT = 82, + ICON_BOX_RIGHT = 83, + ICON_BOX_BOTTOM_RIGHT = 84, + ICON_BOX_BOTTOM = 85, + ICON_BOX_BOTTOM_LEFT = 86, + ICON_BOX_LEFT = 87, + ICON_BOX_TOP_LEFT = 88, + ICON_BOX_CENTER = 89, + ICON_BOX_CIRCLE_MASK = 90, + ICON_POT = 91, + ICON_ALPHA_MULTIPLY = 92, + ICON_ALPHA_CLEAR = 93, + ICON_DITHERING = 94, + ICON_MIPMAPS = 95, + ICON_BOX_GRID = 96, + ICON_GRID = 97, + ICON_BOX_CORNERS_SMALL = 98, + ICON_BOX_CORNERS_BIG = 99, + ICON_FOUR_BOXES = 100, + ICON_GRID_FILL = 101, + ICON_BOX_MULTISIZE = 102, + ICON_ZOOM_SMALL = 103, + ICON_ZOOM_MEDIUM = 104, + ICON_ZOOM_BIG = 105, + ICON_ZOOM_ALL = 106, + ICON_ZOOM_CENTER = 107, + ICON_BOX_DOTS_SMALL = 108, + ICON_BOX_DOTS_BIG = 109, + ICON_BOX_CONCENTRIC = 110, + ICON_BOX_GRID_BIG = 111, + ICON_OK_TICK = 112, + ICON_CROSS = 113, + ICON_ARROW_LEFT = 114, + ICON_ARROW_RIGHT = 115, + ICON_ARROW_DOWN = 116, + ICON_ARROW_UP = 117, + ICON_ARROW_LEFT_FILL = 118, + ICON_ARROW_RIGHT_FILL = 119, + ICON_ARROW_DOWN_FILL = 120, + ICON_ARROW_UP_FILL = 121, + ICON_AUDIO = 122, + ICON_FX = 123, + ICON_WAVE = 124, + ICON_WAVE_SINUS = 125, + ICON_WAVE_SQUARE = 126, + ICON_WAVE_TRIANGULAR = 127, + ICON_CROSS_SMALL = 128, + ICON_PLAYER_PREVIOUS = 129, + ICON_PLAYER_PLAY_BACK = 130, + ICON_PLAYER_PLAY = 131, + ICON_PLAYER_PAUSE = 132, + ICON_PLAYER_STOP = 133, + ICON_PLAYER_NEXT = 134, + ICON_PLAYER_RECORD = 135, + ICON_MAGNET = 136, + ICON_LOCK_CLOSE = 137, + ICON_LOCK_OPEN = 138, + ICON_CLOCK = 139, + ICON_TOOLS = 140, + ICON_GEAR = 141, + ICON_GEAR_BIG = 142, + ICON_BIN = 143, + ICON_HAND_POINTER = 144, + ICON_LASER = 145, + ICON_COIN = 146, + ICON_EXPLOSION = 147, + ICON_1UP = 148, + ICON_PLAYER = 149, + ICON_PLAYER_JUMP = 150, + ICON_KEY = 151, + ICON_DEMON = 152, + ICON_TEXT_POPUP = 153, + ICON_GEAR_EX = 154, + ICON_CRACK = 155, + ICON_CRACK_POINTS = 156, + ICON_STAR = 157, + ICON_DOOR = 158, + ICON_EXIT = 159, + ICON_MODE_2D = 160, + ICON_MODE_3D = 161, + ICON_CUBE = 162, + ICON_CUBE_FACE_TOP = 163, + ICON_CUBE_FACE_LEFT = 164, + ICON_CUBE_FACE_FRONT = 165, + ICON_CUBE_FACE_BOTTOM = 166, + ICON_CUBE_FACE_RIGHT = 167, + ICON_CUBE_FACE_BACK = 168, + ICON_CAMERA = 169, + ICON_SPECIAL = 170, + ICON_LINK_NET = 171, + ICON_LINK_BOXES = 172, + ICON_LINK_MULTI = 173, + ICON_LINK = 174, + ICON_LINK_BROKE = 175, + ICON_TEXT_NOTES = 176, + ICON_NOTEBOOK = 177, + ICON_SUITCASE = 178, + ICON_SUITCASE_ZIP = 179, + ICON_MAILBOX = 180, + ICON_MONITOR = 181, + ICON_PRINTER = 182, + ICON_PHOTO_CAMERA = 183, + ICON_PHOTO_CAMERA_FLASH = 184, + ICON_HOUSE = 185, + ICON_HEART = 186, + ICON_CORNER = 187, + ICON_VERTICAL_BARS = 188, + ICON_VERTICAL_BARS_FILL = 189, + ICON_LIFE_BARS = 190, + ICON_INFO = 191, + ICON_CROSSLINE = 192, + ICON_HELP = 193, + ICON_FILETYPE_ALPHA = 194, + ICON_FILETYPE_HOME = 195, + ICON_LAYERS_VISIBLE = 196, + ICON_LAYERS = 197, + ICON_WINDOW = 198, + ICON_HIDPI = 199, + ICON_FILETYPE_BINARY = 200, + ICON_HEX = 201, + ICON_SHIELD = 202, + ICON_FILE_NEW = 203, + ICON_FOLDER_ADD = 204, + ICON_ALARM = 205, + ICON_CPU = 206, + ICON_ROM = 207, + ICON_STEP_OVER = 208, + ICON_STEP_INTO = 209, + ICON_STEP_OUT = 210, + ICON_RESTART = 211, + ICON_BREAKPOINT_ON = 212, + ICON_BREAKPOINT_OFF = 213, + ICON_BURGER_MENU = 214, + ICON_CASE_SENSITIVE = 215, + ICON_REG_EXP = 216, + ICON_FOLDER = 217, + ICON_FILE = 218, + ICON_SAND_TIMER = 219, + ICON_WARNING = 220, + ICON_HELP_BOX = 221, + ICON_INFO_BOX = 222, + ICON_PRIORITY = 223, + ICON_LAYERS_ISO = 224, + ICON_LAYERS2 = 225, + ICON_MLAYERS = 226, + ICON_MAPS = 227, + ICON_HOT = 228, + ICON_229 = 229, + ICON_230 = 230, + ICON_231 = 231, + ICON_232 = 232, + ICON_233 = 233, + ICON_234 = 234, + ICON_235 = 235, + ICON_236 = 236, + ICON_237 = 237, + ICON_238 = 238, + ICON_239 = 239, + ICON_240 = 240, + ICON_241 = 241, + ICON_242 = 242, + ICON_243 = 243, + ICON_244 = 244, + ICON_245 = 245, + ICON_246 = 246, + ICON_247 = 247, + ICON_248 = 248, + ICON_249 = 249, + ICON_250 = 250, + ICON_251 = 251, + ICON_252 = 252, + ICON_253 = 253, + ICON_254 = 254, + ICON_255 = 255, +} GuiIconName; +#endif + +#endif + +#if defined(__cplusplus) +} // Prevents name mangling of functions +#endif + +#endif // RAYGUI_H + +/*********************************************************************************** +* +* RAYGUI IMPLEMENTATION +* +************************************************************************************/ + +#if defined(RAYGUI_IMPLEMENTATION) + +#include // required for: isspace() [GuiTextBox()] +#include // Required for: FILE, fopen(), fclose(), fprintf(), feof(), fscanf(), snprintf(), vsprintf() [GuiLoadStyle(), GuiLoadIcons()] +#include // Required for: malloc(), calloc(), free() [GuiLoadStyle(), GuiLoadIcons()] +#include // Required for: strlen() [GuiTextBox(), GuiValueBox()], memset(), memcpy() +#include // Required for: va_list, va_start(), vfprintf(), va_end() [TextFormat()] +#include // Required for: roundf() [GuiColorPicker()] + +#ifdef __cplusplus + #define RAYGUI_CLITERAL(name) name +#else + #define RAYGUI_CLITERAL(name) (name) +#endif + +// Check if two rectangles are equal, used to validate a slider bounds as an id +#ifndef CHECK_BOUNDS_ID + #define CHECK_BOUNDS_ID(src, dst) ((src.x == dst.x) && (src.y == dst.y) && (src.width == dst.width) && (src.height == dst.height)) +#endif + +#if !defined(RAYGUI_NO_ICONS) && !defined(RAYGUI_CUSTOM_ICONS) + +// Embedded icons, no external file provided +#define RAYGUI_ICON_SIZE 16 // Size of icons in pixels (squared) +#define RAYGUI_ICON_MAX_ICONS 256 // Maximum number of icons +#define RAYGUI_ICON_MAX_NAME_LENGTH 32 // Maximum length of icon name id + +// Icons data is defined by bit array (every bit represents one pixel) +// Those arrays are stored as unsigned int data arrays, so, +// every array element defines 32 pixels (bits) of information +// One icon is defined by 8 int, (8 int * 32 bit = 256 bit = 16*16 pixels) +// NOTE: Number of elemens depend on RAYGUI_ICON_SIZE (by default 16x16 pixels) +#define RAYGUI_ICON_DATA_ELEMENTS (RAYGUI_ICON_SIZE*RAYGUI_ICON_SIZE/32) + +//---------------------------------------------------------------------------------- +// Icons data for all gui possible icons (allocated on data segment by default) +// +// NOTE 1: Every icon is codified in binary form, using 1 bit per pixel, so, +// every 16x16 icon requires 8 integers (16*16/32) to be stored +// +// NOTE 2: A different icon set could be loaded over this array using GuiLoadIcons(), +// but loaded icons set must be same RAYGUI_ICON_SIZE and no more than RAYGUI_ICON_MAX_ICONS +// +// guiIcons size is by default: 256*(16*16/32) = 2048*4 = 8192 bytes = 8 KB +//---------------------------------------------------------------------------------- +static unsigned int guiIcons[RAYGUI_ICON_MAX_ICONS*RAYGUI_ICON_DATA_ELEMENTS] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_NONE + 0x3ff80000, 0x2f082008, 0x2042207e, 0x40027fc2, 0x40024002, 0x40024002, 0x40024002, 0x00007ffe, // ICON_FOLDER_FILE_OPEN + 0x3ffe0000, 0x44226422, 0x400247e2, 0x5ffa4002, 0x57ea500a, 0x500a500a, 0x40025ffa, 0x00007ffe, // ICON_FILE_SAVE_CLASSIC + 0x00000000, 0x0042007e, 0x40027fc2, 0x40024002, 0x41024002, 0x44424282, 0x793e4102, 0x00000100, // ICON_FOLDER_OPEN + 0x00000000, 0x0042007e, 0x40027fc2, 0x40024002, 0x41024102, 0x44424102, 0x793e4282, 0x00000000, // ICON_FOLDER_SAVE + 0x3ff00000, 0x201c2010, 0x20042004, 0x21042004, 0x24442284, 0x21042104, 0x20042104, 0x00003ffc, // ICON_FILE_OPEN + 0x3ff00000, 0x201c2010, 0x20042004, 0x21042004, 0x21042104, 0x22842444, 0x20042104, 0x00003ffc, // ICON_FILE_SAVE + 0x3ff00000, 0x201c2010, 0x00042004, 0x20041004, 0x20844784, 0x00841384, 0x20042784, 0x00003ffc, // ICON_FILE_EXPORT + 0x3ff00000, 0x201c2010, 0x20042004, 0x20042004, 0x22042204, 0x22042f84, 0x20042204, 0x00003ffc, // ICON_FILE_ADD + 0x3ff00000, 0x201c2010, 0x20042004, 0x20042004, 0x25042884, 0x25042204, 0x20042884, 0x00003ffc, // ICON_FILE_DELETE + 0x3ff00000, 0x201c2010, 0x20042004, 0x20042ff4, 0x20042ff4, 0x20042ff4, 0x20042004, 0x00003ffc, // ICON_FILETYPE_TEXT + 0x3ff00000, 0x201c2010, 0x27042004, 0x244424c4, 0x26442444, 0x20642664, 0x20042004, 0x00003ffc, // ICON_FILETYPE_AUDIO + 0x3ff00000, 0x201c2010, 0x26042604, 0x20042004, 0x35442884, 0x2414222c, 0x20042004, 0x00003ffc, // ICON_FILETYPE_IMAGE + 0x3ff00000, 0x201c2010, 0x20c42004, 0x22442144, 0x22442444, 0x20c42144, 0x20042004, 0x00003ffc, // ICON_FILETYPE_PLAY + 0x3ff00000, 0x3ffc2ff0, 0x3f3c2ff4, 0x3dbc2eb4, 0x3dbc2bb4, 0x3f3c2eb4, 0x3ffc2ff4, 0x00002ff4, // ICON_FILETYPE_VIDEO + 0x3ff00000, 0x201c2010, 0x21842184, 0x21842004, 0x21842184, 0x21842184, 0x20042184, 0x00003ffc, // ICON_FILETYPE_INFO + 0x0ff00000, 0x381c0810, 0x28042804, 0x28042804, 0x28042804, 0x28042804, 0x20102ffc, 0x00003ff0, // ICON_FILE_COPY + 0x00000000, 0x701c0000, 0x079c1e14, 0x55a000f0, 0x079c00f0, 0x701c1e14, 0x00000000, 0x00000000, // ICON_FILE_CUT + 0x01c00000, 0x13e41bec, 0x3f841004, 0x204420c4, 0x20442044, 0x20442044, 0x207c2044, 0x00003fc0, // ICON_FILE_PASTE + 0x00000000, 0x3aa00fe0, 0x2abc2aa0, 0x2aa42aa4, 0x20042aa4, 0x20042004, 0x3ffc2004, 0x00000000, // ICON_CURSOR_HAND + 0x00000000, 0x003c000c, 0x030800c8, 0x30100c10, 0x10202020, 0x04400840, 0x01800280, 0x00000000, // ICON_CURSOR_POINTER + 0x00000000, 0x00180000, 0x01f00078, 0x03e007f0, 0x07c003e0, 0x04000e40, 0x00000000, 0x00000000, // ICON_CURSOR_CLASSIC + 0x00000000, 0x04000000, 0x11000a00, 0x04400a80, 0x01100220, 0x00580088, 0x00000038, 0x00000000, // ICON_PENCIL + 0x04000000, 0x15000a00, 0x50402880, 0x14102820, 0x05040a08, 0x015c028c, 0x007c00bc, 0x00000000, // ICON_PENCIL_BIG + 0x01c00000, 0x01400140, 0x01400140, 0x0ff80140, 0x0ff80808, 0x0aa80808, 0x0aa80aa8, 0x00000ff8, // ICON_BRUSH_CLASSIC + 0x1ffc0000, 0x5ffc7ffe, 0x40004000, 0x00807f80, 0x01c001c0, 0x01c001c0, 0x01c001c0, 0x00000080, // ICON_BRUSH_PAINTER + 0x00000000, 0x00800000, 0x01c00080, 0x03e001c0, 0x07f003e0, 0x036006f0, 0x000001c0, 0x00000000, // ICON_WATER_DROP + 0x00000000, 0x3e003800, 0x1f803f80, 0x0c201e40, 0x02080c10, 0x00840104, 0x00380044, 0x00000000, // ICON_COLOR_PICKER + 0x00000000, 0x07800300, 0x1fe00fc0, 0x3f883fd0, 0x0e021f04, 0x02040402, 0x00f00108, 0x00000000, // ICON_RUBBER + 0x00c00000, 0x02800140, 0x08200440, 0x20081010, 0x2ffe3004, 0x03f807fc, 0x00e001f0, 0x00000040, // ICON_COLOR_BUCKET + 0x00000000, 0x21843ffc, 0x01800180, 0x01800180, 0x01800180, 0x01800180, 0x03c00180, 0x00000000, // ICON_TEXT_T + 0x00800000, 0x01400180, 0x06200340, 0x0c100620, 0x1ff80c10, 0x380c1808, 0x70067004, 0x0000f80f, // ICON_TEXT_A + 0x78000000, 0x50004000, 0x00004800, 0x03c003c0, 0x03c003c0, 0x00100000, 0x0002000a, 0x0000000e, // ICON_SCALE + 0x75560000, 0x5e004002, 0x54001002, 0x41001202, 0x408200fe, 0x40820082, 0x40820082, 0x00006afe, // ICON_RESIZE + 0x00000000, 0x3f003f00, 0x3f003f00, 0x3f003f00, 0x00400080, 0x001c0020, 0x001c001c, 0x00000000, // ICON_FILTER_POINT + 0x6d800000, 0x00004080, 0x40804080, 0x40800000, 0x00406d80, 0x001c0020, 0x001c001c, 0x00000000, // ICON_FILTER_BILINEAR + 0x40080000, 0x1ffe2008, 0x14081008, 0x11081208, 0x10481088, 0x10081028, 0x10047ff8, 0x00001002, // ICON_CROP + 0x00100000, 0x3ffc0010, 0x2ab03550, 0x22b02550, 0x20b02150, 0x20302050, 0x2000fff0, 0x00002000, // ICON_CROP_ALPHA + 0x40000000, 0x1ff82000, 0x04082808, 0x01082208, 0x00482088, 0x00182028, 0x35542008, 0x00000002, // ICON_SQUARE_TOGGLE + 0x00000000, 0x02800280, 0x06c006c0, 0x0ea00ee0, 0x1e901eb0, 0x3e883e98, 0x7efc7e8c, 0x00000000, // ICON_SYMMETRY + 0x01000000, 0x05600100, 0x1d480d50, 0x7d423d44, 0x3d447d42, 0x0d501d48, 0x01000560, 0x00000100, // ICON_SYMMETRY_HORIZONTAL + 0x01800000, 0x04200240, 0x10080810, 0x00001ff8, 0x00007ffe, 0x0ff01ff8, 0x03c007e0, 0x00000180, // ICON_SYMMETRY_VERTICAL + 0x00000000, 0x010800f0, 0x02040204, 0x02040204, 0x07f00308, 0x1c000e00, 0x30003800, 0x00000000, // ICON_LENS + 0x00000000, 0x061803f0, 0x08240c0c, 0x08040814, 0x0c0c0804, 0x23f01618, 0x18002400, 0x00000000, // ICON_LENS_BIG + 0x00000000, 0x00000000, 0x1c7007c0, 0x638e3398, 0x1c703398, 0x000007c0, 0x00000000, 0x00000000, // ICON_EYE_ON + 0x00000000, 0x10002000, 0x04700fc0, 0x610e3218, 0x1c703098, 0x001007a0, 0x00000008, 0x00000000, // ICON_EYE_OFF + 0x00000000, 0x00007ffc, 0x40047ffc, 0x10102008, 0x04400820, 0x02800280, 0x02800280, 0x00000100, // ICON_FILTER_TOP + 0x00000000, 0x40027ffe, 0x10082004, 0x04200810, 0x02400240, 0x02400240, 0x01400240, 0x000000c0, // ICON_FILTER + 0x00800000, 0x00800080, 0x00000080, 0x3c9e0000, 0x00000000, 0x00800080, 0x00800080, 0x00000000, // ICON_TARGET_POINT + 0x00800000, 0x00800080, 0x00800080, 0x3f7e01c0, 0x008001c0, 0x00800080, 0x00800080, 0x00000000, // ICON_TARGET_SMALL + 0x00800000, 0x00800080, 0x03e00080, 0x3e3e0220, 0x03e00220, 0x00800080, 0x00800080, 0x00000000, // ICON_TARGET_BIG + 0x01000000, 0x04400280, 0x01000100, 0x43842008, 0x43849ab2, 0x01002008, 0x04400100, 0x01000280, // ICON_TARGET_MOVE + 0x01000000, 0x04400280, 0x01000100, 0x41042108, 0x41049ff2, 0x01002108, 0x04400100, 0x01000280, // ICON_CURSOR_MOVE + 0x781e0000, 0x500a4002, 0x04204812, 0x00000240, 0x02400000, 0x48120420, 0x4002500a, 0x0000781e, // ICON_CURSOR_SCALE + 0x00000000, 0x20003c00, 0x24002800, 0x01000200, 0x00400080, 0x00140024, 0x003c0004, 0x00000000, // ICON_CURSOR_SCALE_RIGHT + 0x00000000, 0x0004003c, 0x00240014, 0x00800040, 0x02000100, 0x28002400, 0x3c002000, 0x00000000, // ICON_CURSOR_SCALE_LEFT + 0x00000000, 0x00100020, 0x10101fc8, 0x10001020, 0x10001000, 0x10001000, 0x00001fc0, 0x00000000, // ICON_UNDO + 0x00000000, 0x08000400, 0x080813f8, 0x00080408, 0x00080008, 0x00080008, 0x000003f8, 0x00000000, // ICON_REDO + 0x00000000, 0x3ffc0000, 0x20042004, 0x20002000, 0x20402000, 0x3f902020, 0x00400020, 0x00000000, // ICON_REREDO + 0x00000000, 0x3ffc0000, 0x20042004, 0x27fc2004, 0x20202000, 0x3fc82010, 0x00200010, 0x00000000, // ICON_MUTATE + 0x00000000, 0x0ff00000, 0x10081818, 0x11801008, 0x10001180, 0x18101020, 0x00100fc8, 0x00000020, // ICON_ROTATE + 0x00000000, 0x04000200, 0x240429fc, 0x20042204, 0x20442004, 0x3f942024, 0x00400020, 0x00000000, // ICON_REPEAT + 0x00000000, 0x20001000, 0x22104c0e, 0x00801120, 0x11200040, 0x4c0e2210, 0x10002000, 0x00000000, // ICON_SHUFFLE + 0x7ffe0000, 0x50024002, 0x44024802, 0x41024202, 0x40424082, 0x40124022, 0x4002400a, 0x00007ffe, // ICON_EMPTYBOX + 0x00800000, 0x03e00080, 0x08080490, 0x3c9e0808, 0x08080808, 0x03e00490, 0x00800080, 0x00000000, // ICON_TARGET + 0x00800000, 0x00800080, 0x00800080, 0x3ffe01c0, 0x008001c0, 0x00800080, 0x00800080, 0x00000000, // ICON_TARGET_SMALL_FILL + 0x00800000, 0x00800080, 0x03e00080, 0x3ffe03e0, 0x03e003e0, 0x00800080, 0x00800080, 0x00000000, // ICON_TARGET_BIG_FILL + 0x01000000, 0x07c00380, 0x01000100, 0x638c2008, 0x638cfbbe, 0x01002008, 0x07c00100, 0x01000380, // ICON_TARGET_MOVE_FILL + 0x01000000, 0x07c00380, 0x01000100, 0x610c2108, 0x610cfffe, 0x01002108, 0x07c00100, 0x01000380, // ICON_CURSOR_MOVE_FILL + 0x781e0000, 0x6006700e, 0x04204812, 0x00000240, 0x02400000, 0x48120420, 0x700e6006, 0x0000781e, // ICON_CURSOR_SCALE_FILL + 0x00000000, 0x38003c00, 0x24003000, 0x01000200, 0x00400080, 0x000c0024, 0x003c001c, 0x00000000, // ICON_CURSOR_SCALE_RIGHT_FILL + 0x00000000, 0x001c003c, 0x0024000c, 0x00800040, 0x02000100, 0x30002400, 0x3c003800, 0x00000000, // ICON_CURSOR_SCALE_LEFT_FILL + 0x00000000, 0x00300020, 0x10301ff8, 0x10001020, 0x10001000, 0x10001000, 0x00001fc0, 0x00000000, // ICON_UNDO_FILL + 0x00000000, 0x0c000400, 0x0c081ff8, 0x00080408, 0x00080008, 0x00080008, 0x000003f8, 0x00000000, // ICON_REDO_FILL + 0x00000000, 0x3ffc0000, 0x20042004, 0x20002000, 0x20402000, 0x3ff02060, 0x00400060, 0x00000000, // ICON_REREDO_FILL + 0x00000000, 0x3ffc0000, 0x20042004, 0x27fc2004, 0x20202000, 0x3ff82030, 0x00200030, 0x00000000, // ICON_MUTATE_FILL + 0x00000000, 0x0ff00000, 0x10081818, 0x11801008, 0x10001180, 0x18301020, 0x00300ff8, 0x00000020, // ICON_ROTATE_FILL + 0x00000000, 0x06000200, 0x26042ffc, 0x20042204, 0x20442004, 0x3ff42064, 0x00400060, 0x00000000, // ICON_REPEAT_FILL + 0x00000000, 0x30001000, 0x32107c0e, 0x00801120, 0x11200040, 0x7c0e3210, 0x10003000, 0x00000000, // ICON_SHUFFLE_FILL + 0x00000000, 0x30043ffc, 0x24042804, 0x21042204, 0x20442084, 0x20142024, 0x3ffc200c, 0x00000000, // ICON_EMPTYBOX_SMALL + 0x00000000, 0x20043ffc, 0x20042004, 0x20042004, 0x20042004, 0x20042004, 0x3ffc2004, 0x00000000, // ICON_BOX + 0x00000000, 0x23c43ffc, 0x23c423c4, 0x200423c4, 0x20042004, 0x20042004, 0x3ffc2004, 0x00000000, // ICON_BOX_TOP + 0x00000000, 0x3e043ffc, 0x3e043e04, 0x20043e04, 0x20042004, 0x20042004, 0x3ffc2004, 0x00000000, // ICON_BOX_TOP_RIGHT + 0x00000000, 0x20043ffc, 0x20042004, 0x3e043e04, 0x3e043e04, 0x20042004, 0x3ffc2004, 0x00000000, // ICON_BOX_RIGHT + 0x00000000, 0x20043ffc, 0x20042004, 0x20042004, 0x3e042004, 0x3e043e04, 0x3ffc3e04, 0x00000000, // ICON_BOX_BOTTOM_RIGHT + 0x00000000, 0x20043ffc, 0x20042004, 0x20042004, 0x23c42004, 0x23c423c4, 0x3ffc23c4, 0x00000000, // ICON_BOX_BOTTOM + 0x00000000, 0x20043ffc, 0x20042004, 0x20042004, 0x207c2004, 0x207c207c, 0x3ffc207c, 0x00000000, // ICON_BOX_BOTTOM_LEFT + 0x00000000, 0x20043ffc, 0x20042004, 0x207c207c, 0x207c207c, 0x20042004, 0x3ffc2004, 0x00000000, // ICON_BOX_LEFT + 0x00000000, 0x207c3ffc, 0x207c207c, 0x2004207c, 0x20042004, 0x20042004, 0x3ffc2004, 0x00000000, // ICON_BOX_TOP_LEFT + 0x00000000, 0x20043ffc, 0x20042004, 0x23c423c4, 0x23c423c4, 0x20042004, 0x3ffc2004, 0x00000000, // ICON_BOX_CENTER + 0x7ffe0000, 0x40024002, 0x47e24182, 0x4ff247e2, 0x47e24ff2, 0x418247e2, 0x40024002, 0x00007ffe, // ICON_BOX_CIRCLE_MASK + 0x7fff0000, 0x40014001, 0x40014001, 0x49555ddd, 0x4945495d, 0x400149c5, 0x40014001, 0x00007fff, // ICON_POT + 0x7ffe0000, 0x53327332, 0x44ce4cce, 0x41324332, 0x404e40ce, 0x48125432, 0x4006540e, 0x00007ffe, // ICON_ALPHA_MULTIPLY + 0x7ffe0000, 0x53327332, 0x44ce4cce, 0x41324332, 0x5c4e40ce, 0x44124432, 0x40065c0e, 0x00007ffe, // ICON_ALPHA_CLEAR + 0x7ffe0000, 0x42fe417e, 0x42fe417e, 0x42fe417e, 0x42fe417e, 0x42fe417e, 0x42fe417e, 0x00007ffe, // ICON_DITHERING + 0x07fe0000, 0x1ffa0002, 0x7fea000a, 0x402a402a, 0x5b2a512a, 0x5128552a, 0x40205128, 0x00007fe0, // ICON_MIPMAPS + 0x00000000, 0x1ff80000, 0x12481248, 0x12481ff8, 0x1ff81248, 0x12481248, 0x00001ff8, 0x00000000, // ICON_BOX_GRID + 0x12480000, 0x7ffe1248, 0x12481248, 0x12487ffe, 0x7ffe1248, 0x12481248, 0x12487ffe, 0x00001248, // ICON_GRID + 0x00000000, 0x1c380000, 0x1c3817e8, 0x08100810, 0x08100810, 0x17e81c38, 0x00001c38, 0x00000000, // ICON_BOX_CORNERS_SMALL + 0x700e0000, 0x700e5ffa, 0x20042004, 0x20042004, 0x20042004, 0x20042004, 0x5ffa700e, 0x0000700e, // ICON_BOX_CORNERS_BIG + 0x3f7e0000, 0x21422142, 0x21422142, 0x00003f7e, 0x21423f7e, 0x21422142, 0x3f7e2142, 0x00000000, // ICON_FOUR_BOXES + 0x00000000, 0x3bb80000, 0x3bb83bb8, 0x3bb80000, 0x3bb83bb8, 0x3bb80000, 0x3bb83bb8, 0x00000000, // ICON_GRID_FILL + 0x7ffe0000, 0x7ffe7ffe, 0x77fe7000, 0x77fe77fe, 0x777e7700, 0x777e777e, 0x777e777e, 0x0000777e, // ICON_BOX_MULTISIZE + 0x781e0000, 0x40024002, 0x00004002, 0x01800000, 0x00000180, 0x40020000, 0x40024002, 0x0000781e, // ICON_ZOOM_SMALL + 0x781e0000, 0x40024002, 0x00004002, 0x03c003c0, 0x03c003c0, 0x40020000, 0x40024002, 0x0000781e, // ICON_ZOOM_MEDIUM + 0x781e0000, 0x40024002, 0x07e04002, 0x07e007e0, 0x07e007e0, 0x400207e0, 0x40024002, 0x0000781e, // ICON_ZOOM_BIG + 0x781e0000, 0x5ffa4002, 0x1ff85ffa, 0x1ff81ff8, 0x1ff81ff8, 0x5ffa1ff8, 0x40025ffa, 0x0000781e, // ICON_ZOOM_ALL + 0x00000000, 0x2004381c, 0x00002004, 0x00000000, 0x00000000, 0x20040000, 0x381c2004, 0x00000000, // ICON_ZOOM_CENTER + 0x00000000, 0x1db80000, 0x10081008, 0x10080000, 0x00001008, 0x10081008, 0x00001db8, 0x00000000, // ICON_BOX_DOTS_SMALL + 0x35560000, 0x00002002, 0x00002002, 0x00002002, 0x00002002, 0x00002002, 0x35562002, 0x00000000, // ICON_BOX_DOTS_BIG + 0x7ffe0000, 0x40024002, 0x48124ff2, 0x49924812, 0x48124992, 0x4ff24812, 0x40024002, 0x00007ffe, // ICON_BOX_CONCENTRIC + 0x00000000, 0x10841ffc, 0x10841084, 0x1ffc1084, 0x10841084, 0x10841084, 0x00001ffc, 0x00000000, // ICON_BOX_GRID_BIG + 0x00000000, 0x00000000, 0x10000000, 0x04000800, 0x01040200, 0x00500088, 0x00000020, 0x00000000, // ICON_OK_TICK + 0x00000000, 0x10080000, 0x04200810, 0x01800240, 0x02400180, 0x08100420, 0x00001008, 0x00000000, // ICON_CROSS + 0x00000000, 0x02000000, 0x00800100, 0x00200040, 0x00200010, 0x00800040, 0x02000100, 0x00000000, // ICON_ARROW_LEFT + 0x00000000, 0x00400000, 0x01000080, 0x04000200, 0x04000800, 0x01000200, 0x00400080, 0x00000000, // ICON_ARROW_RIGHT + 0x00000000, 0x00000000, 0x00000000, 0x08081004, 0x02200410, 0x00800140, 0x00000000, 0x00000000, // ICON_ARROW_DOWN + 0x00000000, 0x00000000, 0x01400080, 0x04100220, 0x10040808, 0x00000000, 0x00000000, 0x00000000, // ICON_ARROW_UP + 0x00000000, 0x02000000, 0x03800300, 0x03e003c0, 0x03e003f0, 0x038003c0, 0x02000300, 0x00000000, // ICON_ARROW_LEFT_FILL + 0x00000000, 0x00400000, 0x01c000c0, 0x07c003c0, 0x07c00fc0, 0x01c003c0, 0x004000c0, 0x00000000, // ICON_ARROW_RIGHT_FILL + 0x00000000, 0x00000000, 0x00000000, 0x0ff81ffc, 0x03e007f0, 0x008001c0, 0x00000000, 0x00000000, // ICON_ARROW_DOWN_FILL + 0x00000000, 0x00000000, 0x01c00080, 0x07f003e0, 0x1ffc0ff8, 0x00000000, 0x00000000, 0x00000000, // ICON_ARROW_UP_FILL + 0x00000000, 0x18a008c0, 0x32881290, 0x24822686, 0x26862482, 0x12903288, 0x08c018a0, 0x00000000, // ICON_AUDIO + 0x00000000, 0x04800780, 0x004000c0, 0x662000f0, 0x08103c30, 0x130a0e18, 0x0000318e, 0x00000000, // ICON_FX + 0x00000000, 0x00800000, 0x08880888, 0x2aaa0a8a, 0x0a8a2aaa, 0x08880888, 0x00000080, 0x00000000, // ICON_WAVE + 0x00000000, 0x00600000, 0x01080090, 0x02040108, 0x42044204, 0x24022402, 0x00001800, 0x00000000, // ICON_WAVE_SINUS + 0x00000000, 0x07f80000, 0x04080408, 0x04080408, 0x04080408, 0x7c0e0408, 0x00000000, 0x00000000, // ICON_WAVE_SQUARE + 0x00000000, 0x00000000, 0x00a00040, 0x22084110, 0x08021404, 0x00000000, 0x00000000, 0x00000000, // ICON_WAVE_TRIANGULAR + 0x00000000, 0x00000000, 0x04200000, 0x01800240, 0x02400180, 0x00000420, 0x00000000, 0x00000000, // ICON_CROSS_SMALL + 0x00000000, 0x18380000, 0x12281428, 0x10a81128, 0x112810a8, 0x14281228, 0x00001838, 0x00000000, // ICON_PLAYER_PREVIOUS + 0x00000000, 0x18000000, 0x11801600, 0x10181060, 0x10601018, 0x16001180, 0x00001800, 0x00000000, // ICON_PLAYER_PLAY_BACK + 0x00000000, 0x00180000, 0x01880068, 0x18080608, 0x06081808, 0x00680188, 0x00000018, 0x00000000, // ICON_PLAYER_PLAY + 0x00000000, 0x1e780000, 0x12481248, 0x12481248, 0x12481248, 0x12481248, 0x00001e78, 0x00000000, // ICON_PLAYER_PAUSE + 0x00000000, 0x1ff80000, 0x10081008, 0x10081008, 0x10081008, 0x10081008, 0x00001ff8, 0x00000000, // ICON_PLAYER_STOP + 0x00000000, 0x1c180000, 0x14481428, 0x15081488, 0x14881508, 0x14281448, 0x00001c18, 0x00000000, // ICON_PLAYER_NEXT + 0x00000000, 0x03c00000, 0x08100420, 0x10081008, 0x10081008, 0x04200810, 0x000003c0, 0x00000000, // ICON_PLAYER_RECORD + 0x00000000, 0x0c3007e0, 0x13c81818, 0x14281668, 0x14281428, 0x1c381c38, 0x08102244, 0x00000000, // ICON_MAGNET + 0x07c00000, 0x08200820, 0x3ff80820, 0x23882008, 0x21082388, 0x20082108, 0x1ff02008, 0x00000000, // ICON_LOCK_CLOSE + 0x07c00000, 0x08000800, 0x3ff80800, 0x23882008, 0x21082388, 0x20082108, 0x1ff02008, 0x00000000, // ICON_LOCK_OPEN + 0x01c00000, 0x0c180770, 0x3086188c, 0x60832082, 0x60034781, 0x30062002, 0x0c18180c, 0x01c00770, // ICON_CLOCK + 0x0a200000, 0x1b201b20, 0x04200e20, 0x04200420, 0x04700420, 0x0e700e70, 0x0e700e70, 0x04200e70, // ICON_TOOLS + 0x01800000, 0x3bdc318c, 0x0ff01ff8, 0x7c3e1e78, 0x1e787c3e, 0x1ff80ff0, 0x318c3bdc, 0x00000180, // ICON_GEAR + 0x01800000, 0x3ffc318c, 0x1c381ff8, 0x781e1818, 0x1818781e, 0x1ff81c38, 0x318c3ffc, 0x00000180, // ICON_GEAR_BIG + 0x00000000, 0x08080ff8, 0x08081ffc, 0x0aa80aa8, 0x0aa80aa8, 0x0aa80aa8, 0x08080aa8, 0x00000ff8, // ICON_BIN + 0x00000000, 0x00000000, 0x20043ffc, 0x08043f84, 0x04040f84, 0x04040784, 0x000007fc, 0x00000000, // ICON_HAND_POINTER + 0x00000000, 0x24400400, 0x00001480, 0x6efe0e00, 0x00000e00, 0x24401480, 0x00000400, 0x00000000, // ICON_LASER + 0x00000000, 0x03c00000, 0x08300460, 0x11181118, 0x11181118, 0x04600830, 0x000003c0, 0x00000000, // ICON_COIN + 0x00000000, 0x10880080, 0x06c00810, 0x366c07e0, 0x07e00240, 0x00001768, 0x04200240, 0x00000000, // ICON_EXPLOSION + 0x00000000, 0x3d280000, 0x2528252c, 0x3d282528, 0x05280528, 0x05e80528, 0x00000000, 0x00000000, // ICON_1UP + 0x01800000, 0x03c003c0, 0x018003c0, 0x0ff007e0, 0x0bd00bd0, 0x0a500bd0, 0x02400240, 0x02400240, // ICON_PLAYER + 0x01800000, 0x03c003c0, 0x118013c0, 0x03c81ff8, 0x07c003c8, 0x04400440, 0x0c080478, 0x00000000, // ICON_PLAYER_JUMP + 0x3ff80000, 0x30183ff8, 0x30183018, 0x3ff83ff8, 0x03000300, 0x03c003c0, 0x03e00300, 0x000003e0, // ICON_KEY + 0x3ff80000, 0x3ff83ff8, 0x33983ff8, 0x3ff83398, 0x3ff83ff8, 0x00000540, 0x0fe00aa0, 0x00000fe0, // ICON_DEMON + 0x00000000, 0x0ff00000, 0x20041008, 0x25442004, 0x10082004, 0x06000bf0, 0x00000300, 0x00000000, // ICON_TEXT_POPUP + 0x00000000, 0x11440000, 0x07f00be8, 0x1c1c0e38, 0x1c1c0c18, 0x07f00e38, 0x11440be8, 0x00000000, // ICON_GEAR_EX + 0x00000000, 0x20080000, 0x0c601010, 0x07c00fe0, 0x07c007c0, 0x0c600fe0, 0x20081010, 0x00000000, // ICON_CRACK + 0x00000000, 0x20080000, 0x0c601010, 0x04400fe0, 0x04405554, 0x0c600fe0, 0x20081010, 0x00000000, // ICON_CRACK_POINTS + 0x00000000, 0x00800080, 0x01c001c0, 0x1ffc3ffe, 0x03e007f0, 0x07f003e0, 0x0c180770, 0x00000808, // ICON_STAR + 0x0ff00000, 0x08180810, 0x08100818, 0x0a100810, 0x08180810, 0x08100818, 0x08100810, 0x00001ff8, // ICON_DOOR + 0x0ff00000, 0x08100810, 0x08100810, 0x10100010, 0x4f902010, 0x10102010, 0x08100010, 0x00000ff0, // ICON_EXIT + 0x00040000, 0x001f000e, 0x0ef40004, 0x12f41284, 0x0ef41214, 0x10040004, 0x7ffc3004, 0x10003000, // ICON_MODE_2D + 0x78040000, 0x501f600e, 0x0ef44004, 0x12f41284, 0x0ef41284, 0x10140004, 0x7ffc300c, 0x10003000, // ICON_MODE_3D + 0x7fe00000, 0x50286030, 0x47fe4804, 0x44224402, 0x44224422, 0x241275e2, 0x0c06140a, 0x000007fe, // ICON_CUBE + 0x7fe00000, 0x5ff87ff0, 0x47fe4ffc, 0x44224402, 0x44224422, 0x241275e2, 0x0c06140a, 0x000007fe, // ICON_CUBE_FACE_TOP + 0x7fe00000, 0x50386030, 0x47c2483c, 0x443e443e, 0x443e443e, 0x241e75fe, 0x0c06140e, 0x000007fe, // ICON_CUBE_FACE_LEFT + 0x7fe00000, 0x50286030, 0x47fe4804, 0x47fe47fe, 0x47fe47fe, 0x27fe77fe, 0x0ffe17fe, 0x000007fe, // ICON_CUBE_FACE_FRONT + 0x7fe00000, 0x50286030, 0x47fe4804, 0x44224402, 0x44224422, 0x3bf27be2, 0x0bfe1bfa, 0x000007fe, // ICON_CUBE_FACE_BOTTOM + 0x7fe00000, 0x70286030, 0x7ffe7804, 0x7c227c02, 0x7c227c22, 0x3c127de2, 0x0c061c0a, 0x000007fe, // ICON_CUBE_FACE_RIGHT + 0x7fe00000, 0x6fe85ff0, 0x781e77e4, 0x7be27be2, 0x7be27be2, 0x24127be2, 0x0c06140a, 0x000007fe, // ICON_CUBE_FACE_BACK + 0x00000000, 0x2a0233fe, 0x22022602, 0x22022202, 0x2a022602, 0x00a033fe, 0x02080110, 0x00000000, // ICON_CAMERA + 0x00000000, 0x200c3ffc, 0x000c000c, 0x3ffc000c, 0x30003000, 0x30003000, 0x3ffc3004, 0x00000000, // ICON_SPECIAL + 0x00000000, 0x0022003e, 0x012201e2, 0x0100013e, 0x01000100, 0x79000100, 0x4f004900, 0x00007800, // ICON_LINK_NET + 0x00000000, 0x44007c00, 0x45004600, 0x00627cbe, 0x00620022, 0x45007cbe, 0x44004600, 0x00007c00, // ICON_LINK_BOXES + 0x00000000, 0x0044007c, 0x0010007c, 0x3f100010, 0x3f1021f0, 0x3f100010, 0x3f0021f0, 0x00000000, // ICON_LINK_MULTI + 0x00000000, 0x0044007c, 0x00440044, 0x0010007c, 0x00100010, 0x44107c10, 0x440047f0, 0x00007c00, // ICON_LINK + 0x00000000, 0x0044007c, 0x00440044, 0x0000007c, 0x00000010, 0x44007c10, 0x44004550, 0x00007c00, // ICON_LINK_BROKE + 0x02a00000, 0x22a43ffc, 0x20042004, 0x20042ff4, 0x20042ff4, 0x20042ff4, 0x20042004, 0x00003ffc, // ICON_TEXT_NOTES + 0x3ffc0000, 0x20042004, 0x245e27c4, 0x27c42444, 0x2004201e, 0x201e2004, 0x20042004, 0x00003ffc, // ICON_NOTEBOOK + 0x00000000, 0x07e00000, 0x04200420, 0x24243ffc, 0x24242424, 0x24242424, 0x3ffc2424, 0x00000000, // ICON_SUITCASE + 0x00000000, 0x0fe00000, 0x08200820, 0x40047ffc, 0x7ffc5554, 0x40045554, 0x7ffc4004, 0x00000000, // ICON_SUITCASE_ZIP + 0x00000000, 0x20043ffc, 0x3ffc2004, 0x13c81008, 0x100813c8, 0x10081008, 0x1ff81008, 0x00000000, // ICON_MAILBOX + 0x00000000, 0x40027ffe, 0x5ffa5ffa, 0x5ffa5ffa, 0x40025ffa, 0x03c07ffe, 0x1ff81ff8, 0x00000000, // ICON_MONITOR + 0x0ff00000, 0x6bfe7ffe, 0x7ffe7ffe, 0x68167ffe, 0x08106816, 0x08100810, 0x0ff00810, 0x00000000, // ICON_PRINTER + 0x3ff80000, 0xfffe2008, 0x870a8002, 0x904a888a, 0x904a904a, 0x870a888a, 0xfffe8002, 0x00000000, // ICON_PHOTO_CAMERA + 0x0fc00000, 0xfcfe0cd8, 0x8002fffe, 0x84428382, 0x84428442, 0x80028382, 0xfffe8002, 0x00000000, // ICON_PHOTO_CAMERA_FLASH + 0x00000000, 0x02400180, 0x08100420, 0x20041008, 0x23c42004, 0x22442244, 0x3ffc2244, 0x00000000, // ICON_HOUSE + 0x00000000, 0x1c700000, 0x3ff83ef8, 0x3ff83ff8, 0x0fe01ff0, 0x038007c0, 0x00000100, 0x00000000, // ICON_HEART + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x80000000, 0xe000c000, // ICON_CORNER + 0x00000000, 0x14001c00, 0x15c01400, 0x15401540, 0x155c1540, 0x15541554, 0x1ddc1554, 0x00000000, // ICON_VERTICAL_BARS + 0x00000000, 0x03000300, 0x1b001b00, 0x1b601b60, 0x1b6c1b60, 0x1b6c1b6c, 0x1b6c1b6c, 0x00000000, // ICON_VERTICAL_BARS_FILL + 0x00000000, 0x00000000, 0x403e7ffe, 0x7ffe403e, 0x7ffe0000, 0x43fe43fe, 0x00007ffe, 0x00000000, // ICON_LIFE_BARS + 0x7ffc0000, 0x43844004, 0x43844284, 0x43844004, 0x42844284, 0x42844284, 0x40044384, 0x00007ffc, // ICON_INFO + 0x40008000, 0x10002000, 0x04000800, 0x01000200, 0x00400080, 0x00100020, 0x00040008, 0x00010002, // ICON_CROSSLINE + 0x00000000, 0x1ff01ff0, 0x18301830, 0x1f001830, 0x03001f00, 0x00000300, 0x03000300, 0x00000000, // ICON_HELP + 0x3ff00000, 0x2abc3550, 0x2aac3554, 0x2aac3554, 0x2aac3554, 0x2aac3554, 0x2aac3554, 0x00003ffc, // ICON_FILETYPE_ALPHA + 0x3ff00000, 0x201c2010, 0x22442184, 0x28142424, 0x29942814, 0x2ff42994, 0x20042004, 0x00003ffc, // ICON_FILETYPE_HOME + 0x07fe0000, 0x04020402, 0x7fe20402, 0x44224422, 0x44224422, 0x402047fe, 0x40204020, 0x00007fe0, // ICON_LAYERS_VISIBLE + 0x07fe0000, 0x04020402, 0x7c020402, 0x44024402, 0x44024402, 0x402047fe, 0x40204020, 0x00007fe0, // ICON_LAYERS + 0x00000000, 0x40027ffe, 0x7ffe4002, 0x40024002, 0x40024002, 0x40024002, 0x7ffe4002, 0x00000000, // ICON_WINDOW + 0x09100000, 0x09f00910, 0x09100910, 0x00000910, 0x24a2779e, 0x27a224a2, 0x709e20a2, 0x00000000, // ICON_HIDPI + 0x3ff00000, 0x201c2010, 0x2a842e84, 0x2e842a84, 0x2ba42004, 0x2aa42aa4, 0x20042ba4, 0x00003ffc, // ICON_FILETYPE_BINARY + 0x00000000, 0x00000000, 0x00120012, 0x4a5e4bd2, 0x485233d2, 0x00004bd2, 0x00000000, 0x00000000, // ICON_HEX + 0x01800000, 0x381c0660, 0x23c42004, 0x23c42044, 0x13c82204, 0x08101008, 0x02400420, 0x00000180, // ICON_SHIELD + 0x007e0000, 0x20023fc2, 0x40227fe2, 0x400a403a, 0x400a400a, 0x400a400a, 0x4008400e, 0x00007ff8, // ICON_FILE_NEW + 0x00000000, 0x0042007e, 0x40027fc2, 0x44024002, 0x5f024402, 0x44024402, 0x7ffe4002, 0x00000000, // ICON_FOLDER_ADD + 0x44220000, 0x12482244, 0xf3cf0000, 0x14280420, 0x48122424, 0x08100810, 0x1ff81008, 0x03c00420, // ICON_ALARM + 0x0aa00000, 0x1ff80aa0, 0x1068700e, 0x1008706e, 0x1008700e, 0x1008700e, 0x0aa01ff8, 0x00000aa0, // ICON_CPU + 0x07e00000, 0x04201db8, 0x04a01c38, 0x04a01d38, 0x04a01d38, 0x04a01d38, 0x04201d38, 0x000007e0, // ICON_ROM + 0x00000000, 0x03c00000, 0x3c382ff0, 0x3c04380c, 0x01800000, 0x03c003c0, 0x00000180, 0x00000000, // ICON_STEP_OVER + 0x01800000, 0x01800180, 0x01800180, 0x03c007e0, 0x00000180, 0x01800000, 0x03c003c0, 0x00000180, // ICON_STEP_INTO + 0x01800000, 0x07e003c0, 0x01800180, 0x01800180, 0x00000180, 0x01800000, 0x03c003c0, 0x00000180, // ICON_STEP_OUT + 0x00000000, 0x0ff003c0, 0x181c1c34, 0x303c301c, 0x30003000, 0x1c301800, 0x03c00ff0, 0x00000000, // ICON_RESTART + 0x00000000, 0x00000000, 0x07e003c0, 0x0ff00ff0, 0x0ff00ff0, 0x03c007e0, 0x00000000, 0x00000000, // ICON_BREAKPOINT_ON + 0x00000000, 0x00000000, 0x042003c0, 0x08100810, 0x08100810, 0x03c00420, 0x00000000, 0x00000000, // ICON_BREAKPOINT_OFF + 0x00000000, 0x00000000, 0x1ff81ff8, 0x1ff80000, 0x00001ff8, 0x1ff81ff8, 0x00000000, 0x00000000, // ICON_BURGER_MENU + 0x00000000, 0x00000000, 0x00880070, 0x0c880088, 0x1e8810f8, 0x3e881288, 0x00000000, 0x00000000, // ICON_CASE_SENSITIVE + 0x00000000, 0x02000000, 0x07000a80, 0x07001fc0, 0x02000a80, 0x00300030, 0x00000000, 0x00000000, // ICON_REG_EXP + 0x00000000, 0x0042007e, 0x40027fc2, 0x40024002, 0x40024002, 0x40024002, 0x7ffe4002, 0x00000000, // ICON_FOLDER + 0x3ff00000, 0x201c2010, 0x20042004, 0x20042004, 0x20042004, 0x20042004, 0x20042004, 0x00003ffc, // ICON_FILE + 0x1ff00000, 0x20082008, 0x17d02fe8, 0x05400ba0, 0x09200540, 0x23881010, 0x2fe827c8, 0x00001ff0, // ICON_SAND_TIMER + 0x01800000, 0x02400240, 0x05a00420, 0x09900990, 0x11881188, 0x21842004, 0x40024182, 0x00003ffc, // ICON_WARNING + 0x7ffe0000, 0x4ff24002, 0x4c324ff2, 0x4f824c02, 0x41824f82, 0x41824002, 0x40024182, 0x00007ffe, // ICON_HELP_BOX + 0x7ffe0000, 0x41824002, 0x40024182, 0x41824182, 0x41824182, 0x41824182, 0x40024182, 0x00007ffe, // ICON_INFO_BOX + 0x01800000, 0x04200240, 0x10080810, 0x7bde2004, 0x0a500a50, 0x08500bd0, 0x08100850, 0x00000ff0, // ICON_PRIORITY + 0x01800000, 0x18180660, 0x80016006, 0x98196006, 0x99996666, 0x19986666, 0x01800660, 0x00000000, // ICON_LAYERS_ISO + 0x07fe0000, 0x1c020402, 0x74021402, 0x54025402, 0x54025402, 0x500857fe, 0x40205ff8, 0x00007fe0, // ICON_LAYERS2 + 0x0ffe0000, 0x3ffa0802, 0x7fea200a, 0x402a402a, 0x422a422a, 0x422e422a, 0x40384e28, 0x00007fe0, // ICON_MLAYERS + 0x0ffe0000, 0x3ffa0802, 0x7fea200a, 0x402a402a, 0x5b2a512a, 0x512e552a, 0x40385128, 0x00007fe0, // ICON_MAPS + 0x04200000, 0x1cf00c60, 0x11f019f0, 0x0f3807b8, 0x1e3c0f3c, 0x1c1c1e1c, 0x1e3c1c1c, 0x00000f70, // ICON_HOT + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_229 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_230 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_231 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_232 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_233 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_234 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_235 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_236 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_237 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_238 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_239 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_240 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_241 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_242 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_243 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_244 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_245 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_246 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_247 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_248 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_249 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_250 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_251 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_252 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_253 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_254 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_255 +}; + +// NOTE: A pointer to current icons array should be defined +static unsigned int *guiIconsPtr = guiIcons; + +#endif // !RAYGUI_NO_ICONS && !RAYGUI_CUSTOM_ICONS + +#ifndef RAYGUI_ICON_SIZE + #define RAYGUI_ICON_SIZE 0 +#endif + +// WARNING: Those values define the total size of the style data array, +// if changed, previous saved styles could become incompatible +#define RAYGUI_MAX_CONTROLS 16 // Maximum number of controls +#define RAYGUI_MAX_PROPS_BASE 16 // Maximum number of base properties +#define RAYGUI_MAX_PROPS_EXTENDED 8 // Maximum number of extended properties + +//---------------------------------------------------------------------------------- +// Types and Structures Definition +//---------------------------------------------------------------------------------- +// Gui control property style color element +typedef enum { BORDER = 0, BASE, TEXT, OTHER } GuiPropertyElement; + +//---------------------------------------------------------------------------------- +// Global Variables Definition +//---------------------------------------------------------------------------------- +static GuiState guiState = STATE_NORMAL; // Gui global state, if !STATE_NORMAL, forces defined state + +static Font guiFont = { 0 }; // Gui current font (WARNING: highly coupled to raylib) +static bool guiLocked = false; // Gui lock state (no inputs processed) +static float guiAlpha = 1.0f; // Gui controls transparency + +static unsigned int guiIconScale = 1; // Gui icon default scale (if icons enabled) + +static bool guiTooltip = false; // Tooltip enabled/disabled +static const char *guiTooltipPtr = NULL; // Tooltip string pointer (string provided by user) + +static bool guiControlExclusiveMode = false; // Gui control exclusive mode (no inputs processed except current control) +static Rectangle guiControlExclusiveRec = { 0 }; // Gui control exclusive bounds rectangle, used as an unique identifier + +static int textBoxCursorIndex = 0; // Cursor index, shared by all GuiTextBox*() +//static int blinkCursorFrameCounter = 0; // Frame counter for cursor blinking +static int autoCursorCounter = 0; // Frame counter for automatic repeated cursor movement on key-down (cooldown and delay) + +//---------------------------------------------------------------------------------- +// Style data array for all gui style properties (allocated on data segment by default) +// +// NOTE 1: First set of BASE properties are generic to all controls but could be individually +// overwritten per control, first set of EXTENDED properties are generic to all controls and +// can not be overwritten individually but custom EXTENDED properties can be used by control +// +// NOTE 2: A new style set could be loaded over this array using GuiLoadStyle(), +// but default gui style could always be recovered with GuiLoadStyleDefault() +// +// guiStyle size is by default: 16*(16 + 8) = 384*4 = 1536 bytes = 1.5 KB +//---------------------------------------------------------------------------------- +static unsigned int guiStyle[RAYGUI_MAX_CONTROLS*(RAYGUI_MAX_PROPS_BASE + RAYGUI_MAX_PROPS_EXTENDED)] = { 0 }; + +static bool guiStyleLoaded = false; // Style loaded flag for lazy style initialization + +//---------------------------------------------------------------------------------- +// Standalone Mode Functions Declaration +// +// NOTE: raygui depend on some raylib input and drawing functions +// To use raygui as standalone library, below functions must be defined by the user +//---------------------------------------------------------------------------------- +#if defined(RAYGUI_STANDALONE) + +#define KEY_RIGHT 262 +#define KEY_LEFT 263 +#define KEY_DOWN 264 +#define KEY_UP 265 +#define KEY_BACKSPACE 259 +#define KEY_ENTER 257 + +#define MOUSE_LEFT_BUTTON 0 + +// Input required functions +//------------------------------------------------------------------------------- +static Vector2 GetMousePosition(void); +static float GetMouseWheelMove(void); +static bool IsMouseButtonDown(int button); +static bool IsMouseButtonPressed(int button); +static bool IsMouseButtonReleased(int button); + +static bool IsKeyDown(int key); +static bool IsKeyPressed(int key); +static int GetCharPressed(void); // -- GuiTextBox(), GuiValueBox() +//------------------------------------------------------------------------------- + +// Drawing required functions +//------------------------------------------------------------------------------- +static void DrawRectangle(int x, int y, int width, int height, Color color); // -- GuiDrawRectangle() +static void DrawRectangleGradientEx(Rectangle rec, Color col1, Color col2, Color col3, Color col4); // -- GuiColorPicker() +//------------------------------------------------------------------------------- + +// Text required functions +//------------------------------------------------------------------------------- +static Font GetFontDefault(void); // -- GuiLoadStyleDefault() +static Font LoadFontEx(const char *fileName, int fontSize, int *codepoints, int codepointCount); // -- GuiLoadStyle(), load font + +static Texture2D LoadTextureFromImage(Image image); // -- GuiLoadStyle(), required to load texture from embedded font atlas image +static void SetShapesTexture(Texture2D tex, Rectangle rec); // -- GuiLoadStyle(), required to set shapes rec to font white rec (optimization) + +static char *LoadFileText(const char *fileName); // -- GuiLoadStyle(), required to load charset data +static void UnloadFileText(char *text); // -- GuiLoadStyle(), required to unload charset data + +static const char *GetDirectoryPath(const char *filePath); // -- GuiLoadStyle(), required to find charset/font file from text .rgs + +static int *LoadCodepoints(const char *text, int *count); // -- GuiLoadStyle(), required to load required font codepoints list +static void UnloadCodepoints(int *codepoints); // -- GuiLoadStyle(), required to unload codepoints list + +static unsigned char *DecompressData(const unsigned char *compData, int compDataSize, int *dataSize); // -- GuiLoadStyle() +//------------------------------------------------------------------------------- + +// raylib functions already implemented in raygui +//------------------------------------------------------------------------------- +static Color GetColor(int hexValue); // Returns a Color struct from hexadecimal value +static int ColorToInt(Color color); // Returns hexadecimal value for a Color +static bool CheckCollisionPointRec(Vector2 point, Rectangle rec); // Check if point is inside rectangle +static const char *TextFormat(const char *text, ...); // Formatting of text with variables to 'embed' +static const char **TextSplit(const char *text, char delimiter, int *count); // Split text into multiple strings +static int TextToInteger(const char *text); // Get integer value from text +static float TextToFloat(const char *text); // Get float value from text + +static int GetCodepointNext(const char *text, int *codepointSize); // Get next codepoint in a UTF-8 encoded text +static const char *CodepointToUTF8(int codepoint, int *byteSize); // Encode codepoint into UTF-8 text (char array size returned as parameter) + +static void DrawRectangleGradientV(int posX, int posY, int width, int height, Color color1, Color color2); // Draw rectangle vertical gradient +//------------------------------------------------------------------------------- + +#endif // RAYGUI_STANDALONE + +//---------------------------------------------------------------------------------- +// Module specific Functions Declaration +//---------------------------------------------------------------------------------- +static void GuiLoadStyleFromMemory(const unsigned char *fileData, int dataSize); // Load style from memory (binary only) + +static int GetTextWidth(const char *text); // Gui get text width using gui font and style +static Rectangle GetTextBounds(int control, Rectangle bounds); // Get text bounds considering control bounds +static const char *GetTextIcon(const char *text, int *iconId); // Get text icon if provided and move text cursor + +static void GuiDrawText(const char *text, Rectangle textBounds, int alignment, Color tint); // Gui draw text using default font +static void GuiDrawRectangle(Rectangle rec, int borderWidth, Color borderColor, Color color); // Gui draw rectangle using default raygui style + +static const char **GuiTextSplit(const char *text, char delimiter, int *count, int *textRow); // Split controls text into multiple strings +static Vector3 ConvertHSVtoRGB(Vector3 hsv); // Convert color data from HSV to RGB +static Vector3 ConvertRGBtoHSV(Vector3 rgb); // Convert color data from RGB to HSV + +static int GuiScrollBar(Rectangle bounds, int value, int minValue, int maxValue); // Scroll bar control, used by GuiScrollPanel() +static void GuiTooltip(Rectangle controlRec); // Draw tooltip using control rec position + +static Color GuiFade(Color color, float alpha); // Fade color by an alpha factor + +//---------------------------------------------------------------------------------- +// Gui Setup Functions Definition +//---------------------------------------------------------------------------------- +// Enable gui global state +// NOTE: We check for STATE_DISABLED to avoid messing custom global state setups +void GuiEnable(void) { if (guiState == STATE_DISABLED) guiState = STATE_NORMAL; } + +// Disable gui global state +// NOTE: We check for STATE_NORMAL to avoid messing custom global state setups +void GuiDisable(void) { if (guiState == STATE_NORMAL) guiState = STATE_DISABLED; } + +// Lock gui global state +void GuiLock(void) { guiLocked = true; } + +// Unlock gui global state +void GuiUnlock(void) { guiLocked = false; } + +// Check if gui is locked (global state) +bool GuiIsLocked(void) { return guiLocked; } + +// Set gui controls alpha global state +void GuiSetAlpha(float alpha) +{ + if (alpha < 0.0f) alpha = 0.0f; + else if (alpha > 1.0f) alpha = 1.0f; + + guiAlpha = alpha; +} + +// Set gui state (global state) +void GuiSetState(int state) { guiState = (GuiState)state; } + +// Get gui state (global state) +int GuiGetState(void) { return guiState; } + +// Set custom gui font +// NOTE: Font loading/unloading is external to raygui +void GuiSetFont(Font font) +{ + if (font.texture.id > 0) + { + // NOTE: If we try to setup a font but default style has not been + // lazily loaded before, it will be overwritten, so we need to force + // default style loading first + if (!guiStyleLoaded) GuiLoadStyleDefault(); + + guiFont = font; + } +} + +// Get custom gui font +Font GuiGetFont(void) +{ + return guiFont; +} + +// Set control style property value +void GuiSetStyle(int control, int property, int value) +{ + if (!guiStyleLoaded) GuiLoadStyleDefault(); + guiStyle[control*(RAYGUI_MAX_PROPS_BASE + RAYGUI_MAX_PROPS_EXTENDED) + property] = value; + + // Default properties are propagated to all controls + if ((control == 0) && (property < RAYGUI_MAX_PROPS_BASE)) + { + for (int i = 1; i < RAYGUI_MAX_CONTROLS; i++) guiStyle[i*(RAYGUI_MAX_PROPS_BASE + RAYGUI_MAX_PROPS_EXTENDED) + property] = value; + } +} + +// Get control style property value +int GuiGetStyle(int control, int property) +{ + if (!guiStyleLoaded) GuiLoadStyleDefault(); + return guiStyle[control*(RAYGUI_MAX_PROPS_BASE + RAYGUI_MAX_PROPS_EXTENDED) + property]; +} + +//---------------------------------------------------------------------------------- +// Gui Controls Functions Definition +//---------------------------------------------------------------------------------- + +// Window Box control +int GuiWindowBox(Rectangle bounds, const char *title) +{ + // Window title bar height (including borders) + // NOTE: This define is also used by GuiMessageBox() and GuiTextInputBox() + #if !defined(RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT) + #define RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT 24 + #endif + + #if !defined(RAYGUI_WINDOWBOX_CLOSEBUTTON_HEIGHT) + #define RAYGUI_WINDOWBOX_CLOSEBUTTON_HEIGHT 18 + #endif + + int result = 0; + //GuiState state = guiState; + + int statusBarHeight = RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT; + + Rectangle statusBar = { bounds.x, bounds.y, bounds.width, (float)statusBarHeight }; + if (bounds.height < statusBarHeight*2.0f) bounds.height = statusBarHeight*2.0f; + + const float vPadding = statusBarHeight/2.0f - RAYGUI_WINDOWBOX_CLOSEBUTTON_HEIGHT/2.0f; + Rectangle windowPanel = { bounds.x, bounds.y + (float)statusBarHeight - 1, bounds.width, bounds.height - (float)statusBarHeight + 1 }; + Rectangle closeButtonRec = { statusBar.x + statusBar.width - GuiGetStyle(STATUSBAR, BORDER_WIDTH) - RAYGUI_WINDOWBOX_CLOSEBUTTON_HEIGHT - vPadding, + statusBar.y + vPadding, RAYGUI_WINDOWBOX_CLOSEBUTTON_HEIGHT, RAYGUI_WINDOWBOX_CLOSEBUTTON_HEIGHT }; + + // Update control + //-------------------------------------------------------------------- + // NOTE: Logic is directly managed by button + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + GuiStatusBar(statusBar, title); // Draw window header as status bar + GuiPanel(windowPanel, NULL); // Draw window base + + // Draw window close button + int tempBorderWidth = GuiGetStyle(BUTTON, BORDER_WIDTH); + int tempTextAlignment = GuiGetStyle(BUTTON, TEXT_ALIGNMENT); + GuiSetStyle(BUTTON, BORDER_WIDTH, 1); + GuiSetStyle(BUTTON, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER); +#if defined(RAYGUI_NO_ICONS) + result = GuiButton(closeButtonRec, "x"); +#else + result = GuiButton(closeButtonRec, GuiIconText(ICON_CROSS_SMALL, NULL)); +#endif + GuiSetStyle(BUTTON, BORDER_WIDTH, tempBorderWidth); + GuiSetStyle(BUTTON, TEXT_ALIGNMENT, tempTextAlignment); + //-------------------------------------------------------------------- + + return result; // Window close button clicked: result = 1 +} + +// Group Box control with text name +int GuiGroupBox(Rectangle bounds, const char *text) +{ + #if !defined(RAYGUI_GROUPBOX_LINE_THICK) + #define RAYGUI_GROUPBOX_LINE_THICK 1 + #endif + + int result = 0; + GuiState state = guiState; + + // Draw control + //-------------------------------------------------------------------- + GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y, RAYGUI_GROUPBOX_LINE_THICK, bounds.height }, 0, BLANK, GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? (int)BORDER_COLOR_DISABLED : (int)LINE_COLOR))); + GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y + bounds.height - 1, bounds.width, RAYGUI_GROUPBOX_LINE_THICK }, 0, BLANK, GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? (int)BORDER_COLOR_DISABLED : (int)LINE_COLOR))); + GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x + bounds.width - 1, bounds.y, RAYGUI_GROUPBOX_LINE_THICK, bounds.height }, 0, BLANK, GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? (int)BORDER_COLOR_DISABLED : (int)LINE_COLOR))); + + GuiLine(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y - GuiGetStyle(DEFAULT, TEXT_SIZE)/2, bounds.width, (float)GuiGetStyle(DEFAULT, TEXT_SIZE) }, text); + //-------------------------------------------------------------------- + + return result; +} + +// Line control +int GuiLine(Rectangle bounds, const char *text) +{ + #if !defined(RAYGUI_LINE_MARGIN_TEXT) + #define RAYGUI_LINE_MARGIN_TEXT 12 + #endif + #if !defined(RAYGUI_LINE_TEXT_PADDING) + #define RAYGUI_LINE_TEXT_PADDING 4 + #endif + + int result = 0; + GuiState state = guiState; + + Color color = GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? (int)BORDER_COLOR_DISABLED : (int)LINE_COLOR)); + + // Draw control + //-------------------------------------------------------------------- + if (text == NULL) GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y + bounds.height/2, bounds.width, 1 }, 0, BLANK, color); + else + { + Rectangle textBounds = { 0 }; + textBounds.width = (float)GetTextWidth(text) + 2; + textBounds.height = bounds.height; + textBounds.x = bounds.x + RAYGUI_LINE_MARGIN_TEXT; + textBounds.y = bounds.y; + + // Draw line with embedded text label: "--- text --------------" + GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y + bounds.height/2, RAYGUI_LINE_MARGIN_TEXT - RAYGUI_LINE_TEXT_PADDING, 1 }, 0, BLANK, color); + GuiDrawText(text, textBounds, TEXT_ALIGN_LEFT, color); + GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x + 12 + textBounds.width + 4, bounds.y + bounds.height/2, bounds.width - textBounds.width - RAYGUI_LINE_MARGIN_TEXT - RAYGUI_LINE_TEXT_PADDING, 1 }, 0, BLANK, color); + } + //-------------------------------------------------------------------- + + return result; +} + +// Panel control +int GuiPanel(Rectangle bounds, const char *text) +{ + #if !defined(RAYGUI_PANEL_BORDER_WIDTH) + #define RAYGUI_PANEL_BORDER_WIDTH 1 + #endif + + int result = 0; + GuiState state = guiState; + + // Text will be drawn as a header bar (if provided) + Rectangle statusBar = { bounds.x, bounds.y, bounds.width, (float)RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT }; + if ((text != NULL) && (bounds.height < RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT*2.0f)) bounds.height = RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT*2.0f; + + if (text != NULL) + { + // Move panel bounds after the header bar + bounds.y += (float)RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT - 1; + bounds.height -= (float)RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT - 1; + } + + // Draw control + //-------------------------------------------------------------------- + if (text != NULL) GuiStatusBar(statusBar, text); // Draw panel header as status bar + + GuiDrawRectangle(bounds, RAYGUI_PANEL_BORDER_WIDTH, GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? (int)BORDER_COLOR_DISABLED : (int)LINE_COLOR)), + GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? (int)BASE_COLOR_DISABLED : (int)BACKGROUND_COLOR))); + //-------------------------------------------------------------------- + + return result; +} + +// Tab Bar control +// NOTE: Using GuiToggle() for the TABS +int GuiTabBar(Rectangle bounds, const char **text, int count, int *active) +{ + #define RAYGUI_TABBAR_ITEM_WIDTH 160 + + int result = -1; + //GuiState state = guiState; + + Rectangle tabBounds = { bounds.x, bounds.y, RAYGUI_TABBAR_ITEM_WIDTH, bounds.height }; + + if (*active < 0) *active = 0; + else if (*active > count - 1) *active = count - 1; + + int offsetX = 0; // Required in case tabs go out of screen + offsetX = (*active + 2)*RAYGUI_TABBAR_ITEM_WIDTH - GetScreenWidth(); + if (offsetX < 0) offsetX = 0; + + bool toggle = false; // Required for individual toggles + + // Draw control + //-------------------------------------------------------------------- + for (int i = 0; i < count; i++) + { + tabBounds.x = bounds.x + (RAYGUI_TABBAR_ITEM_WIDTH + 4)*i - offsetX; + + if (tabBounds.x < GetScreenWidth()) + { + // Draw tabs as toggle controls + int textAlignment = GuiGetStyle(TOGGLE, TEXT_ALIGNMENT); + int textPadding = GuiGetStyle(TOGGLE, TEXT_PADDING); + GuiSetStyle(TOGGLE, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT); + GuiSetStyle(TOGGLE, TEXT_PADDING, 8); + + if (i == (*active)) + { + toggle = true; + GuiToggle(tabBounds, GuiIconText(12, text[i]), &toggle); + } + else + { + toggle = false; + GuiToggle(tabBounds, GuiIconText(12, text[i]), &toggle); + if (toggle) *active = i; + } + + // Close tab with middle mouse button pressed + if (CheckCollisionPointRec(GetMousePosition(), tabBounds) && IsMouseButtonPressed(MOUSE_MIDDLE_BUTTON)) result = i; + + GuiSetStyle(TOGGLE, TEXT_PADDING, textPadding); + GuiSetStyle(TOGGLE, TEXT_ALIGNMENT, textAlignment); + + // Draw tab close button + // NOTE: Only draw close button for current tab: if (CheckCollisionPointRec(mousePosition, tabBounds)) + int tempBorderWidth = GuiGetStyle(BUTTON, BORDER_WIDTH); + int tempTextAlignment = GuiGetStyle(BUTTON, TEXT_ALIGNMENT); + GuiSetStyle(BUTTON, BORDER_WIDTH, 1); + GuiSetStyle(BUTTON, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER); +#if defined(RAYGUI_NO_ICONS) + if (GuiButton(RAYGUI_CLITERAL(Rectangle){ tabBounds.x + tabBounds.width - 14 - 5, tabBounds.y + 5, 14, 14 }, "x")) result = i; +#else + if (GuiButton(RAYGUI_CLITERAL(Rectangle){ tabBounds.x + tabBounds.width - 14 - 5, tabBounds.y + 5, 14, 14 }, GuiIconText(ICON_CROSS_SMALL, NULL))) result = i; +#endif + GuiSetStyle(BUTTON, BORDER_WIDTH, tempBorderWidth); + GuiSetStyle(BUTTON, TEXT_ALIGNMENT, tempTextAlignment); + } + } + + // Draw tab-bar bottom line + GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y + bounds.height - 1, bounds.width, 1 }, 0, BLANK, GetColor(GuiGetStyle(TOGGLE, BORDER_COLOR_NORMAL))); + //-------------------------------------------------------------------- + + return result; // Return as result the current TAB closing requested +} + +// Scroll Panel control +int GuiScrollPanel(Rectangle bounds, const char *text, Rectangle content, Vector2 *scroll, Rectangle *view) +{ + #define RAYGUI_MIN_SCROLLBAR_WIDTH 40 + #define RAYGUI_MIN_SCROLLBAR_HEIGHT 40 + #define RAYGUI_MIN_MOUSE_WHEEL_SPEED 20 + + int result = 0; + GuiState state = guiState; + + Rectangle temp = { 0 }; + if (view == NULL) view = &temp; + + Vector2 scrollPos = { 0.0f, 0.0f }; + if (scroll != NULL) scrollPos = *scroll; + + // Text will be drawn as a header bar (if provided) + Rectangle statusBar = { bounds.x, bounds.y, bounds.width, (float)RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT }; + if (bounds.height < RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT*2.0f) bounds.height = RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT*2.0f; + + if (text != NULL) + { + // Move panel bounds after the header bar + bounds.y += (float)RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT - 1; + bounds.height -= (float)RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT + 1; + } + + bool hasHorizontalScrollBar = (content.width > bounds.width - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH))? true : false; + bool hasVerticalScrollBar = (content.height > bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH))? true : false; + + // Recheck to account for the other scrollbar being visible + if (!hasHorizontalScrollBar) hasHorizontalScrollBar = (hasVerticalScrollBar && (content.width > (bounds.width - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH))))? true : false; + if (!hasVerticalScrollBar) hasVerticalScrollBar = (hasHorizontalScrollBar && (content.height > (bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH))))? true : false; + + int horizontalScrollBarWidth = hasHorizontalScrollBar? GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH) : 0; + int verticalScrollBarWidth = hasVerticalScrollBar? GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH) : 0; + Rectangle horizontalScrollBar = { + (float)((GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE)? (float)bounds.x + verticalScrollBarWidth : (float)bounds.x) + GuiGetStyle(DEFAULT, BORDER_WIDTH), + (float)bounds.y + bounds.height - horizontalScrollBarWidth - GuiGetStyle(DEFAULT, BORDER_WIDTH), + (float)bounds.width - verticalScrollBarWidth - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH), + (float)horizontalScrollBarWidth + }; + Rectangle verticalScrollBar = { + (float)((GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE)? (float)bounds.x + GuiGetStyle(DEFAULT, BORDER_WIDTH) : (float)bounds.x + bounds.width - verticalScrollBarWidth - GuiGetStyle(DEFAULT, BORDER_WIDTH)), + (float)bounds.y + GuiGetStyle(DEFAULT, BORDER_WIDTH), + (float)verticalScrollBarWidth, + (float)bounds.height - horizontalScrollBarWidth - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) + }; + + // Make sure scroll bars have a minimum width/height + if (horizontalScrollBar.width < RAYGUI_MIN_SCROLLBAR_WIDTH) horizontalScrollBar.width = RAYGUI_MIN_SCROLLBAR_WIDTH; + if (verticalScrollBar.height < RAYGUI_MIN_SCROLLBAR_HEIGHT) verticalScrollBar.height = RAYGUI_MIN_SCROLLBAR_HEIGHT; + + // Calculate view area (area without the scrollbars) + *view = (GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE)? + RAYGUI_CLITERAL(Rectangle){ bounds.x + verticalScrollBarWidth + GuiGetStyle(DEFAULT, BORDER_WIDTH), bounds.y + GuiGetStyle(DEFAULT, BORDER_WIDTH), bounds.width - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - verticalScrollBarWidth, bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - horizontalScrollBarWidth } : + RAYGUI_CLITERAL(Rectangle){ bounds.x + GuiGetStyle(DEFAULT, BORDER_WIDTH), bounds.y + GuiGetStyle(DEFAULT, BORDER_WIDTH), bounds.width - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - verticalScrollBarWidth, bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - horizontalScrollBarWidth }; + + // Clip view area to the actual content size + if (view->width > content.width) view->width = content.width; + if (view->height > content.height) view->height = content.height; + + float horizontalMin = hasHorizontalScrollBar? ((GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE)? (float)-verticalScrollBarWidth : 0) - (float)GuiGetStyle(DEFAULT, BORDER_WIDTH) : (((float)GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE)? (float)-verticalScrollBarWidth : 0) - (float)GuiGetStyle(DEFAULT, BORDER_WIDTH); + float horizontalMax = hasHorizontalScrollBar? content.width - bounds.width + (float)verticalScrollBarWidth + GuiGetStyle(DEFAULT, BORDER_WIDTH) - (((float)GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE)? (float)verticalScrollBarWidth : 0) : (float)-GuiGetStyle(DEFAULT, BORDER_WIDTH); + float verticalMin = hasVerticalScrollBar? 0.0f : -1.0f; + float verticalMax = hasVerticalScrollBar? content.height - bounds.height + (float)horizontalScrollBarWidth + (float)GuiGetStyle(DEFAULT, BORDER_WIDTH) : (float)-GuiGetStyle(DEFAULT, BORDER_WIDTH); + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked) + { + Vector2 mousePoint = GetMousePosition(); + + // Check button state + if (CheckCollisionPointRec(mousePoint, bounds)) + { + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = STATE_PRESSED; + else state = STATE_FOCUSED; + +#if defined(SUPPORT_SCROLLBAR_KEY_INPUT) + if (hasHorizontalScrollBar) + { + if (IsKeyDown(KEY_RIGHT)) scrollPos.x -= GuiGetStyle(SCROLLBAR, SCROLL_SPEED); + if (IsKeyDown(KEY_LEFT)) scrollPos.x += GuiGetStyle(SCROLLBAR, SCROLL_SPEED); + } + + if (hasVerticalScrollBar) + { + if (IsKeyDown(KEY_DOWN)) scrollPos.y -= GuiGetStyle(SCROLLBAR, SCROLL_SPEED); + if (IsKeyDown(KEY_UP)) scrollPos.y += GuiGetStyle(SCROLLBAR, SCROLL_SPEED); + } +#endif + float wheelMove = GetMouseWheelMove(); + + // Set scrolling speed with mouse wheel based on ratio between bounds and content + Vector2 mouseWheelSpeed = { content.width/bounds.width, content.height/bounds.height }; + if (mouseWheelSpeed.x < RAYGUI_MIN_MOUSE_WHEEL_SPEED) mouseWheelSpeed.x = RAYGUI_MIN_MOUSE_WHEEL_SPEED; + if (mouseWheelSpeed.y < RAYGUI_MIN_MOUSE_WHEEL_SPEED) mouseWheelSpeed.y = RAYGUI_MIN_MOUSE_WHEEL_SPEED; + + // Horizontal and vertical scrolling with mouse wheel + if (hasHorizontalScrollBar && (IsKeyDown(KEY_LEFT_CONTROL) || IsKeyDown(KEY_LEFT_SHIFT))) scrollPos.x += wheelMove*mouseWheelSpeed.x; + else scrollPos.y += wheelMove*mouseWheelSpeed.y; // Vertical scroll + } + } + + // Normalize scroll values + if (scrollPos.x > -horizontalMin) scrollPos.x = -horizontalMin; + if (scrollPos.x < -horizontalMax) scrollPos.x = -horizontalMax; + if (scrollPos.y > -verticalMin) scrollPos.y = -verticalMin; + if (scrollPos.y < -verticalMax) scrollPos.y = -verticalMax; + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + if (text != NULL) GuiStatusBar(statusBar, text); // Draw panel header as status bar + + GuiDrawRectangle(bounds, 0, BLANK, GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR))); // Draw background + + // Save size of the scrollbar slider + const int slider = GuiGetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE); + + // Draw horizontal scrollbar if visible + if (hasHorizontalScrollBar) + { + // Change scrollbar slider size to show the diff in size between the content width and the widget width + GuiSetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE, (int)(((bounds.width - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - verticalScrollBarWidth)/(int)content.width)*((int)bounds.width - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - verticalScrollBarWidth))); + scrollPos.x = (float)-GuiScrollBar(horizontalScrollBar, (int)-scrollPos.x, (int)horizontalMin, (int)horizontalMax); + } + else scrollPos.x = 0.0f; + + // Draw vertical scrollbar if visible + if (hasVerticalScrollBar) + { + // Change scrollbar slider size to show the diff in size between the content height and the widget height + GuiSetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE, (int)(((bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - horizontalScrollBarWidth)/(int)content.height)*((int)bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - horizontalScrollBarWidth))); + scrollPos.y = (float)-GuiScrollBar(verticalScrollBar, (int)-scrollPos.y, (int)verticalMin, (int)verticalMax); + } + else scrollPos.y = 0.0f; + + // Draw detail corner rectangle if both scroll bars are visible + if (hasHorizontalScrollBar && hasVerticalScrollBar) + { + Rectangle corner = { (GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE)? (bounds.x + GuiGetStyle(DEFAULT, BORDER_WIDTH) + 2) : (horizontalScrollBar.x + horizontalScrollBar.width + 2), verticalScrollBar.y + verticalScrollBar.height + 2, (float)horizontalScrollBarWidth - 4, (float)verticalScrollBarWidth - 4 }; + GuiDrawRectangle(corner, 0, BLANK, GetColor(GuiGetStyle(LISTVIEW, TEXT + (state*3)))); + } + + // Draw scrollbar lines depending on current state + GuiDrawRectangle(bounds, GuiGetStyle(LISTVIEW, BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER + (state*3))), BLANK); + + // Set scrollbar slider size back to the way it was before + GuiSetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE, slider); + //-------------------------------------------------------------------- + + if (scroll != NULL) *scroll = scrollPos; + + return result; +} + +// Label control +int GuiLabel(Rectangle bounds, const char *text) +{ + int result = 0; + GuiState state = guiState; + + // Update control + //-------------------------------------------------------------------- + //... + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + GuiDrawText(text, GetTextBounds(LABEL, bounds), GuiGetStyle(LABEL, TEXT_ALIGNMENT), GetColor(GuiGetStyle(LABEL, TEXT + (state*3)))); + //-------------------------------------------------------------------- + + return result; +} + +// Button control, returns true when clicked +int GuiButton(Rectangle bounds, const char *text) +{ + int result = 0; + GuiState state = guiState; + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode) + { + Vector2 mousePoint = GetMousePosition(); + + // Check button state + if (CheckCollisionPointRec(mousePoint, bounds)) + { + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = STATE_PRESSED; + else state = STATE_FOCUSED; + + if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) result = 1; + } + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + GuiDrawRectangle(bounds, GuiGetStyle(BUTTON, BORDER_WIDTH), GetColor(GuiGetStyle(BUTTON, BORDER + (state*3))), GetColor(GuiGetStyle(BUTTON, BASE + (state*3)))); + GuiDrawText(text, GetTextBounds(BUTTON, bounds), GuiGetStyle(BUTTON, TEXT_ALIGNMENT), GetColor(GuiGetStyle(BUTTON, TEXT + (state*3)))); + + if (state == STATE_FOCUSED) GuiTooltip(bounds); + //------------------------------------------------------------------ + + return result; // Button pressed: result = 1 +} + +// Label button control +int GuiLabelButton(Rectangle bounds, const char *text) +{ + GuiState state = guiState; + bool pressed = false; + + // NOTE: We force bounds.width to be all text + float textWidth = (float)GetTextWidth(text); + if ((bounds.width - 2*GuiGetStyle(LABEL, BORDER_WIDTH) - 2*GuiGetStyle(LABEL, TEXT_PADDING)) < textWidth) bounds.width = textWidth + 2*GuiGetStyle(LABEL, BORDER_WIDTH) + 2*GuiGetStyle(LABEL, TEXT_PADDING) + 2; + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode) + { + Vector2 mousePoint = GetMousePosition(); + + // Check checkbox state + if (CheckCollisionPointRec(mousePoint, bounds)) + { + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = STATE_PRESSED; + else state = STATE_FOCUSED; + + if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) pressed = true; + } + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + GuiDrawText(text, GetTextBounds(LABEL, bounds), GuiGetStyle(LABEL, TEXT_ALIGNMENT), GetColor(GuiGetStyle(LABEL, TEXT + (state*3)))); + //-------------------------------------------------------------------- + + return pressed; +} + +// Toggle Button control +int GuiToggle(Rectangle bounds, const char *text, bool *active) +{ + int result = 0; + GuiState state = guiState; + + bool temp = false; + if (active == NULL) active = &temp; + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode) + { + Vector2 mousePoint = GetMousePosition(); + + // Check toggle button state + if (CheckCollisionPointRec(mousePoint, bounds)) + { + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = STATE_PRESSED; + else if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) + { + state = STATE_NORMAL; + *active = !(*active); + } + else state = STATE_FOCUSED; + } + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + if (state == STATE_NORMAL) + { + GuiDrawRectangle(bounds, GuiGetStyle(TOGGLE, BORDER_WIDTH), GetColor(GuiGetStyle(TOGGLE, ((*active)? BORDER_COLOR_PRESSED : (BORDER + state*3)))), GetColor(GuiGetStyle(TOGGLE, ((*active)? BASE_COLOR_PRESSED : (BASE + state*3))))); + GuiDrawText(text, GetTextBounds(TOGGLE, bounds), GuiGetStyle(TOGGLE, TEXT_ALIGNMENT), GetColor(GuiGetStyle(TOGGLE, ((*active)? TEXT_COLOR_PRESSED : (TEXT + state*3))))); + } + else + { + GuiDrawRectangle(bounds, GuiGetStyle(TOGGLE, BORDER_WIDTH), GetColor(GuiGetStyle(TOGGLE, BORDER + state*3)), GetColor(GuiGetStyle(TOGGLE, BASE + state*3))); + GuiDrawText(text, GetTextBounds(TOGGLE, bounds), GuiGetStyle(TOGGLE, TEXT_ALIGNMENT), GetColor(GuiGetStyle(TOGGLE, TEXT + state*3))); + } + + if (state == STATE_FOCUSED) GuiTooltip(bounds); + //-------------------------------------------------------------------- + + return result; +} + +// Toggle Group control +int GuiToggleGroup(Rectangle bounds, const char *text, int *active) +{ + #if !defined(RAYGUI_TOGGLEGROUP_MAX_ITEMS) + #define RAYGUI_TOGGLEGROUP_MAX_ITEMS 32 + #endif + + int result = 0; + float initBoundsX = bounds.x; + + int temp = 0; + if (active == NULL) active = &temp; + + bool toggle = false; // Required for individual toggles + + // Get substrings items from text (items pointers) + int rows[RAYGUI_TOGGLEGROUP_MAX_ITEMS] = { 0 }; + int itemCount = 0; + const char **items = GuiTextSplit(text, ';', &itemCount, rows); + + int prevRow = rows[0]; + + for (int i = 0; i < itemCount; i++) + { + if (prevRow != rows[i]) + { + bounds.x = initBoundsX; + bounds.y += (bounds.height + GuiGetStyle(TOGGLE, GROUP_PADDING)); + prevRow = rows[i]; + } + + if (i == (*active)) + { + toggle = true; + GuiToggle(bounds, items[i], &toggle); + } + else + { + toggle = false; + GuiToggle(bounds, items[i], &toggle); + if (toggle) *active = i; + } + + bounds.x += (bounds.width + GuiGetStyle(TOGGLE, GROUP_PADDING)); + } + + return result; +} + +// Toggle Slider control extended +int GuiToggleSlider(Rectangle bounds, const char *text, int *active) +{ + int result = 0; + GuiState state = guiState; + + int temp = 0; + if (active == NULL) active = &temp; + + //bool toggle = false; // Required for individual toggles + + // Get substrings items from text (items pointers) + int itemCount = 0; + const char **items = NULL; + + if (text != NULL) items = GuiTextSplit(text, ';', &itemCount, NULL); + + Rectangle slider = { + 0, // Calculated later depending on the active toggle + bounds.y + GuiGetStyle(SLIDER, BORDER_WIDTH) + GuiGetStyle(SLIDER, SLIDER_PADDING), + (bounds.width - 2*GuiGetStyle(SLIDER, BORDER_WIDTH) - (itemCount + 1)*GuiGetStyle(SLIDER, SLIDER_PADDING))/itemCount, + bounds.height - 2*GuiGetStyle(SLIDER, BORDER_WIDTH) - 2*GuiGetStyle(SLIDER, SLIDER_PADDING) }; + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked) + { + Vector2 mousePoint = GetMousePosition(); + + if (CheckCollisionPointRec(mousePoint, bounds)) + { + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = STATE_PRESSED; + else if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) + { + state = STATE_PRESSED; + (*active)++; + result = 1; + } + else state = STATE_FOCUSED; + } + + if ((*active) && (state != STATE_FOCUSED)) state = STATE_PRESSED; + } + + if (*active >= itemCount) *active = 0; + slider.x = bounds.x + GuiGetStyle(SLIDER, BORDER_WIDTH) + (*active + 1)*GuiGetStyle(SLIDER, SLIDER_PADDING) + (*active)*slider.width; + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + GuiDrawRectangle(bounds, GuiGetStyle(SLIDER, BORDER_WIDTH), GetColor(GuiGetStyle(TOGGLE, BORDER + (state*3))), + GetColor(GuiGetStyle(TOGGLE, BASE_COLOR_NORMAL))); + + // Draw internal slider + if (state == STATE_NORMAL) GuiDrawRectangle(slider, 0, BLANK, GetColor(GuiGetStyle(SLIDER, BASE_COLOR_PRESSED))); + else if (state == STATE_FOCUSED) GuiDrawRectangle(slider, 0, BLANK, GetColor(GuiGetStyle(SLIDER, BASE_COLOR_FOCUSED))); + else if (state == STATE_PRESSED) GuiDrawRectangle(slider, 0, BLANK, GetColor(GuiGetStyle(SLIDER, BASE_COLOR_PRESSED))); + + // Draw text in slider + if (text != NULL) + { + Rectangle textBounds = { 0 }; + textBounds.width = (float)GetTextWidth(text); + textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE); + textBounds.x = slider.x + slider.width/2 - textBounds.width/2; + textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2; + + GuiDrawText(items[*active], textBounds, GuiGetStyle(TOGGLE, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(TOGGLE, TEXT + (state*3))), guiAlpha)); + } + //-------------------------------------------------------------------- + + return result; +} + +// Check Box control, returns 1 when state changed +int GuiCheckBox(Rectangle bounds, const char *text, bool *checked) +{ + int result = 0; + GuiState state = guiState; + + bool temp = false; + if (checked == NULL) checked = &temp; + + Rectangle textBounds = { 0 }; + + if (text != NULL) + { + textBounds.width = (float)GetTextWidth(text) + 2; + textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE); + textBounds.x = bounds.x + bounds.width + GuiGetStyle(CHECKBOX, TEXT_PADDING); + textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2; + if (GuiGetStyle(CHECKBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_LEFT) textBounds.x = bounds.x - textBounds.width - GuiGetStyle(CHECKBOX, TEXT_PADDING); + } + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode) + { + Vector2 mousePoint = GetMousePosition(); + + Rectangle totalBounds = { + (GuiGetStyle(CHECKBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_LEFT)? textBounds.x : bounds.x, + bounds.y, + bounds.width + textBounds.width + GuiGetStyle(CHECKBOX, TEXT_PADDING), + bounds.height, + }; + + // Check checkbox state + if (CheckCollisionPointRec(mousePoint, totalBounds)) + { + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = STATE_PRESSED; + else state = STATE_FOCUSED; + + if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) + { + *checked = !(*checked); + result = 1; + } + } + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + GuiDrawRectangle(bounds, GuiGetStyle(CHECKBOX, BORDER_WIDTH), GetColor(GuiGetStyle(CHECKBOX, BORDER + (state*3))), BLANK); + + if (*checked) + { + Rectangle check = { bounds.x + GuiGetStyle(CHECKBOX, BORDER_WIDTH) + GuiGetStyle(CHECKBOX, CHECK_PADDING), + bounds.y + GuiGetStyle(CHECKBOX, BORDER_WIDTH) + GuiGetStyle(CHECKBOX, CHECK_PADDING), + bounds.width - 2*(GuiGetStyle(CHECKBOX, BORDER_WIDTH) + GuiGetStyle(CHECKBOX, CHECK_PADDING)), + bounds.height - 2*(GuiGetStyle(CHECKBOX, BORDER_WIDTH) + GuiGetStyle(CHECKBOX, CHECK_PADDING)) }; + GuiDrawRectangle(check, 0, BLANK, GetColor(GuiGetStyle(CHECKBOX, TEXT + state*3))); + } + + GuiDrawText(text, textBounds, (GuiGetStyle(CHECKBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_RIGHT)? TEXT_ALIGN_LEFT : TEXT_ALIGN_RIGHT, GetColor(GuiGetStyle(LABEL, TEXT + (state*3)))); + //-------------------------------------------------------------------- + + return result; +} + +// Combo Box control +int GuiComboBox(Rectangle bounds, const char *text, int *active) +{ + int result = 0; + GuiState state = guiState; + + int temp = 0; + if (active == NULL) active = &temp; + + bounds.width -= (GuiGetStyle(COMBOBOX, COMBO_BUTTON_WIDTH) + GuiGetStyle(COMBOBOX, COMBO_BUTTON_SPACING)); + + Rectangle selector = { (float)bounds.x + bounds.width + GuiGetStyle(COMBOBOX, COMBO_BUTTON_SPACING), + (float)bounds.y, (float)GuiGetStyle(COMBOBOX, COMBO_BUTTON_WIDTH), (float)bounds.height }; + + // Get substrings items from text (items pointers, lengths and count) + int itemCount = 0; + const char **items = GuiTextSplit(text, ';', &itemCount, NULL); + + if (*active < 0) *active = 0; + else if (*active > (itemCount - 1)) *active = itemCount - 1; + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked && (itemCount > 1) && !guiControlExclusiveMode) + { + Vector2 mousePoint = GetMousePosition(); + + if (CheckCollisionPointRec(mousePoint, bounds) || + CheckCollisionPointRec(mousePoint, selector)) + { + if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) + { + *active += 1; + if (*active >= itemCount) *active = 0; // Cyclic combobox + } + + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = STATE_PRESSED; + else state = STATE_FOCUSED; + } + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + // Draw combo box main + GuiDrawRectangle(bounds, GuiGetStyle(COMBOBOX, BORDER_WIDTH), GetColor(GuiGetStyle(COMBOBOX, BORDER + (state*3))), GetColor(GuiGetStyle(COMBOBOX, BASE + (state*3)))); + GuiDrawText(items[*active], GetTextBounds(COMBOBOX, bounds), GuiGetStyle(COMBOBOX, TEXT_ALIGNMENT), GetColor(GuiGetStyle(COMBOBOX, TEXT + (state*3)))); + + // Draw selector using a custom button + // NOTE: BORDER_WIDTH and TEXT_ALIGNMENT forced values + int tempBorderWidth = GuiGetStyle(BUTTON, BORDER_WIDTH); + int tempTextAlign = GuiGetStyle(BUTTON, TEXT_ALIGNMENT); + GuiSetStyle(BUTTON, BORDER_WIDTH, 1); + GuiSetStyle(BUTTON, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER); + + GuiButton(selector, TextFormat("%i/%i", *active + 1, itemCount)); + + GuiSetStyle(BUTTON, TEXT_ALIGNMENT, tempTextAlign); + GuiSetStyle(BUTTON, BORDER_WIDTH, tempBorderWidth); + //-------------------------------------------------------------------- + + return result; +} + +// Dropdown Box control +// NOTE: Returns mouse click +int GuiDropdownBox(Rectangle bounds, const char *text, int *active, bool editMode) +{ + int result = 0; + GuiState state = guiState; + + int temp = 0; + if (active == NULL) active = &temp; + + int itemSelected = *active; + int itemFocused = -1; + + int direction = 0; // Dropdown box open direction: down (default) + if (GuiGetStyle(DROPDOWNBOX, DROPDOWN_ROLL_UP) == 1) direction = 1; // Up + + // Get substrings items from text (items pointers, lengths and count) + int itemCount = 0; + const char **items = GuiTextSplit(text, ';', &itemCount, NULL); + + Rectangle boundsOpen = bounds; + boundsOpen.height = (itemCount + 1)*(bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING)); + if (direction == 1) boundsOpen.y -= itemCount*(bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING)) + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING); + + Rectangle itemBounds = bounds; + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && (editMode || !guiLocked) && (itemCount > 1) && !guiControlExclusiveMode) + { + Vector2 mousePoint = GetMousePosition(); + + if (editMode) + { + state = STATE_PRESSED; + + // Check if mouse has been pressed or released outside limits + if (!CheckCollisionPointRec(mousePoint, boundsOpen)) + { + if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON) || IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) result = 1; + } + + // Check if already selected item has been pressed again + if (CheckCollisionPointRec(mousePoint, bounds) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) result = 1; + + // Check focused and selected item + for (int i = 0; i < itemCount; i++) + { + // Update item rectangle y position for next item + if (direction == 0) itemBounds.y += (bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING)); + else itemBounds.y -= (bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING)); + + if (CheckCollisionPointRec(mousePoint, itemBounds)) + { + itemFocused = i; + if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) + { + itemSelected = i; + result = 1; // Item selected + } + break; + } + } + + itemBounds = bounds; + } + else + { + if (CheckCollisionPointRec(mousePoint, bounds)) + { + if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) + { + result = 1; + state = STATE_PRESSED; + } + else state = STATE_FOCUSED; + } + } + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + if (editMode) GuiPanel(boundsOpen, NULL); + + GuiDrawRectangle(bounds, GuiGetStyle(DROPDOWNBOX, BORDER_WIDTH), GetColor(GuiGetStyle(DROPDOWNBOX, BORDER + state*3)), GetColor(GuiGetStyle(DROPDOWNBOX, BASE + state*3))); + GuiDrawText(items[itemSelected], GetTextBounds(DROPDOWNBOX, bounds), GuiGetStyle(DROPDOWNBOX, TEXT_ALIGNMENT), GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + state*3))); + + if (editMode) + { + // Draw visible items + for (int i = 0; i < itemCount; i++) + { + // Update item rectangle y position for next item + if (direction == 0) itemBounds.y += (bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING)); + else itemBounds.y -= (bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING)); + + if (i == itemSelected) + { + GuiDrawRectangle(itemBounds, GuiGetStyle(DROPDOWNBOX, BORDER_WIDTH), GetColor(GuiGetStyle(DROPDOWNBOX, BORDER_COLOR_PRESSED)), GetColor(GuiGetStyle(DROPDOWNBOX, BASE_COLOR_PRESSED))); + GuiDrawText(items[i], GetTextBounds(DROPDOWNBOX, itemBounds), GuiGetStyle(DROPDOWNBOX, TEXT_ALIGNMENT), GetColor(GuiGetStyle(DROPDOWNBOX, TEXT_COLOR_PRESSED))); + } + else if (i == itemFocused) + { + GuiDrawRectangle(itemBounds, GuiGetStyle(DROPDOWNBOX, BORDER_WIDTH), GetColor(GuiGetStyle(DROPDOWNBOX, BORDER_COLOR_FOCUSED)), GetColor(GuiGetStyle(DROPDOWNBOX, BASE_COLOR_FOCUSED))); + GuiDrawText(items[i], GetTextBounds(DROPDOWNBOX, itemBounds), GuiGetStyle(DROPDOWNBOX, TEXT_ALIGNMENT), GetColor(GuiGetStyle(DROPDOWNBOX, TEXT_COLOR_FOCUSED))); + } + else GuiDrawText(items[i], GetTextBounds(DROPDOWNBOX, itemBounds), GuiGetStyle(DROPDOWNBOX, TEXT_ALIGNMENT), GetColor(GuiGetStyle(DROPDOWNBOX, TEXT_COLOR_NORMAL))); + } + } + + if (!GuiGetStyle(DROPDOWNBOX, DROPDOWN_ARROW_HIDDEN)) + { + // Draw arrows (using icon if available) +#if defined(RAYGUI_NO_ICONS) + GuiDrawText("v", RAYGUI_CLITERAL(Rectangle){ bounds.x + bounds.width - GuiGetStyle(DROPDOWNBOX, ARROW_PADDING), bounds.y + bounds.height/2 - 2, 10, 10 }, + TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + (state*3)))); +#else + GuiDrawText(direction? "#121#" : "#120#", RAYGUI_CLITERAL(Rectangle){ bounds.x + bounds.width - GuiGetStyle(DROPDOWNBOX, ARROW_PADDING), bounds.y + bounds.height/2 - 6, 10, 10 }, + TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + (state*3)))); // ICON_ARROW_DOWN_FILL +#endif + } + //-------------------------------------------------------------------- + + *active = itemSelected; + + // TODO: Use result to return more internal states: mouse-press out-of-bounds, mouse-press over selected-item... + return result; // Mouse click: result = 1 +} + +// Text Box control +// NOTE: Returns true on ENTER pressed (useful for data validation) +int GuiTextBox(Rectangle bounds, char *text, int textSize, bool editMode) +{ + #if !defined(RAYGUI_TEXTBOX_AUTO_CURSOR_COOLDOWN) + #define RAYGUI_TEXTBOX_AUTO_CURSOR_COOLDOWN 30 // Frames to wait for autocursor movement + #endif + #if !defined(RAYGUI_TEXTBOX_AUTO_CURSOR_DELAY) + #define RAYGUI_TEXTBOX_AUTO_CURSOR_DELAY 2 // Frames delay for autocursor movement + #endif + + int result = 0; + GuiState state = guiState; + + bool multiline = false; // TODO: Consider multiline text input + int wrapMode = GuiGetStyle(DEFAULT, TEXT_WRAP_MODE); + + Rectangle textBounds = GetTextBounds(TEXTBOX, bounds); + int textLength = (text != NULL)? (int)strlen(text) : 0; // Get current text length + int thisCursorIndex = textBoxCursorIndex; + if (thisCursorIndex > textLength) thisCursorIndex = textLength; + int textWidth = GetTextWidth(text) - GetTextWidth(text + thisCursorIndex); + int textIndexOffset = 0; // Text index offset to start drawing in the box + + // Cursor rectangle + // NOTE: Position X value should be updated + Rectangle cursor = { + textBounds.x + textWidth + GuiGetStyle(DEFAULT, TEXT_SPACING), + textBounds.y + textBounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE), + 2, + (float)GuiGetStyle(DEFAULT, TEXT_SIZE)*2 + }; + + if (cursor.height >= bounds.height) cursor.height = bounds.height - GuiGetStyle(TEXTBOX, BORDER_WIDTH)*2; + if (cursor.y < (bounds.y + GuiGetStyle(TEXTBOX, BORDER_WIDTH))) cursor.y = bounds.y + GuiGetStyle(TEXTBOX, BORDER_WIDTH); + + // Mouse cursor rectangle + // NOTE: Initialized outside of screen + Rectangle mouseCursor = cursor; + mouseCursor.x = -1; + mouseCursor.width = 1; + + // Blink-cursor frame counter + //if (!autoCursorMode) blinkCursorFrameCounter++; + //else blinkCursorFrameCounter = 0; + + // Update control + //-------------------------------------------------------------------- + // WARNING: Text editing is only supported under certain conditions: + if ((state != STATE_DISABLED) && // Control not disabled + !GuiGetStyle(TEXTBOX, TEXT_READONLY) && // TextBox not on read-only mode + !guiLocked && // Gui not locked + !guiControlExclusiveMode && // No gui slider on dragging + (wrapMode == TEXT_WRAP_NONE)) // No wrap mode + { + Vector2 mousePosition = GetMousePosition(); + + if (editMode) + { + // GLOBAL: Auto-cursor movement logic + // NOTE: Keystrokes are handled repeatedly when button is held down for some time + if (IsKeyDown(KEY_LEFT) || IsKeyDown(KEY_RIGHT) || IsKeyDown(KEY_UP) || IsKeyDown(KEY_DOWN) || IsKeyDown(KEY_BACKSPACE) || IsKeyDown(KEY_DELETE)) autoCursorCounter++; + else autoCursorCounter = 0; + + bool autoCursorShouldTrigger = (autoCursorCounter > RAYGUI_TEXTBOX_AUTO_CURSOR_COOLDOWN) && ((autoCursorCounter % RAYGUI_TEXTBOX_AUTO_CURSOR_DELAY) == 0); + + state = STATE_PRESSED; + + if (textBoxCursorIndex > textLength) textBoxCursorIndex = textLength; + + // If text does not fit in the textbox and current cursor position is out of bounds, + // we add an index offset to text for drawing only what requires depending on cursor + while (textWidth >= textBounds.width) + { + int nextCodepointSize = 0; + GetCodepointNext(text + textIndexOffset, &nextCodepointSize); + + textIndexOffset += nextCodepointSize; + + textWidth = GetTextWidth(text + textIndexOffset) - GetTextWidth(text + textBoxCursorIndex); + } + + int codepoint = GetCharPressed(); // Get Unicode codepoint + if (multiline && IsKeyPressed(KEY_ENTER)) codepoint = (int)'\n'; + + // Encode codepoint as UTF-8 + int codepointSize = 0; + const char *charEncoded = CodepointToUTF8(codepoint, &codepointSize); + + // Handle Paste action + if (IsKeyPressed(KEY_V) && (IsKeyDown(KEY_LEFT_CONTROL) || IsKeyDown(KEY_RIGHT_CONTROL))) + { + const char *pasteText = GetClipboardText(); + if (pasteText != NULL) + { + int pasteLength = 0; + int pasteCodepoint; + int pasteCodepointSize; + // count how many codepoints to copy, stopping at the first unwanted control character + while (true) + { + pasteCodepoint = GetCodepointNext(pasteText + pasteLength, &pasteCodepointSize); + if (textLength + pasteLength + pasteCodepointSize >= textSize) break; + if (!(multiline && (pasteCodepoint == (int)'\n')) && !(pasteCodepoint >= 32)) break; + pasteLength += pasteCodepointSize; + } + if (pasteLength > 0) + { + // Move forward data from cursor position + for (int i = textLength + pasteLength; i > textBoxCursorIndex; i--) text[i] = text[i - pasteLength]; + + // Paste data in at cursor + for (int i = 0; i < pasteLength; i++) text[textBoxCursorIndex + i] = pasteText[i]; + + textBoxCursorIndex += pasteLength; + textLength += pasteLength; + text[textLength] = '\0'; + } + } + } + // Add codepoint to text, at current cursor position + // NOTE: Make sure we do not overflow buffer size + else if (((multiline && (codepoint == (int)'\n')) || (codepoint >= 32)) && ((textLength + codepointSize) < textSize)) + { + // Move forward data from cursor position + for (int i = (textLength + codepointSize); i > textBoxCursorIndex; i--) text[i] = text[i - codepointSize]; + + // Add new codepoint in current cursor position + for (int i = 0; i < codepointSize; i++) text[textBoxCursorIndex + i] = charEncoded[i]; + + textBoxCursorIndex += codepointSize; + textLength += codepointSize; + + // Make sure text last character is EOL + text[textLength] = '\0'; + } + + // Move cursor to start + if ((textLength > 0) && IsKeyPressed(KEY_HOME)) textBoxCursorIndex = 0; + + // Move cursor to end + if ((textLength > textBoxCursorIndex) && IsKeyPressed(KEY_END)) textBoxCursorIndex = textLength; + + // Delete related codepoints from text, after current cursor position + if ((textLength > textBoxCursorIndex) && IsKeyPressed(KEY_DELETE) && (IsKeyDown(KEY_LEFT_CONTROL) || IsKeyDown(KEY_RIGHT_CONTROL))) + { + int offset = textBoxCursorIndex; + int accCodepointSize = 0; + int nextCodepointSize; + int nextCodepoint; + // Check characters of the same type to delete (either ASCII punctuation or anything non-whitespace) + // Not using isalnum() since it only works on ASCII characters + nextCodepoint = GetCodepointNext(text + offset, &nextCodepointSize); + bool puctuation = ispunct(nextCodepoint & 0xFF); + while (offset < textLength) + { + if ((puctuation && !ispunct(nextCodepoint & 0xFF)) || (!puctuation && (isspace(nextCodepoint & 0xFF) || ispunct(nextCodepoint & 0xFF)))) + break; + offset += nextCodepointSize; + accCodepointSize += nextCodepointSize; + nextCodepoint = GetCodepointNext(text + offset, &nextCodepointSize); + } + // Check whitespace to delete (ASCII only) + while (offset < textLength) + { + if (!isspace(nextCodepoint & 0xFF)) + break; + offset += nextCodepointSize; + accCodepointSize += nextCodepointSize; + nextCodepoint = GetCodepointNext(text + offset, &nextCodepointSize); + } + + // Move text after cursor forward (including final null terminator) + for (int i = offset; i <= textLength; i++) text[i - accCodepointSize] = text[i]; + + textLength -= accCodepointSize; + } + // Delete single codepoint from text, after current cursor position + else if ((textLength > textBoxCursorIndex) && (IsKeyPressed(KEY_DELETE) || (IsKeyDown(KEY_DELETE) && autoCursorShouldTrigger))) + { + int nextCodepointSize = 0; + GetCodepointNext(text + textBoxCursorIndex, &nextCodepointSize); + + // Move text after cursor forward (including final null terminator) + for (int i = textBoxCursorIndex + nextCodepointSize; i <= textLength; i++) text[i - nextCodepointSize] = text[i]; + + textLength -= nextCodepointSize; + } + + // Delete related codepoints from text, before current cursor position + if ((textBoxCursorIndex > 0) && IsKeyPressed(KEY_BACKSPACE) && (IsKeyDown(KEY_LEFT_CONTROL) || IsKeyDown(KEY_RIGHT_CONTROL))) + { + int offset = textBoxCursorIndex; + int accCodepointSize = 0; + int prevCodepointSize; + int prevCodepoint; + + // Check whitespace to delete (ASCII only) + while (offset > 0) + { + prevCodepoint = GetCodepointPrevious(text + offset, &prevCodepointSize); + if (!isspace(prevCodepoint & 0xFF)) break; + + offset -= prevCodepointSize; + accCodepointSize += prevCodepointSize; + } + // Check characters of the same type to delete (either ASCII punctuation or anything non-whitespace) + // Not using isalnum() since it only works on ASCII characters + bool puctuation = ispunct(prevCodepoint & 0xFF); + while (offset > 0) + { + prevCodepoint = GetCodepointPrevious(text + offset, &prevCodepointSize); + if ((puctuation && !ispunct(prevCodepoint & 0xFF)) || (!puctuation && (isspace(prevCodepoint & 0xFF) || ispunct(prevCodepoint & 0xFF)))) break; + + offset -= prevCodepointSize; + accCodepointSize += prevCodepointSize; + } + + // Move text after cursor forward (including final null terminator) + for (int i = textBoxCursorIndex; i <= textLength; i++) text[i - accCodepointSize] = text[i]; + + textLength -= accCodepointSize; + textBoxCursorIndex -= accCodepointSize; + } + // Delete single codepoint from text, before current cursor position + else if ((textBoxCursorIndex > 0) && (IsKeyPressed(KEY_BACKSPACE) || (IsKeyDown(KEY_BACKSPACE) && autoCursorShouldTrigger))) + { + int prevCodepointSize = 0; + + GetCodepointPrevious(text + textBoxCursorIndex, &prevCodepointSize); + + // Move text after cursor forward (including final null terminator) + for (int i = textBoxCursorIndex; i <= textLength; i++) text[i - prevCodepointSize] = text[i]; + + textLength -= prevCodepointSize; + textBoxCursorIndex -= prevCodepointSize; + } + + // Move cursor position with keys + if ((textBoxCursorIndex > 0) && IsKeyPressed(KEY_LEFT) && (IsKeyDown(KEY_LEFT_CONTROL) || IsKeyDown(KEY_RIGHT_CONTROL))) + { + int offset = textBoxCursorIndex; + int accCodepointSize = 0; + int prevCodepointSize; + int prevCodepoint; + + // Check whitespace to skip (ASCII only) + while (offset > 0) + { + prevCodepoint = GetCodepointPrevious(text + offset, &prevCodepointSize); + if (!isspace(prevCodepoint & 0xFF)) break; + + offset -= prevCodepointSize; + accCodepointSize += prevCodepointSize; + } + + // Check characters of the same type to skip (either ASCII punctuation or anything non-whitespace) + // Not using isalnum() since it only works on ASCII characters + bool puctuation = ispunct(prevCodepoint & 0xFF); + while (offset > 0) + { + prevCodepoint = GetCodepointPrevious(text + offset, &prevCodepointSize); + if ((puctuation && !ispunct(prevCodepoint & 0xFF)) || (!puctuation && (isspace(prevCodepoint & 0xFF) || ispunct(prevCodepoint & 0xFF)))) break; + + offset -= prevCodepointSize; + accCodepointSize += prevCodepointSize; + } + + textBoxCursorIndex = offset; + } + else if ((textBoxCursorIndex > 0) && (IsKeyPressed(KEY_LEFT) || (IsKeyDown(KEY_LEFT) && autoCursorShouldTrigger))) + { + int prevCodepointSize = 0; + GetCodepointPrevious(text + textBoxCursorIndex, &prevCodepointSize); + + textBoxCursorIndex -= prevCodepointSize; + } + else if ((textLength > textBoxCursorIndex) && IsKeyPressed(KEY_RIGHT) && (IsKeyDown(KEY_LEFT_CONTROL) || IsKeyDown(KEY_RIGHT_CONTROL))) + { + int offset = textBoxCursorIndex; + int accCodepointSize = 0; + int nextCodepointSize; + int nextCodepoint; + + // Check characters of the same type to skip (either ASCII punctuation or anything non-whitespace) + // Not using isalnum() since it only works on ASCII characters + nextCodepoint = GetCodepointNext(text + offset, &nextCodepointSize); + bool puctuation = ispunct(nextCodepoint & 0xFF); + while (offset < textLength) + { + if ((puctuation && !ispunct(nextCodepoint & 0xFF)) || (!puctuation && (isspace(nextCodepoint & 0xFF) || ispunct(nextCodepoint & 0xFF)))) break; + + offset += nextCodepointSize; + accCodepointSize += nextCodepointSize; + nextCodepoint = GetCodepointNext(text + offset, &nextCodepointSize); + } + + // Check whitespace to skip (ASCII only) + while (offset < textLength) + { + if (!isspace(nextCodepoint & 0xFF)) break; + + offset += nextCodepointSize; + accCodepointSize += nextCodepointSize; + nextCodepoint = GetCodepointNext(text + offset, &nextCodepointSize); + } + + textBoxCursorIndex = offset; + } + else if ((textLength > textBoxCursorIndex) && (IsKeyPressed(KEY_RIGHT) || (IsKeyDown(KEY_RIGHT) && autoCursorShouldTrigger))) + { + int nextCodepointSize = 0; + GetCodepointNext(text + textBoxCursorIndex, &nextCodepointSize); + + textBoxCursorIndex += nextCodepointSize; + } + + // Move cursor position with mouse + if (CheckCollisionPointRec(mousePosition, textBounds)) // Mouse hover text + { + float scaleFactor = (float)GuiGetStyle(DEFAULT, TEXT_SIZE)/(float)guiFont.baseSize; + int codepointIndex = 0; + float glyphWidth = 0.0f; + float widthToMouseX = 0; + int mouseCursorIndex = 0; + + for (int i = textIndexOffset; i < textLength; i += codepointSize) + { + codepoint = GetCodepointNext(&text[i], &codepointSize); + codepointIndex = GetGlyphIndex(guiFont, codepoint); + + if (guiFont.glyphs[codepointIndex].advanceX == 0) glyphWidth = ((float)guiFont.recs[codepointIndex].width*scaleFactor); + else glyphWidth = ((float)guiFont.glyphs[codepointIndex].advanceX*scaleFactor); + + if (mousePosition.x <= (textBounds.x + (widthToMouseX + glyphWidth/2))) + { + mouseCursor.x = textBounds.x + widthToMouseX; + mouseCursorIndex = i; + break; + } + + widthToMouseX += (glyphWidth + (float)GuiGetStyle(DEFAULT, TEXT_SPACING)); + } + + // Check if mouse cursor is at the last position + int textEndWidth = GetTextWidth(text + textIndexOffset); + if (GetMousePosition().x >= (textBounds.x + textEndWidth - glyphWidth/2)) + { + mouseCursor.x = textBounds.x + textEndWidth; + mouseCursorIndex = textLength; + } + + // Place cursor at required index on mouse click + if ((mouseCursor.x >= 0) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) + { + cursor.x = mouseCursor.x; + textBoxCursorIndex = mouseCursorIndex; + } + } + else mouseCursor.x = -1; + + // Recalculate cursor position.y depending on textBoxCursorIndex + cursor.x = bounds.x + GuiGetStyle(TEXTBOX, TEXT_PADDING) + GetTextWidth(text + textIndexOffset) - GetTextWidth(text + textBoxCursorIndex) + GuiGetStyle(DEFAULT, TEXT_SPACING); + //if (multiline) cursor.y = GetTextLines() + + // Finish text editing on ENTER or mouse click outside bounds + if ((!multiline && IsKeyPressed(KEY_ENTER)) || + (!CheckCollisionPointRec(mousePosition, bounds) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON))) + { + textBoxCursorIndex = 0; // GLOBAL: Reset the shared cursor index + autoCursorCounter = 0; // GLOBAL: Reset counter for repeated keystrokes + result = 1; + } + } + else + { + if (CheckCollisionPointRec(mousePosition, bounds)) + { + state = STATE_FOCUSED; + + if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) + { + textBoxCursorIndex = textLength; // GLOBAL: Place cursor index to the end of current text + autoCursorCounter = 0; // GLOBAL: Reset counter for repeated keystrokes + result = 1; + } + } + } + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + if (state == STATE_PRESSED) + { + GuiDrawRectangle(bounds, GuiGetStyle(TEXTBOX, BORDER_WIDTH), GetColor(GuiGetStyle(TEXTBOX, BORDER + (state*3))), GetColor(GuiGetStyle(TEXTBOX, BASE_COLOR_PRESSED))); + } + else if (state == STATE_DISABLED) + { + GuiDrawRectangle(bounds, GuiGetStyle(TEXTBOX, BORDER_WIDTH), GetColor(GuiGetStyle(TEXTBOX, BORDER + (state*3))), GetColor(GuiGetStyle(TEXTBOX, BASE_COLOR_DISABLED))); + } + else GuiDrawRectangle(bounds, GuiGetStyle(TEXTBOX, BORDER_WIDTH), GetColor(GuiGetStyle(TEXTBOX, BORDER + (state*3))), BLANK); + + // Draw text considering index offset if required + // NOTE: Text index offset depends on cursor position + GuiDrawText(text + textIndexOffset, textBounds, GuiGetStyle(TEXTBOX, TEXT_ALIGNMENT), GetColor(GuiGetStyle(TEXTBOX, TEXT + (state*3)))); + + // Draw cursor + if (editMode && !GuiGetStyle(TEXTBOX, TEXT_READONLY)) + { + //if (autoCursorMode || ((blinkCursorFrameCounter/40)%2 == 0)) + GuiDrawRectangle(cursor, 0, BLANK, GetColor(GuiGetStyle(TEXTBOX, BORDER_COLOR_PRESSED))); + + // Draw mouse position cursor (if required) + if (mouseCursor.x >= 0) GuiDrawRectangle(mouseCursor, 0, BLANK, GetColor(GuiGetStyle(TEXTBOX, BORDER_COLOR_PRESSED))); + } + else if (state == STATE_FOCUSED) GuiTooltip(bounds); + //-------------------------------------------------------------------- + + return result; // Mouse button pressed: result = 1 +} + +/* +// Text Box control with multiple lines and word-wrap +// NOTE: This text-box is readonly, no editing supported by default +bool GuiTextBoxMulti(Rectangle bounds, char *text, int textSize, bool editMode) +{ + bool pressed = false; + + GuiSetStyle(TEXTBOX, TEXT_READONLY, 1); + GuiSetStyle(DEFAULT, TEXT_WRAP_MODE, TEXT_WRAP_WORD); // WARNING: If wrap mode enabled, text editing is not supported + GuiSetStyle(DEFAULT, TEXT_ALIGNMENT_VERTICAL, TEXT_ALIGN_TOP); + + // TODO: Implement methods to calculate cursor position properly + pressed = GuiTextBox(bounds, text, textSize, editMode); + + GuiSetStyle(DEFAULT, TEXT_ALIGNMENT_VERTICAL, TEXT_ALIGN_MIDDLE); + GuiSetStyle(DEFAULT, TEXT_WRAP_MODE, TEXT_WRAP_NONE); + GuiSetStyle(TEXTBOX, TEXT_READONLY, 0); + + return pressed; +} +*/ + +// Spinner control, returns selected value +int GuiSpinner(Rectangle bounds, const char *text, int *value, int minValue, int maxValue, bool editMode) +{ + int result = 1; + GuiState state = guiState; + + int tempValue = *value; + + Rectangle valueBoxBounds = { + bounds.x + GuiGetStyle(VALUEBOX, SPINNER_BUTTON_WIDTH) + GuiGetStyle(VALUEBOX, SPINNER_BUTTON_SPACING), + bounds.y, + bounds.width - 2*(GuiGetStyle(VALUEBOX, SPINNER_BUTTON_WIDTH) + GuiGetStyle(VALUEBOX, SPINNER_BUTTON_SPACING)), bounds.height }; + Rectangle leftButtonBound = { (float)bounds.x, (float)bounds.y, (float)GuiGetStyle(VALUEBOX, SPINNER_BUTTON_WIDTH), (float)bounds.height }; + Rectangle rightButtonBound = { (float)bounds.x + bounds.width - GuiGetStyle(VALUEBOX, SPINNER_BUTTON_WIDTH), (float)bounds.y, + (float)GuiGetStyle(VALUEBOX, SPINNER_BUTTON_WIDTH), (float)bounds.height }; + + Rectangle textBounds = { 0 }; + if (text != NULL) + { + textBounds.width = (float)GetTextWidth(text) + 2; + textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE); + textBounds.x = bounds.x + bounds.width + GuiGetStyle(VALUEBOX, TEXT_PADDING); + textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2; + if (GuiGetStyle(VALUEBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_LEFT) textBounds.x = bounds.x - textBounds.width - GuiGetStyle(VALUEBOX, TEXT_PADDING); + } + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode) + { + Vector2 mousePoint = GetMousePosition(); + + // Check spinner state + if (CheckCollisionPointRec(mousePoint, bounds)) + { + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = STATE_PRESSED; + else state = STATE_FOCUSED; + } + } + +#if defined(RAYGUI_NO_ICONS) + if (GuiButton(leftButtonBound, "<")) tempValue--; + if (GuiButton(rightButtonBound, ">")) tempValue++; +#else + if (GuiButton(leftButtonBound, GuiIconText(ICON_ARROW_LEFT_FILL, NULL))) tempValue--; + if (GuiButton(rightButtonBound, GuiIconText(ICON_ARROW_RIGHT_FILL, NULL))) tempValue++; +#endif + + if (!editMode) + { + if (tempValue < minValue) tempValue = minValue; + if (tempValue > maxValue) tempValue = maxValue; + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + result = GuiValueBox(valueBoxBounds, NULL, &tempValue, minValue, maxValue, editMode); + + // Draw value selector custom buttons + // NOTE: BORDER_WIDTH and TEXT_ALIGNMENT forced values + int tempBorderWidth = GuiGetStyle(BUTTON, BORDER_WIDTH); + int tempTextAlign = GuiGetStyle(BUTTON, TEXT_ALIGNMENT); + GuiSetStyle(BUTTON, BORDER_WIDTH, GuiGetStyle(VALUEBOX, BORDER_WIDTH)); + GuiSetStyle(BUTTON, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER); + + GuiSetStyle(BUTTON, TEXT_ALIGNMENT, tempTextAlign); + GuiSetStyle(BUTTON, BORDER_WIDTH, tempBorderWidth); + + // Draw text label if provided + GuiDrawText(text, textBounds, (GuiGetStyle(VALUEBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_RIGHT)? TEXT_ALIGN_LEFT : TEXT_ALIGN_RIGHT, GetColor(GuiGetStyle(LABEL, TEXT + (state*3)))); + //-------------------------------------------------------------------- + + *value = tempValue; + return result; +} + +// Value Box control, updates input text with numbers +// NOTE: Requires static variables: frameCounter +int GuiValueBox(Rectangle bounds, const char *text, int *value, int minValue, int maxValue, bool editMode) +{ + #if !defined(RAYGUI_VALUEBOX_MAX_CHARS) + #define RAYGUI_VALUEBOX_MAX_CHARS 32 + #endif + + int result = 0; + GuiState state = guiState; + + char textValue[RAYGUI_VALUEBOX_MAX_CHARS + 1] = "\0"; + snprintf(textValue, RAYGUI_VALUEBOX_MAX_CHARS + 1, "%i", *value); + + Rectangle textBounds = { 0 }; + if (text != NULL) + { + textBounds.width = (float)GetTextWidth(text) + 2; + textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE); + textBounds.x = bounds.x + bounds.width + GuiGetStyle(VALUEBOX, TEXT_PADDING); + textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2; + if (GuiGetStyle(VALUEBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_LEFT) textBounds.x = bounds.x - textBounds.width - GuiGetStyle(VALUEBOX, TEXT_PADDING); + } + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode) + { + Vector2 mousePoint = GetMousePosition(); + + bool valueHasChanged = false; + + if (editMode) + { + state = STATE_PRESSED; + + int keyCount = (int)strlen(textValue); + + // Only allow keys in range [48..57] + if (keyCount < RAYGUI_VALUEBOX_MAX_CHARS) + { + if (GetTextWidth(textValue) < bounds.width) + { + int key = GetCharPressed(); + if ((key >= 48) && (key <= 57)) + { + textValue[keyCount] = (char)key; + keyCount++; + valueHasChanged = true; + } + } + } + + // Delete text + if (keyCount > 0) + { + if (IsKeyPressed(KEY_BACKSPACE)) + { + keyCount--; + textValue[keyCount] = '\0'; + valueHasChanged = true; + } + } + + if (valueHasChanged) *value = TextToInteger(textValue); + + // NOTE: We are not clamp values until user input finishes + //if (*value > maxValue) *value = maxValue; + //else if (*value < minValue) *value = minValue; + + if ((IsKeyPressed(KEY_ENTER) || IsKeyPressed(KEY_KP_ENTER)) || (!CheckCollisionPointRec(mousePoint, bounds) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON))) + { + if (*value > maxValue) *value = maxValue; + else if (*value < minValue) *value = minValue; + + result = 1; + } + } + else + { + if (*value > maxValue) *value = maxValue; + else if (*value < minValue) *value = minValue; + + if (CheckCollisionPointRec(mousePoint, bounds)) + { + state = STATE_FOCUSED; + if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) result = 1; + } + } + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + Color baseColor = BLANK; + if (state == STATE_PRESSED) baseColor = GetColor(GuiGetStyle(VALUEBOX, BASE_COLOR_PRESSED)); + else if (state == STATE_DISABLED) baseColor = GetColor(GuiGetStyle(VALUEBOX, BASE_COLOR_DISABLED)); + + GuiDrawRectangle(bounds, GuiGetStyle(VALUEBOX, BORDER_WIDTH), GetColor(GuiGetStyle(VALUEBOX, BORDER + (state*3))), baseColor); + GuiDrawText(textValue, GetTextBounds(VALUEBOX, bounds), TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(VALUEBOX, TEXT + (state*3)))); + + // Draw cursor rectangle + if (editMode) + { + // NOTE: ValueBox internal text is always centered + Rectangle cursor = { bounds.x + GetTextWidth(textValue)/2 + bounds.width/2 + 1, + bounds.y + GuiGetStyle(TEXTBOX, BORDER_WIDTH) + 2, + 2, bounds.height - GuiGetStyle(TEXTBOX, BORDER_WIDTH)*2 - 4 }; + if (cursor.height > bounds.height) cursor.height = bounds.height - GuiGetStyle(TEXTBOX, BORDER_WIDTH)*2; + GuiDrawRectangle(cursor, 0, BLANK, GetColor(GuiGetStyle(VALUEBOX, BORDER_COLOR_PRESSED))); + } + + // Draw text label if provided + GuiDrawText(text, textBounds, (GuiGetStyle(VALUEBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_RIGHT)? TEXT_ALIGN_LEFT : TEXT_ALIGN_RIGHT, GetColor(GuiGetStyle(LABEL, TEXT + (state*3)))); + //-------------------------------------------------------------------- + + return result; +} + +// Floating point Value Box control, updates input val_str with numbers +// NOTE: Requires static variables: frameCounter +int GuiValueBoxFloat(Rectangle bounds, const char *text, char *textValue, float *value, bool editMode) +{ + #if !defined(RAYGUI_VALUEBOX_MAX_CHARS) + #define RAYGUI_VALUEBOX_MAX_CHARS 32 + #endif + + int result = 0; + GuiState state = guiState; + + //char textValue[RAYGUI_VALUEBOX_MAX_CHARS + 1] = "\0"; + //snprintf(textValue, sizeof(textValue), "%2.2f", *value); + + Rectangle textBounds = {0}; + if (text != NULL) + { + textBounds.width = (float)GetTextWidth(text) + 2; + textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE); + textBounds.x = bounds.x + bounds.width + GuiGetStyle(VALUEBOX, TEXT_PADDING); + textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2; + if (GuiGetStyle(VALUEBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_LEFT) textBounds.x = bounds.x - textBounds.width - GuiGetStyle(VALUEBOX, TEXT_PADDING); + } + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode) + { + Vector2 mousePoint = GetMousePosition(); + + bool valueHasChanged = false; + + if (editMode) + { + state = STATE_PRESSED; + + int keyCount = (int)strlen(textValue); + + // Only allow keys in range [48..57] + if (keyCount < RAYGUI_VALUEBOX_MAX_CHARS) + { + if (GetTextWidth(textValue) < bounds.width) + { + int key = GetCharPressed(); + if (((key >= 48) && (key <= 57)) || + (key == '.') || + ((keyCount == 0) && (key == '+')) || // NOTE: Sign can only be in first position + ((keyCount == 0) && (key == '-'))) + { + textValue[keyCount] = (char)key; + keyCount++; + + valueHasChanged = true; + } + } + } + + // Pressed backspace + if (IsKeyPressed(KEY_BACKSPACE)) + { + if (keyCount > 0) + { + keyCount--; + textValue[keyCount] = '\0'; + valueHasChanged = true; + } + } + + if (valueHasChanged) *value = TextToFloat(textValue); + + if ((IsKeyPressed(KEY_ENTER) || IsKeyPressed(KEY_KP_ENTER)) || (!CheckCollisionPointRec(mousePoint, bounds) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON))) result = 1; + } + else + { + if (CheckCollisionPointRec(mousePoint, bounds)) + { + state = STATE_FOCUSED; + if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) result = 1; + } + } + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + Color baseColor = BLANK; + if (state == STATE_PRESSED) baseColor = GetColor(GuiGetStyle(VALUEBOX, BASE_COLOR_PRESSED)); + else if (state == STATE_DISABLED) baseColor = GetColor(GuiGetStyle(VALUEBOX, BASE_COLOR_DISABLED)); + + GuiDrawRectangle(bounds, GuiGetStyle(VALUEBOX, BORDER_WIDTH), GetColor(GuiGetStyle(VALUEBOX, BORDER + (state*3))), baseColor); + GuiDrawText(textValue, GetTextBounds(VALUEBOX, bounds), TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(VALUEBOX, TEXT + (state*3)))); + + // Draw cursor + if (editMode) + { + // NOTE: ValueBox internal text is always centered + Rectangle cursor = {bounds.x + GetTextWidth(textValue)/2 + bounds.width/2 + 1, + bounds.y + 2*GuiGetStyle(VALUEBOX, BORDER_WIDTH), 4, + bounds.height - 4*GuiGetStyle(VALUEBOX, BORDER_WIDTH)}; + GuiDrawRectangle(cursor, 0, BLANK, GetColor(GuiGetStyle(VALUEBOX, BORDER_COLOR_PRESSED))); + } + + // Draw text label if provided + GuiDrawText(text, textBounds, + (GuiGetStyle(VALUEBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_RIGHT)? TEXT_ALIGN_LEFT : TEXT_ALIGN_RIGHT, + GetColor(GuiGetStyle(LABEL, TEXT + (state*3)))); + //-------------------------------------------------------------------- + + return result; +} + +// Slider control with pro parameters +// NOTE: Other GuiSlider*() controls use this one +int GuiSliderPro(Rectangle bounds, const char *textLeft, const char *textRight, float *value, float minValue, float maxValue, int sliderWidth) +{ + int result = 0; + GuiState state = guiState; + + float temp = (maxValue - minValue)/2.0f; + if (value == NULL) value = &temp; + float oldValue = *value; + + Rectangle slider = { bounds.x, bounds.y + GuiGetStyle(SLIDER, BORDER_WIDTH) + GuiGetStyle(SLIDER, SLIDER_PADDING), + 0, bounds.height - 2*GuiGetStyle(SLIDER, BORDER_WIDTH) - 2*GuiGetStyle(SLIDER, SLIDER_PADDING) }; + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked) + { + Vector2 mousePoint = GetMousePosition(); + + if (guiControlExclusiveMode) // Allows to keep dragging outside of bounds + { + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) + { + if (CHECK_BOUNDS_ID(bounds, guiControlExclusiveRec)) + { + state = STATE_PRESSED; + // Get equivalent value and slider position from mousePosition.x + *value = (maxValue - minValue)*((mousePoint.x - bounds.x - sliderWidth/2)/(bounds.width-sliderWidth)) + minValue; + } + } + else + { + guiControlExclusiveMode = false; + guiControlExclusiveRec = RAYGUI_CLITERAL(Rectangle){ 0, 0, 0, 0 }; + } + } + else if (CheckCollisionPointRec(mousePoint, bounds)) + { + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) + { + state = STATE_PRESSED; + guiControlExclusiveMode = true; + guiControlExclusiveRec = bounds; // Store bounds as an identifier when dragging starts + + if (!CheckCollisionPointRec(mousePoint, slider)) + { + // Get equivalent value and slider position from mousePosition.x + *value = (maxValue - minValue)*((mousePoint.x - bounds.x - sliderWidth/2)/(bounds.width-sliderWidth)) + minValue; + } + } + else state = STATE_FOCUSED; + } + + if (*value > maxValue) *value = maxValue; + else if (*value < minValue) *value = minValue; + } + + // Control value change check + if (oldValue == *value) result = 0; + else result = 1; + + // Slider bar limits check + float sliderValue = (((*value - minValue)/(maxValue - minValue))*(bounds.width - sliderWidth - 2*GuiGetStyle(SLIDER, BORDER_WIDTH))); + if (sliderWidth > 0) // Slider + { + slider.x += sliderValue; + slider.width = (float)sliderWidth; + if (slider.x <= (bounds.x + GuiGetStyle(SLIDER, BORDER_WIDTH))) slider.x = bounds.x + GuiGetStyle(SLIDER, BORDER_WIDTH); + else if ((slider.x + slider.width) >= (bounds.x + bounds.width)) slider.x = bounds.x + bounds.width - slider.width - GuiGetStyle(SLIDER, BORDER_WIDTH); + } + else if (sliderWidth == 0) // SliderBar + { + slider.x += GuiGetStyle(SLIDER, BORDER_WIDTH); + slider.width = sliderValue; + if (slider.width > bounds.width) slider.width = bounds.width - 2*GuiGetStyle(SLIDER, BORDER_WIDTH); + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + GuiDrawRectangle(bounds, GuiGetStyle(SLIDER, BORDER_WIDTH), GetColor(GuiGetStyle(SLIDER, BORDER + (state*3))), GetColor(GuiGetStyle(SLIDER, (state != STATE_DISABLED)? BASE_COLOR_NORMAL : BASE_COLOR_DISABLED))); + + // Draw slider internal bar (depends on state) + if (state == STATE_NORMAL) GuiDrawRectangle(slider, 0, BLANK, GetColor(GuiGetStyle(SLIDER, BASE_COLOR_PRESSED))); + else if (state == STATE_FOCUSED) GuiDrawRectangle(slider, 0, BLANK, GetColor(GuiGetStyle(SLIDER, TEXT_COLOR_FOCUSED))); + else if (state == STATE_PRESSED) GuiDrawRectangle(slider, 0, BLANK, GetColor(GuiGetStyle(SLIDER, TEXT_COLOR_PRESSED))); + else if (state == STATE_DISABLED) GuiDrawRectangle(slider, 0, BLANK, GetColor(GuiGetStyle(SLIDER, TEXT_COLOR_DISABLED))); + + // Draw left/right text if provided + if (textLeft != NULL) + { + Rectangle textBounds = { 0 }; + textBounds.width = (float)GetTextWidth(textLeft); + textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE); + textBounds.x = bounds.x - textBounds.width - GuiGetStyle(SLIDER, TEXT_PADDING); + textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2; + + GuiDrawText(textLeft, textBounds, TEXT_ALIGN_RIGHT, GetColor(GuiGetStyle(LABEL, TEXT + (state*3)))); + } + + if (textRight != NULL) + { + Rectangle textBounds = { 0 }; + textBounds.width = (float)GetTextWidth(textRight); + textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE); + textBounds.x = bounds.x + bounds.width + GuiGetStyle(SLIDER, TEXT_PADDING); + textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2; + + GuiDrawText(textRight, textBounds, TEXT_ALIGN_LEFT, GetColor(GuiGetStyle(LABEL, TEXT + (state*3)))); + } + //-------------------------------------------------------------------- + + return result; +} + +// Slider control extended, returns selected value and has text +int GuiSlider(Rectangle bounds, const char *textLeft, const char *textRight, float *value, float minValue, float maxValue) +{ + return GuiSliderPro(bounds, textLeft, textRight, value, minValue, maxValue, GuiGetStyle(SLIDER, SLIDER_WIDTH)); +} + +// Slider Bar control extended, returns selected value +int GuiSliderBar(Rectangle bounds, const char *textLeft, const char *textRight, float *value, float minValue, float maxValue) +{ + return GuiSliderPro(bounds, textLeft, textRight, value, minValue, maxValue, 0); +} + +// Progress Bar control extended, shows current progress value +int GuiProgressBar(Rectangle bounds, const char *textLeft, const char *textRight, float *value, float minValue, float maxValue) +{ + int result = 0; + GuiState state = guiState; + + float temp = (maxValue - minValue)/2.0f; + if (value == NULL) value = &temp; + + // Progress bar + Rectangle progress = { bounds.x + GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), + bounds.y + GuiGetStyle(PROGRESSBAR, BORDER_WIDTH) + GuiGetStyle(PROGRESSBAR, PROGRESS_PADDING), 0, + bounds.height - GuiGetStyle(PROGRESSBAR, BORDER_WIDTH) - 2*GuiGetStyle(PROGRESSBAR, PROGRESS_PADDING) -1 }; + + // Update control + //-------------------------------------------------------------------- + if (*value > maxValue) *value = maxValue; + + // WARNING: Working with floats could lead to rounding issues + if ((state != STATE_DISABLED)) progress.width = ((float)*value/(maxValue - minValue))*(bounds.width - 2*GuiGetStyle(PROGRESSBAR, BORDER_WIDTH)); + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + if (state == STATE_DISABLED) + { + GuiDrawRectangle(bounds, GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), GetColor(GuiGetStyle(PROGRESSBAR, BORDER + (state*3))), BLANK); + } + else + { + if (*value > minValue) + { + // Draw progress bar with colored border, more visual + GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y, (int)progress.width + (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH) }, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BORDER_COLOR_FOCUSED))); + GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y + 1, (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), bounds.height - 2 }, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BORDER_COLOR_FOCUSED))); + GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y + bounds.height - 1, (int)progress.width + (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH) }, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BORDER_COLOR_FOCUSED))); + } + else GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y, (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), bounds.height+GuiGetStyle(PROGRESSBAR, BORDER_WIDTH)-1 }, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BORDER_COLOR_NORMAL))); + + if (*value >= maxValue) GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x + progress.width + (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), bounds.y, (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), bounds.height+GuiGetStyle(PROGRESSBAR, BORDER_WIDTH)-1}, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BORDER_COLOR_FOCUSED))); + else + { + // Draw borders not yet reached by value + GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x + (int)progress.width + (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), bounds.y, bounds.width - (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH) - (int)progress.width - 1, (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH) }, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BORDER_COLOR_NORMAL))); + GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x + (int)progress.width + (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), bounds.y + bounds.height - 1, bounds.width - (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH) - (int)progress.width - 1, (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH) }, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BORDER_COLOR_NORMAL))); + GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x + bounds.width - (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), bounds.y, (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), bounds.height+GuiGetStyle(PROGRESSBAR, BORDER_WIDTH)-1 }, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BORDER_COLOR_NORMAL))); + } + + // Draw slider internal progress bar (depends on state) + GuiDrawRectangle(progress, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BASE_COLOR_PRESSED))); + } + + // Draw left/right text if provided + if (textLeft != NULL) + { + Rectangle textBounds = { 0 }; + textBounds.width = (float)GetTextWidth(textLeft); + textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE); + textBounds.x = bounds.x - textBounds.width - GuiGetStyle(PROGRESSBAR, TEXT_PADDING); + textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2; + + GuiDrawText(textLeft, textBounds, TEXT_ALIGN_RIGHT, GetColor(GuiGetStyle(LABEL, TEXT + (state*3)))); + } + + if (textRight != NULL) + { + Rectangle textBounds = { 0 }; + textBounds.width = (float)GetTextWidth(textRight); + textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE); + textBounds.x = bounds.x + bounds.width + GuiGetStyle(PROGRESSBAR, TEXT_PADDING); + textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2; + + GuiDrawText(textRight, textBounds, TEXT_ALIGN_LEFT, GetColor(GuiGetStyle(LABEL, TEXT + (state*3)))); + } + //-------------------------------------------------------------------- + + return result; +} + +// Status Bar control +int GuiStatusBar(Rectangle bounds, const char *text) +{ + int result = 0; + GuiState state = guiState; + + // Draw control + //-------------------------------------------------------------------- + GuiDrawRectangle(bounds, GuiGetStyle(STATUSBAR, BORDER_WIDTH), GetColor(GuiGetStyle(STATUSBAR, BORDER + (state*3))), GetColor(GuiGetStyle(STATUSBAR, BASE + (state*3)))); + GuiDrawText(text, GetTextBounds(STATUSBAR, bounds), GuiGetStyle(STATUSBAR, TEXT_ALIGNMENT), GetColor(GuiGetStyle(STATUSBAR, TEXT + (state*3)))); + //-------------------------------------------------------------------- + + return result; +} + +// Dummy rectangle control, intended for placeholding +int GuiDummyRec(Rectangle bounds, const char *text) +{ + int result = 0; + GuiState state = guiState; + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode) + { + Vector2 mousePoint = GetMousePosition(); + + // Check button state + if (CheckCollisionPointRec(mousePoint, bounds)) + { + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = STATE_PRESSED; + else state = STATE_FOCUSED; + } + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + GuiDrawRectangle(bounds, 0, BLANK, GetColor(GuiGetStyle(DEFAULT, (state != STATE_DISABLED)? BASE_COLOR_NORMAL : BASE_COLOR_DISABLED))); + GuiDrawText(text, GetTextBounds(DEFAULT, bounds), TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(BUTTON, (state != STATE_DISABLED)? TEXT_COLOR_NORMAL : TEXT_COLOR_DISABLED))); + //------------------------------------------------------------------ + + return result; +} + +// List View control +int GuiListView(Rectangle bounds, const char *text, int *scrollIndex, int *active) +{ + int result = 0; + int itemCount = 0; + const char **items = NULL; + + if (text != NULL) items = GuiTextSplit(text, ';', &itemCount, NULL); + + result = GuiListViewEx(bounds, items, itemCount, scrollIndex, active, NULL); + + return result; +} + +// List View control with extended parameters +int GuiListViewEx(Rectangle bounds, const char **text, int count, int *scrollIndex, int *active, int *focus) +{ + int result = 0; + GuiState state = guiState; + + int itemFocused = (focus == NULL)? -1 : *focus; + int itemSelected = (active == NULL)? -1 : *active; + + // Check if we need a scroll bar + bool useScrollBar = false; + if ((GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) + GuiGetStyle(LISTVIEW, LIST_ITEMS_SPACING))*count > bounds.height) useScrollBar = true; + + // Define base item rectangle [0] + Rectangle itemBounds = { 0 }; + itemBounds.x = bounds.x + GuiGetStyle(LISTVIEW, LIST_ITEMS_SPACING); + itemBounds.y = bounds.y + GuiGetStyle(LISTVIEW, LIST_ITEMS_SPACING) + GuiGetStyle(DEFAULT, BORDER_WIDTH); + itemBounds.width = bounds.width - 2*GuiGetStyle(LISTVIEW, LIST_ITEMS_SPACING) - GuiGetStyle(DEFAULT, BORDER_WIDTH); + itemBounds.height = (float)GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT); + if (useScrollBar) itemBounds.width -= GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH); + + // Get items on the list + int visibleItems = (int)bounds.height/(GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) + GuiGetStyle(LISTVIEW, LIST_ITEMS_SPACING)); + if (visibleItems > count) visibleItems = count; + + int startIndex = (scrollIndex == NULL)? 0 : *scrollIndex; + if ((startIndex < 0) || (startIndex > (count - visibleItems))) startIndex = 0; + int endIndex = startIndex + visibleItems; + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode) + { + Vector2 mousePoint = GetMousePosition(); + + // Check mouse inside list view + if (CheckCollisionPointRec(mousePoint, bounds)) + { + state = STATE_FOCUSED; + + // Check focused and selected item + for (int i = 0; i < visibleItems; i++) + { + if (CheckCollisionPointRec(mousePoint, itemBounds)) + { + itemFocused = startIndex + i; + if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) + { + if (itemSelected == (startIndex + i)) itemSelected = -1; + else itemSelected = startIndex + i; + } + break; + } + + // Update item rectangle y position for next item + itemBounds.y += (GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) + GuiGetStyle(LISTVIEW, LIST_ITEMS_SPACING)); + } + + if (useScrollBar) + { + int wheelMove = (int)GetMouseWheelMove(); + startIndex -= wheelMove; + + if (startIndex < 0) startIndex = 0; + else if (startIndex > (count - visibleItems)) startIndex = count - visibleItems; + + endIndex = startIndex + visibleItems; + if (endIndex > count) endIndex = count; + } + } + else itemFocused = -1; + + // Reset item rectangle y to [0] + itemBounds.y = bounds.y + GuiGetStyle(LISTVIEW, LIST_ITEMS_SPACING) + GuiGetStyle(DEFAULT, BORDER_WIDTH); + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + GuiDrawRectangle(bounds, GuiGetStyle(LISTVIEW, BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER + state*3)), GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR))); // Draw background + + // Draw visible items + for (int i = 0; ((i < visibleItems) && (text != NULL)); i++) + { + if (GuiGetStyle(LISTVIEW, LIST_ITEMS_BORDER_NORMAL)) GuiDrawRectangle(itemBounds, GuiGetStyle(LISTVIEW, LIST_ITEMS_BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER_COLOR_NORMAL)), BLANK); + + if (state == STATE_DISABLED) + { + if ((startIndex + i) == itemSelected) GuiDrawRectangle(itemBounds, GuiGetStyle(LISTVIEW, LIST_ITEMS_BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER_COLOR_DISABLED)), GetColor(GuiGetStyle(LISTVIEW, BASE_COLOR_DISABLED))); + + GuiDrawText(text[startIndex + i], GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT), GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_DISABLED))); + } + else + { + if (((startIndex + i) == itemSelected) && (active != NULL)) + { + // Draw item selected + GuiDrawRectangle(itemBounds, GuiGetStyle(LISTVIEW, LIST_ITEMS_BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER_COLOR_PRESSED)), GetColor(GuiGetStyle(LISTVIEW, BASE_COLOR_PRESSED))); + GuiDrawText(text[startIndex + i], GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT), GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_PRESSED))); + } + else if (((startIndex + i) == itemFocused)) // && (focus != NULL)) // NOTE: We want items focused, despite not returned! + { + // Draw item focused + GuiDrawRectangle(itemBounds, GuiGetStyle(LISTVIEW, LIST_ITEMS_BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER_COLOR_FOCUSED)), GetColor(GuiGetStyle(LISTVIEW, BASE_COLOR_FOCUSED))); + GuiDrawText(text[startIndex + i], GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT), GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_FOCUSED))); + } + else + { + // Draw item normal (no rectangle) + GuiDrawText(text[startIndex + i], GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT), GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_NORMAL))); + } + } + + // Update item rectangle y position for next item + itemBounds.y += (GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) + GuiGetStyle(LISTVIEW, LIST_ITEMS_SPACING)); + } + + if (useScrollBar) + { + Rectangle scrollBarBounds = { + bounds.x + bounds.width - GuiGetStyle(LISTVIEW, BORDER_WIDTH) - GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH), + bounds.y + GuiGetStyle(LISTVIEW, BORDER_WIDTH), (float)GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH), + bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) + }; + + // Calculate percentage of visible items and apply same percentage to scrollbar + float percentVisible = (float)(endIndex - startIndex)/count; + float sliderSize = bounds.height*percentVisible; + + int prevSliderSize = GuiGetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE); // Save default slider size + int prevScrollSpeed = GuiGetStyle(SCROLLBAR, SCROLL_SPEED); // Save default scroll speed + GuiSetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE, (int)sliderSize); // Change slider size + GuiSetStyle(SCROLLBAR, SCROLL_SPEED, count - visibleItems); // Change scroll speed + + startIndex = GuiScrollBar(scrollBarBounds, startIndex, 0, count - visibleItems); + + GuiSetStyle(SCROLLBAR, SCROLL_SPEED, prevScrollSpeed); // Reset scroll speed to default + GuiSetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE, prevSliderSize); // Reset slider size to default + } + //-------------------------------------------------------------------- + + if (active != NULL) *active = itemSelected; + if (focus != NULL) *focus = itemFocused; + if (scrollIndex != NULL) *scrollIndex = startIndex; + + return result; +} + +// Color Panel control - Color (RGBA) variant. +int GuiColorPanel(Rectangle bounds, const char *text, Color *color) +{ + int result = 0; + + Vector3 vcolor = { (float)color->r/255.0f, (float)color->g/255.0f, (float)color->b/255.0f }; + Vector3 hsv = ConvertRGBtoHSV(vcolor); + Vector3 prevHsv = hsv; // workaround to see if GuiColorPanelHSV modifies the hsv. + + GuiColorPanelHSV(bounds, text, &hsv); + + // Check if the hsv was changed, only then change the color. + // This is required, because the Color->HSV->Color conversion has precision errors. + // Thus the assignment from HSV to Color should only be made, if the HSV has a new user-entered value. + // Otherwise GuiColorPanel would often modify it's color without user input. + // TODO: GuiColorPanelHSV could return 1 if the slider was dragged, to simplify this check. + if (hsv.x != prevHsv.x || hsv.y != prevHsv.y || hsv.z != prevHsv.z) + { + Vector3 rgb = ConvertHSVtoRGB(hsv); + + // NOTE: Vector3ToColor() only available on raylib 1.8.1 + *color = RAYGUI_CLITERAL(Color){ (unsigned char)(255.0f*rgb.x), + (unsigned char)(255.0f*rgb.y), + (unsigned char)(255.0f*rgb.z), + color->a }; + } + return result; +} + +// Color Bar Alpha control +// NOTE: Returns alpha value normalized [0..1] +int GuiColorBarAlpha(Rectangle bounds, const char *text, float *alpha) +{ + #if !defined(RAYGUI_COLORBARALPHA_CHECKED_SIZE) + #define RAYGUI_COLORBARALPHA_CHECKED_SIZE 10 + #endif + + int result = 0; + GuiState state = guiState; + Rectangle selector = { (float)bounds.x + (*alpha)*bounds.width - GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_HEIGHT)/2, + (float)bounds.y - GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_OVERFLOW), + (float)GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_HEIGHT), + (float)bounds.height + GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_OVERFLOW)*2 }; + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked) + { + Vector2 mousePoint = GetMousePosition(); + + if (guiControlExclusiveMode) // Allows to keep dragging outside of bounds + { + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) + { + if (CHECK_BOUNDS_ID(bounds, guiControlExclusiveRec)) + { + state = STATE_PRESSED; + + *alpha = (mousePoint.x - bounds.x)/bounds.width; + if (*alpha <= 0.0f) *alpha = 0.0f; + if (*alpha >= 1.0f) *alpha = 1.0f; + } + } + else + { + guiControlExclusiveMode = false; + guiControlExclusiveRec = RAYGUI_CLITERAL(Rectangle){ 0, 0, 0, 0 }; + } + } + else if (CheckCollisionPointRec(mousePoint, bounds) || CheckCollisionPointRec(mousePoint, selector)) + { + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) + { + state = STATE_PRESSED; + guiControlExclusiveMode = true; + guiControlExclusiveRec = bounds; // Store bounds as an identifier when dragging starts + + *alpha = (mousePoint.x - bounds.x)/bounds.width; + if (*alpha <= 0.0f) *alpha = 0.0f; + if (*alpha >= 1.0f) *alpha = 1.0f; + //selector.x = bounds.x + (int)(((alpha - 0)/(100 - 0))*(bounds.width - 2*GuiGetStyle(SLIDER, BORDER_WIDTH))) - selector.width/2; + } + else state = STATE_FOCUSED; + } + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + // Draw alpha bar: checked background + if (state != STATE_DISABLED) + { + int checksX = (int)bounds.width/RAYGUI_COLORBARALPHA_CHECKED_SIZE; + int checksY = (int)bounds.height/RAYGUI_COLORBARALPHA_CHECKED_SIZE; + + for (int x = 0; x < checksX; x++) + { + for (int y = 0; y < checksY; y++) + { + Rectangle check = { bounds.x + x*RAYGUI_COLORBARALPHA_CHECKED_SIZE, bounds.y + y*RAYGUI_COLORBARALPHA_CHECKED_SIZE, RAYGUI_COLORBARALPHA_CHECKED_SIZE, RAYGUI_COLORBARALPHA_CHECKED_SIZE }; + GuiDrawRectangle(check, 0, BLANK, ((x + y)%2)? Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER_COLOR_DISABLED)), 0.4f) : Fade(GetColor(GuiGetStyle(COLORPICKER, BASE_COLOR_DISABLED)), 0.4f)); + } + } + + DrawRectangleGradientEx(bounds, RAYGUI_CLITERAL(Color){ 255, 255, 255, 0 }, RAYGUI_CLITERAL(Color){ 255, 255, 255, 0 }, Fade(RAYGUI_CLITERAL(Color){ 0, 0, 0, 255 }, guiAlpha), Fade(RAYGUI_CLITERAL(Color){ 0, 0, 0, 255 }, guiAlpha)); + } + else DrawRectangleGradientEx(bounds, Fade(GetColor(GuiGetStyle(COLORPICKER, BASE_COLOR_DISABLED)), 0.1f), Fade(GetColor(GuiGetStyle(COLORPICKER, BASE_COLOR_DISABLED)), 0.1f), Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER_COLOR_DISABLED)), guiAlpha), Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER_COLOR_DISABLED)), guiAlpha)); + + GuiDrawRectangle(bounds, GuiGetStyle(COLORPICKER, BORDER_WIDTH), GetColor(GuiGetStyle(COLORPICKER, BORDER + state*3)), BLANK); + + // Draw alpha bar: selector + GuiDrawRectangle(selector, 0, BLANK, GetColor(GuiGetStyle(COLORPICKER, BORDER + state*3))); + //-------------------------------------------------------------------- + + return result; +} + +// Color Bar Hue control +// Returns hue value normalized [0..1] +// NOTE: Other similar bars (for reference): +// Color GuiColorBarSat() [WHITE->color] +// Color GuiColorBarValue() [BLACK->color], HSV/HSL +// float GuiColorBarLuminance() [BLACK->WHITE] +int GuiColorBarHue(Rectangle bounds, const char *text, float *hue) +{ + int result = 0; + GuiState state = guiState; + Rectangle selector = { (float)bounds.x - GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_OVERFLOW), (float)bounds.y + (*hue)/360.0f*bounds.height - GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_HEIGHT)/2, (float)bounds.width + GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_OVERFLOW)*2, (float)GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_HEIGHT) }; + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked) + { + Vector2 mousePoint = GetMousePosition(); + + if (guiControlExclusiveMode) // Allows to keep dragging outside of bounds + { + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) + { + if (CHECK_BOUNDS_ID(bounds, guiControlExclusiveRec)) + { + state = STATE_PRESSED; + + *hue = (mousePoint.y - bounds.y)*360/bounds.height; + if (*hue <= 0.0f) *hue = 0.0f; + if (*hue >= 359.0f) *hue = 359.0f; + } + } + else + { + guiControlExclusiveMode = false; + guiControlExclusiveRec = RAYGUI_CLITERAL(Rectangle){ 0, 0, 0, 0 }; + } + } + else if (CheckCollisionPointRec(mousePoint, bounds) || CheckCollisionPointRec(mousePoint, selector)) + { + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) + { + state = STATE_PRESSED; + guiControlExclusiveMode = true; + guiControlExclusiveRec = bounds; // Store bounds as an identifier when dragging starts + + *hue = (mousePoint.y - bounds.y)*360/bounds.height; + if (*hue <= 0.0f) *hue = 0.0f; + if (*hue >= 359.0f) *hue = 359.0f; + + } + else state = STATE_FOCUSED; + + /*if (IsKeyDown(KEY_UP)) + { + hue -= 2.0f; + if (hue <= 0.0f) hue = 0.0f; + } + else if (IsKeyDown(KEY_DOWN)) + { + hue += 2.0f; + if (hue >= 360.0f) hue = 360.0f; + }*/ + } + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + if (state != STATE_DISABLED) + { + // Draw hue bar:color bars + // TODO: Use directly DrawRectangleGradientEx(bounds, color1, color2, color2, color1); + DrawRectangleGradientV((int)bounds.x, (int)(bounds.y), (int)bounds.width, (int)ceilf(bounds.height/6), Fade(RAYGUI_CLITERAL(Color){ 255, 0, 0, 255 }, guiAlpha), Fade(RAYGUI_CLITERAL(Color){ 255, 255, 0, 255 }, guiAlpha)); + DrawRectangleGradientV((int)bounds.x, (int)(bounds.y + bounds.height/6), (int)bounds.width, (int)ceilf(bounds.height/6), Fade(RAYGUI_CLITERAL(Color){ 255, 255, 0, 255 }, guiAlpha), Fade(RAYGUI_CLITERAL(Color){ 0, 255, 0, 255 }, guiAlpha)); + DrawRectangleGradientV((int)bounds.x, (int)(bounds.y + 2*(bounds.height/6)), (int)bounds.width, (int)ceilf(bounds.height/6), Fade(RAYGUI_CLITERAL(Color){ 0, 255, 0, 255 }, guiAlpha), Fade(RAYGUI_CLITERAL(Color){ 0, 255, 255, 255 }, guiAlpha)); + DrawRectangleGradientV((int)bounds.x, (int)(bounds.y + 3*(bounds.height/6)), (int)bounds.width, (int)ceilf(bounds.height/6), Fade(RAYGUI_CLITERAL(Color){ 0, 255, 255, 255 }, guiAlpha), Fade(RAYGUI_CLITERAL(Color){ 0, 0, 255, 255 }, guiAlpha)); + DrawRectangleGradientV((int)bounds.x, (int)(bounds.y + 4*(bounds.height/6)), (int)bounds.width, (int)ceilf(bounds.height/6), Fade(RAYGUI_CLITERAL(Color){ 0, 0, 255, 255 }, guiAlpha), Fade(RAYGUI_CLITERAL(Color){ 255, 0, 255, 255 }, guiAlpha)); + DrawRectangleGradientV((int)bounds.x, (int)(bounds.y + 5*(bounds.height/6)), (int)bounds.width, (int)(bounds.height/6), Fade(RAYGUI_CLITERAL(Color){ 255, 0, 255, 255 }, guiAlpha), Fade(RAYGUI_CLITERAL(Color){ 255, 0, 0, 255 }, guiAlpha)); + } + else DrawRectangleGradientV((int)bounds.x, (int)bounds.y, (int)bounds.width, (int)bounds.height, Fade(Fade(GetColor(GuiGetStyle(COLORPICKER, BASE_COLOR_DISABLED)), 0.1f), guiAlpha), Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER_COLOR_DISABLED)), guiAlpha)); + + GuiDrawRectangle(bounds, GuiGetStyle(COLORPICKER, BORDER_WIDTH), GetColor(GuiGetStyle(COLORPICKER, BORDER + state*3)), BLANK); + + // Draw hue bar: selector + GuiDrawRectangle(selector, 0, BLANK, GetColor(GuiGetStyle(COLORPICKER, BORDER + state*3))); + //-------------------------------------------------------------------- + + return result; +} + +// Color Picker control +// NOTE: It's divided in multiple controls: +// Color GuiColorPanel(Rectangle bounds, Color color) +// float GuiColorBarAlpha(Rectangle bounds, float alpha) +// float GuiColorBarHue(Rectangle bounds, float value) +// NOTE: bounds define GuiColorPanel() size +// NOTE: this picker converts RGB to HSV, which can cause the Hue control to jump. If you have this problem, consider using the HSV variant instead +int GuiColorPicker(Rectangle bounds, const char *text, Color *color) +{ + int result = 0; + + Color temp = { 200, 0, 0, 255 }; + if (color == NULL) color = &temp; + + GuiColorPanel(bounds, NULL, color); + + Rectangle boundsHue = { (float)bounds.x + bounds.width + GuiGetStyle(COLORPICKER, HUEBAR_PADDING), (float)bounds.y, (float)GuiGetStyle(COLORPICKER, HUEBAR_WIDTH), (float)bounds.height }; + //Rectangle boundsAlpha = { bounds.x, bounds.y + bounds.height + GuiGetStyle(COLORPICKER, BARS_PADDING), bounds.width, GuiGetStyle(COLORPICKER, BARS_THICK) }; + + // NOTE: this conversion can cause low hue-resolution, if the r, g and b value are very similar, which causes the hue bar to shift around when only the GuiColorPanel is used. + Vector3 hsv = ConvertRGBtoHSV(RAYGUI_CLITERAL(Vector3){ (*color).r/255.0f, (*color).g/255.0f, (*color).b/255.0f }); + + GuiColorBarHue(boundsHue, NULL, &hsv.x); + + //color.a = (unsigned char)(GuiColorBarAlpha(boundsAlpha, (float)color.a/255.0f)*255.0f); + Vector3 rgb = ConvertHSVtoRGB(hsv); + + *color = RAYGUI_CLITERAL(Color){ (unsigned char)roundf(rgb.x*255.0f), (unsigned char)roundf(rgb.y*255.0f), (unsigned char)roundf(rgb.z*255.0f), (*color).a }; + + return result; +} + +// Color Picker control that avoids conversion to RGB and back to HSV on each call, thus avoiding jittering. +// The user can call ConvertHSVtoRGB() to convert *colorHsv value to RGB. +// NOTE: It's divided in multiple controls: +// int GuiColorPanelHSV(Rectangle bounds, const char *text, Vector3 *colorHsv) +// int GuiColorBarAlpha(Rectangle bounds, const char *text, float *alpha) +// float GuiColorBarHue(Rectangle bounds, float value) +// NOTE: bounds define GuiColorPanelHSV() size +int GuiColorPickerHSV(Rectangle bounds, const char *text, Vector3 *colorHsv) +{ + int result = 0; + + Vector3 tempHsv = { 0 }; + + if (colorHsv == NULL) + { + const Vector3 tempColor = { 200.0f/255.0f, 0.0f, 0.0f }; + tempHsv = ConvertRGBtoHSV(tempColor); + colorHsv = &tempHsv; + } + + GuiColorPanelHSV(bounds, NULL, colorHsv); + + const Rectangle boundsHue = { (float)bounds.x + bounds.width + GuiGetStyle(COLORPICKER, HUEBAR_PADDING), (float)bounds.y, (float)GuiGetStyle(COLORPICKER, HUEBAR_WIDTH), (float)bounds.height }; + + GuiColorBarHue(boundsHue, NULL, &colorHsv->x); + + return result; +} + +// Color Panel control - HSV variant +int GuiColorPanelHSV(Rectangle bounds, const char *text, Vector3 *colorHsv) +{ + int result = 0; + GuiState state = guiState; + Vector2 pickerSelector = { 0 }; + + const Color colWhite = { 255, 255, 255, 255 }; + const Color colBlack = { 0, 0, 0, 255 }; + + pickerSelector.x = bounds.x + (float)colorHsv->y*bounds.width; // HSV: Saturation + pickerSelector.y = bounds.y + (1.0f - (float)colorHsv->z)*bounds.height; // HSV: Value + + Vector3 maxHue = { colorHsv->x, 1.0f, 1.0f }; + Vector3 rgbHue = ConvertHSVtoRGB(maxHue); + Color maxHueCol = { (unsigned char)(255.0f*rgbHue.x), + (unsigned char)(255.0f*rgbHue.y), + (unsigned char)(255.0f*rgbHue.z), 255 }; + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked) + { + Vector2 mousePoint = GetMousePosition(); + + if (guiControlExclusiveMode) // Allows to keep dragging outside of bounds + { + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) + { + if (CHECK_BOUNDS_ID(bounds, guiControlExclusiveRec)) + { + pickerSelector = mousePoint; + + if (pickerSelector.x < bounds.x) pickerSelector.x = bounds.x; + if (pickerSelector.x > bounds.x + bounds.width) pickerSelector.x = bounds.x + bounds.width; + if (pickerSelector.y < bounds.y) pickerSelector.y = bounds.y; + if (pickerSelector.y > bounds.y + bounds.height) pickerSelector.y = bounds.y + bounds.height; + + // Calculate color from picker + Vector2 colorPick = { pickerSelector.x - bounds.x, pickerSelector.y - bounds.y }; + + colorPick.x /= (float)bounds.width; // Get normalized value on x + colorPick.y /= (float)bounds.height; // Get normalized value on y + + colorHsv->y = colorPick.x; + colorHsv->z = 1.0f - colorPick.y; + + } + } + else + { + guiControlExclusiveMode = false; + guiControlExclusiveRec = RAYGUI_CLITERAL(Rectangle){ 0, 0, 0, 0 }; + } + } + else if (CheckCollisionPointRec(mousePoint, bounds)) + { + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) + { + state = STATE_PRESSED; + guiControlExclusiveMode = true; + guiControlExclusiveRec = bounds; + pickerSelector = mousePoint; + + // Calculate color from picker + Vector2 colorPick = { pickerSelector.x - bounds.x, pickerSelector.y - bounds.y }; + + colorPick.x /= (float)bounds.width; // Get normalized value on x + colorPick.y /= (float)bounds.height; // Get normalized value on y + + colorHsv->y = colorPick.x; + colorHsv->z = 1.0f - colorPick.y; + } + else state = STATE_FOCUSED; + } + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + if (state != STATE_DISABLED) + { + DrawRectangleGradientEx(bounds, Fade(colWhite, guiAlpha), Fade(colWhite, guiAlpha), Fade(maxHueCol, guiAlpha), Fade(maxHueCol, guiAlpha)); + DrawRectangleGradientEx(bounds, Fade(colBlack, 0), Fade(colBlack, guiAlpha), Fade(colBlack, guiAlpha), Fade(colBlack, 0)); + + // Draw color picker: selector + Rectangle selector = { pickerSelector.x - GuiGetStyle(COLORPICKER, COLOR_SELECTOR_SIZE)/2, pickerSelector.y - GuiGetStyle(COLORPICKER, COLOR_SELECTOR_SIZE)/2, (float)GuiGetStyle(COLORPICKER, COLOR_SELECTOR_SIZE), (float)GuiGetStyle(COLORPICKER, COLOR_SELECTOR_SIZE) }; + GuiDrawRectangle(selector, 0, BLANK, colWhite); + } + else + { + DrawRectangleGradientEx(bounds, Fade(Fade(GetColor(GuiGetStyle(COLORPICKER, BASE_COLOR_DISABLED)), 0.1f), guiAlpha), Fade(Fade(colBlack, 0.6f), guiAlpha), Fade(Fade(colBlack, 0.6f), guiAlpha), Fade(Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER_COLOR_DISABLED)), 0.6f), guiAlpha)); + } + + GuiDrawRectangle(bounds, GuiGetStyle(COLORPICKER, BORDER_WIDTH), GetColor(GuiGetStyle(COLORPICKER, BORDER + state*3)), BLANK); + //-------------------------------------------------------------------- + + return result; +} + +// Message Box control +int GuiMessageBox(Rectangle bounds, const char *title, const char *message, const char *buttons) +{ + #if !defined(RAYGUI_MESSAGEBOX_BUTTON_HEIGHT) + #define RAYGUI_MESSAGEBOX_BUTTON_HEIGHT 24 + #endif + #if !defined(RAYGUI_MESSAGEBOX_BUTTON_PADDING) + #define RAYGUI_MESSAGEBOX_BUTTON_PADDING 12 + #endif + + int result = -1; // Returns clicked button from buttons list, 0 refers to closed window button + + int buttonCount = 0; + const char **buttonsText = GuiTextSplit(buttons, ';', &buttonCount, NULL); + Rectangle buttonBounds = { 0 }; + buttonBounds.x = bounds.x + RAYGUI_MESSAGEBOX_BUTTON_PADDING; + buttonBounds.y = bounds.y + bounds.height - RAYGUI_MESSAGEBOX_BUTTON_HEIGHT - RAYGUI_MESSAGEBOX_BUTTON_PADDING; + buttonBounds.width = (bounds.width - RAYGUI_MESSAGEBOX_BUTTON_PADDING*(buttonCount + 1))/buttonCount; + buttonBounds.height = RAYGUI_MESSAGEBOX_BUTTON_HEIGHT; + + //int textWidth = GetTextWidth(message) + 2; + + Rectangle textBounds = { 0 }; + textBounds.x = bounds.x + RAYGUI_MESSAGEBOX_BUTTON_PADDING; + textBounds.y = bounds.y + RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT + RAYGUI_MESSAGEBOX_BUTTON_PADDING; + textBounds.width = bounds.width - RAYGUI_MESSAGEBOX_BUTTON_PADDING*2; + textBounds.height = bounds.height - RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT - 3*RAYGUI_MESSAGEBOX_BUTTON_PADDING - RAYGUI_MESSAGEBOX_BUTTON_HEIGHT; + + // Draw control + //-------------------------------------------------------------------- + if (GuiWindowBox(bounds, title)) result = 0; + + int prevTextAlignment = GuiGetStyle(LABEL, TEXT_ALIGNMENT); + GuiSetStyle(LABEL, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER); + GuiLabel(textBounds, message); + GuiSetStyle(LABEL, TEXT_ALIGNMENT, prevTextAlignment); + + prevTextAlignment = GuiGetStyle(BUTTON, TEXT_ALIGNMENT); + GuiSetStyle(BUTTON, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER); + + for (int i = 0; i < buttonCount; i++) + { + if (GuiButton(buttonBounds, buttonsText[i])) result = i + 1; + buttonBounds.x += (buttonBounds.width + RAYGUI_MESSAGEBOX_BUTTON_PADDING); + } + + GuiSetStyle(BUTTON, TEXT_ALIGNMENT, prevTextAlignment); + //-------------------------------------------------------------------- + + return result; +} + +// Text Input Box control, ask for text +int GuiTextInputBox(Rectangle bounds, const char *title, const char *message, const char *buttons, char *text, int textMaxSize, bool *secretViewActive) +{ + #if !defined(RAYGUI_TEXTINPUTBOX_BUTTON_HEIGHT) + #define RAYGUI_TEXTINPUTBOX_BUTTON_HEIGHT 24 + #endif + #if !defined(RAYGUI_TEXTINPUTBOX_BUTTON_PADDING) + #define RAYGUI_TEXTINPUTBOX_BUTTON_PADDING 12 + #endif + #if !defined(RAYGUI_TEXTINPUTBOX_HEIGHT) + #define RAYGUI_TEXTINPUTBOX_HEIGHT 26 + #endif + + // Used to enable text edit mode + // WARNING: No more than one GuiTextInputBox() should be open at the same time + static bool textEditMode = false; + + int result = -1; + + int buttonCount = 0; + const char **buttonsText = GuiTextSplit(buttons, ';', &buttonCount, NULL); + Rectangle buttonBounds = { 0 }; + buttonBounds.x = bounds.x + RAYGUI_TEXTINPUTBOX_BUTTON_PADDING; + buttonBounds.y = bounds.y + bounds.height - RAYGUI_TEXTINPUTBOX_BUTTON_HEIGHT - RAYGUI_TEXTINPUTBOX_BUTTON_PADDING; + buttonBounds.width = (bounds.width - RAYGUI_TEXTINPUTBOX_BUTTON_PADDING*(buttonCount + 1))/buttonCount; + buttonBounds.height = RAYGUI_TEXTINPUTBOX_BUTTON_HEIGHT; + + int messageInputHeight = (int)bounds.height - RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT - GuiGetStyle(STATUSBAR, BORDER_WIDTH) - RAYGUI_TEXTINPUTBOX_BUTTON_HEIGHT - 2*RAYGUI_TEXTINPUTBOX_BUTTON_PADDING; + + Rectangle textBounds = { 0 }; + if (message != NULL) + { + int textSize = GetTextWidth(message) + 2; + + textBounds.x = bounds.x + bounds.width/2 - textSize/2; + textBounds.y = bounds.y + RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT + messageInputHeight/4 - (float)GuiGetStyle(DEFAULT, TEXT_SIZE)/2; + textBounds.width = (float)textSize; + textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE); + } + + Rectangle textBoxBounds = { 0 }; + textBoxBounds.x = bounds.x + RAYGUI_TEXTINPUTBOX_BUTTON_PADDING; + textBoxBounds.y = bounds.y + RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT - RAYGUI_TEXTINPUTBOX_HEIGHT/2; + if (message == NULL) textBoxBounds.y = bounds.y + 24 + RAYGUI_TEXTINPUTBOX_BUTTON_PADDING; + else textBoxBounds.y += (messageInputHeight/2 + messageInputHeight/4); + textBoxBounds.width = bounds.width - RAYGUI_TEXTINPUTBOX_BUTTON_PADDING*2; + textBoxBounds.height = RAYGUI_TEXTINPUTBOX_HEIGHT; + + // Draw control + //-------------------------------------------------------------------- + if (GuiWindowBox(bounds, title)) result = 0; + + // Draw message if available + if (message != NULL) + { + int prevTextAlignment = GuiGetStyle(LABEL, TEXT_ALIGNMENT); + GuiSetStyle(LABEL, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER); + GuiLabel(textBounds, message); + GuiSetStyle(LABEL, TEXT_ALIGNMENT, prevTextAlignment); + } + + if (secretViewActive != NULL) + { + static char stars[] = "****************"; + if (GuiTextBox(RAYGUI_CLITERAL(Rectangle){ textBoxBounds.x, textBoxBounds.y, textBoxBounds.width - 4 - RAYGUI_TEXTINPUTBOX_HEIGHT, textBoxBounds.height }, + ((*secretViewActive == 1) || textEditMode)? text : stars, textMaxSize, textEditMode)) textEditMode = !textEditMode; + + GuiToggle(RAYGUI_CLITERAL(Rectangle){ textBoxBounds.x + textBoxBounds.width - RAYGUI_TEXTINPUTBOX_HEIGHT, textBoxBounds.y, RAYGUI_TEXTINPUTBOX_HEIGHT, RAYGUI_TEXTINPUTBOX_HEIGHT }, (*secretViewActive == 1)? "#44#" : "#45#", secretViewActive); + } + else + { + if (GuiTextBox(textBoxBounds, text, textMaxSize, textEditMode)) textEditMode = !textEditMode; + } + + int prevBtnTextAlignment = GuiGetStyle(BUTTON, TEXT_ALIGNMENT); + GuiSetStyle(BUTTON, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER); + + for (int i = 0; i < buttonCount; i++) + { + if (GuiButton(buttonBounds, buttonsText[i])) result = i + 1; + buttonBounds.x += (buttonBounds.width + RAYGUI_MESSAGEBOX_BUTTON_PADDING); + } + + if (result >= 0) textEditMode = false; + + GuiSetStyle(BUTTON, TEXT_ALIGNMENT, prevBtnTextAlignment); + //-------------------------------------------------------------------- + + return result; // Result is the pressed button index +} + +// Grid control +// NOTE: Returns grid mouse-hover selected cell +// About drawing lines at subpixel spacing, simple put, not easy solution: +// https://stackoverflow.com/questions/4435450/2d-opengl-drawing-lines-that-dont-exactly-fit-pixel-raster +int GuiGrid(Rectangle bounds, const char *text, float spacing, int subdivs, Vector2 *mouseCell) +{ + // Grid lines alpha amount + #if !defined(RAYGUI_GRID_ALPHA) + #define RAYGUI_GRID_ALPHA 0.15f + #endif + + int result = 0; + GuiState state = guiState; + + Vector2 mousePoint = GetMousePosition(); + Vector2 currentMouseCell = { -1, -1 }; + + float spaceWidth = spacing/(float)subdivs; + int linesV = (int)(bounds.width/spaceWidth) + 1; + int linesH = (int)(bounds.height/spaceWidth) + 1; + + int color = GuiGetStyle(DEFAULT, LINE_COLOR); + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode) + { + if (CheckCollisionPointRec(mousePoint, bounds)) + { + // NOTE: Cell values must be the upper left of the cell the mouse is in + currentMouseCell.x = floorf((mousePoint.x - bounds.x)/spacing); + currentMouseCell.y = floorf((mousePoint.y - bounds.y)/spacing); + } + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + if (state == STATE_DISABLED) color = GuiGetStyle(DEFAULT, BORDER_COLOR_DISABLED); + + if (subdivs > 0) + { + // Draw vertical grid lines + for (int i = 0; i < linesV; i++) + { + Rectangle lineV = { bounds.x + spacing*i/subdivs, bounds.y, 1, bounds.height + 1 }; + GuiDrawRectangle(lineV, 0, BLANK, ((i%subdivs) == 0)? GuiFade(GetColor(color), RAYGUI_GRID_ALPHA*4) : GuiFade(GetColor(color), RAYGUI_GRID_ALPHA)); + } + + // Draw horizontal grid lines + for (int i = 0; i < linesH; i++) + { + Rectangle lineH = { bounds.x, bounds.y + spacing*i/subdivs, bounds.width + 1, 1 }; + GuiDrawRectangle(lineH, 0, BLANK, ((i%subdivs) == 0)? GuiFade(GetColor(color), RAYGUI_GRID_ALPHA*4) : GuiFade(GetColor(color), RAYGUI_GRID_ALPHA)); + } + } + + if (mouseCell != NULL) *mouseCell = currentMouseCell; + return result; +} + +//---------------------------------------------------------------------------------- +// Tooltip management functions +// NOTE: Tooltips requires some global variables: tooltipPtr +//---------------------------------------------------------------------------------- +// Enable gui tooltips (global state) +void GuiEnableTooltip(void) { guiTooltip = true; } + +// Disable gui tooltips (global state) +void GuiDisableTooltip(void) { guiTooltip = false; } + +// Set tooltip string +void GuiSetTooltip(const char *tooltip) { guiTooltipPtr = tooltip; } + +//---------------------------------------------------------------------------------- +// Styles loading functions +//---------------------------------------------------------------------------------- + +// Load raygui style file (.rgs) +// NOTE: By default a binary file is expected, that file could contain a custom font, +// in that case, custom font image atlas is GRAY+ALPHA and pixel data can be compressed (DEFLATE) +void GuiLoadStyle(const char *fileName) +{ + #define MAX_LINE_BUFFER_SIZE 256 + + bool tryBinary = false; + if (!guiStyleLoaded) GuiLoadStyleDefault(); + + // Try reading the files as text file first + FILE *rgsFile = fopen(fileName, "rt"); + + if (rgsFile != NULL) + { + char buffer[MAX_LINE_BUFFER_SIZE] = { 0 }; + fgets(buffer, MAX_LINE_BUFFER_SIZE, rgsFile); + + if (buffer[0] == '#') + { + int controlId = 0; + int propertyId = 0; + unsigned int propertyValue = 0; + + while (!feof(rgsFile)) + { + switch (buffer[0]) + { + case 'p': + { + // Style property: p + + sscanf(buffer, "p %d %d 0x%x", &controlId, &propertyId, &propertyValue); + GuiSetStyle(controlId, propertyId, (int)propertyValue); + + } break; + case 'f': + { + // Style font: f + + int fontSize = 0; + char charmapFileName[256] = { 0 }; + char fontFileName[256] = { 0 }; + sscanf(buffer, "f %d %s %[^\r\n]s", &fontSize, charmapFileName, fontFileName); + + Font font = { 0 }; + int *codepoints = NULL; + int codepointCount = 0; + + if (charmapFileName[0] != '0') + { + // Load text data from file + // NOTE: Expected an UTF-8 array of codepoints, no separation + char *textData = LoadFileText(TextFormat("%s/%s", GetDirectoryPath(fileName), charmapFileName)); + codepoints = LoadCodepoints(textData, &codepointCount); + UnloadFileText(textData); + } + + if (fontFileName[0] != '\0') + { + // In case a font is already loaded and it is not default internal font, unload it + if (font.texture.id != GetFontDefault().texture.id) UnloadTexture(font.texture); + + if (codepointCount > 0) font = LoadFontEx(TextFormat("%s/%s", GetDirectoryPath(fileName), fontFileName), fontSize, codepoints, codepointCount); + else font = LoadFontEx(TextFormat("%s/%s", GetDirectoryPath(fileName), fontFileName), fontSize, NULL, 0); // Default to 95 standard codepoints + } + + // If font texture not properly loaded, revert to default font and size/spacing + if (font.texture.id == 0) + { + font = GetFontDefault(); + GuiSetStyle(DEFAULT, TEXT_SIZE, 10); + GuiSetStyle(DEFAULT, TEXT_SPACING, 1); + } + + UnloadCodepoints(codepoints); + + if ((font.texture.id > 0) && (font.glyphCount > 0)) GuiSetFont(font); + + } break; + default: break; + } + + fgets(buffer, MAX_LINE_BUFFER_SIZE, rgsFile); + } + } + else tryBinary = true; + + fclose(rgsFile); + } + + if (tryBinary) + { + rgsFile = fopen(fileName, "rb"); + + if (rgsFile != NULL) + { + fseek(rgsFile, 0, SEEK_END); + int fileDataSize = ftell(rgsFile); + fseek(rgsFile, 0, SEEK_SET); + + if (fileDataSize > 0) + { + unsigned char *fileData = (unsigned char *)RAYGUI_MALLOC(fileDataSize*sizeof(unsigned char)); + fread(fileData, sizeof(unsigned char), fileDataSize, rgsFile); + + GuiLoadStyleFromMemory(fileData, fileDataSize); + + RAYGUI_FREE(fileData); + } + + fclose(rgsFile); + } + } +} + +// Load style default over global style +void GuiLoadStyleDefault(void) +{ + // We set this variable first to avoid cyclic function calls + // when calling GuiSetStyle() and GuiGetStyle() + guiStyleLoaded = true; + + // Initialize default LIGHT style property values + // WARNING: Default value are applied to all controls on set but + // they can be overwritten later on for every custom control + GuiSetStyle(DEFAULT, BORDER_COLOR_NORMAL, 0x838383ff); + GuiSetStyle(DEFAULT, BASE_COLOR_NORMAL, 0xc9c9c9ff); + GuiSetStyle(DEFAULT, TEXT_COLOR_NORMAL, 0x686868ff); + GuiSetStyle(DEFAULT, BORDER_COLOR_FOCUSED, 0x5bb2d9ff); + GuiSetStyle(DEFAULT, BASE_COLOR_FOCUSED, 0xc9effeff); + GuiSetStyle(DEFAULT, TEXT_COLOR_FOCUSED, 0x6c9bbcff); + GuiSetStyle(DEFAULT, BORDER_COLOR_PRESSED, 0x0492c7ff); + GuiSetStyle(DEFAULT, BASE_COLOR_PRESSED, 0x97e8ffff); + GuiSetStyle(DEFAULT, TEXT_COLOR_PRESSED, 0x368bafff); + GuiSetStyle(DEFAULT, BORDER_COLOR_DISABLED, 0xb5c1c2ff); + GuiSetStyle(DEFAULT, BASE_COLOR_DISABLED, 0xe6e9e9ff); + GuiSetStyle(DEFAULT, TEXT_COLOR_DISABLED, 0xaeb7b8ff); + GuiSetStyle(DEFAULT, BORDER_WIDTH, 1); + GuiSetStyle(DEFAULT, TEXT_PADDING, 0); + GuiSetStyle(DEFAULT, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER); + + // Initialize default extended property values + // NOTE: By default, extended property values are initialized to 0 + GuiSetStyle(DEFAULT, TEXT_SIZE, 10); // DEFAULT, shared by all controls + GuiSetStyle(DEFAULT, TEXT_SPACING, 1); // DEFAULT, shared by all controls + GuiSetStyle(DEFAULT, LINE_COLOR, 0x90abb5ff); // DEFAULT specific property + GuiSetStyle(DEFAULT, BACKGROUND_COLOR, 0xf5f5f5ff); // DEFAULT specific property + GuiSetStyle(DEFAULT, TEXT_LINE_SPACING, 15); // DEFAULT, 15 pixels between lines + GuiSetStyle(DEFAULT, TEXT_ALIGNMENT_VERTICAL, TEXT_ALIGN_MIDDLE); // DEFAULT, text aligned vertically to middle of text-bounds + + // Initialize control-specific property values + // NOTE: Those properties are in default list but require specific values by control type + GuiSetStyle(LABEL, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT); + GuiSetStyle(BUTTON, BORDER_WIDTH, 2); + GuiSetStyle(SLIDER, TEXT_PADDING, 4); + GuiSetStyle(PROGRESSBAR, TEXT_PADDING, 4); + GuiSetStyle(CHECKBOX, TEXT_PADDING, 4); + GuiSetStyle(CHECKBOX, TEXT_ALIGNMENT, TEXT_ALIGN_RIGHT); + GuiSetStyle(DROPDOWNBOX, TEXT_PADDING, 0); + GuiSetStyle(DROPDOWNBOX, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER); + GuiSetStyle(TEXTBOX, TEXT_PADDING, 4); + GuiSetStyle(TEXTBOX, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT); + GuiSetStyle(VALUEBOX, TEXT_PADDING, 0); + GuiSetStyle(VALUEBOX, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT); + GuiSetStyle(STATUSBAR, TEXT_PADDING, 8); + GuiSetStyle(STATUSBAR, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT); + + // Initialize extended property values + // NOTE: By default, extended property values are initialized to 0 + GuiSetStyle(TOGGLE, GROUP_PADDING, 2); + GuiSetStyle(SLIDER, SLIDER_WIDTH, 16); + GuiSetStyle(SLIDER, SLIDER_PADDING, 1); + GuiSetStyle(PROGRESSBAR, PROGRESS_PADDING, 1); + GuiSetStyle(CHECKBOX, CHECK_PADDING, 1); + GuiSetStyle(COMBOBOX, COMBO_BUTTON_WIDTH, 32); + GuiSetStyle(COMBOBOX, COMBO_BUTTON_SPACING, 2); + GuiSetStyle(DROPDOWNBOX, ARROW_PADDING, 16); + GuiSetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING, 2); + GuiSetStyle(VALUEBOX, SPINNER_BUTTON_WIDTH, 24); + GuiSetStyle(VALUEBOX, SPINNER_BUTTON_SPACING, 2); + GuiSetStyle(SCROLLBAR, BORDER_WIDTH, 0); + GuiSetStyle(SCROLLBAR, ARROWS_VISIBLE, 0); + GuiSetStyle(SCROLLBAR, ARROWS_SIZE, 6); + GuiSetStyle(SCROLLBAR, SCROLL_SLIDER_PADDING, 0); + GuiSetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE, 16); + GuiSetStyle(SCROLLBAR, SCROLL_PADDING, 0); + GuiSetStyle(SCROLLBAR, SCROLL_SPEED, 12); + GuiSetStyle(LISTVIEW, LIST_ITEMS_HEIGHT, 28); + GuiSetStyle(LISTVIEW, LIST_ITEMS_SPACING, 2); + GuiSetStyle(LISTVIEW, LIST_ITEMS_BORDER_WIDTH, 1); + GuiSetStyle(LISTVIEW, SCROLLBAR_WIDTH, 12); + GuiSetStyle(LISTVIEW, SCROLLBAR_SIDE, SCROLLBAR_RIGHT_SIDE); + GuiSetStyle(COLORPICKER, COLOR_SELECTOR_SIZE, 8); + GuiSetStyle(COLORPICKER, HUEBAR_WIDTH, 16); + GuiSetStyle(COLORPICKER, HUEBAR_PADDING, 8); + GuiSetStyle(COLORPICKER, HUEBAR_SELECTOR_HEIGHT, 8); + GuiSetStyle(COLORPICKER, HUEBAR_SELECTOR_OVERFLOW, 2); + + if (guiFont.texture.id != GetFontDefault().texture.id) + { + // Unload previous font texture + UnloadTexture(guiFont.texture); + RL_FREE(guiFont.recs); + RL_FREE(guiFont.glyphs); + guiFont.recs = NULL; + guiFont.glyphs = NULL; + + // Setup default raylib font + guiFont = GetFontDefault(); + + // NOTE: Default raylib font character 95 is a white square + Rectangle whiteChar = guiFont.recs[95]; + + // NOTE: We set up a 1px padding on char rectangle to avoid pixel bleeding on MSAA filtering + SetShapesTexture(guiFont.texture, RAYGUI_CLITERAL(Rectangle){ whiteChar.x + 1, whiteChar.y + 1, whiteChar.width - 2, whiteChar.height - 2 }); + } +} + +// Get text with icon id prepended +// NOTE: Useful to add icons by name id (enum) instead of +// a number that can change between ricon versions +const char *GuiIconText(int iconId, const char *text) +{ +#if defined(RAYGUI_NO_ICONS) + return NULL; +#else + static char buffer[1024] = { 0 }; + static char iconBuffer[16] = { 0 }; + + if (text != NULL) + { + memset(buffer, 0, 1024); + snprintf(buffer, 1024, "#%03i#", iconId); + + for (int i = 5; i < 1024; i++) + { + buffer[i] = text[i - 5]; + if (text[i - 5] == '\0') break; + } + + return buffer; + } + else + { + snprintf(iconBuffer, 16, "#%03i#", iconId); + + return iconBuffer; + } +#endif +} + +#if !defined(RAYGUI_NO_ICONS) +// Get full icons data pointer +unsigned int *GuiGetIcons(void) { return guiIconsPtr; } + +// Load raygui icons file (.rgi) +// NOTE: In case nameIds are required, they can be requested with loadIconsName, +// they are returned as a guiIconsName[iconCount][RAYGUI_ICON_MAX_NAME_LENGTH], +// WARNING: guiIconsName[]][] memory should be manually freed! +char **GuiLoadIcons(const char *fileName, bool loadIconsName) +{ + // Style File Structure (.rgi) + // ------------------------------------------------------ + // Offset | Size | Type | Description + // ------------------------------------------------------ + // 0 | 4 | char | Signature: "rGI " + // 4 | 2 | short | Version: 100 + // 6 | 2 | short | reserved + + // 8 | 2 | short | Num icons (N) + // 10 | 2 | short | Icons size (Options: 16, 32, 64) (S) + + // Icons name id (32 bytes per name id) + // foreach (icon) + // { + // 12+32*i | 32 | char | Icon NameId + // } + + // Icons data: One bit per pixel, stored as unsigned int array (depends on icon size) + // S*S pixels/32bit per unsigned int = K unsigned int per icon + // foreach (icon) + // { + // ... | K | unsigned int | Icon Data + // } + + FILE *rgiFile = fopen(fileName, "rb"); + + char **guiIconsName = NULL; + + if (rgiFile != NULL) + { + char signature[5] = { 0 }; + short version = 0; + short reserved = 0; + short iconCount = 0; + short iconSize = 0; + + fread(signature, 1, 4, rgiFile); + fread(&version, sizeof(short), 1, rgiFile); + fread(&reserved, sizeof(short), 1, rgiFile); + fread(&iconCount, sizeof(short), 1, rgiFile); + fread(&iconSize, sizeof(short), 1, rgiFile); + + if ((signature[0] == 'r') && + (signature[1] == 'G') && + (signature[2] == 'I') && + (signature[3] == ' ')) + { + if (loadIconsName) + { + guiIconsName = (char **)RAYGUI_MALLOC(iconCount*sizeof(char **)); + for (int i = 0; i < iconCount; i++) + { + guiIconsName[i] = (char *)RAYGUI_MALLOC(RAYGUI_ICON_MAX_NAME_LENGTH); + fread(guiIconsName[i], 1, RAYGUI_ICON_MAX_NAME_LENGTH, rgiFile); + } + } + else fseek(rgiFile, iconCount*RAYGUI_ICON_MAX_NAME_LENGTH, SEEK_CUR); + + // Read icons data directly over internal icons array + fread(guiIconsPtr, sizeof(unsigned int), iconCount*(iconSize*iconSize/32), rgiFile); + } + + fclose(rgiFile); + } + + return guiIconsName; +} + +// Load icons from memory +// WARNING: Binary files only +char **GuiLoadIconsFromMemory(const unsigned char *fileData, int dataSize, bool loadIconsName) +{ + unsigned char *fileDataPtr = (unsigned char *)fileData; + char **guiIconsName = NULL; + + char signature[5] = { 0 }; + short version = 0; + short reserved = 0; + short iconCount = 0; + short iconSize = 0; + + memcpy(signature, fileDataPtr, 4); + memcpy(&version, fileDataPtr + 4, sizeof(short)); + memcpy(&reserved, fileDataPtr + 4 + 2, sizeof(short)); + memcpy(&iconCount, fileDataPtr + 4 + 2 + 2, sizeof(short)); + memcpy(&iconSize, fileDataPtr + 4 + 2 + 2 + 2, sizeof(short)); + fileDataPtr += 12; + + if ((signature[0] == 'r') && + (signature[1] == 'G') && + (signature[2] == 'I') && + (signature[3] == ' ')) + { + if (loadIconsName) + { + guiIconsName = (char **)RAYGUI_MALLOC(iconCount*sizeof(char *)); + for (int i = 0; i < iconCount; i++) + { + guiIconsName[i] = (char *)RAYGUI_MALLOC(RAYGUI_ICON_MAX_NAME_LENGTH); + memcpy(guiIconsName[i], fileDataPtr, RAYGUI_ICON_MAX_NAME_LENGTH); + fileDataPtr += RAYGUI_ICON_MAX_NAME_LENGTH; + } + } + else + { + // Skip icon name data if not required + fileDataPtr += iconCount*RAYGUI_ICON_MAX_NAME_LENGTH; + } + + int iconDataSize = iconCount*(iconSize*iconSize/32)*sizeof(unsigned int); + guiIconsPtr = (unsigned int *)RAYGUI_MALLOC(iconDataSize); + + memcpy(guiIconsPtr, fileDataPtr, iconDataSize); + } + + return guiIconsName; +} + +// Draw selected icon using rectangles pixel-by-pixel +void GuiDrawIcon(int iconId, int posX, int posY, int pixelSize, Color color) +{ + #define BIT_CHECK(a,b) ((a) & (1u<<(b))) + + for (int i = 0, y = 0; i < RAYGUI_ICON_SIZE*RAYGUI_ICON_SIZE/32; i++) + { + for (int k = 0; k < 32; k++) + { + if (BIT_CHECK(guiIconsPtr[iconId*RAYGUI_ICON_DATA_ELEMENTS + i], k)) + { + #if !defined(RAYGUI_STANDALONE) + GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ (float)posX + (k%RAYGUI_ICON_SIZE)*pixelSize, (float)posY + y*pixelSize, (float)pixelSize, (float)pixelSize }, 0, BLANK, color); + #endif + } + + if ((k == 15) || (k == 31)) y++; + } + } +} + +// Set icon drawing size +void GuiSetIconScale(int scale) +{ + if (scale >= 1) guiIconScale = scale; +} + +#endif // !RAYGUI_NO_ICONS + +//---------------------------------------------------------------------------------- +// Module specific Functions Definition +//---------------------------------------------------------------------------------- + +// Load style from memory +// WARNING: Binary files only +static void GuiLoadStyleFromMemory(const unsigned char *fileData, int dataSize) +{ + unsigned char *fileDataPtr = (unsigned char *)fileData; + + char signature[5] = { 0 }; + short version = 0; + short reserved = 0; + int propertyCount = 0; + + memcpy(signature, fileDataPtr, 4); + memcpy(&version, fileDataPtr + 4, sizeof(short)); + memcpy(&reserved, fileDataPtr + 4 + 2, sizeof(short)); + memcpy(&propertyCount, fileDataPtr + 4 + 2 + 2, sizeof(int)); + fileDataPtr += 12; + + if ((signature[0] == 'r') && + (signature[1] == 'G') && + (signature[2] == 'S') && + (signature[3] == ' ')) + { + short controlId = 0; + short propertyId = 0; + unsigned int propertyValue = 0; + + for (int i = 0; i < propertyCount; i++) + { + memcpy(&controlId, fileDataPtr, sizeof(short)); + memcpy(&propertyId, fileDataPtr + 2, sizeof(short)); + memcpy(&propertyValue, fileDataPtr + 2 + 2, sizeof(unsigned int)); + fileDataPtr += 8; + + if (controlId == 0) // DEFAULT control + { + // If a DEFAULT property is loaded, it is propagated to all controls + // NOTE: All DEFAULT properties should be defined first in the file + GuiSetStyle(0, (int)propertyId, propertyValue); + + if (propertyId < RAYGUI_MAX_PROPS_BASE) for (int j = 1; j < RAYGUI_MAX_CONTROLS; j++) GuiSetStyle(j, (int)propertyId, propertyValue); + } + else GuiSetStyle((int)controlId, (int)propertyId, propertyValue); + } + + // Font loading is highly dependant on raylib API to load font data and image + +#if !defined(RAYGUI_STANDALONE) + // Load custom font if available + int fontDataSize = 0; + memcpy(&fontDataSize, fileDataPtr, sizeof(int)); + fileDataPtr += 4; + + if (fontDataSize > 0) + { + Font font = { 0 }; + int fontType = 0; // 0-Normal, 1-SDF + + memcpy(&font.baseSize, fileDataPtr, sizeof(int)); + memcpy(&font.glyphCount, fileDataPtr + 4, sizeof(int)); + memcpy(&fontType, fileDataPtr + 4 + 4, sizeof(int)); + fileDataPtr += 12; + + // Load font white rectangle + Rectangle fontWhiteRec = { 0 }; + memcpy(&fontWhiteRec, fileDataPtr, sizeof(Rectangle)); + fileDataPtr += 16; + + // Load font image parameters + int fontImageUncompSize = 0; + int fontImageCompSize = 0; + memcpy(&fontImageUncompSize, fileDataPtr, sizeof(int)); + memcpy(&fontImageCompSize, fileDataPtr + 4, sizeof(int)); + fileDataPtr += 8; + + Image imFont = { 0 }; + imFont.mipmaps = 1; + memcpy(&imFont.width, fileDataPtr, sizeof(int)); + memcpy(&imFont.height, fileDataPtr + 4, sizeof(int)); + memcpy(&imFont.format, fileDataPtr + 4 + 4, sizeof(int)); + fileDataPtr += 12; + + if ((fontImageCompSize > 0) && (fontImageCompSize != fontImageUncompSize)) + { + // Compressed font atlas image data (DEFLATE), it requires DecompressData() + int dataUncompSize = 0; + unsigned char *compData = (unsigned char *)RAYGUI_MALLOC(fontImageCompSize); + memcpy(compData, fileDataPtr, fontImageCompSize); + fileDataPtr += fontImageCompSize; + + imFont.data = DecompressData(compData, fontImageCompSize, &dataUncompSize); + + // Security check, dataUncompSize must match the provided fontImageUncompSize + if (dataUncompSize != fontImageUncompSize) RAYGUI_LOG("WARNING: Uncompressed font atlas image data could be corrupted"); + + RAYGUI_FREE(compData); + } + else + { + // Font atlas image data is not compressed + imFont.data = (unsigned char *)RAYGUI_MALLOC(fontImageUncompSize); + memcpy(imFont.data, fileDataPtr, fontImageUncompSize); + fileDataPtr += fontImageUncompSize; + } + + if (font.texture.id != GetFontDefault().texture.id) UnloadTexture(font.texture); + font.texture = LoadTextureFromImage(imFont); + + RAYGUI_FREE(imFont.data); + + // Validate font atlas texture was loaded correctly + if (font.texture.id != 0) + { + // Load font recs data + int recsDataSize = font.glyphCount*sizeof(Rectangle); + int recsDataCompressedSize = 0; + + // WARNING: Version 400 adds the compression size parameter + if (version >= 400) + { + // RGS files version 400 support compressed recs data + memcpy(&recsDataCompressedSize, fileDataPtr, sizeof(int)); + fileDataPtr += sizeof(int); + } + + if ((recsDataCompressedSize > 0) && (recsDataCompressedSize != recsDataSize)) + { + // Recs data is compressed, uncompress it + unsigned char *recsDataCompressed = (unsigned char *)RAYGUI_MALLOC(recsDataCompressedSize); + + memcpy(recsDataCompressed, fileDataPtr, recsDataCompressedSize); + fileDataPtr += recsDataCompressedSize; + + int recsDataUncompSize = 0; + font.recs = (Rectangle *)DecompressData(recsDataCompressed, recsDataCompressedSize, &recsDataUncompSize); + + // Security check, data uncompressed size must match the expected original data size + if (recsDataUncompSize != recsDataSize) RAYGUI_LOG("WARNING: Uncompressed font recs data could be corrupted"); + + RAYGUI_FREE(recsDataCompressed); + } + else + { + // Recs data is uncompressed + font.recs = (Rectangle *)RAYGUI_CALLOC(font.glyphCount, sizeof(Rectangle)); + for (int i = 0; i < font.glyphCount; i++) + { + memcpy(&font.recs[i], fileDataPtr, sizeof(Rectangle)); + fileDataPtr += sizeof(Rectangle); + } + } + + // Load font glyphs info data + int glyphsDataSize = font.glyphCount*16; // 16 bytes data per glyph + int glyphsDataCompressedSize = 0; + + // WARNING: Version 400 adds the compression size parameter + if (version >= 400) + { + // RGS files version 400 support compressed glyphs data + memcpy(&glyphsDataCompressedSize, fileDataPtr, sizeof(int)); + fileDataPtr += sizeof(int); + } + + // Allocate required glyphs space to fill with data + font.glyphs = (GlyphInfo *)RAYGUI_CALLOC(font.glyphCount, sizeof(GlyphInfo)); + + if ((glyphsDataCompressedSize > 0) && (glyphsDataCompressedSize != glyphsDataSize)) + { + // Glyphs data is compressed, uncompress it + unsigned char *glypsDataCompressed = (unsigned char *)RAYGUI_MALLOC(glyphsDataCompressedSize); + + memcpy(glypsDataCompressed, fileDataPtr, glyphsDataCompressedSize); + fileDataPtr += glyphsDataCompressedSize; + + int glyphsDataUncompSize = 0; + unsigned char *glyphsDataUncomp = DecompressData(glypsDataCompressed, glyphsDataCompressedSize, &glyphsDataUncompSize); + + // Security check, data uncompressed size must match the expected original data size + if (glyphsDataUncompSize != glyphsDataSize) RAYGUI_LOG("WARNING: Uncompressed font glyphs data could be corrupted"); + + unsigned char *glyphsDataUncompPtr = glyphsDataUncomp; + + for (int i = 0; i < font.glyphCount; i++) + { + memcpy(&font.glyphs[i].value, glyphsDataUncompPtr, sizeof(int)); + memcpy(&font.glyphs[i].offsetX, glyphsDataUncompPtr + 4, sizeof(int)); + memcpy(&font.glyphs[i].offsetY, glyphsDataUncompPtr + 8, sizeof(int)); + memcpy(&font.glyphs[i].advanceX, glyphsDataUncompPtr + 12, sizeof(int)); + glyphsDataUncompPtr += 16; + } + + RAYGUI_FREE(glypsDataCompressed); + RAYGUI_FREE(glyphsDataUncomp); + } + else + { + // Glyphs data is uncompressed + for (int i = 0; i < font.glyphCount; i++) + { + memcpy(&font.glyphs[i].value, fileDataPtr, sizeof(int)); + memcpy(&font.glyphs[i].offsetX, fileDataPtr + 4, sizeof(int)); + memcpy(&font.glyphs[i].offsetY, fileDataPtr + 8, sizeof(int)); + memcpy(&font.glyphs[i].advanceX, fileDataPtr + 12, sizeof(int)); + fileDataPtr += 16; + } + } + } + else font = GetFontDefault(); // Fallback in case of errors loading font atlas texture + + GuiSetFont(font); + + // Set font texture source rectangle to be used as white texture to draw shapes + // NOTE: It makes possible to draw shapes and text (full UI) in a single draw call + if ((fontWhiteRec.x > 0) && + (fontWhiteRec.y > 0) && + (fontWhiteRec.width > 0) && + (fontWhiteRec.height > 0)) SetShapesTexture(font.texture, fontWhiteRec); + } +#endif + } +} + +// Gui get text width considering icon +static int GetTextWidth(const char *text) +{ + #if !defined(ICON_TEXT_PADDING) + #define ICON_TEXT_PADDING 4 + #endif + + Vector2 textSize = { 0 }; + int textIconOffset = 0; + + if ((text != NULL) && (text[0] != '\0')) + { + if (text[0] == '#') + { + for (int i = 1; (i < 5) && (text[i] != '\0'); i++) + { + if (text[i] == '#') + { + textIconOffset = i; + break; + } + } + } + + text += textIconOffset; + + // Make sure guiFont is set, GuiGetStyle() initializes it lazynessly + float fontSize = (float)GuiGetStyle(DEFAULT, TEXT_SIZE); + + // Custom MeasureText() implementation + if ((guiFont.texture.id > 0) && (text != NULL)) + { + // Get size in bytes of text, considering end of line and line break + int size = 0; + for (int i = 0; i < MAX_LINE_BUFFER_SIZE; i++) + { + if ((text[i] != '\0') && (text[i] != '\n')) size++; + else break; + } + + float scaleFactor = fontSize/(float)guiFont.baseSize; + textSize.y = (float)guiFont.baseSize*scaleFactor; + float glyphWidth = 0.0f; + + for (int i = 0, codepointSize = 0; i < size; i += codepointSize) + { + int codepoint = GetCodepointNext(&text[i], &codepointSize); + int codepointIndex = GetGlyphIndex(guiFont, codepoint); + + if (guiFont.glyphs[codepointIndex].advanceX == 0) glyphWidth = ((float)guiFont.recs[codepointIndex].width*scaleFactor); + else glyphWidth = ((float)guiFont.glyphs[codepointIndex].advanceX*scaleFactor); + + textSize.x += (glyphWidth + (float)GuiGetStyle(DEFAULT, TEXT_SPACING)); + } + } + + if (textIconOffset > 0) textSize.x += (RAYGUI_ICON_SIZE + ICON_TEXT_PADDING); + } + + return (int)textSize.x; +} + +// Get text bounds considering control bounds +static Rectangle GetTextBounds(int control, Rectangle bounds) +{ + Rectangle textBounds = bounds; + + textBounds.x = bounds.x + GuiGetStyle(control, BORDER_WIDTH); + textBounds.y = bounds.y + GuiGetStyle(control, BORDER_WIDTH) + GuiGetStyle(control, TEXT_PADDING); + textBounds.width = bounds.width - 2*GuiGetStyle(control, BORDER_WIDTH) - 2*GuiGetStyle(control, TEXT_PADDING); + textBounds.height = bounds.height - 2*GuiGetStyle(control, BORDER_WIDTH) - 2*GuiGetStyle(control, TEXT_PADDING); // NOTE: Text is processed line per line! + + // Depending on control, TEXT_PADDING and TEXT_ALIGNMENT properties could affect the text-bounds + switch (control) + { + case COMBOBOX: + case DROPDOWNBOX: + case LISTVIEW: + // TODO: Special cases (no label): COMBOBOX, DROPDOWNBOX, LISTVIEW + case SLIDER: + case CHECKBOX: + case VALUEBOX: + case CONTROL11: + // TODO: More special cases (label on side): SLIDER, CHECKBOX, VALUEBOX, SPINNER + default: + { + // TODO: WARNING: TEXT_ALIGNMENT is already considered in GuiDrawText() + if (GuiGetStyle(control, TEXT_ALIGNMENT) == TEXT_ALIGN_RIGHT) textBounds.x -= GuiGetStyle(control, TEXT_PADDING); + else textBounds.x += GuiGetStyle(control, TEXT_PADDING); + } + break; + } + + return textBounds; +} + +// Get text icon if provided and move text cursor +// NOTE: We support up to 999 values for iconId +static const char *GetTextIcon(const char *text, int *iconId) +{ +#if !defined(RAYGUI_NO_ICONS) + *iconId = -1; + if (text[0] == '#') // Maybe we have an icon! + { + char iconValue[4] = { 0 }; // Maximum length for icon value: 3 digits + '\0' + + int pos = 1; + while ((pos < 4) && (text[pos] >= '0') && (text[pos] <= '9')) + { + iconValue[pos - 1] = text[pos]; + pos++; + } + + if (text[pos] == '#') + { + *iconId = TextToInteger(iconValue); + + // Move text pointer after icon + // WARNING: If only icon provided, it could point to EOL character: '\0' + if (*iconId >= 0) text += (pos + 1); + } + } +#endif + + return text; +} + +// Get text divided into lines (by line-breaks '\n') +static const char **GetTextLines(const char *text, int *count) +{ + #define RAYGUI_MAX_TEXT_LINES 128 + + static const char *lines[RAYGUI_MAX_TEXT_LINES] = { 0 }; + for (int i = 0; i < RAYGUI_MAX_TEXT_LINES; i++) lines[i] = NULL; // Init NULL pointers to substrings + + int textSize = (int)strlen(text); + + lines[0] = text; + int len = 0; + *count = 1; + //int lineSize = 0; // Stores current line size, not returned + + for (int i = 0, k = 0; (i < textSize) && (*count < RAYGUI_MAX_TEXT_LINES); i++) + { + if (text[i] == '\n') + { + //lineSize = len; + k++; + lines[k] = &text[i + 1]; // WARNING: next value is valid? + len = 0; + *count += 1; + } + else len++; + } + + //lines[*count - 1].size = len; + + return lines; +} + +// Get text width to next space for provided string +static float GetNextSpaceWidth(const char *text, int *nextSpaceIndex) +{ + float width = 0; + int codepointByteCount = 0; + int codepoint = 0; + int index = 0; + float glyphWidth = 0; + float scaleFactor = (float)GuiGetStyle(DEFAULT, TEXT_SIZE)/guiFont.baseSize; + + for (int i = 0; text[i] != '\0'; i++) + { + if (text[i] != ' ') + { + codepoint = GetCodepoint(&text[i], &codepointByteCount); + index = GetGlyphIndex(guiFont, codepoint); + glyphWidth = (guiFont.glyphs[index].advanceX == 0)? guiFont.recs[index].width*scaleFactor : guiFont.glyphs[index].advanceX*scaleFactor; + width += (glyphWidth + (float)GuiGetStyle(DEFAULT, TEXT_SPACING)); + } + else + { + *nextSpaceIndex = i; + break; + } + } + + return width; +} + +// Gui draw text using default font +static void GuiDrawText(const char *text, Rectangle textBounds, int alignment, Color tint) +{ + #define TEXT_VALIGN_PIXEL_OFFSET(h) ((int)h%2) // Vertical alignment for pixel perfect + + #if !defined(ICON_TEXT_PADDING) + #define ICON_TEXT_PADDING 4 + #endif + + if ((text == NULL) || (text[0] == '\0')) return; // Security check + + // PROCEDURE: + // - Text is processed line per line + // - For every line, horizontal alignment is defined + // - For all text, vertical alignment is defined (multiline text only) + // - For every line, wordwrap mode is checked (useful for GuitextBox(), read-only) + + // Get text lines (using '\n' as delimiter) to be processed individually + // WARNING: We can't use GuiTextSplit() function because it can be already used + // before the GuiDrawText() call and its buffer is static, it would be overriden :( + int lineCount = 0; + const char **lines = GetTextLines(text, &lineCount); + + // Text style variables + //int alignment = GuiGetStyle(DEFAULT, TEXT_ALIGNMENT); + int alignmentVertical = GuiGetStyle(DEFAULT, TEXT_ALIGNMENT_VERTICAL); + int wrapMode = GuiGetStyle(DEFAULT, TEXT_WRAP_MODE); // Wrap-mode only available in read-only mode, no for text editing + + // TODO: WARNING: This totalHeight is not valid for vertical alignment in case of word-wrap + float totalHeight = (float)(lineCount*GuiGetStyle(DEFAULT, TEXT_SIZE) + (lineCount - 1)*GuiGetStyle(DEFAULT, TEXT_SIZE)/2); + float posOffsetY = 0.0f; + + for (int i = 0; i < lineCount; i++) + { + int iconId = 0; + lines[i] = GetTextIcon(lines[i], &iconId); // Check text for icon and move cursor + + // Get text position depending on alignment and iconId + //--------------------------------------------------------------------------------- + Vector2 textBoundsPosition = { textBounds.x, textBounds.y }; + float textBoundsWidthOffset = 0.0f; + + // NOTE: We get text size after icon has been processed + // WARNING: GetTextWidth() also processes text icon to get width! -> Really needed? + int textSizeX = GetTextWidth(lines[i]); + + // If text requires an icon, add size to measure + if (iconId >= 0) + { + textSizeX += RAYGUI_ICON_SIZE*guiIconScale; + + // WARNING: If only icon provided, text could be pointing to EOF character: '\0' +#if !defined(RAYGUI_NO_ICONS) + if ((lines[i] != NULL) && (lines[i][0] != '\0')) textSizeX += ICON_TEXT_PADDING; +#endif + } + + // Check guiTextAlign global variables + switch (alignment) + { + case TEXT_ALIGN_LEFT: textBoundsPosition.x = textBounds.x; break; + case TEXT_ALIGN_CENTER: textBoundsPosition.x = textBounds.x + textBounds.width/2 - textSizeX/2; break; + case TEXT_ALIGN_RIGHT: textBoundsPosition.x = textBounds.x + textBounds.width - textSizeX; break; + default: break; + } + + if (textSizeX > textBounds.width && (lines[i] != NULL) && (lines[i][0] != '\0')) textBoundsPosition.x = textBounds.x; + + switch (alignmentVertical) + { + // Only valid in case of wordWrap = 0; + case TEXT_ALIGN_TOP: textBoundsPosition.y = textBounds.y + posOffsetY; break; + case TEXT_ALIGN_MIDDLE: textBoundsPosition.y = textBounds.y + posOffsetY + textBounds.height/2 - totalHeight/2 + TEXT_VALIGN_PIXEL_OFFSET(textBounds.height); break; + case TEXT_ALIGN_BOTTOM: textBoundsPosition.y = textBounds.y + posOffsetY + textBounds.height - totalHeight + TEXT_VALIGN_PIXEL_OFFSET(textBounds.height); break; + default: break; + } + + // NOTE: Make sure we get pixel-perfect coordinates, + // In case of decimals we got weird text positioning + textBoundsPosition.x = (float)((int)textBoundsPosition.x); + textBoundsPosition.y = (float)((int)textBoundsPosition.y); + //--------------------------------------------------------------------------------- + + // Draw text (with icon if available) + //--------------------------------------------------------------------------------- +#if !defined(RAYGUI_NO_ICONS) + if (iconId >= 0) + { + // NOTE: We consider icon height, probably different than text size + GuiDrawIcon(iconId, (int)textBoundsPosition.x, (int)(textBounds.y + textBounds.height/2 - RAYGUI_ICON_SIZE*guiIconScale/2 + TEXT_VALIGN_PIXEL_OFFSET(textBounds.height)), guiIconScale, tint); + textBoundsPosition.x += (float)(RAYGUI_ICON_SIZE*guiIconScale + ICON_TEXT_PADDING); + textBoundsWidthOffset = (float)(RAYGUI_ICON_SIZE*guiIconScale + ICON_TEXT_PADDING); + } +#endif + // Get size in bytes of text, + // considering end of line and line break + int lineSize = 0; + for (int c = 0; (lines[i][c] != '\0') && (lines[i][c] != '\n') && (lines[i][c] != '\r'); c++, lineSize++){ } + float scaleFactor = (float)GuiGetStyle(DEFAULT, TEXT_SIZE)/guiFont.baseSize; + + int lastSpaceIndex = 0; + bool tempWrapCharMode = false; + + int textOffsetY = 0; + float textOffsetX = 0.0f; + float glyphWidth = 0; + + int ellipsisWidth = GetTextWidth("..."); + bool textOverflow = false; + for (int c = 0, codepointSize = 0; c < lineSize; c += codepointSize) + { + int codepoint = GetCodepointNext(&lines[i][c], &codepointSize); + int index = GetGlyphIndex(guiFont, codepoint); + + // NOTE: Normally we exit the decoding sequence as soon as a bad byte is found (and return 0x3f) + // but we need to draw all of the bad bytes using the '?' symbol moving one byte + if (codepoint == 0x3f) codepointSize = 1; // TODO: Review not recognized codepoints size + + // Get glyph width to check if it goes out of bounds + if (guiFont.glyphs[index].advanceX == 0) glyphWidth = ((float)guiFont.recs[index].width*scaleFactor); + else glyphWidth = (float)guiFont.glyphs[index].advanceX*scaleFactor; + + // Wrap mode text measuring, to validate if + // it can be drawn or a new line is required + if (wrapMode == TEXT_WRAP_CHAR) + { + // Jump to next line if current character reach end of the box limits + if ((textOffsetX + glyphWidth) > textBounds.width - textBoundsWidthOffset) + { + textOffsetX = 0.0f; + textOffsetY += GuiGetStyle(DEFAULT, TEXT_LINE_SPACING); + + if (tempWrapCharMode) // Wrap at char level when too long words + { + wrapMode = TEXT_WRAP_WORD; + tempWrapCharMode = false; + } + } + } + else if (wrapMode == TEXT_WRAP_WORD) + { + if (codepoint == 32) lastSpaceIndex = c; + + // Get width to next space in line + int nextSpaceIndex = 0; + float nextSpaceWidth = GetNextSpaceWidth(lines[i] + c, &nextSpaceIndex); + + int nextSpaceIndex2 = 0; + float nextWordSize = GetNextSpaceWidth(lines[i] + lastSpaceIndex + 1, &nextSpaceIndex2); + + if (nextWordSize > textBounds.width - textBoundsWidthOffset) + { + // Considering the case the next word is longer than bounds + tempWrapCharMode = true; + wrapMode = TEXT_WRAP_CHAR; + } + else if ((textOffsetX + nextSpaceWidth) > textBounds.width - textBoundsWidthOffset) + { + textOffsetX = 0.0f; + textOffsetY += GuiGetStyle(DEFAULT, TEXT_LINE_SPACING); + } + } + + if (codepoint == '\n') break; // WARNING: Lines are already processed manually, no need to keep drawing after this codepoint + else + { + // TODO: There are multiple types of spaces in Unicode, + // maybe it's a good idea to add support for more: http://jkorpela.fi/chars/spaces.html + if ((codepoint != ' ') && (codepoint != '\t')) // Do not draw codepoints with no glyph + { + if (wrapMode == TEXT_WRAP_NONE) + { + // Draw only required text glyphs fitting the textBounds.width + if (textSizeX > textBounds.width) + { + if (textOffsetX <= (textBounds.width - glyphWidth - textBoundsWidthOffset - ellipsisWidth)) + { + DrawTextCodepoint(guiFont, codepoint, RAYGUI_CLITERAL(Vector2){ textBoundsPosition.x + textOffsetX, textBoundsPosition.y + textOffsetY }, (float)GuiGetStyle(DEFAULT, TEXT_SIZE), GuiFade(tint, guiAlpha)); + } + else if (!textOverflow) + { + textOverflow = true; + + for (int j = 0; j < ellipsisWidth; j += ellipsisWidth/3) + { + DrawTextCodepoint(guiFont, '.', RAYGUI_CLITERAL(Vector2){ textBoundsPosition.x + textOffsetX + j, textBoundsPosition.y + textOffsetY }, (float)GuiGetStyle(DEFAULT, TEXT_SIZE), GuiFade(tint, guiAlpha)); + } + } + } + else + { + DrawTextCodepoint(guiFont, codepoint, RAYGUI_CLITERAL(Vector2){ textBoundsPosition.x + textOffsetX, textBoundsPosition.y + textOffsetY }, (float)GuiGetStyle(DEFAULT, TEXT_SIZE), GuiFade(tint, guiAlpha)); + } + } + else if ((wrapMode == TEXT_WRAP_CHAR) || (wrapMode == TEXT_WRAP_WORD)) + { + // Draw only glyphs inside the bounds + if ((textBoundsPosition.y + textOffsetY) <= (textBounds.y + textBounds.height - GuiGetStyle(DEFAULT, TEXT_SIZE))) + { + DrawTextCodepoint(guiFont, codepoint, RAYGUI_CLITERAL(Vector2){ textBoundsPosition.x + textOffsetX, textBoundsPosition.y + textOffsetY }, (float)GuiGetStyle(DEFAULT, TEXT_SIZE), GuiFade(tint, guiAlpha)); + } + } + } + + if (guiFont.glyphs[index].advanceX == 0) textOffsetX += ((float)guiFont.recs[index].width*scaleFactor + (float)GuiGetStyle(DEFAULT, TEXT_SPACING)); + else textOffsetX += ((float)guiFont.glyphs[index].advanceX*scaleFactor + (float)GuiGetStyle(DEFAULT, TEXT_SPACING)); + } + } + + if (wrapMode == TEXT_WRAP_NONE) posOffsetY += (float)GuiGetStyle(DEFAULT, TEXT_LINE_SPACING); + else if ((wrapMode == TEXT_WRAP_CHAR) || (wrapMode == TEXT_WRAP_WORD)) posOffsetY += (textOffsetY + (float)GuiGetStyle(DEFAULT, TEXT_LINE_SPACING)); + //--------------------------------------------------------------------------------- + } + +#if defined(RAYGUI_DEBUG_TEXT_BOUNDS) + GuiDrawRectangle(textBounds, 0, WHITE, Fade(BLUE, 0.4f)); +#endif +} + +// Gui draw rectangle using default raygui plain style with borders +static void GuiDrawRectangle(Rectangle rec, int borderWidth, Color borderColor, Color color) +{ + if (color.a > 0) + { + // Draw rectangle filled with color + DrawRectangle((int)rec.x, (int)rec.y, (int)rec.width, (int)rec.height, GuiFade(color, guiAlpha)); + } + + if (borderWidth > 0) + { + // Draw rectangle border lines with color + DrawRectangle((int)rec.x, (int)rec.y, (int)rec.width, borderWidth, GuiFade(borderColor, guiAlpha)); + DrawRectangle((int)rec.x, (int)rec.y + borderWidth, borderWidth, (int)rec.height - 2*borderWidth, GuiFade(borderColor, guiAlpha)); + DrawRectangle((int)rec.x + (int)rec.width - borderWidth, (int)rec.y + borderWidth, borderWidth, (int)rec.height - 2*borderWidth, GuiFade(borderColor, guiAlpha)); + DrawRectangle((int)rec.x, (int)rec.y + (int)rec.height - borderWidth, (int)rec.width, borderWidth, GuiFade(borderColor, guiAlpha)); + } + +#if defined(RAYGUI_DEBUG_RECS_BOUNDS) + DrawRectangle((int)rec.x, (int)rec.y, (int)rec.width, (int)rec.height, Fade(RED, 0.4f)); +#endif +} + +// Draw tooltip using control bounds +static void GuiTooltip(Rectangle controlRec) +{ + if (!guiLocked && guiTooltip && (guiTooltipPtr != NULL) && !guiControlExclusiveMode) + { + Vector2 textSize = MeasureTextEx(GuiGetFont(), guiTooltipPtr, (float)GuiGetStyle(DEFAULT, TEXT_SIZE), (float)GuiGetStyle(DEFAULT, TEXT_SPACING)); + + if ((controlRec.x + textSize.x + 16) > GetScreenWidth()) controlRec.x -= (textSize.x + 16 - controlRec.width); + + GuiPanel(RAYGUI_CLITERAL(Rectangle){ controlRec.x, controlRec.y + controlRec.height + 4, textSize.x + 16, GuiGetStyle(DEFAULT, TEXT_SIZE) + 8.f }, NULL); + + int textPadding = GuiGetStyle(LABEL, TEXT_PADDING); + int textAlignment = GuiGetStyle(LABEL, TEXT_ALIGNMENT); + GuiSetStyle(LABEL, TEXT_PADDING, 0); + GuiSetStyle(LABEL, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER); + GuiLabel(RAYGUI_CLITERAL(Rectangle){ controlRec.x, controlRec.y + controlRec.height + 4, textSize.x + 16, GuiGetStyle(DEFAULT, TEXT_SIZE) + 8.f }, guiTooltipPtr); + GuiSetStyle(LABEL, TEXT_ALIGNMENT, textAlignment); + GuiSetStyle(LABEL, TEXT_PADDING, textPadding); + } +} + +// Split controls text into multiple strings +// Also check for multiple columns (required by GuiToggleGroup()) +static const char **GuiTextSplit(const char *text, char delimiter, int *count, int *textRow) +{ + // NOTE: Current implementation returns a copy of the provided string with '\0' (string end delimiter) + // inserted between strings defined by "delimiter" parameter. No memory is dynamically allocated, + // all used memory is static... it has some limitations: + // 1. Maximum number of possible split strings is set by RAYGUI_TEXTSPLIT_MAX_ITEMS + // 2. Maximum size of text to split is RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE + // NOTE: Those definitions could be externally provided if required + + // TODO: HACK: GuiTextSplit() - Review how textRows are returned to user + // textRow is an externally provided array of integers that stores row number for every splitted string + + #if !defined(RAYGUI_TEXTSPLIT_MAX_ITEMS) + #define RAYGUI_TEXTSPLIT_MAX_ITEMS 128 + #endif + #if !defined(RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE) + #define RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE 1024 + #endif + + static const char *result[RAYGUI_TEXTSPLIT_MAX_ITEMS] = { NULL }; // String pointers array (points to buffer data) + static char buffer[RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE] = { 0 }; // Buffer data (text input copy with '\0' added) + memset(buffer, 0, RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE); + + result[0] = buffer; + int counter = 1; + + if (textRow != NULL) textRow[0] = 0; + + // Count how many substrings we have on text and point to every one + for (int i = 0; i < RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE; i++) + { + buffer[i] = text[i]; + if (buffer[i] == '\0') break; + else if ((buffer[i] == delimiter) || (buffer[i] == '\n')) + { + result[counter] = buffer + i + 1; + + if (textRow != NULL) + { + if (buffer[i] == '\n') textRow[counter] = textRow[counter - 1] + 1; + else textRow[counter] = textRow[counter - 1]; + } + + buffer[i] = '\0'; // Set an end of string at this point + + counter++; + if (counter >= RAYGUI_TEXTSPLIT_MAX_ITEMS) break; + } + } + + *count = counter; + + return result; +} + +// Convert color data from RGB to HSV +// NOTE: Color data should be passed normalized +static Vector3 ConvertRGBtoHSV(Vector3 rgb) +{ + Vector3 hsv = { 0 }; + float min = 0.0f; + float max = 0.0f; + float delta = 0.0f; + + min = (rgb.x < rgb.y)? rgb.x : rgb.y; + min = (min < rgb.z)? min : rgb.z; + + max = (rgb.x > rgb.y)? rgb.x : rgb.y; + max = (max > rgb.z)? max : rgb.z; + + hsv.z = max; // Value + delta = max - min; + + if (delta < 0.00001f) + { + hsv.y = 0.0f; + hsv.x = 0.0f; // Undefined, maybe NAN? + return hsv; + } + + if (max > 0.0f) + { + // NOTE: If max is 0, this divide would cause a crash + hsv.y = (delta/max); // Saturation + } + else + { + // NOTE: If max is 0, then r = g = b = 0, s = 0, h is undefined + hsv.y = 0.0f; + hsv.x = 0.0f; // Undefined, maybe NAN? + return hsv; + } + + // NOTE: Comparing float values could not work properly + if (rgb.x >= max) hsv.x = (rgb.y - rgb.z)/delta; // Between yellow & magenta + else + { + if (rgb.y >= max) hsv.x = 2.0f + (rgb.z - rgb.x)/delta; // Between cyan & yellow + else hsv.x = 4.0f + (rgb.x - rgb.y)/delta; // Between magenta & cyan + } + + hsv.x *= 60.0f; // Convert to degrees + + if (hsv.x < 0.0f) hsv.x += 360.0f; + + return hsv; +} + +// Convert color data from HSV to RGB +// NOTE: Color data should be passed normalized +static Vector3 ConvertHSVtoRGB(Vector3 hsv) +{ + Vector3 rgb = { 0 }; + float hh = 0.0f, p = 0.0f, q = 0.0f, t = 0.0f, ff = 0.0f; + long i = 0; + + // NOTE: Comparing float values could not work properly + if (hsv.y <= 0.0f) + { + rgb.x = hsv.z; + rgb.y = hsv.z; + rgb.z = hsv.z; + return rgb; + } + + hh = hsv.x; + if (hh >= 360.0f) hh = 0.0f; + hh /= 60.0f; + + i = (long)hh; + ff = hh - i; + p = hsv.z*(1.0f - hsv.y); + q = hsv.z*(1.0f - (hsv.y*ff)); + t = hsv.z*(1.0f - (hsv.y*(1.0f - ff))); + + switch (i) + { + case 0: + { + rgb.x = hsv.z; + rgb.y = t; + rgb.z = p; + } break; + case 1: + { + rgb.x = q; + rgb.y = hsv.z; + rgb.z = p; + } break; + case 2: + { + rgb.x = p; + rgb.y = hsv.z; + rgb.z = t; + } break; + case 3: + { + rgb.x = p; + rgb.y = q; + rgb.z = hsv.z; + } break; + case 4: + { + rgb.x = t; + rgb.y = p; + rgb.z = hsv.z; + } break; + case 5: + default: + { + rgb.x = hsv.z; + rgb.y = p; + rgb.z = q; + } break; + } + + return rgb; +} + +// Scroll bar control (used by GuiScrollPanel()) +static int GuiScrollBar(Rectangle bounds, int value, int minValue, int maxValue) +{ + GuiState state = guiState; + + // Is the scrollbar horizontal or vertical? + bool isVertical = (bounds.width > bounds.height)? false : true; + + // The size (width or height depending on scrollbar type) of the spinner buttons + const int spinnerSize = GuiGetStyle(SCROLLBAR, ARROWS_VISIBLE)? + (isVertical? (int)bounds.width - 2*GuiGetStyle(SCROLLBAR, BORDER_WIDTH) : + (int)bounds.height - 2*GuiGetStyle(SCROLLBAR, BORDER_WIDTH)) : 0; + + // Arrow buttons [<] [>] [∧] [∨] + Rectangle arrowUpLeft = { 0 }; + Rectangle arrowDownRight = { 0 }; + + // Actual area of the scrollbar excluding the arrow buttons + Rectangle scrollbar = { 0 }; + + // Slider bar that moves --[///]----- + Rectangle slider = { 0 }; + + // Normalize value + if (value > maxValue) value = maxValue; + if (value < minValue) value = minValue; + + int valueRange = maxValue - minValue; + if (valueRange <= 0) valueRange = 1; + + int sliderSize = GuiGetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE); + if (sliderSize < 1) sliderSize = 1; // TODO: Consider a minimum slider size + + // Calculate rectangles for all of the components + arrowUpLeft = RAYGUI_CLITERAL(Rectangle){ + (float)bounds.x + GuiGetStyle(SCROLLBAR, BORDER_WIDTH), + (float)bounds.y + GuiGetStyle(SCROLLBAR, BORDER_WIDTH), + (float)spinnerSize, (float)spinnerSize }; + + if (isVertical) + { + arrowDownRight = RAYGUI_CLITERAL(Rectangle){ (float)bounds.x + GuiGetStyle(SCROLLBAR, BORDER_WIDTH), (float)bounds.y + bounds.height - spinnerSize - GuiGetStyle(SCROLLBAR, BORDER_WIDTH), (float)spinnerSize, (float)spinnerSize }; + scrollbar = RAYGUI_CLITERAL(Rectangle){ bounds.x + GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SCROLL_PADDING), arrowUpLeft.y + arrowUpLeft.height, bounds.width - 2*(GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SCROLL_PADDING)), bounds.height - arrowUpLeft.height - arrowDownRight.height - 2*GuiGetStyle(SCROLLBAR, BORDER_WIDTH) }; + + // Make sure the slider won't get outside of the scrollbar + sliderSize = (sliderSize >= scrollbar.height)? ((int)scrollbar.height - 2) : sliderSize; + slider = RAYGUI_CLITERAL(Rectangle){ + bounds.x + GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SCROLL_SLIDER_PADDING), + scrollbar.y + (int)(((float)(value - minValue)/valueRange)*(scrollbar.height - sliderSize)), + bounds.width - 2*(GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SCROLL_SLIDER_PADDING)), + (float)sliderSize }; + } + else // horizontal + { + arrowDownRight = RAYGUI_CLITERAL(Rectangle){ (float)bounds.x + bounds.width - spinnerSize - GuiGetStyle(SCROLLBAR, BORDER_WIDTH), (float)bounds.y + GuiGetStyle(SCROLLBAR, BORDER_WIDTH), (float)spinnerSize, (float)spinnerSize }; + scrollbar = RAYGUI_CLITERAL(Rectangle){ arrowUpLeft.x + arrowUpLeft.width, bounds.y + GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SCROLL_PADDING), bounds.width - arrowUpLeft.width - arrowDownRight.width - 2*GuiGetStyle(SCROLLBAR, BORDER_WIDTH), bounds.height - 2*(GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SCROLL_PADDING)) }; + + // Make sure the slider won't get outside of the scrollbar + sliderSize = (sliderSize >= scrollbar.width)? ((int)scrollbar.width - 2) : sliderSize; + slider = RAYGUI_CLITERAL(Rectangle){ + scrollbar.x + (int)(((float)(value - minValue)/valueRange)*(scrollbar.width - sliderSize)), + bounds.y + GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SCROLL_SLIDER_PADDING), + (float)sliderSize, + bounds.height - 2*(GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SCROLL_SLIDER_PADDING)) }; + } + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked) + { + Vector2 mousePoint = GetMousePosition(); + + if (guiControlExclusiveMode) // Allows to keep dragging outside of bounds + { + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON) && + !CheckCollisionPointRec(mousePoint, arrowUpLeft) && + !CheckCollisionPointRec(mousePoint, arrowDownRight)) + { + if (CHECK_BOUNDS_ID(bounds, guiControlExclusiveRec)) + { + state = STATE_PRESSED; + + if (isVertical) value = (int)(((float)(mousePoint.y - scrollbar.y - slider.height/2)*valueRange)/(scrollbar.height - slider.height) + minValue); + else value = (int)(((float)(mousePoint.x - scrollbar.x - slider.width/2)*valueRange)/(scrollbar.width - slider.width) + minValue); + } + } + else + { + guiControlExclusiveMode = false; + guiControlExclusiveRec = RAYGUI_CLITERAL(Rectangle){ 0, 0, 0, 0 }; + } + } + else if (CheckCollisionPointRec(mousePoint, bounds)) + { + state = STATE_FOCUSED; + + // Handle mouse wheel + int wheel = (int)GetMouseWheelMove(); + if (wheel != 0) value += wheel; + + // Handle mouse button down + if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) + { + guiControlExclusiveMode = true; + guiControlExclusiveRec = bounds; // Store bounds as an identifier when dragging starts + + // Check arrows click + if (CheckCollisionPointRec(mousePoint, arrowUpLeft)) value -= valueRange/GuiGetStyle(SCROLLBAR, SCROLL_SPEED); + else if (CheckCollisionPointRec(mousePoint, arrowDownRight)) value += valueRange/GuiGetStyle(SCROLLBAR, SCROLL_SPEED); + else if (!CheckCollisionPointRec(mousePoint, slider)) + { + // If click on scrollbar position but not on slider, place slider directly on that position + if (isVertical) value = (int)(((float)(mousePoint.y - scrollbar.y - slider.height/2)*valueRange)/(scrollbar.height - slider.height) + minValue); + else value = (int)(((float)(mousePoint.x - scrollbar.x - slider.width/2)*valueRange)/(scrollbar.width - slider.width) + minValue); + } + + state = STATE_PRESSED; + } + + // Keyboard control on mouse hover scrollbar + /* + if (isVertical) + { + if (IsKeyDown(KEY_DOWN)) value += 5; + else if (IsKeyDown(KEY_UP)) value -= 5; + } + else + { + if (IsKeyDown(KEY_RIGHT)) value += 5; + else if (IsKeyDown(KEY_LEFT)) value -= 5; + } + */ + } + + // Normalize value + if (value > maxValue) value = maxValue; + if (value < minValue) value = minValue; + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + GuiDrawRectangle(bounds, GuiGetStyle(SCROLLBAR, BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER + state*3)), GetColor(GuiGetStyle(DEFAULT, BORDER_COLOR_DISABLED))); // Draw the background + + GuiDrawRectangle(scrollbar, 0, BLANK, GetColor(GuiGetStyle(BUTTON, BASE_COLOR_NORMAL))); // Draw the scrollbar active area background + GuiDrawRectangle(slider, 0, BLANK, GetColor(GuiGetStyle(SLIDER, BORDER + state*3))); // Draw the slider bar + + // Draw arrows (using icon if available) + if (GuiGetStyle(SCROLLBAR, ARROWS_VISIBLE)) + { +#if defined(RAYGUI_NO_ICONS) + GuiDrawText(isVertical? "^" : "<", + RAYGUI_CLITERAL(Rectangle){ arrowUpLeft.x, arrowUpLeft.y, isVertical? bounds.width : bounds.height, isVertical? bounds.width : bounds.height }, + TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + (state*3)))); + GuiDrawText(isVertical? "v" : ">", + RAYGUI_CLITERAL(Rectangle){ arrowDownRight.x, arrowDownRight.y, isVertical? bounds.width : bounds.height, isVertical? bounds.width : bounds.height }, + TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + (state*3)))); +#else + GuiDrawText(isVertical? "#121#" : "#118#", + RAYGUI_CLITERAL(Rectangle){ arrowUpLeft.x, arrowUpLeft.y, isVertical? bounds.width : bounds.height, isVertical? bounds.width : bounds.height }, + TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(SCROLLBAR, TEXT + state*3))); // ICON_ARROW_UP_FILL / ICON_ARROW_LEFT_FILL + GuiDrawText(isVertical? "#120#" : "#119#", + RAYGUI_CLITERAL(Rectangle){ arrowDownRight.x, arrowDownRight.y, isVertical? bounds.width : bounds.height, isVertical? bounds.width : bounds.height }, + TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(SCROLLBAR, TEXT + state*3))); // ICON_ARROW_DOWN_FILL / ICON_ARROW_RIGHT_FILL +#endif + } + //-------------------------------------------------------------------- + + return value; +} + +// Color fade-in or fade-out, alpha goes from 0.0f to 1.0f +// WARNING: It multiplies current alpha by alpha scale factor +static Color GuiFade(Color color, float alpha) +{ + if (alpha < 0.0f) alpha = 0.0f; + else if (alpha > 1.0f) alpha = 1.0f; + + Color result = { color.r, color.g, color.b, (unsigned char)(color.a*alpha) }; + + return result; +} + +#if defined(RAYGUI_STANDALONE) +// Returns a Color struct from hexadecimal value +static Color GetColor(int hexValue) +{ + Color color; + + color.r = (unsigned char)(hexValue >> 24) & 0xFF; + color.g = (unsigned char)(hexValue >> 16) & 0xFF; + color.b = (unsigned char)(hexValue >> 8) & 0xFF; + color.a = (unsigned char)hexValue & 0xFF; + + return color; +} + +// Returns hexadecimal value for a Color +static int ColorToInt(Color color) +{ + return (((int)color.r << 24) | ((int)color.g << 16) | ((int)color.b << 8) | (int)color.a); +} + +// Check if point is inside rectangle +static bool CheckCollisionPointRec(Vector2 point, Rectangle rec) +{ + bool collision = false; + + if ((point.x >= rec.x) && (point.x <= (rec.x + rec.width)) && + (point.y >= rec.y) && (point.y <= (rec.y + rec.height))) collision = true; + + return collision; +} + +// Formatting of text with variables to 'embed' +static const char *TextFormat(const char *text, ...) +{ + #if !defined(RAYGUI_TEXTFORMAT_MAX_SIZE) + #define RAYGUI_TEXTFORMAT_MAX_SIZE 256 + #endif + + static char buffer[RAYGUI_TEXTFORMAT_MAX_SIZE]; + + va_list args; + va_start(args, text); + vsprintf(buffer, text, args); + va_end(args); + + return buffer; +} + +// Draw rectangle with vertical gradient fill color +// NOTE: This function is only used by GuiColorPicker() +static void DrawRectangleGradientV(int posX, int posY, int width, int height, Color color1, Color color2) +{ + Rectangle bounds = { (float)posX, (float)posY, (float)width, (float)height }; + DrawRectangleGradientEx(bounds, color1, color2, color2, color1); +} + +// Split string into multiple strings +const char **TextSplit(const char *text, char delimiter, int *count) +{ + // NOTE: Current implementation returns a copy of the provided string with '\0' (string end delimiter) + // inserted between strings defined by "delimiter" parameter. No memory is dynamically allocated, + // all used memory is static... it has some limitations: + // 1. Maximum number of possible split strings is set by RAYGUI_TEXTSPLIT_MAX_ITEMS + // 2. Maximum size of text to split is RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE + + #if !defined(RAYGUI_TEXTSPLIT_MAX_ITEMS) + #define RAYGUI_TEXTSPLIT_MAX_ITEMS 128 + #endif + #if !defined(RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE) + #define RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE 1024 + #endif + + static const char *result[RAYGUI_TEXTSPLIT_MAX_ITEMS] = { NULL }; + static char buffer[RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE] = { 0 }; + memset(buffer, 0, RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE); + + result[0] = buffer; + int counter = 0; + + if (text != NULL) + { + counter = 1; + + // Count how many substrings we have on text and point to every one + for (int i = 0; i < RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE; i++) + { + buffer[i] = text[i]; + if (buffer[i] == '\0') break; + else if (buffer[i] == delimiter) + { + buffer[i] = '\0'; // Set an end of string at this point + result[counter] = buffer + i + 1; + counter++; + + if (counter == RAYGUI_TEXTSPLIT_MAX_ITEMS) break; + } + } + } + + *count = counter; + return result; +} + +// Get integer value from text +// NOTE: This function replaces atoi() [stdlib.h] +static int TextToInteger(const char *text) +{ + int value = 0; + int sign = 1; + + if ((text[0] == '+') || (text[0] == '-')) + { + if (text[0] == '-') sign = -1; + text++; + } + + for (int i = 0; ((text[i] >= '0') && (text[i] <= '9')); ++i) value = value*10 + (int)(text[i] - '0'); + + return value*sign; +} + +// Get float value from text +// NOTE: This function replaces atof() [stdlib.h] +// WARNING: Only '.' character is understood as decimal point +static float TextToFloat(const char *text) +{ + float value = 0.0f; + float sign = 1.0f; + + if ((text[0] == '+') || (text[0] == '-')) + { + if (text[0] == '-') sign = -1.0f; + text++; + } + + int i = 0; + for (; ((text[i] >= '0') && (text[i] <= '9')); i++) value = value*10.0f + (float)(text[i] - '0'); + + if (text[i++] != '.') value *= sign; + else + { + float divisor = 10.0f; + for (; ((text[i] >= '0') && (text[i] <= '9')); i++) + { + value += ((float)(text[i] - '0'))/divisor; + divisor = divisor*10.0f; + } + } + + return value; +} + +// Encode codepoint into UTF-8 text (char array size returned as parameter) +static const char *CodepointToUTF8(int codepoint, int *byteSize) +{ + static char utf8[6] = { 0 }; + int size = 0; + + if (codepoint <= 0x7f) + { + utf8[0] = (char)codepoint; + size = 1; + } + else if (codepoint <= 0x7ff) + { + utf8[0] = (char)(((codepoint >> 6) & 0x1f) | 0xc0); + utf8[1] = (char)((codepoint & 0x3f) | 0x80); + size = 2; + } + else if (codepoint <= 0xffff) + { + utf8[0] = (char)(((codepoint >> 12) & 0x0f) | 0xe0); + utf8[1] = (char)(((codepoint >> 6) & 0x3f) | 0x80); + utf8[2] = (char)((codepoint & 0x3f) | 0x80); + size = 3; + } + else if (codepoint <= 0x10ffff) + { + utf8[0] = (char)(((codepoint >> 18) & 0x07) | 0xf0); + utf8[1] = (char)(((codepoint >> 12) & 0x3f) | 0x80); + utf8[2] = (char)(((codepoint >> 6) & 0x3f) | 0x80); + utf8[3] = (char)((codepoint & 0x3f) | 0x80); + size = 4; + } + + *byteSize = size; + + return utf8; +} + +// Get next codepoint in a UTF-8 encoded text, scanning until '\0' is found +// When a invalid UTF-8 byte is encountered we exit as soon as possible and a '?'(0x3f) codepoint is returned +// Total number of bytes processed are returned as a parameter +// NOTE: the standard says U+FFFD should be returned in case of errors +// but that character is not supported by the default font in raylib +static int GetCodepointNext(const char *text, int *codepointSize) +{ + const char *ptr = text; + int codepoint = 0x3f; // Codepoint (defaults to '?') + *codepointSize = 1; + + // Get current codepoint and bytes processed + if (0xf0 == (0xf8 & ptr[0])) + { + // 4 byte UTF-8 codepoint + if (((ptr[1] & 0xC0) ^ 0x80) || ((ptr[2] & 0xC0) ^ 0x80) || ((ptr[3] & 0xC0) ^ 0x80)) { return codepoint; } //10xxxxxx checks + codepoint = ((0x07 & ptr[0]) << 18) | ((0x3f & ptr[1]) << 12) | ((0x3f & ptr[2]) << 6) | (0x3f & ptr[3]); + *codepointSize = 4; + } + else if (0xe0 == (0xf0 & ptr[0])) + { + // 3 byte UTF-8 codepoint */ + if (((ptr[1] & 0xC0) ^ 0x80) || ((ptr[2] & 0xC0) ^ 0x80)) { return codepoint; } //10xxxxxx checks + codepoint = ((0x0f & ptr[0]) << 12) | ((0x3f & ptr[1]) << 6) | (0x3f & ptr[2]); + *codepointSize = 3; + } + else if (0xc0 == (0xe0 & ptr[0])) + { + // 2 byte UTF-8 codepoint + if ((ptr[1] & 0xC0) ^ 0x80) { return codepoint; } //10xxxxxx checks + codepoint = ((0x1f & ptr[0]) << 6) | (0x3f & ptr[1]); + *codepointSize = 2; + } + else if (0x00 == (0x80 & ptr[0])) + { + // 1 byte UTF-8 codepoint + codepoint = ptr[0]; + *codepointSize = 1; + } + + return codepoint; +} +#endif // RAYGUI_STANDALONE + +#endif // RAYGUI_IMPLEMENTATION diff --git a/shaders/vignette.fs b/shaders/postfx.fs similarity index 100% rename from shaders/vignette.fs rename to shaders/postfx.fs diff --git a/src/engine/asset.h b/src/engine/asset.h new file mode 100644 index 0000000..af20ad3 --- /dev/null +++ b/src/engine/asset.h @@ -0,0 +1,11 @@ +#ifndef ASSET_H +#define ASSET_H + +typedef struct { + const char* path; + float frameWidth; + float frameHeight; + float rotation; +} TextureAsset; + +#endif // ASSET_H diff --git a/src/engine/postfx.h b/src/engine/postfx.h new file mode 100644 index 0000000..11b7861 --- /dev/null +++ b/src/engine/postfx.h @@ -0,0 +1,46 @@ +#ifndef POSTFX_H +#define POSTFX_H + +typedef struct { + Shader shader; + int resolutionLoc; + int strengthLoc; + float strength; +} PostProcessing; + +PostProcessing CreatePostFX(const char* shaderPath, float strength){ + PostProcessing postFX = {0}; + postFX.shader = LoadShader(NULL, shaderPath); + + if (postFX.shader.id == 0) { + TraceLog(LOG_ERROR, "Failed to load shader: %s", shaderPath); + return postFX; + } + + postFX.strength = strength; + postFX.resolutionLoc = GetShaderLocation(postFX.shader, "resolution"); + postFX.strengthLoc = GetShaderLocation(postFX.shader, "strength"); + Vector2 resolution = { (float)GetScreenWidth(), (float)GetScreenHeight() }; + SetShaderValue(postFX.shader, postFX.resolutionLoc, &resolution, SHADER_UNIFORM_VEC2); + return postFX; +} + +void UpdatePostFX(PostProcessing *postFX){ + if (postFX->shader.id == 0) return; + SetShaderValue(postFX->shader, postFX->strengthLoc, &postFX->strength, SHADER_UNIFORM_FLOAT); + Vector2 resolution = { (float)GetScreenWidth(), (float)GetScreenHeight() }; + SetShaderValue(postFX->shader, postFX->resolutionLoc, &resolution, SHADER_UNIFORM_VEC2); +} + +void RenderPostFX(PostProcessing *postFX, RenderTexture2D *target){ + BeginShaderMode(postFX->shader); + DrawTextureRec(target->texture, (Rectangle){ 0, 0, target->texture.width, target->texture.height }, (Vector2){ 0, 0 }, WHITE); + EndShaderMode(); +} + +void UnloadPostFX(PostProcessing *postFX){ + if (postFX->shader.id == 0) return; + UnloadShader(postFX->shader); +} + +#endif // POSTFX_H diff --git a/src/engine/shader.h b/src/engine/shader.h deleted file mode 100644 index 40fb91d..0000000 --- a/src/engine/shader.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef SHADER_H -#define SHADER_H - -typedef struct { - Shader shader; - int resolutionLoc; - int strengthLoc; - float strength; -} VignetteShader; - -VignetteShader CreateShader(const char* shaderPath, float strength){ - VignetteShader vignetteShader = {0}; - vignetteShader.shader = LoadShader(NULL, shaderPath); - - if (vignetteShader.shader.id == 0) { - TraceLog(LOG_ERROR, "Failed to load shader: %s", shaderPath); - return vignetteShader; - } - - vignetteShader.strength = strength; - vignetteShader.resolutionLoc = GetShaderLocation(vignetteShader.shader, "resolution"); - vignetteShader.strengthLoc = GetShaderLocation(vignetteShader.shader, "strength"); - Vector2 resolution = { (float)GetScreenWidth(), (float)GetScreenHeight() }; - SetShaderValue(vignetteShader.shader, vignetteShader.resolutionLoc, &resolution, SHADER_UNIFORM_VEC2); - return vignetteShader; -} - -void UpdateShader(VignetteShader* vignetteShader){ - if (vignetteShader->shader.id == 0) return; - SetShaderValue(vignetteShader->shader, vignetteShader->strengthLoc, &vignetteShader->strength, SHADER_UNIFORM_FLOAT); - Vector2 resolution = { (float)GetScreenWidth(), (float)GetScreenHeight() }; - SetShaderValue(vignetteShader->shader, vignetteShader->resolutionLoc, &resolution, SHADER_UNIFORM_VEC2); -} - -void UnloadVignetteShader(VignetteShader* vignetteShader){ - if (vignetteShader->shader.id == 0) return; - UnloadShader(vignetteShader->shader); -} - -#endif // SHADER_H

wNV- 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