From e1760c06b2ed667d16d2b00eab20d66531d57d98 Mon Sep 17 00:00:00 2001 From: pvtrx Date: Mon, 13 Oct 2025 16:05:41 +0200 Subject: [PATCH] Added files from info2Praktikum_Wortsalat --- EinfuehrungInGit.pdf | Bin 0 -> 552828 bytes EinfuehrungTesting.pdf | Bin 0 -> 58311 bytes Makefiles.pdf | Bin 0 -> 188734 bytes Start_Windows/game.c | 23 + Start_Windows/game.h | 11 + Start_Windows/graphicalGame.c | 455 +++ Start_Windows/graphicalGame.h | 8 + Start_Windows/input.c | 12 + Start_Windows/input.h | 11 + Start_Windows/main.c | 54 + Start_Windows/makefile | 46 + Start_Windows/raylib/raylib.h | 1708 ++++++++ Start_Windows/raylib/raymath.h | 2941 ++++++++++++++ Start_Windows/raylib/rlgl.h | 5262 +++++++++++++++++++++++++ Start_Windows/unit_tests.c | 143 + Start_Windows/unity/makefile | 3 + Start_Windows/unity/unity.c | 2622 ++++++++++++ Start_Windows/unity/unity.h | 698 ++++ Start_Windows/unity/unity_internals.h | 1271 ++++++ Start_Windows/words.txt | 5 + Wordsalad_Aufgabenstellung.pdf | Bin 0 -> 108280 bytes 21 files changed, 15273 insertions(+) create mode 100644 EinfuehrungInGit.pdf create mode 100644 EinfuehrungTesting.pdf create mode 100644 Makefiles.pdf create mode 100644 Start_Windows/game.c create mode 100644 Start_Windows/game.h create mode 100644 Start_Windows/graphicalGame.c create mode 100644 Start_Windows/graphicalGame.h create mode 100644 Start_Windows/input.c create mode 100644 Start_Windows/input.h create mode 100644 Start_Windows/main.c create mode 100644 Start_Windows/makefile create mode 100644 Start_Windows/raylib/raylib.h create mode 100644 Start_Windows/raylib/raymath.h create mode 100644 Start_Windows/raylib/rlgl.h create mode 100644 Start_Windows/unit_tests.c create mode 100644 Start_Windows/unity/makefile create mode 100644 Start_Windows/unity/unity.c create mode 100644 Start_Windows/unity/unity.h create mode 100644 Start_Windows/unity/unity_internals.h create mode 100644 Start_Windows/words.txt create mode 100644 Wordsalad_Aufgabenstellung.pdf diff --git a/EinfuehrungInGit.pdf b/EinfuehrungInGit.pdf new file mode 100644 index 0000000000000000000000000000000000000000..bbaa9f8aa652cf601ba50c2b536bd3f879176af0 GIT binary patch literal 552828 zcmb5W1yEhhwl%tO*f?wm?(Xic!QI{63Bldn-Q9v)aCg_>4#71+13&rBx%b?9?^eD4 z^EjGjIaQ2Z{$e2U-U5fGk8zL=MK*Kt4W3Su=YJS4$$+ zk0;8E5>~dZX3mTfwnnaIVrC`|re*>HKo?hMGb1~odv=McoDH5NO4m$nd83ieuQ|0% z!~uWx#2~~#D*aL70~C%_bW(Cntk;LTb_}yC1$^Fq zy_Nm3SliN<%L|V{w<#f^Zzf6RE>q9R-BQ@@Dcq(gc=LK@VvgmjH}%X`xA1AdcYH4{bE_TNAvK>WMealjFQ01l&ZXDs zG3ok;cQag7(#^gl$TZHXm?xM>rsxz);P)@~XD zGL>VB+4J4xhl)FjuId0^AT4SDf;jPwP5Sat2e+Mhu`iXQ%QN4|j4n)p0G3(o-M~`y zAO>UVuy~QYXn%gXoe`*rS*EW))p{kB+_2T~G1xCeh>dw#`Qkr?kO|O%e}kCM5C#qd z6GUyC5tSc;$JP|mqg7cDGMU|Cp7jfw?^!Zq{7a#y3UEp-kVjMfsSw=If{ED3%Q1h( zkA>wSVQBJ<1c7x{D+It~YBI%+DOC-`&CSmf&(X%iG>O2lg##gQznH*X2SA(V{o#SvH?Rho|9gd&&exFXU-!$0Pu0-7{ zvU!9Q1!G|dqx7 z%^gAG*mTL{CVUMlqyHxOY@=^#Zopy8D#>|l#$|iDOBbrc&9%R)%lj0Xjty?--MRn$ zk2d$S-*`aQ@OHAxlGG!KWbR6lA7|9VALx)y{nIGX+z|0pxeW1+B27QSl>9gWYiw9F zO>xQ1FKvfQc0V7$ck$PaQ`IuEjJU%+NCxo#fQ93F+XBt(P5+Ig58q$#0sms|uZN43 z`ETq$&)EKhOjQp@Ge%7XV{0=LS4NdD#;$+EQg%ibW{etErhhTZ%|yib+04qq(v^st zgNRYY%GE{D%vsdI&e6f%%-)rVi-=Lw!Pdc9#nH&bj8V+Y&C0|~SyJS`U@j)A`Y(|G zmk?lPW@7uuqatVIVnf8t^j9Ph{YL=2|9Ia4ph!zdNdUmWzyKQ`KfwDsKokH04*vK0 zaF8Dt6f6`JBqS6N1_l}y0f>MA4}^zDL_$MBL_$S^heyFgK}82)U|=91f5O59VWELA zKz|DXgZRh;2?YlQ1qVWeM+E)=`w3<4GGeGq^L0Dwb$ye$~u zza0!D6f^`l80<$ZE*Jm|>VL-lP5luK1NOcKK!5-PfTKX5003aG<^Rsj)jRX+Uqr+VdgOt#}shw{7SkyqwBS54Q zWj4AQ^dKwWbD)YvmCPyXh-L)vR#$4(5Lp=$=g9V&{2W8lUuWiKa?Ig)xiTVkO zFZR$HaI(21{u(j>W?%V48}ZL-Zy!|+JC6Rrx)I*43LUi}tzYzX0zW3Gi*o~}y`#P0+As{2KqMc>wG z{AZo4Ox1@@7R;<3&`c?_0lGAqkHahT|z4kjXFI_01sy|xjj##hhlyIXlO z_ZCK2f4%tXb0^PQ)aXV?;TJ{AY|}IeA8F1bFYfDd+d)nqWS&b@G^ioezjI=F>HA%3#6+5!+S(GgGE~lUvJdSptL{3Ty@;Z+P*%`LX4LVO zY~@+Q5Nlx+X1GTM78TYH^`dtlJxxuvv1&>mm3=wD#5%?fplOG;gtzzM9!{F?ThiYx zUHlHUDw!OGERzSmo@bqYa#nefea`<)wexyJSC4$Tt&O(D*43?wmX)2;Dlqk&en}1? zmEM7dMA!|fNUS4waW#{!m}q{uWT))~$L3kx_Et#C7y$7x$mvi3;2-V-VBi3le}?Oa z4+;Q=!Uhe(z(hkQVnq3h9LwIs_ z@_CCi!jZD({_LXFVWh; zD|J{3_+{#OiKSQ2Xv_5ApfHtO9&t6LKKA@N+;$REsh$Lz(}L~j{3!QQp=HWeIrtMa zz{GhtL%TP!p(H?MfkVuctN07Y?P8vF$8}ZSia~Uoun|%e*$?$yf=drVae_;|x5hZU zD~lwT{T#ZEKY4Ix%Jz?n@ctl9v1V38BqPI`X?BV7(>?#lzwh~+x%y|{{^Pk@eMDlNR{IMY5 z-kPB}9^ujY`XYdKxwejtDSf_Gbc_F|n((IO6KnTg^#c%WGPrPKa3D|0KYetjbrmb% zbI!d<*LD!;@2-$l5j8FSkqX(Ox!_*1`Zie8J`sLMvD{!j(ZUDGV6W8!ACTAgug}wb zE?v2DGqJ7>SHHbQyztg-V^ir9X}-CR7iE=_LUvgOMwv#o*RiR_+&TGI%cFm{{%Y(t zI*4f5H`a0V5T%u&{LQkz!M=C;YM)!jfacMpxxkC=jK71HmVX5O8#tc_M31d|nD}KJ z?1RhbGu4Ch)vs*#V=um}JiHT=Cg1wn=<8}W3HvjX0#7HKk>fY1uK*FerRW+)GZ*TV zcYxyW(6_a5?5>80#YGxiGGWaL6m}OP!sCP0eLg`qj2-3C!9gBIS9i&dT**1fjx@jO z{Sn^PgN?^ynQNK$yG-S^QAZ5U_;*0xH+$Z8ZvHPXQ0RFtu7`XVe!ahclMtFVaDykL zETp8_{_#3Kust4Kok?iSBefu?Cl950QjVy`Ho3;Q14DKA!PJJzf%Y1c?e?P+(Ndj#<$VYcepCS1hjxd7gMxwjm%0N3hXg>NLZJ~u zqo6YjEA@deNZ5>=0ut(3SVf!zG1AEwBF%pWu*{3AZz2 zZumu9qj~Pb{hQHd^kJpLi)bSghK=x(yI6IeW7Co;1-@pi4&`Sa(FT;PQ@CyTvDGmt zV#C4CoZR9iYjA>9^wqM@P70=+b=lK$zg)e34Nm4bCNBY@K`F%IG+0Nr^E$y8*iEIB z5S5tA#=_ddRNJDT6USZ0!bJk)F2uqQVi|SkG9R!I&2jrfuS-F^CW$jWMQt|iq1@db z$rL4IXZ>M7i9jof)RT_xbn|)~@`9MY zgvcl)r;nbZE+xfLr(m}$TBs^cCgxA643CJ$X(eK~t;GS__7b8;J6j=@kkfp-Vdxg? zKQH}3&E8IH0H)U);-*X%TBtj;sn(yIY4^JYfA(lRam%y`m|2sHC1k^3jq<62TI*K- z(QQ&XL&^eaUNDZUezntr>qKdezvv-Kdx|k0$X|dL>6@3NcXB!K#dxey281E|JK78) zc`7@D`q6!4*Ebit!DUnSDoW>y_VgZ}M?vmnbR1xcI z*7+nU$g<^~-;*?*UAy}Z$P}$Ep!uXjky8ps!_GV-$A-g`x!`6)Fc&`tl-;cRvr&c& zd0^d-w=PF9s@s&Lj5IyDtXIBTWQRB9WThaQCX>aeR938IZ`R~eoKeaBlzMlFIq}5k z>WQDSi>MzuwV3>(292jppIxH-C%(AYdQq4nubR(`!5A|`Y)|C?{j+!(6<2yQx=3-t zu4aNIr)>_#Ugg$c%$tDE_2Fv?xv@GvC}u52R`C1SvZ7U>(?E$rmH*6#q+s}v6n|F% zU=ZN{nrQ$&rqB?OsAwp}%;+qv!XObPqkwuM5>g@KzUzNP1Nc9pfw1;PW05(FG2@Lo z1;KaC$7;zIk3zNnX!IPV%3&3!9-aMO5dLnH|;+=eA1*=eOu=n z<12WPQhW-OZZ%d)EQnPeRedhzt41qch1J}bD1GC|r0IgTy?v72;#016&5zLS8G^5N z$}Aii+ieef^ZF;F)>jD|Ow({HBS;fEFd#Qcd*I7AT<*)VD&2OK8>S{MySr$)fqDH! zSN19T;tG4fs^N;QWu8mfga)@V{%`J3dU0!8EB8~irpJ=T9zxw)r z05(m=D3ZqphNO0WL967{tA+g@+7l)8Vp0r{S;C$Q^%fr7ygR|e29>sE?|hk&7u~0! z1eL*`SBc&p9oHG?t0qrM!@}5p>qYQ&U_6w3hyAAVm_3`~-b24WdRFLT5($8Sf`Whn zLVv7_J{;Ib7!?u)?QhQtyVR2?^%05u)d6!*AW~K~W#_=e0w%@6{@rU)0X;pFk^LG-;68{Yd<$Rub18W-w8x&_@RSVBf`4P9l`wpJEZXC zW|z#_`K8I{W?1u$6{G@l{4mHbs3VvVNg645wN zgm94dpOWxs8+?B~3a2qC#%+(%-Kx8nFg3|Ey$)+w)$Qg#O3<>Wndd7<6+>|7qqz5e zNm=DFhm@6?KNI6mBPeH>FE7#^giAc!6D=tBrzi!U03%G%2$A+sucBSZ=e*7|M;O#J zx|<>rFVLDqlj3Aq;V5BhV3X5Ns{bi(%Y5>=iRWupJuj609e7BoFUDhEg_U1~FKPr9 z%R^L4xIn}s67<HvE{ymsM7N&rsrc9$qrH}i&Hnkqeow3+RrfY zCs?lW3S8dQdTT{;i$-5&ejUoliQ-sLxri3gN*8cQ*R#_6XpZ?GfU1cv<8)Ef;R%gc zpV?|(l8Kvw5ByRnBq2|W@DS~x|U*t zh=@EQk6G%(sZTj3Uoe|5jt(pRr)HZ)4KNLz44BT=F=hFi)UP}De`~kNVn!PxRcxHT zbnp0y?|V!{lE{~mCAlLmn@z|hW%piJE=?ztBt&M*-mjb7EcliFd?AgqhU!Bnq2m4X z>#9!4bPX8faqLjUG>JznmY1wyc}bH-qLGB=puH6kd3s21X#UMRz$Lg5r440~K=9I$ z9whX`Q8_~yM^no=B}T`bS`)2231roTQH(uUg=17OD>|)MvejJ8Q}an;iI5qd7ATX- zw`!awrIOA7bLDzhqxx`oFv?zQo+c+;SdaR5kZ10zDLXXYefl;wdChEb#Hdr|#k2L= zxTt6Gy7j4twO5aKb^eJcGH{>KmP!nk$+9rP(m5(xKu-2if(e{@0ecxTiS9x^ka<`A zN{u@_JG?E=ChY6^wg6Z#33 zhpjT_uR~|fE_?`DPf^P!ThoOPhq;AkoJZGPPr2Y9;k3~sMoqLi#c1{m*e1T-{7{I- zGgNa}$MSE0-{KLaaiuKs?JJCT=m_QhR}?vi7V6fEinnO42xdDnu$9NN4q4{@nJJ)3B5>$+Ht ztDcjeby=4c?I+qGb9^|ZGX|soINnZ2Qzx^vZs{y*J1`fM)fYyJ^4gbIwEy2$r;0%q zQOu4)xv5lf*-0)7@1x~wieybbqh}heAtD%7*8WL0H>%#t;^2z*-e5;-zVFknBJ9*) zM&uH-Ypoh)`VP$dVyw*1G=Zg_Ks_;6@>3{yN}T=tN^C@%IU~y$r>|ceZcsJ4itzJh zLSYQ)h2Y$q(TYuzvQ3AyE=OQA-{CU(ABqKhcV!A6iWw*_bzbmq4_P`PIbXcjm%jX4 zc&4p>^u@uEJJ#Q^w9u6!el@`_zU(ly>vhKmHN$Ba^a+9acizu;0H?J2l#IWjd;%Q< z{!UStx1A%yY|bU`9I=Jw3MQTADX)Hb>Yh+y<4L2C78&uYvyLj2{za@P4%%pxRC2Q|cUV4{(&iN^$uhuC;qpt(}cE%202Hwyad>l6; zEqt7}EZPIDl7fsnU2f4XA!#6$ILjYq9{sr%4>z0C_yCG_1RPqGh`85xz$Of;b>;;v zX12W&!t$_+-p`DBi!3^({sk_JegTEmNz>{cwgvwv3W^MxNEX!*-7ZuLp*17n>dAT! z+{CVt{r|@et_jF=5=sFlhTuA#u%11roQ#c3OdgUZ4w}SrrDcewj^`|jQC;EMNVycm zf@4+$*sP+&va4wR6Sk6X=x=rGoJ<8JQm@5~>F?hJuR&qC4tPje2czrH{`2HNx9_^v zrS(mYU?sfFcPb(|uSVp_X-pKC?DJ&2yF+A)X4Pyf`R14Ymmn1C)tGM3NDy>}sFBv^ zi>k_FbZV){mkCxTBQuo5!w*SDBF&^o4g`v@=Wa4gFd{FdV2fqwh&Rb%XH*^deJE{e zln+}DIMjz#769?@g&Qh>7=>BM=vp|Sz$u|`j)Cens@gvc?|?N4`|ma#3euj;7OWoz#K&T(T1kc(>yugq;fhBFmt>(a@62q9H4Be> zRf4H}$}?koWnWt~G%sZb2^FTx*+1GOGon(R&Y?k#8l736G*9PiBE)`NRM8*zmc;Wyp@K!!w7my$%AXMjzp&XGju_xg3XMQZ!KuD15{_v;B zXcfZNg$qPu%8^Oe;hKcPz@AJ8GNB~@LND{~Io>~_ozpa%?w<8z&!=o4qtgamE=oU( zP2W_H>9B}c-C(5Vj_q!K9!D#TsH&6JS1*dG2_|pjzHhm&bUB8Njnp34D{X`mB^8wE zn0=zy09%S(grkuU>7qir$T0!u%~iw3kX%gGjDBq!BVpw(`8ow|A{`G!w>TrWdDHf@ zZZ)^QMt_k-&OFUQJdJO+*Rrp;nPT)yjPJGSh|1RQ8K{8x4pPDXHbg832IyX>)7 zXv~?CG{4f0-ITT~;hsph@f4PClqqAgRU#G$VU*pNZBX$+j=%k&eX>p1-+mfrw^g*> zHt^b-FM{hJlyxp{=1FX_#n2W_7&+%WRN-JEu9U>UL!ZsVA{Hi>Y0s<`*<}4HZG6fw zVd$d1=0KW{37RcP2VgQxH_5_4rZvlnouMBxlY3<#`UJ`LFHU6@Ldo8mt&NbL}!nmT;@{0Hp< zX9|oKP)#;-8~;X>7Vto&SphOM_OY}#49OD-2!^ONhbj*E0d?)mm_gj=`no%5T>~NR zj8lKWX0%s+#O7O)FPYoBe=(9gCtn^>IN5Qb&VfOU_PPK=K_@~NCru(^Mm+wc*5Kb- zKh`awHTQ)C4Tk_-pQ4|_hQdyf)wI9SYegd8{J2G|yXj|h1&i4h|5=T?42>MS|L1aS zOz&lFoeWd?gZrn*PzuvIaIO~E+j?!WC;@3_rHd&z5IVRhwy}gP6g3UY_a9}6DC<~` zIJEIgal}Q)7?P+(zv#jFe!~#j(MSHo_QbbF+FPIE`W>2%k{SAVE_^qEVWWZ|r0G%n^}EVM z&O>lf#dHx9vY4ggaS`7IvSD>~7s z`Z2)ccto-5U*)2H5en2{bKO@z;n2wBt9_EE+1*NmH=I8&Y?VAcPa=!nMLUw1HAmO`34xw5F5wsfR7@$IJZs@#;s8YuMw5IoIWKjpYT+c| zh+@LIcpMBzV>ZTKEGldfLmmDmGBjX2D!Yiuugo;gI3GPiL`-Yp(=HA>i)L0&h+)EP z1e@|yGmxRhTH|`tpHaiF9ZZddhPO6rOtrWkm8y*Jr~DVdK;vtI3Zqqk9ewS{?#F`e zpZ&3a6bs7T4BxdM-^cww*QE2q(A`M%^SWU39kSC*p2y2{B{%)297SGS-?yvr!C?Gt zQ$qHaX)Bcxh}xOXqIUrBlT%1CY;;A=@E1Qmq#l9WIKO_{Ut1Y5yzc&}Js zKktC`$@Fr$yT9fJO4Prb6(9D7zgv9&C^#@wV!($%(#Q!VAfcfCny7E?M(DpykSOnf zB^dwj_%oj!a;qt1B9E}&9^L^2Yr;gAOMDT&bjNc5nxEbK!x~#A7Yi6Lj6`PyeEJn^ zg&jeM^O#^F+@2QL>%wTR6So)M20Ud*=Jf|VS4l&2W)SrTLL=?`O#zg$c}OdhcV)8B zq;1czp^D0o^st9a7A@g8d$4CJ1ka$NaEPebwv(F4^C^x7EhkqIG{pYJeIzDk_xcsn z2Pd8}3m-E}5!AkJ=0e&@Ud|+MPu`5x{yM_e&hRv$sJ8%5m~DJ{Oi$If&4=e@1Ox&% z$s&Ts2Qz9%M?NG9u`DfcoBJF@34n6WOTdW2nJ}`e+@6!ihGbEF`6)9#U5^_cy1ZL- zyCH6Wy)Tu|PmYa&ZmigPK$Rm5fyS9qnmIN)q1o7_3lZ11_Pv*aG$F40<9q_uSESgV zpDW9rvE^n&HKE}ppzxhB(NQy}phGBmk8(f7V6p;3EOA>Wt}=3%93=n|k+Zz`L7Zr1 zXpM@jOa~)YF8Tf;ayoUlxUKr#!DSZv>eDmX8ION_h)2|}(2sg>OrHdL-vNl&mMK4< zXNG%hx_fk%UWJ$hlIHqt2Mc0KIPc2K%R}uKy4SCU??m#TsRI4ana31|rI;~DgrsPy zRsv<$&PpLw`(>lxBSssgcZ5nc55S6i4w=rwz<8H*aRZMhessR>&;yJ@ox@^;XdwZ~ zjWqJ{aMkvB+G3-9j1(L9?cxLW=ds7RvFow-ZyVlG9MgYV=c!m54Y@iW9{0Y7r*`cV z^mf5_A2`oZL zStr*mv-;4&8-Yy(#9DNx);J&RQ;&}@INr}A6NAi}q(4#OoseN`hT?A4;oh^xz=~Uo z582#aeSKI^FFjp(xH$#D;XEGq9d~CHK7+17PwkGsoNLZ%0RqaN%;g2d?h70=uq3U*!5p4I0vpzVAq+0ISHo6#;UpsOew^viM(t$ zjk%hxdT=bOg?7ebIoX4!Wg)PmbE+wRZZcR)2g#$;poZ8}1iuB8pn#$2y=Ym~{tI~k z@Q0?SZwAJR=p%?N4h2gK*xiDy28mEDuf|VgN0qrpDNND&EZh-XtZjm z%1LYrD7Bp$ud7Wt4%Ak;-%^)_t{&2Q_#;g6;{@G%;6}iN28TfTKv!=*5xhzCtCB_T`R4ySw>vI3TGI2)f2`#gb zK66@`?>Y{6GZCp;Un17tliW7C{eRh~zT+5t04O*Ye> z$X9ECWgfxs&o*)|9ek%KI7%6QaL31C1DUyv$AsSOyy%yI8a2LSmtY*EuC!kvZFGEC zC}Jj`Fk<8kE=us-evH(gK}wf8DOBSaZhsE`KpIMytz{$x&*?Gq95l&lAl9`= zUvMp?XxR5}o8L$8zY$p-pc}kJMr$*b{Sk#GDhVvBD&X}%!4$yq#|9dax`6j@;Yq-P z;$ZO>u4ugZ*=*ORn} z!I%kAyY0^%eBUu4xJPA%dvUj=31;CP$@c}5?`KUU!IGKQ!a^TSN;!eZ3|I?gx44=+ z8mb#s2KzbhuhrT40|MGJ=EuyrF=f3T)i=m(BDk8TRE9y52SV&^vStiJHQT|VHhm%> z_Ro4{hDVwp(eh=n2Mb}#6dq0~+F_~!ycMem4+zA9!QwV}TQAh7#*06!bS+*TqB znU$nnh)_9}w`?V6ORc(}o(Ou)s8b1x;_fOxDj$vYc<5~BLROUqaC#ho{G6``$yt(6 zLWD&NRfD6J9PeS#cBm+n0Y)XR5H%!S&Pxj?CgR?jUW-&CCQDRsGsA`b z<6@k|g}lfdu|G4cW*(=~*jQeJr1<15*OxNM2y`JzHK{#pGrsKmyGB7V(kC%=IzqXb zH=xRu&#`$gy^^c*&|KH7Vk#lhKv5A12P+?(1fUbse}lyCQ&XgwCh~?Jv4m)x0ih%n zko21|-DhEm?_HGXB(|#s(`t|P$7U&k5srYvV3n9u`%~WJ?XOV;h6|mI+8_^8=ZRAx zMSj-A4l4*qCr~5PTH<&9W$Ekt2*=ub?XwdR?3Ry;A2DQ?4Tm4ffV_f5a$`fLIPv0r z{oSaLeiWX$i7LVazXNOH2Ufa`5l+HxIVl*bwvbo?O>w9G=QfZU3L@t3oa^3vJ2Sv^ z?0|u;+a7?=RL=RF%c-(gSrMyLs=iO1Wty6hoCpdUj^7?+_KG88>vktr4tRqi9dJ9XvT|if{TLTFB0;J{Fi{ zkno{zsp7cSb=>|s4b_q(%p*bMJAhY$UYo!=h}RE(3lW;Up&TicX{SWwGcSB*n{zY& zt>HYLds|wdF_|!q1RK*YUvJjrLO3Wa6o_jWX8K(U3j0fPbm2yTxnlG4DIT%0mcjaSKt)@VZ%e($LS8`u|4G0~+azfCxZ7J;So8QG9o6O3>wobvx2Z4=x)Vd-*%mS$cvgKT{Bl z=Fu1M{xS2d+v@6VAQv{vd_751lR%z>Fa)lURpN{*^&4*aNKEtTS#dDBi=ul^Khpi_^}+!7$u3Pj8$={nmRz*RB$4e-9KKDiG2J^ z->NsIPI@T-k!_cQ%VgX%9V)_CaJx&7MoIHg!cPdk2E5HT zdMw`!DQ*Wq1)4+qas!|C)~urHf$WNaalNRVM2G_ZSdsDh)lzATtgB&2c>H&hS@e9|ab<y1D5Kt4mbm0@FC(f`w|WH#&AU=Es*=mYg3wQvD3}1Km**oeAQtB51qax{0a9}(BHDUfBe#n&W)Z2J1>%@_Ko9p8E zJWWufsbPZ)O|FU~kS5tBVJg@bMslcsQj*$OHJn0RBtqC(Z5Z{13I)J^LcZ!y6>NHj>B9lA(K$O_mf7DS`%$6(B@X zM-tW-KHdPSPf~}5vHHm%f&rGnoyni7JOAah!uiRwuJAkNnIc=4ahryPcjpEe=jdWo$Q zvNcIjnd+JhSFOz41A8LQ!P+^5(20>WKNg9uD8!B457^E%f+{S^ma$})Srg>wO#sRBZ z6kj>uyP(?GVE()ZEb>jgZz)q0;Qz73Ys~yhQJ*$4UfS%s6X*ES&6@xdGC}b8@B&0- z`jv<7YJ~;JDWE9QyR}>PYrfkUczl)C?Qidv6x^CFGKH71&ACR!@eL_K#%wfhdfSz} z$;Gr#NLY!!@YkQ@>h_BF;P><-4CN{Y=jR&! zD3Jx&9202G0KWw1GAc1M>YHeO<6}7$EVTTcZ@D6T-AF33#pa2P5A^wU1r9H6n-(tE zt;c=I#a?gHNZ7!`xG(3gk7nL1EN6q?1Mg#leuOz0V!n|qDV!vyuRXvo-#F`!3{Erd zlFIHD>051PenGa@rvB^m6$L;$w%o32o=uwH3+;vbJDMIA{N@=puyRsvrIv1`e?s;(;yT}KGS8x*N>@2nqCF8&miSMV4v1*K z6c+@*>w$}Q1%6S01IFB}495CVlPU)*2>f%7 z2YzXO#T&WrmK??M8J-xo? zRM?-@wo9IhD^x5CBR+WEET~oGq1#_f8{)^UA^+ril%!^RZL;r)X)ewBEZ*bhdb6EY26 z60a>w(zZxD$qM@^OfL@63b^m~slK%3_JeC@iim6Z3=HM=GlZM!0L#WJXQ2?M9VJT0m}yr<0_g*WxW|pmf;m8UQDlW|r4pKm-7G+UgwPn22xlsH6H(e#m8Cl83_yNy z_upX6O6uU6WKh~!gxKRfD5ovIz^6xATeu@~mtF(zO)5>cM?|PaG$7c~ah22vHXKlu zm?SHl8jTw$v)+47{VKit`+JZq)6@J$v*r{VjC_C_l1zbN`>Yy zm5lj_O&Vqnp=l|BW+gZxd-qK7(QMUlf#JWc)BXMWP($wYh>5u8;+m#r->6`%YQtVm z#Sg*nzQ_dT{}zrXTXMUUE%WMBeqVrHTTXK z%abvp9mA=xinV1`EVI7aF&hK(WZbV-qN1C^$f|$OHiyfWtl!}M$?awiQIe{ba~0?` zj4GfmUzYLEn16a~qn8jX2s?;F1}R}NSSYYle7@4U=J)sVf49+qAD`g2@V&j zDE|5_JWwx=WX^0{VzV${oA=w0Y9@Xx4>LPZ8vffyxg#ZAHdIBLABh8HcNe2ttdm=$ z3!;&DI?0hy{)Axf{sW2@4lRjtQ5W37N$t%B1}K{X8+#-!twml^(a%rFTIodt{WpB^j4t zKL*3L;ea0+@0a3_&n1rnR;1FYWaC3?wWoL?NG$5Od=Vmtae}Iv^rvy>hXS?1{Ws1w zlQ&(<$Y3n*s?GuYB%oL)pOs%5pmyln6^Y$P25aR{ddmWZ>BjQ-)M+Q)buJ(lv+7h2 zq>w5FW_s_QcjLRcSFoBTeor()+}-hUEWkd^MxVtKOF#syju^D9_0j&!J>h4IBruv( zah9ddX4$9;0yerncg?tJ5M5RW%QD|Ldc61=4)_Zk)0F!7U!|{`s4^$F6jQm?0805@Njskp|{T}%gj1c5IIp$@(?*VU}F0w`;!K7=~kZuw146>g8D8P%l zH|}Y9QjJ{Kw0bxRrv)sr(q4N~MaV}gQzXJbk^Al#P#$+zajk?BS#S;im@uQD!nJT@ z6%EA#R?7f}Oo6*foV3s;^F{|?fT6=(Ue3oAK36PVwG>JRKS34%ca+HN=X!KNDgge;%vFu2ZTR^T|}8=RzLYM zT7Y+#nNM*Q8~U3TimeYRsL&gEs)sbuxoWuERFP^?N2{0m&raSuBJR+A%@8rhq3q_p zMO$)Hr!GxbW965sZdTHSHnKHvM@|o^u@QxAApwrgyIRp%G88y}DeoO84r!?lP+Yo~ z2CIl*Az`1xccy*1Ru?hi{JF|4>r@A}6ym&@NTHh#q|Vl?BOugS>*sJCiaYc3f-2Jy z3&>dl(dNg)*T&bK!KdEzY{<^s6&y`SRRs_<(;W`zz=gE4Es1&G#0RJ5uHt~017)t)M{E=xQthmM%JT>NbTsvJ-Oi4!pdyv~ zE#0)xdAx5MXG@wYUk?B^G!$Y@H9R+V{qxvsJ7Q^%r!ro|#o=eO^;K#a+ZY0Z3m(FH zorQieW}GUJI$sSi1NzicXto_P9sdG#_Z=5vxMW=r7g$U^dP=0mhpZ;cGG}^9uu#4G zEd+cmeGt@MnLb2zuB*_gOP-mncqsBqh>xY{ROmTK{_DVy4T9EWpXIdBhg2aisN!so04OEw5663Vk{{1ZEw&U zb#+p`bNy1Pz70QF%&Im1V!=%$JRyas!%$VrXY-r2p7J5eA&wqjGEY>%Vjdh~XDT>I z3;APoymm@7kttY1LDlL=7;TEFUombw-cLfkG<#`@kJMbZuv4a*tziR}sxJFLmD72A zZQf6y-)=)M-xE-0l;5re-BuEp>5GWYk(6ype$OfKPp-eod48Z zna{}LEwalBpXsgNNP7pq3@sUjxoj4f$)j>`2c0zDj9$oa}*b(?6PBKJa`R0iWCO~e`KSZ^fI~vh%2>1;I zQ*%=}j_5p(^)oJ(?7>3b3RitEr=~ixK)yhvCxRQ$sqjS28*4vwaGK*DK`xxT)xM3X zQ}?z=q6dFy1zI9t?|NQj0*}8~5C!rfv40Ve$7=pmZk4^v<$0>8SB`q$z^m9ULtL-x zD*SL%u_Xr_6?3CYESNQ#Z2#po2EHJOU(L@0NkZdzWTk@b7}hQXtQwWPBBY#k58jg*%2iOdZd7TfrR)qkXl&c9E>Mw( zw15&!dUgs)S9%Z3q7^Kc*n)eb*POyFKFJHzKk4@A-W&+CxCZYGYWu~s$%V(=X3U#W zODNIX@skR`+xke{2?ilJ9`p>}K|!9ic`2=Juk^XY)=$`>)IXA_bDkWii*Ln--i~O9 zwfaC6YpXt}@}mIQr&ePk>=`k+cZd{nqufE{$sW>9_vj)+B^$`x?-O$k;?5N@0mCAk zJ|l!AB=%^|7U@t+{B&;(EGI!(ZWjsAIbn{6+eC6qSbu<>x!t4AXWZZWIPK4>@06e| zLp>;$w8}i(L7m@Y&GV61uW}O${9S0|F=XX<;+itNtWN4zuzMBAt2sQ7g1mLaU3A8SE)#`Jx+jw2EjiYtw}h5_q=SqfOTG$(d-X=}&zef)L^-m~J>>-;3^ z5+gEMbl1Y0&VOQf@OYImydz+3jIFC@P$-DM$Y!r6HtXZ$zxK(=!@|C+^dSO`POxS zLbV}pN?TVlWU4 z*8e_*&ir3T)Bp2<2h)Biue5TUsqi7ScXlUJK=5#-rXdBucK&4$MH17#qPP=o+& z{fz5;*whL3>1DCR%bd&xk(M~#yuGTba;8G2wL0K!`|{}b$$Hw$wt)9ptHamL?XHV& z_31B=L&=a`ty{@>&t(dmFB*Rg@b6zeo;S2Ify04UguEET9tQ;uq?PAJ>Jti$st=N1 z-z(RXHc8DaS0aB-RR-=4b*ONDPU5bf`T1Nv#Wbz)IfJi*gHa^X`KrD+TsIKeG_=W;qDBSqz(!|fD zS0GdKx#OiT_2zQM-f!jqF!z>GaXj1K@8It4?ry;$xVr{-cM0z9PH=a3cXtB8-JReb z;FA1~KKJ~ed#=2=vu4feuG+P0pr*R3d++b3GqD3ABCkwvk$lMmoeWOD0bQs3(tE{( z@U;g4*=msp;Egl}aNAt#kswSY1O>6%*Q9#tbu#l)`JY1N(j_ug#ByLtBcu*1XAR;|6@hr#M(e{+9g) zf~gwk>u$9Rf2I%~gJ`B8WM1#=XBRzBdth#juS@aVjD(TEz;!hKAj~F=Bedtx#+%eX z2iH&rn?F1m)=z*NW14xzJ2MPG8a~Cb{H!nhtBf8s& zzF|}4LeZ8$U*ZD;cLP1^U!SkKO&GNdzAL{?Fn&R$ z%E0qe@WpNpGiAPt?5ihFhez}jNFuzE`^f903?qT*3~ z*q@xwJX}VlDI!3J5oQ>D-fT|=p}KB_ylOL2P=>C5C6|zCR%EISp#aP>*}fwotMP?_ zewEh@{JR*f-i*3wP?<1YRfn3&%OD#YEpmyCs@|b^d#FC88P5OgE*3 zVU%dK;|#3g#5ukhXhIbXSW8oW?})Y2`>qgBJ_O&7P}N5@fOpW6O^p^`25l}gM8-*m zVTl=^%ZY95poZdXAwgB7uK_h>Q`u0hU9VA@K8F1oa$=p&&DfmR$k`nZ$gpTNUUv=( zH!_cJo>ey|zUoa19yQ{X8N_bfoeHw&`%b1N*pn;B&*ZQJyX{pG`M;Y4SyljE3jMHrODm1?Y(EKCd z)4INkpguZ-G7ILFtM=z%dwm7Z%6e1Cf2~j%<}hG11sDACf30A2L|%r#Tq^cBhY_i zh_L-WyD0v9pdqc-W|a{(_!W@~+6c%>N|I5Jp>=VIX0J)gPd`MjoQzwDp8L#=%WY#; zn4C=VYa;zNg7%6A>T6iMS(%7E9#*5x{E)fY^*;ST4@-ofDLTkBEqK-!Se|-JR}-eo z34^WF!M{}?SZJcks5Bx2jD41A(G?abdnPT6EsWEv7B#BQV}y4-sJLtG({3j8TdhQF zm!nsq8a-SITRSzDzu~#FEIctn^r8>iyZMD2iq*B>SUlcWCDoo+BlEedum z-udTJDTf-Z3Hw0N*wx#Kr8vgIly*Fq6-Wfu9flE3Yl^N!+g?0%RI`wdhfJ`K35y&p zUQud@;J?gSFHolgw!USAiiEshE0@fG?n@ zu09!QqIQ+|feHNQ`KoFGa&lFy`(p|4P*2PX36X_RbHA6(IC55L3Ql&b&N&?j#M2`~ z+@xC}yDR_vXXCaAUL?GFqT4l1OAcOTjZJJx%K*Zs;*78m%%aTIVNE_EA3Knh2fWRX#73+1^uPQ8lY|91*M#kenI%_QSHc6;^AtMZpoh*nZuA(mO`a1N^N+!bU$o#?h?16ZhI^J zeChPa){;#S3+pH$sNrt_3KxnIRj zps#pbma$PZ1}GJg81NI#DDsMgCia9=H@A%fypZXpqs7PTNyh=hb)M_5ioW)?*z`Q+ z&2f83#ctUQXg-~G(Kj1TWhN`Ad&n_j=afDPA~MXpPDXe?8$;Q*zXv4wL?SRn8h2~V zq`g>g>gQhK27hUxn(grJi_V6=Wz*?yDx{3TugwWXOP&mu+Xf%v@G@D1!X5x!Da}8T zsmnpZ(zMAAyqiA|9L{{^u4{>Hz z6FQbJCyeTcL>fPQ?1JZxF?#k>4#QKD;0Pe<68%RSCLarBn(4HCvi^3t-Z2<@Q`Y5P zEEyt^z|1Y-&okT$HN^)0^?MNt%iLAg)lE>Y;WW}K5h1z;8{w4=1=ftFW+%8}T`o1Y z#ORdAvY{E?bTVRTz%4&Fe$v=~nhbwO*s*c^3p|VS|Hi40jg|c$^eh&Z50cjZdwdov zJL5m_S!{oZdjB&%OB^8n|2upZkR&k4zu~j+{s{R0jh_Vp`4>M6>LU{r=XWCLKT?4I z%D@K!{teLjyFTDAepZ?9U-Gm6$DahnhiBPL#!)g~qDezUIsXSg`1jCI4axeAuM2Lv zy3GVlbB0OIR*YTjfwf@_^;Wz)e1;oYH#FE*-;O6|kqtQ+kSO%!?e>VJ2rF=~X zsg3j5|6_}0<`A5DX^+LHJW3kIuz&U7?sgtVP?ya_PBXyiddh?l8vCc#i+~USps!ZJ z7*)cwH%fwx75}$Z)^|7t_j(80(uQg@Sel_J!oD9e|CjlP1ctP8!P@iYz5`nok5r%~ zgq+7WkL<**cHAWfA%jb{szP^8bgtdIKYjf31Al|qeO2{}Z@}{s02}trx0&00J|?B* zZPoo&Y3$DI&bA1ux45w@(VMx)ihYL5yUhHFQB}>40b9lmbnwy!Gbl_>uU6Tj zHJoHp^z;t6*=1fS-s_;3eeAL9`xcjw~Mr#pQyYC`_!-vU1U zg$Nlz=+nsoAtl$fGDa6;8D^W_{E5cvp6+&z} z?$A}E=V+c7jvPCXWViik<2`~m?|Wz?ur7RaQ|YBw<4!l7zhlaX_fxExv-{xgXMQ&Y zNZmiZ13q!>(Wyk_E__`n)DcVgKE-RB-Mz|BP#q)FX&bI$XKvH@CK&PO>%a{bmMDrw zYU}b65KXS1H2zvtTl;=}>vrq>%89=~Ge!fko!jy+o`Fb4=EooEhwHe^NDk~8y4^vKeg%pS|$9aR{#Lw8gI|KPC!z(BzM=$1e}fJ$Hha0n!16ja8~@`z{{Y@g7HNC=sj^?dFAo=5*1$~Fy| z=@21H`|X3YD(WRzGwNJC5QK2igBI%!C(Ty+qj<|ryVar7qU){xfmW=QSs-(Hkxsq3 z;uhKaqlA8u+}T|}b1gB>|Gv0zP<=e(8$7O<*SYCW9pwQBdhvHa6l^JzsK>3x>`j$J zU_7Fa$CsC6%9R#{e8teZp8oYroo~nl8QFv<{GHYA@UC}WO<$**C6+TEc2n&6WagHA=Z!2$DyzHasP`qB=g2WE=>)Xj0kH~bOI+sr`X@!A zrn1?$bo5;{Xx2R5F+4UI5#SAWU6F?Nx++6Ws<5vlqiYJZGIeDMiarU&OR#9j(Nv&1 zVHy4cZxXl8e7Y0)BC%H-!xn84i=0%$&e@|sOnjBEGtu^x@g0z(%-*7N2aPkt9n^=P z+R8W`&^G9Oh~{sntUd9FKrle#)+&>yB?QyS>aapwbK^NE%)&E95)WStvidMUu(ZRTCA( zYeY(UksOl2Qq}yV9(^9OH%;!wEGIHKB~);hZHSMwU%s93r7SLYnON*6GN?or({4VK z-R{)~wP97pv*m|AlVke}uS1W&kto^@L7B8re*I{WkD9ga$Xj1@cr<7Ub5syxEPiLl`$08;FG!uL6DA%c( zWZxt9_+ZKOmTgLU{+w{9SmdGnv_M0mYR93QUqavb8!DzuCg}XE*VrRjeY(={52B%> zg}nKS7K3CMIzDNkEbg5~*t45%UP*GQxQnH3pHK$Y@MD{b6fb|sQf=DmB=GZO1rLog zG_$ou)l?>R%F_nhTtnWmhZ@J+=2?&%^4&A_+dW%oO^+24o%5)gs4Yc2rhVq3omsMX zKx^f4UD|boSx8M|)u6Zf6e{Fw1$r;{j6G6xuN&Gzh_RD|gD$hOBPBFWYyv-XR7fid zk}=Ahz}k7v9=?o&UMq1!&JsJ6OV*vhD*6=ejiBNFLwVF9C+^Yl+kI$|c2v@^9$Mfa z_QCG{Th4>iDjN{>VZ8kOp73&|+9-l~S+Z{yeIFl|;)_{?G|X#}_DvVBggOq#r|8f= zam%$`Q<9|U>A*4N8GbD8LUu2QUtvNM6|yUF9_4~L@ub?uX0;h>|^GqGh=E7O2 zrA=?CX-<@WjcEm+MaFA+qP0NR3>VP}5Blnsm3pG|$^UNAJ4CHo%-CcKNM&pV>GqbH zixXR9=n3sZm9Ou{{5ImOGC-V|4Wa8F313U9I^W(<`=B7{2J$AFSN6fTBoK(q?C>)_ zGJgxvs)O8(965O6+Wr*UC>GGAB4s6&J8D@RHnH5SekWn>NWZrUoj1al43=9S{Y2}~ zzq+M1RkeIdZfK<$@(t6x)&bM^cmbj=?p9lkt9mC|d02a?+?zq`^l?!x0W~Aq0UBcP z<6Ojw^jpXG0d@j~`PDzrM`|4)?p{E6U zsmwIpqy36NWS!<)(R&TP9Cw$4P#p&kaqYeezd_%M0G$9I^pZjSYTWe9Yi>hNMZZ*| zs*Azeo;05XGsiPXHzCu5m;QuIx5Pt5nxN{oKv5+&FA{!JlCI>pqaSo=kLx+<2_%~6 z=3uDaSiam6t})k@m?jmK!iW5DDMfia;-1#en977i0f+6=$ed_UIc;*zGR=UZPcksL zd#ETy8*htwRep?rg61~l=3LYi)uy-ts@HSYUmKCZ&V)fSTX0`>_e~N&wbYJoV>-B< z7Bw4GYPU6=c3ol2%1rt5*$ui@sMKw7kO5-#4dO{jj`UEun4dm;L!#ZkusI(8G2f#w zlt%ELWh!1I)}%Az0VkeAzDqVQeuooY(i2ud%4qHjk_yTG=}i)Bsy1G?M#9Nj_#B+Z z1IJe?D{W^}K`>nEx3vL~Mhi6CxLD(@Z^%JLjN?Blab?kCMKE+4MyfYZ7vj>wd1sID zB6K`b=3L*<$jPAlI~6oHJ+!T5tZ|%5&I4si2*B(^NGGd#%3#?H?Dp%&8?u17j@f=f z&^G>hyF)b~o8{L180rr=+i%Gx5IET1D2~6Wj(>*ww{Y{%!h?jFML{2pSkKP>&mjK= zXQM?;oAn9;_X>&8m+dRK5)nUKLfl_2@hXY??tvP%L7#E`4xqGRe#`6_Y%gZ&V@HE$ zu*+6@P({Dofb*iNw2tBp2cxY#Ip4a1E9NP!IfejFn>AXCo`ynAz!ER^Ck}F0snN$} zGUJw4v7t8lfkU7~8iD-HhUQL{Gd5injiUuz{8Y;8M6mDES-Z2Uf+7+WcC-`wPBX5W z7rBPBd-_ZXm<<&gnv#MrWHkTPA6UQ3l3@Yn4<;F@OfPByM_vWv|0w-XsHtoQ_aONq^*<@Q%K9(`rq zl=Nre;Up|+g+Ad2JDg%M-8>c6m}`x)*veV1kHq&ksUTe#s^ZEEa+J?{O#Vt`Kxd~) zVjGXgt{JaoGFxcCZkr<_e8xAgDb--2)pl3hR?Nd9JD!aflS`c4n4mV7o-BD{XQU0d z(Sg?~FqQ{`eDqMWz{z z=Gwdm=15-7^pE(SY_rOVeG6Y5JX(5OVf=VDeFlzls80)4(luWkrvjp^V>>DETc^URo3 zjd`<6 zWm@vIe94!^Fe14}KnRP0bsXuY?t3_{1l7sa>|>D64GV!+L%jHA#(MqoOT5Ilo~Z^n zVDuYoC&JMDv+WYiCj!JebvqmO%4BL197o;kt{M-U`PO>chWOa#T(ia#lW>)!AfoXTJlop8IGm;(IXs zv%J0eG}=UBos1f72Gn1%xuyLAqEfo~Z@a@7DV5yXhoY8F*H$?>7k%~`;4SaLoN z6uf+-{X7y4vEsB%yV`m8HyXQhW(VN!0HLc&$L#GAeWpNR=`k_h#~1Dj)qWoP?o(WK zAkCDi^+WQDs))(JIC&hCrlh6KE2#7Qk;Zd_#Ie`#KEyRidZn|9Zsc$9-cE{IuMM9t zmoHzrl_!0SHDQ)9$#l6zJ0${A{Ew%)Xe1Dq6W6dszQM;c1d6SzaZvHQs+slSZn#xe ztZ0fTOg=FUbQE)%#l&nw;r67NKGt|Rk_5A5S;5X!o|nxRhzfo0+k{o0khC^3nF#pg zi!fB>`U|$;gTKFMV2{bT3{NE_=CPVBr%(y@!E$b_sgke4FT-{fT2-%W-mFj0a^Nvv zx~M{x0Gw)QIb+YN-OcZXL&;?$b~0tx#%>51T&3eVm0n&%r^Am}*VkH_|FBSp$1D)H z#vT5=_73pDMhG2Ga;0SNG)1x$?VG(}`^pW!WTM4L|KgoIBGQpz&ecuC9N}EoD2Esc}q`O5UzLv+qg5+HU0s@X(#eU>{9kU-nIK zeFyMZT<3d;m=~*<&6fpN?p)n@vyy)0W?R@(9{Auj=*l^F5x|k=-M3XGJu_T|<4BXN ze8}ISYk%&*vU*4$u+bP?2|#dBbahL9d+6SkeUz3@$i?(}2L!QV1}=|uh&hMAKz78} zC@AP>sf#K~iD$e6Msl{SO`a}fP)G0(m@2Da&-1~zJ&C03iIF+eb{ahH!uK{y7VZ`+ z6xBC17ma)d_+Lsf((b^Ci5yXM)_IA$8{$7-WuoyAzXLu+Q?T1IG)(Rnn5}QN3y{!R2zaJn+BbtomR4o zy{1NAX-E-2k31ZrPC)*ZBOP3fSabdN4vfL~o1mCp^>a@}bl4oV$9Ea^r z+Y{gBG+=0?a5wCy;8o6})v0|>oV5pzCj)EI2sL{&`KXOITSuUCrA@X%xj^TvTRBoF zY+=6O$`OZh{it<8g?8nvxt62q{qgnU81&i(Ta&2SUT3e80hM()3nBaXr@L1k?-hZF z-pxZEx(5O;-0NwK2dje3c~PRLE)?0hj#txmePerP2_Qn%%L&%~2(Jd21YN#Xajxd_ z4-u}j;6U@YXBXE`rqrhmTn;{!<*Zh%p0kQA>=%nO{w0gjsCpNZ7Ht{<`>gAuRu8v zAVB$|*{EOb?B{(my@{!osKXYEOy}O<%MQ<7ye@q9c&Fx{X}Yd%v`Z*Bu-}xi(Z9Z> zK6DC9AhqmMS&}k!$RYL;(fn-fQ&-C^V4GeXFu7hEkJM3?L!jGM?SUVsYHET9 zxC^W?6;RdFnU-hs`w|LW%{4_v&;mbD03IF(^DP;poHXSq9mX!%;< z;MHMm_tJyZdhvt3)ppuTwiJ8Z0VnM97U8%ymFt(&TcEe&5en6bh=D^4X_JgW~i*+{vqy z*PXRJFOoo~QV0qk#ShM+YR3t|Hti5%s4D>RHQWKA$A&A=uiIqAezxFHhiku(>@Uu1 z*K#4?IHIcTaF`PvFhKJ`I8f5)6q6#sF(6VsfIEprk)?R4%#YNk0 z((t>*q0$blumg)#AXYd?zAaF7RnkGf5Fa8s7GY?;8-u%g&1=jzI1=&9M#dNBe8#Sa zPf2wH_k7aAV;a{@1ZJAr?5(%?w1|Vjedibs>SN779?&BhaZgAwT_=EhYZVJ3Rh$T;<=0531H*2dAYngzv zD*DHK3X6DM_+N`vpH8dfD_R_Lc6K5#AKvUN_G?b7sOLvM9b?aVrw#H%YDY#nxW5dh zLxd&3YbM36+`(g@@V|=KK-w_7c{YxrO6UO&%X7%M&fR}-x!Y>+J`XwwoUm06=e1Lg zc>4^snwn*T(feQwqkdV(!vLS!0w%D~sH-|&Daggy?i#+ef^11!+3m6Rru0JV9e;*FcDq0(k>H!vgU_iJK)?m3t&*P5x{XY!iJ8 zrNq5&j-lI)uNrqwKV(8#U=Tt zo1h3%~PK|UyqV1SQE+3(xEKpzmsKai@A%W3)AOGL)cA0S4(ZC|^80WrP< zhH5f>zR!G?QhS4Fxhx-$LW8Ro6i)ld2%mtFin#^%rP8OtC~^(F_U1A0B_w=?&6}H5 zB9hE>^U3ktSXrovsXYGFr-Z$e;#gE8jZ!H4i+(OHTj!~>v5k{Poij17F+E!O9#R&9 zD+DoGSmApI@NK-#a2gg5UH<7NdsFrPSgsX*Lw@?RBKhcd%r}KwRHPyZ+@9QbKn#po zLVA94^+zuf6}f4`Pjz0?0}US47&s z8`S#?x~XzP1!?(!ZuF6Vi6;T#aW0)M7#;-=4-l%1y@*-KRBfxC3 zTgo+h%f!zb(Sbj68Wbd{CA%21LB34cy1WTGAlXq$H>ALgt8C1`%1{vt+P(#S-6>DN zFn4QW5^u+){Eh}XPpH?d)Y)3Za1>{+FWFFB%QLKTAm8I&s+~hzXMPVDh}mZuer^p7 zTpp_?AfPnYI_%aj#_PDEswjH!I9J=BJoX6h z9pIO?!|jy-Eh>}jBzvDRh^hn0crFL-pa*`dQtz;zgli%cS!mi4^z6?v0yICrAj|3`cTSNYCY9nw+?sDBNK~vu zKuv=n%|?n!rURRH<3l`d_e98Qh@a*r+!ql=PU8Z`RiDG?&FZn36P-(*rBU}G3=W!j z!!tU{%Oxn(`XF?0NE932`oq33K~GUt&w8t5IliU4wrs>F(wFvX2|*h1mAdX&rUF-G zm_2~gKt-j>YmAZiPIQuJ4cY`wUI=E57(jjFoN5TUGlARVjL5Z2^xW5iXVsc9LKE1R z)ibViWuwXx6jVuLH<5%)PW9rsn^s#hJFiZG;mL# zSoX;ecxwKG3D;Q42ZQXYvUb73BNYP;$z%uU?^A(!2S6Oi>62b(!Q3_<~WQ`WAgIM^;jU5d~TRS1xu$L);E6K=&USx)2 zQD8}_+j!L6WDfRw3{&;!V@YYf47BQV*&T%}u@WT{lnjr19xByj9Lg*TZzb@ z=@uV)_XToJa`hJ_cpOM8<@(36sp+>f&lRahk{YZ&poA%c6XU(bRpP5VRL`KvabRc@ zTOAj7&%B{f-^w^66VQ{M%J-S@o-4OYj@1ER^i^L*i z!XeN>&SjRz#>ogK`;s7=|CI#!&xNRT?R4oo=2P%KZhO4oibSmbgi7WG z6X}HB@uM(q8!E4lWrJT2Im@{!G_(@A?P@2y-c2b6=9@A+!T!7q5-8#_BsDG1ms&c# z!G|0h06fYOhNP)1td@=HJt8ji9DgGk1&RCVY%xBGpEa07ke-E5uvTAe2QA0a_mUlN@Y~e&bLrz#!rGFP(!=}M6D>|;v?>=_2CSW!TX>H3il5B zwMq*|S?GoSQ>jI&{=J2ci@c6=$LwFxGk(E(Lt)8(2_kKbnBkcZ*(X+_n(b?+OvFR# zic{SCc;*NEO1rm@03>qth=bw)wxvlGF5Sf zl8mC%@Ile4vf8!u+anJf`UmuMr-`#*$H#m+C$U6Z2Tz0N9%n)%dQt*m8o6(r`D@Nv z_7zsp*D$N^$~6Owh4;uRhK^J=316!cEF#S8OKU~193KUG=P08t{WZG>56mv*Q|yK> zbmpFj)e;PT(J+>%_BJyrLB{kna{JjL76*2$iX!912(li4f?!{WV$NzIXNqzu8v6jJ zLV5TXj;**$)e}RgQk`I%!dOZunZgQY9+5Ij_HTDKOmaHF7J-D&%O z?v{4^b9;7>&yo$c4^)FTYPO&n7y5_k&%;ll@WAnF;Xp@UG{<3_j zj{18O{*RSD4bsO-AM|g)^*_bq6J6^ z0{MyJE^qZ1;*lFTiL`gppR^$A)}nylONfAi;UAbou$f7x-*FH`7s2QhMIEv~?(PJL z^oT6XIv=!{T1bAidjzjFS0KH%m;BKV?)}r;F;QjTrt8b|Cb_Bb$ci;|HW6x&fCU-1 zPF!UGE{@#7Cd(Pc0@%PjXv_^215H&sCLeFxJHRjlEg#-l#t(J+xk8`Xcyzy(K6Ra) zNSJ|}FHo!ID!Y?P0VGz}rQI5WgwEdx+zR|@Jf4N4I982rnW1F0+^}txXg6QCSwOSa0*@hJ-fz%5fLo0=8DLukz4x(lmJ` zGl5u4@iw6#_?ESQzh(xL2HKB{GI!Qj*Q}{qU3q9D?=Mmbw3yKhVBc-~H8GB_6c;mB z&q_A#*!d1{joG)lB2HE7Xvd*CbI^Bo#chshb;}RIGXNX~7kp9_v%CmA#&wxAo^0Q( zIG&#(4C?+2bS`%0!gVd1qmC! z!9&(z`3?6GgP{vJlj4zK0zb;l!9>cC;k2S>C7r{oi_B^ckK-0+XYo2W@ z;ttO8E$gA2idShevt;h|ug`hphGA}}C09|dH3}Gw3IWcp)ZoQEZ+bvEs|V<2^Dhdz zK6f&!2A_xcyK_G)VKXm&KHA*LU>`-GGn;|C_-RP)s)N^OsO%QstfcA6gV0F*d_@$r z|IK@|#kS(-jZ22{M3Sn}=&iahDvA24iD6clrF&A(1a^2A8lGwC{p(nx!v@7)m+2q5 ztbZo&-!fYNF?l~G?(d|m+TNMVD?Q(B!hd9B{pQ*hm4YFncFH|svXcO)Th5Pw0HFCn zbBEgWxe2}2@|z{-4S8xm=qb4U2D%T8RV+bG~Tz_5&vx zO!`sUsagHB69?--WWFE22pQdb@McP85m7^6_yuxYhWWrby}tTnbZ>7$_+3|vSEdRC zf9jLu5zu%V(EM>2HmD5AM}lKHhgVcrk!MGCzh5Jb@1~eHzg49=kz$YfT~()D3O=Lg zTWXzJFv^iFiD*JfD!%p_hs{S&=AKe!A@{-$d7~fbXHBZY_8>VtJ3OzNRKo_hHYdZ^ z(l|##5SkOZN){P{>}TAjulCqkThSWY7F(GZ)5I?KcmwQ1jR8TFM5}e31|^vm2pL#3 zU){lusm~Z>@Ut`B{C;W30Wg3~0GQ=8cv;N1*Wo{7xHf7)6k%b}I>R@>^z_8JY0s!L zJxop%IG}-4cK2gmA>62`*cYkWVMq^@K%)X0NY{*4IL)iq+-5&xp%*uL7+3lgo;YGG!@}t&&`pnT0!C;xdmsR8n6XDtz zjZ66#(+(Mh`jfl^fEX7>CWx6_h4R4g?LgM)_^n9bb|GdlRcXjg z-CY(IaapwT+;8kEph$ngT73uD!6Qagfzg3Ha(X~%oIF-@JTlgx;=tK=f70$%5#hE3 zmqV&vM#xw`P^QUE2bx>7ejPakHq%FCewd<9I%aB@UxiQ&i%`TNS*$7|ck27P9#U}o zGdr*h4W6QOu?kcVJugwAI93ZPtg7kfy<>8bEN|W0S@S0sE4E6wi*MRqcJg34AT+NR zIgT-XvN+Mb8mvHQ75RqX@z)YR@M94{Rcrw0o%O{id+{)(>ND63TZc8@ge~JvhXlar zsEU0TDdN&Sk6m!ONLFcwGPO_b#hr4F5J(Q1s(iiJtxAB)R}sS@$0l9$#1t!lix?_j z2)+Pk8Du5fI8PkYomuqRqPP;H7E4b-<*{d`pNQ{$->yg?z_Z_p$2@l2& zNY1qH#3XT4{o$IHs$JB3TDnHqE2F{x1gnbO1l*&RUNHwRz;k>NjmlMiQXOl`3|QC+ zq?tJmK?I{Q=wXrl#oX>4$^7J>8bl)^u`b<4SFGY*rMP7vl)VQVwTvn|r6wjle$wmS zf=6qS1Ivz8UC=LDETS88fn~8Fi=E@8`3`6iK`h~w+XXtY6!nAY)yBmoNQ8tAkV6|H zrANPPU9^2<>I2wA@{_~Euf9qUQ(xYBY;S_~izWgiiw9$NN29?jQ;_~p)XVZZRXe)| z!0+#l39Pz;r0xg)*kKl^-&L<=4X4>7z-PjZ@b_}U{$Uhc$VooPRo3`0%|7H4_zHoW zN1ur1W3`0}ndf31VC%gZzaSZ$qunyk^nEJ>f_e(pGaWr#7VbK=M?-W$IIZf~=LUnK zKd9O~>d8O?rGaHuztyqRo}dj_+*e3n8kG_W0M3{qGdYY`sd>Dh&_gBh15k+&H#%%s zk_~keqTms8HhvLpXxgd1(D4r7-xC8Is+FQbs*I4A*!RECg0|t7T`!`3)@vuvM(XRb z>oCc5%0SjI=Lj{Gq(ESEoXoPiF>-nfxvbG9J36Lon{$r~!CEQ>&YZDOmn&SUY;r)5_IY5d+_(z=ZiTZ z!1iEfsvzo&J)+u0XG|3q;2CkV8@NiL;e?*g~l(VW4w* zIkv38-GP+R@gRWwH4(|Y9=}CzqL8F6bc*FU$)rGzz#?_Qk2!9K?Ts4^B5^D#A&zME zyi|Y`KfpZ;Wj#aU|1#>ZxBBt+4v;7?6HZFAeq^dw(1s2v1Unio;!9Wu!vUv*9iceNt3$UnFlEsd@*E{eVRwvHT>DqRPXIKw5cU>zV{OGIAnTcmg$i&f7Jtl zuv)0l4b1a>Bl%T40tNEK(@}*BRPje>WguoNA}5fXM2sJjp?mL5q^gJF|CaFuPh+f8tY9;x=+6(2I7*Omw+p1da>_3UWI<0!vqaK^TT0>+f6(J4iZmCO5wofEBO))3Ldl| zI43DU1gaFwhcxLEZL7}RmuJQYSKjkCgp^_>M&j07|8$Z`uFQ^WHgI(>F1J4H2h z%}~r1W-JEQl4Jc~jAQGuxI&HhqwlP1KV47=-^mdXOhNeP5CL)E^dL<#L!1*4`i;2c zwZpyIu9zh>2Cg?enX(s^2BIPOMqiDJaBDSZse>_QvORqxZ=mZEa)%v`aPMk;2Po`v zLyX>K+O_*-igCUAOGju45_LmEfxQ%`5$`WC|5SUwtYXpY<@nB(2YR0L?rmxpd zNy_`=<$^I1Z{sMVWJ*G16^}X}t6^aVu0xO#9=Rse&3t`Cl(LI3c7Oh&9N$0@;aD0o z?s*~7#E*39eUtKHDS+#V*SKtMs98)DA{YY6BfG|VPM2D4uTF`6(o*Y!e2{oCJbUiG zI#@t2(s$VO+Bma=IQ;KZ%=An0DQpK!(|*UVm-PMBTm4{PH-D}_4J9Q?pcw#XH89V`U zwfzSAA4*TCks|0AbwHY?aoI zBLGv`Hr>zKNLhyNf;}?w+vZN_5W7*6Q3K?*D>J{m9H&pXt1*Jl$_ujEEDvyM4iILS zD~=}gVmO9xut?|jPfMy+S$E-{XO+4`rV_O(xB8EBL^`afbN9e-b`N%%OcbR9Z#Mk0 z!wRvEU=QdQFo7WZEW(FD8RQzqpF4b|SeNpDg8Q3fzF0z9)6~n zB+Xg^LV>UK5=EnWCIs{Jy?sHux-FCc84ZOdwPY|-9$P?Z-_--N+~+vA)u9^6#q`y4 zhW*7*+5LfVEHiO63RTPvbC~aOJXefw_%TOV(2hK9FEkoomk~EZ0f46Q4MzY&)7H9V%^~2@pF(!BsFwr z9A-4JYbZm6?!4*;A_qcafqAOeU+suUaybv!^Awu(IYL3_ZvKmP-B@2;p7B{ z$@-u5sRYQB^YcBclAABN4M`UPIZ*wRi&lhF-rpe8eB-|u1p&ION-4$qIuq}Y#o9(r2Q3}l%NI~s^j>gTiDVs^2 zJSwrZr(uX$Ft8_`hZ`YlD5(ltA%DDruK@$^UsizpnkWy8UJT_2lQD7oD|v zDG*&l&`#Rk^20?}V6q^xA|w&+Q*{0|l8%W>H#>JdH#f+VUI5%DQh=~P&gRD>&j~_z zF1i!FNnZPJRvs{0U|yvZ7=Hyn4$BddXd@9D6?L~{Wg#Yf!ox-Lk7%+ew2CcZ!(k@E9C9PO9X zDSN%VBH}oPejjUcxmCj#A67NjY_Y1L_9O zDGdX{@cl5(0)2Kyz46vb{mANzre*f4x}H)RNS<(pm}L?e*|H8> zD|PRKUApU{`AJ`;i22QCx~{hA#GiLtV2>P-t1+q&kh8OS+HX($ZzpxKRvRSi9Y%vOQncaxWg-Tk*^4jK z4_NnxlVx8IJ^v2?Y(SI0*`IZ8yYpP`Tk{QTu7aBRZfQnA)N*kuZVvu*(efATwe05-H|!hn|0e+a~N6&U0=0% z;^NI07u>_u<(nr5?5{k4=z||?UL#D6>vKG?clFyY_}Vpi-(+lA__|iVZB-}V87gqD z7rJ78x6mohIJM|wj{u>Qn}yW~hx6s`QHqRJtQwQ@!l=3!T|KDSw!m~(fRBrs<-sf) zMPiHV({VA+xEtLDEna#XZA1NQt#N6x`s<8`xV~b;V!wTDy3(=U+8MYwfBzB>>|gbE zoZvA&=)^J{*!HaB@I}iW-yh0DJ-0uhNXXPTIJ4;eM4#|69u}sEfS|&gfho7g6`ecp z(3|1)F`|)YzCD5I&*Mk5b$toS*Ly7WvZ#Q+tzdb*co5D1?`@KZ8L>!14j0{&vt83zt$?|!TP3H zP_skLTYg;dnQBGaBbX!~**dGo^s@9lHpBwo zoq)Gz;IU@*zxT0!xA5_0_}%XaI56Xg>e~y>)s;O)yY|zZxo22>-Z=X@AMyy{k2Rm2 z;qDCARkLS4g~yWl2f~&;aleA^J7%3#YaX%Uqfm=`y#k&dJ{$_T>_7MnUa#=!6FwgH zc^(Gw`r(H!@ZA|UhQt!YP35USC`P)Xb9!~xB7WvY?bTm@7~%ec_{Y>C{_W2!3Jn%y zYtW*3wbG^PHg8_1bj>=&Yt$)It3{0lmCICY+^l~6^0i9MCvUPL77*yt7+of#YfT&{ z^1P^B6O&fZ1YVF}C6wj&BJI(R{pRG#$G#-cxkh~>$10goAGC@_X$?g9mr4!~=M z=>tq-n9G2pA_MS|VLAcx80IukPML;-2g9@mRx->%pqe~ID14N%M!+V9*#Xp(+4&TzP=%PE`TAXo9&2AnZ9)D;&LrGEbW~ODSyl>ggsdvG;4-uMLmjbOlW~^ur%g5Vobikn>n&L z7My!KrH}BxQRCXm57>74r7E=i@jfFx~Zw$|LJDxs533QmZGh&#`+@LJMqzrEzTp zaHaj12aPJW{qB)wdA(Iotti#Y1!wD481Nmvf1p)ItSsHt1+#a93(j&Tq2;x~(g@vt za^2dU=eO;+aOv#!G4kzK53k*Lea4Zw|4bvHR?3(UZ+~kdUb17t6rO2t5&^k-RgDfl7FNNHOOxo zc5C!kNJ5KjgAF!V6-1T#&!Dm`o!MZ64K~|C# zR>Av;c8r3sLnddGN{J^-w#ox$E!y+ZmRuyMgG?hFi}N*Qj8=n4kjdqCGU-+Fzx5vZ zwIS(%s1P;0W~OD7OjO8ZOzzA~8C&|9Bn^6$TZ7vT>?5m?U&xqF!IZaABq@U?yb;(H zSr~;(4?!}dOh&$!wNWGqgE9o}ol`LS2*PAeBWV^JMUpaTCi*?u?PPixk}R3_UmHb| zGDHOQPp)5uq_T^6Wur)v#?}0G`uM>xDeM^=MQng(x?HaYVHkNN|HejEQ&^*Xu? zqx?;^*eH^8kv=scgI#oYSFT`e6tRKAj*;gmTsT`gJ9|6jFP z_AEIvq)C&)p3Xb6X!fg(B1spK$RNv8rbM3Hg>t6W;{n?!l5`POU)UF@m0OSTYNJTf z#cveRzrt#xNYY01RWrR#u#F-~7X}tqqoNGLI9fZ$789TJU?N3yT0{h=u~i93Vla^+ z1s|WgeEG`RcYcH^tgX0Jl7fj8QRd2?BS#Jg$4YaLh(|1=G4bSeaofq7q=Y}#A{2WQT520Ch*(kNPC`pP|IC?fli&{ErALBvXn+(>AtZLlC>MUmYJEwv36M64*{k;jyQ6Ku**qE>VnD1YqDp9~Z7>@IR;A{_(=Sn@68w&+)SBP7@@-lq$%D);f{qj- zK6VnK=I@S`)9aluZLuL9@O4dz#@BJ~3eH{&?UM8Kmq`_?EW>X>W3kdAPZFv?q_DtzBWJsT(Lc12NTD5MxTy4`Li5E{t z2YYG2`F{%%!@R$7LO6tQQKU|dAc{QR-M$+=7q1COcG}n5=ZDv$qo+@uI(7V+t%g7% z#?uLidg#UL%+-D4=k~7Av{)+p()IK*Bt|VVuQUSgKrluOmr*v}BvxFl+qm1ZfA>7T z;sFlL^)kRfYO7yxY0_(cx?UcLw8|p#VV}KNgsbV7m%GYkeG%6rNr=uYB79F)R`Z9#u=7VeR(doZ%SiYB!zY!(xp_?Wl&6>|0HlQmnT?k9^oEF%N$XnoGFPH$l&mx+klcbD zRTmt8rBX{zGTTT8!EX%2_m$Vy?ZCJ#=#pp9o5^q=7i^np5+}&8-G5FC6!rf*L~?o+ zvft+uh4g>AF+u*xB z+(wba2azSC`?~c(aH6K0;x06V9|F&5RQOCO(glGU zmesAclmBP^6$YwL{6-h^C08yDCO_E{)chCld(oIRB`|`Dwf5i{8uD?aI9J_t#ABrTc4R}T1L*u(>ZL^a2ot_M}AE-zi!6i zezEODae&v5_x)XE9C2+lf{hc27^3vZht}Oe)0GKORiCHh09}pe*zj;X@0X6b|Ng|f zNh7X;c*Q&}3>q+yVn}ytt`-^5bD;F|P-psAqJT9Mi8G^%h&?p~whUK^9U|O1g~3fK z&dgz4-S6Ok?fLQ=94T9=H1nP^hNWvAJU&%2u+I8FQ6d&X{qS>bl~U%x*f7}4k;DmF z#+%2ABHgHgAkY{9@194=R1p!d2#&|hg1f!1+BrePYK;gEck?s$3MGX?>+?uID3r4D zJbsIK1T|}kW_n*_Dz#vETc)eT2B|!vz+%)6mOk#10tox2{-r_)9sD{~xD5?*KBY5= zqz8CBbNopWrIP3qg_a{qSsg+5cab!Pw14dS76?&`Ha(K~AmI6DATZLVulREVj{L*p zUA1;@5LC$h!j0r7CxIdDGND6@NuN0mT z4v+e$kmKnu1t22W-OXKs+ZWe4OwNNrAGJTJ^?izTQ$c{+6xm%{_4q^vq9yk2Q1cM= z26&K>UF@(ADokwf6;&_jzXPyp=<%$35dAb?^tZB}ghC-UEs{t;-P^aPL7#4eV;0u4 z@Kdn(T4@*1WxJutcAZZ!!OS4T z1_VW1rO`pgD6(L>bHk??;&=`wFOhvZ!m{zUPC`V|b7#pOvXRpyNK6QSH#1z)8$UV0 z`agIYfFOVR_2H(s_xPJnzS1FQv0w^VBNP#r3Ot=?}au-{4;4hfT!08aZ-}$F@1xwCZW&TwA_(%bBeLQ8EI)*O&^9MYkOW?#Ip> z4;9^*d04#1XVYX5;j$J&Xh{4Jgt$&0Xu|}Kt_AWOp{>C2oG3gGijR-`&w*O0VZ?pm4 z(`pyxw+(tuV;9Y?Nz~}mSfh2)L|)LX^^y+^PJhw7AM{^@C^;~ndVC=>2>aU+7xG-U zMd_#m*NxHB{yCRH{iGXPznWf6S5 zYX1;I*qFWLKZF|n+t5XS_l;{m0`Hd{4#0!?Yfpt}vR*awC;jIjZMbmQRj!Fow15pV z(d1e6VHN=8$%UPAOImm!AjkORbEsl8CT`NPmZ5XV0d zxb6*eFSn}Ey9EzkUA;z~l3q>~>lA8@oz1(+Pb2*m^M25O4@8HEsu0Xts)?@JMSPmj zy6X*m8Qp05*W0~n-BTS=3r7Ng;A0PA>_{D@$U!nH$L@mDmkrDC-w{0~s4=9*0u|I| zjW8k;P17(H&gSq#g=tf&;K6cMb9_dMHDZSU5JiX$sL|uLiK04A%hv+FG~Z1|QqO>h zaPC4rAj(O8x{8tWA^8iPBdJ$Zufh943*$-tNsJy%lzhD-ldHm&e32{8Yjwwd{gn<;1{vIrAQ69r0+ZT0X>FAClnE zU`R8fIB>8;!A%f0JJh>_HK~g>d5_HJ|NLe&E{MhV^j&X*WB+Isf*2@0p^EYcgcDD@ zXYTY_TXF ze3X1Uc=*V{ga4fbIT{RVOr9$D^!snvpF5EC-h{&89*^#1T!W0UqX_Bs@EfrhKz?HV zXqE`M+2GpWMy?1L@(%r<4!iKubEBj8fKgOG#d;M?ie3DWcQiC&EDJ)5(lRQSbkdnn zijb-PXbB&588*2&0>9vOlRV5?WQq+%L{-nik@x6Khf~Jq(Ix;IAhI4#3tmn8fN^iH zWv+Ph_*fjCFO9QrY@bqTkJ!}(2vsBYdPLhs$*=kybjyJ*=>CTS@iiFOluYYSQg|ZW z+GRO$yZesnD?KwWL#A_oelre*+Ppxl9#75p=oTo|B7L!K_K$WikntJ5?dp7IE{-js zHo&6JfqyPuWT-K)x@WAG(gZxopE_-tfz&~d24cyznSkZj{!6jd8cbobDTiZ5y3_*^ zK3ti4Hrg_cQ%~Zu{oyWy6uyi*=Csm?6LPd9Q|=M^CrkFf_d`<@e0*jOjxHvnBnG9w z9*5h~jc0iMqr4xR*hK;N?cFu6lD!5m?JNj%Nthn_p-Xh63;e^sW!?_m1&*%pCGK5j z5#c|6eE;U{AMpK~zkh)LH!pvGUoS5oA75WzQ@c;s<-ud+Ph%S{Du(GxW=F29-%6f$ zQPikKkyUFT=;B>D{PQi2-A?YJ;jr}^@Q3pvv3Bh}_-n~OxYw|&_A;zefdW}SVyJz} zf8d-eWzh?$HGhemxic|kvJqIxq|Dmx!=-x9%;!W|9vae&tm)FHOPiK_OPBWNt8{5I z*!i1w3+)k3vh2jq6B(vKz=KpN6pGbCvkDki z(X+%fROoXl4I7a1*nylME`3IwvB4SkKTi>$PP1)krXPNd_D*k-__PRp6nTL++tF7M zA%1{YaO};$ot6Jg{}7uq)XfY5?gEY$|5FMQEs`wwMv5DLHBuJK(aovEDopLTqB5sy zJ&Ws8i0Olx;{wv1Ib9}1=s0mj9v1VPwVsQ_>H%wQa)IVPjtq{Mw&i)#_Q^z=Z0LRe zNu(Fz;6(CQ^(i1Jz|YY7+pA=8uZ<^4;f>;xqk+7^mA+^YaMR8gBOShvY5)CMaA4`? zZ*xs?N`2u(vg@kH-lNK+?nwV^|2#=^;(W66vvY^zMcryo65l~%5yAJ59X;`Z(1WG> zBOEoVc$OMp9Q}UlDZG6JdO;-L2xSD$Q2)^YWdwGv@GNfOp?|Ir1Pp2#+fVxi+H9!% zWgZSz5KP(e(7r>fOH56`ycnqI@)1DH|l+x1#C&fp@s zFWUA>d<-GodnZkyQbkK}EY%`X&IVq3oapW=F+8WNK$i$Rf_n$UfOyzRf`-ywQcj33x~Fzzk2EL@(e>Bo!YwTz||}JH}1T6 z_0ryrCk}5uac%ehD_0L}I&^x=_I3GM?{`Ubr@jO{P2&SE#T{Ina7fTx+PCsZI9!%2 zeuwbmv)8=GiyvoGxBTI@bfF90Z&|wfc8K3KFMV+zbbIaY=q4bpUL2w@1nkWct4%Lc z2yD`QG&K3d`T>tZ!J2SboI}U5wQAL@QoUx?s#UAk{<~47sx@m>t5T&}Epnks^;&;b ztMylv8q$SoRcqC()xJ%kD~Zmd5%47SfEhze`yDJbqxH(b3T1{d`!wYmH+J;DVmENW zBh;C2Bvtbi`n*|hTgoyDB>EPZlx2Y-9*^Q=LO!4!yMaONX1zb)FIk>{TO zYK~L8y4b}7)hE*P=$b?~C&UXVMLL#Eb}O`Yj@`8#UsPO9d_mq)s&ux`x{%-Li2z8GhM!)!xt51 zuE`sY{WY3w`+aqSG?-;^cR&eGa3UKQuV1_I7t3===Q6xC(?Zs&$G^23J<4C!%OQ@&y!W=}}zYSoH<`_gYn>9(lXKeTkJ>s71NDE#5y>;df8 zCY3)#IZG!H2LLVuPN{y&023SVIO8Y8a-4$(yP3@n)W$A;pSoEi1(PLtj)-{9f_wT+ zcy{=-2mV^}=7k8&xpOR3HxAth!ADPgJQa)!XEX?XNd}?w(5U_W|pge!$S|y5AY|x-$(b9Dr)+=AM zS{27?jmlPN(6C~$iZzRuETYVn^H{`8LybEPT)O7I2F;&D7#jeG?ZsZjeoNlG1fjk^ zvAHJZ=nKxgk@ATS0&bi*cmCX|v*%8qI(_#1y{jirpF4l{Gpd zxqANG`8&6cc>X%pPd!A<&J)_mi@3*aeYq3s?8+h@H3>22l7lXG@y5hIG=oK&9hghX zl!^?}hu4>xYimunZyWo#9*^2{;$i(%ntJvw$LM-{SGPCvD9jPwK`<>&GIT%R33? zdcHW^to_*N3A~tuW8*05 zqHX`Uh4AS=abX^)F}C6}L*kLEx9c#4E@Aq0OuvG3|9OgNb4uwDS@jEeQG6?;)7XS9 zlQNAlqjgBEUQ9m|rv*}x$C>!BMkEOEp6u|zK!a)M^4OEAFyaEC zh|hnPA|j$5z}8-sI72$(L|zvf^iTYl$Gj9NV8#=%_~8@R{d@uMdYpnePjdf)^z5)` zO{l7r4=6qa*fNJUBFs#;X0-mrh6rykGQJa)wdZ+bQj|P}PXp%$oUO<#BRq93u%R1bjXHE&i+#QL5vo9#n7~)B>;F)fSO|9{I#aM-eW7 zQ>h3^!+AbjT5O7kglY)}x}C}MxS5NQ%j8iL@ylolm{zQ+-bko$DSw+6X3p-TjYl*K z=Xl&JyD$EuLtQoyeWi}jB2Usk)LBt9KAhFCzl?oBqha+}cZn4Oc|4fp`bupxGKHKu zzq25*({O7C%`L|2$tDwfNK+hdjx--4hprRNpXe^ihfsrBJ$143(p!*wPvFZt-B2B zcHPVr**3;_YBQ5>C5nOLZpSvb(e#fYvkkFEF{<1m6^&iolq*<3$nM5jh#ePl_V zf9=SHWJL!*jbCxh1H$noJ(CIXR`sq0u9S)-7(98FaAat%8z_UVNJCLW1SPzdl@a0A%9Ius|@JnMklwQ+6Kw~2eu@FFH23{H=i{{uD| zp@@ga50;IeT{6);nWVJfa6RuG3!Y{Y(e^g*q0A1k9b>1jDjP$Kg6_ANJh2BEfr(q7 zuHGyVv-Z85ga_SlVa(T+=g|Ej#+(RA52wz+8ph5bMM8DUuk@U+Ssi{tj&n_-r8bNG z-9+IH4GM_=*5?I^?a;(|TwWU_$G;vylvn>gn~d~c;&5q1(Z|(Y zt@dyW0vAHVZ!{r%mD7%qUH=)15S?jkHhm(!hj>Q8--85EB@pYuGd)g}iaSNjZ3BxMl-6Iw#=IW` z?)jA)6gy_mo-=ROs+Nr2rD;^=Kp}h!A!aPFC&(KiD0EKYcX|MM5W- zyUH?;P2TaoG!g}5c3Wil0h4)IRG9dJXq+NaSr{^w{fA@wJdcTP80%&piag0|uEV&N z#c%POG#|ovBRcry&p+XLZCoFDA<+LLUVwiBHq^>%lAEMOuy`Y$E_nTq8#=mv%ZQU@ z;!KgXJ+!91r>?!YO)e4pL>pUaRfs}7f1beDwvB92LSGCL*U%$?HFg&g+ z8fLdvrJLehPRp*ekY>y@(tBTY?>YBZmBO1xm#fgs`(^QpReScxH63FLRBk+^c5zo# zI`qqW+N#wEd6bPc(ph>BFn@&cav0>Q1?)3~j>Wd3wJvW|5 zzegB*f>7jTH*2GaHp)n?iZ~e)KETLqdLUi|@JjVM9_}l(jJ;uPT7*nAI~$Iy(Y0fj z{!KqT?~c2*aki%iQ7jFwpwF(*RCvyux5|k|M1Y@vfY;e`mtT!ALXjWZ_tM}*^KIbq z9-GV(CZZ1?@>w#)DbXS;jZj3J1yY21=ZN8MAE%8t51$+GI)l$QLY{oW*{`_yfn5#X z$)~OCaD{--(Ult1tJAJShxTpyPi&q$yTK;voL*BPg40{3lZM{>c3B(#7H`A&tjR`3x!Qn|q&|JU=YQ>moqQ zkZGbVXmeOuG+3W>#a6~`q5*5n*uN-nx=<{Wf^M|OsKa}DNQW%2aF=va*}~gSKV=~@ z{OF!>rWYpGM2t?aDIgT7s3za{=1n~bSf9MmLF{I-7r%=}3FvBH;^Dg-j^ED~uwP_BOI8g16`(<$p9QJ1&1~fvMIVOZ$Fz7N1bJcZDV)@AjyJ5Qo%era+uh6>KyuvZ8nx@WWxdCf$Yyb0`Ukx>yTs=J%r>3LsX#BI|VV^fIGx%K_ ziM4$&a+&|YtHJBeT5fTkZMZ!m=OLMz3sk;I=;>WyDKt1=Sg*-t&vg1?`rR?B5>XD9 zO1WTQpV{@G_Jeb+Ow6pP6cJ-vv&K}2c-}!DMM{K=xKZXAhV__V3#=dB*U!XEK(TnG z2&3q6;L_f)vwBx=;+T%vs`sPFrL!|}X0AB>Ebgsbd{k8T{Si1U6VnpYc7Mp7GM93W zzXpVPW;u>bb55lB@}%ze z8e`O@2BO%i_@v12ytNBnAjSl-kJYMh&JaZox5K15s5b*sx7-}$^}XJQxf`*uGbXS0 zp8d?vE4EH08D4LnAHD%$5#6DUVleQ4l1CRVSsqBC%A)vXbcQjZQndK3tgaEmCE&rb zX$|VuBdA}a%lxf>TI7z!4n@IK1G#))V3P^0TYkhnH_%-QGLBba8WYaeD9m(e?dH z*H=Gt4$_0Lm~}J0cfNV-YmDD2hKLAs`YGK@CnDWDr+1QcpI*f}E3o#)!cZeiXZMa| zfq##T%Y$N^UCD2!UySWwNMTMjD8&rL^PJAd-lHJ5tVG^puUrc@R) z%2THg+?kpMPl3~>Hke!HS2jy+XcVU_jVJu6!NB1tlglA%wj9|UvN~kXku9r3Hu}xM zAxF;Su8}@Nw7@%kJmZwlkfc9UJmmGfz#$ozL)ZK+;qN_ScCh6!+HYVeU3wp zRTDv;h<_K*!@@f0;`O6AxO6F$QjZ47QDzzW=vTR}LkRyj=OAYR#?s}}0g;Lj{&7xy zZDwP-TKl^ZCPFoeiL`JoQz-2s0&b!si|~vTdk*02|g|v z)Ve~Bj1hy8JWH|aeWo5!(~KwLysA*E@u_*Sbzv~AVkxU(In&NP>H<1M^`%+k#*LeQ zm(%_jF_naNWuon^$Q25ueZj=?7jHk)TA*1yoUI=L8q53 zU3~4AbZSXDR+5gxr33i#Ns>+^-!!Zs#3D}@wf>}3OP-gHPMa|}!orHb>kYTQ`un5SAybJB^r;(ml8 zJ)%=Yr%?z~>>?(g%nkk?w=w)`mY3LBqv|H`k!2L)I#@hjWUkn>p@SE#EFnfM(hI9Z3LLV(|@yTF^AWt%n0;K3uZblN~;nmc|e`mdweLgTjWOz*AH zsD9V+oLa+43+DpPlz2@uJi%*R=|N6_{sLg42Ggn8o2o>&p=&lBxc!aQjxtBNYoPY1 zl(kwD8iesOhNh>pV^XX_PzVc7H+_V3Hbjx1Duw(NeT$qq)O634HjY!m#PD#HTE#_Z zkvRLF0zRaB1C8BD9Bw-&j6Jkq{Cr+sjg*}t2 zR;Rk-;$iDdfJ@ezJvvwLI$UJ`fDysiTT`a%Kbc=WQO=q67@c}N$XwznO z?Ve>Xe6LpPNttdOU|J6TYwwjD56m6?MLmT#l{ZMP3Q^#@D>b;F^FN}zPp3twQEC6v z{ixi0z_|IF?tGWjAe|oR+@lL75d{|StLae_a;A-sWCg)9W3*oy)F({VW()4!Jic(+ z%rSMFS6XK_gONBW83%QgUDC8lIj(Zv2aU#JTJx<;sW(Iz_X6#ktia$F zD82k+foEtx;9$lOtZ%%&uKA^-WsFuA50GYCGHxHomh9_FOV|D+i8c(F{5&Mm!B3f7 zsf-|sygEAr!h*n&Y zHQ%#7MCFl(GJ4@@m6nUlFC7)b=eBfChOS>gyxytUZsIfiGA|^bK|pZNXc|E#mn$Q7 zMP!*v)@#vw)V9a&9JQ;cOZ)9{ExpHy6-o^)FJn$uK@$e8tR*PnlKbq(dre1d?O ztI3|gS-$L1u7;lTe$Q$pLPujw?wDbXvm!Dnx|+9x3%fMbH440yth#F z1ATZ0AN-o~20q%&d7h_1tsQ7ls57$~9dj2g?jHDeeaD9A*8r`UqkVG~EBbDGs?U5- zzXHzjAYJ4wBWf>0y`{=uFQjaW($&{9sO2Caw3iY0LmBa_H2F)`YdDt>Sv*;=SiWQi zMm%M~f}J#Eo;7kH{ddTjbGj*(dPIM+(q%&XJ&2zC;t$VzkAI-i_|T8!(yPY;__z07 zsp01Xzo$WX{fGzmh5Tk%JM-6{G9(#`2~B)_!T}FIe7pbH3vCCh-xJ;9OoS0!?m4Lt z;EjN%0eJI(xa6P7pNwl5FVfMKlV9@+aYEoaF~_g~=uBGg3^zdQV5s^VcRyr=DLS2? zyb1W^i9th50zMcCc8bD~if@S-ZF1<-A3%dP4!Im0ispAHQrt0rW_kJ&MY3nf<5)aj z*6c-#JLbufzd+XfC3EL0MlR$joGo7gS$gFP^Q1_O8G^{yQIyExkhMqwhr-1j3uIQL zEnXx?mfTdjY((6=TIuo->GC_|E|M)7}fZNNrZ{NIjCSR|e-@1Kx<^1NY^K0@_ zy70!Ce7$z2UvHe>yc=3d{qBXYC6+~?wE=#-dHv??TjvPrK5C_NejQc1*YxF^H=o>I z{D^nyr06pN;X87)@YGIgp>?OwiXAV@m_!k2_-}w49;2DD;7=%0D}DnsOzax34r{IQ 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 ErC?oWm@abNp9 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�NNRViz+Q3hdl58IewWtuHopwF;BrI?pj zJG2Yo5@#Go%px#25STqZsW_y}w#=3Ge79?u?S3ZU_UeS-8?Qda=2p#UuP(?)*iu)$d zy2wVj&aw$4ht-9Y5dEW3K%#es5eE&yIkOnnBp*cvUCRE&mdi?R*2L4-T^h+Q-5!WM zs#v%-bu2&RtEPT@{1oUBAp29 zr&jPMTso0JiDT}CZeoEGcPE8+l>~zIeOb`_9Yk@|r*{5e zE^ajTes15)HZ!+l%v1G^h~@~XWBPVBQ;ti0diGY@H9b2x$8oS3{b3%8eiqM_LS9wt zm6>v>I%{Xowv}gq^PoLG5UUc|CotFIeC(d(hSdy&iGJN+>UYq3lh>mJWGeRL-vffX ziBrKu%PrqP=JtPN-XD6D9YYg>(x>uCf3=xoN-vW-+Ag_nu&(42m9k+plcnPZ_Hzjx zY$uDZt_N@4*UIB84?#e{$>F&gLx@@jI`3v(4}Du8UIxI+PvyRY*zR zcD*{ctaqaY!n;^vu)Jpxhm=o$XQyR`qWJk(wmS-4e@lzXkB?%7Be_|S7fCZ{AAsJ? zXTX*H%>~}ADcfy`)k8@=h!fU;r!Eo)4Hsm%FUr@y0NMvF$_FwD32(jWo~GM-$M@Q& zDQoa9x9xAkraQ%OEkZTCNG$b5LlOb+@DbF|iM80V*FEhOHMaIc)F8>MxdOSlxtpBK z0L$1fulyGEtm;bG2x_uwGAF~(mZ+L{k@?%#1ei!jZ7`C$DsrKL!VDHecRV)-fQ?Ta zv(NamS;!z`8#Gcnhj8d5!`~d*7?T(53E}x~h(tbCLkbV$1NHk?84VYnWHI@{rRi(H z;r+@rt#KSwZ3!k*mvnMih_`-ya9?^DXvP_k(?yhFZHT36V@&;oZ7RVA3Crc#TX-X9SpZ_FDqY z4s4ObIFma>Ft7}ejjH8G>rELj>)So^HASU(;3Bh2?^+Obl#PEgt7yx9{H1~pC4+VF z-O0@WqXUwxcWc8X5Lj0DU2F=g=t$xy_`3Sru7L~cDd>ZPnQ;L)n?&!|FOt>VsD&to z5t1Sj5gj@sJ|d_#?bvoCY&uiwz!N&M#z@$+l^(Nao$RBF-j|nUXjuW74EW}VwjaPz zF(hxVVPHS>x|a#R>_3o$k}E_R`Gr%YZ%xWfg9YmH%2`c>*tTQ~v~(elwpfim6=X%~ zr!K~rMW8E-bJ%!`88|PWxA66dGJ!U%~IRCZ5W<|eld$aO%x8HlVEB5rg!Y)sD_Z`IaJc7t)NQW`~we6C- zJ7qDr%%W`pS+~ffwQiYZgCFUDI{o8A5}k4JsN<8Vkh{Ks6fkjm%ZS(sp@?$Mv1P<7 zx91mU1DoSTPw@6-^SFUu{$2R4MH?nxhw{z6&%a-H0!7UHV#w-NIcH4@-YRK_1_YBG z_+guC$a3tOG%oYhn%Z9#U{TTSx@y+*J%g;(`%*962Ho|$8&(R?7)3z(kUVzNk!b46 zf9|(fRQgc#ge+Vm!mo~om4ueaDYpUk(ucGl(>HC*xFS@fHaG6R6$lT$f^-tE6~ijW zDSluG4CkGs)VJxoDLn6WiK9)-_yw!oek`&1E#T?yS(MkY6xA9J9i!Q?>Ja&})%MK>=hRA4w=>>;+_(K#_)|SC4i|@0Ba>~ht2Sk1 zt`)uKi9XBSTeNj5tNN`RUeEoaWKH9q8c!`{|s~AOy=L2PXkODcmbJdy&ZIWKO2u8{2BEoA^#I z`nVYsw!7$AsewB9Ps3)c>~a>$_aUfcm2LH_iCbX<-Qta9&$n+5%Sr~qV7s_I(yu3a zY(6{ro2e@G_DSo6$mfpdcC4ohddpU8)(hmt&#q=+Wt;Qzu8Z!)?&ar8n11!QaQmLD zk8gN(+?LVF%MNa|_`i1pqL?k8d&C=#S~6_xjB=y3vSo0ncZUXqu?cCUroa=9T^tp*x9rd&ho*Q|uu7S&vj_Kz&r?L8*ba$GAj-95Y7;8-+9;;&r^ zBkw!E;uxFVrtMGb&_o^Hyw8j}ypA1o)N%$nt=#5>?8;qw%-*&|+cLQg0wAP7-w@;P zqwQg6h_u~{cZ*^!tHU^~ex>}%_AfH-US?=56=%G>%SWZ5mR5uqQs*{SXy_JFOh}vqaRXX%3RGxs zFIMV#NH*&kgq5e1?QThP4WpX@Y7o(0)Eg`QPHU$WtYgwCmUOkR!Md2UvR)iizNXRa zz=cmf|33TGvBffkBv0ux8d(*Ql>rji)Uf<6;Lj{`fhR zp5ZnFq1=iYuz(sj4o;|0(i@*%k$`q)J;#b&0@dbeW-$IMKdh?+BT(SVJa@Bhg@;re zTe7lP;+dC*XlGN)KGEwlS#blJKqfJ7G|}MureJ3a8&J_gLrKFu@Q3Gg_*=hj>0So} z8d$Qu-qBEaO_^2AEIQXpZWDieX7Q!8ti$2&KPEL%a>Z%2%$`^Ki)yc1aA7)uZ#7P9 z=G|KEZ|u7?K5lm~-wunrba3C2)DLHG z_InW_h4nB*)6NDgu0PLyjrr;Lz76anFRaIbv!nJ5GxoUN2qp5ro!-A}hsk$&Ypk8S zehOfhH?%ATO%?WZlV4g(&YNO?JM?mF_zClvLtj|j5a3BvUbDA zb@B1=Y@a$bmAV<1vtu@g9ed&6;&B+D6_?y7{ zJosD7@YI#}63?dq7|^SKVn^SI+f~@7d(iSnw&V@%PV3Vd`PQK6)wDP4)gCA!_T)qC zSK>%yJH8to_achApnX&-pc`?$G=i_bx*y>wfSC3L}ohR!nb|xVK#bE?s+k>h*Y72A;dtaXTt8MIFTK9UvBxrD71RKF_>F-U~ z%x5AJ!*SRA-~?6X)c(jI*wMcBZ>Sa8`pj~;gN_x!>9waOxYfw;+n+&8<-yUmLNsNN zpX9s#erCg8l6?~9yxXTQHsUpjwcyy14McwH2e}c9jFd|1+WmOMDen86xvV6?V{DOc ziqLDCKUn2V+osyb5%?vW25Z`j=QE5T zjDYu3X!d9%&O+Or5k@~sbt|gfp#XQ9Q2Ys~%j^5JNUzY^CN!jT*rXopT@+L7E~E|S zrU~!nwu%M$;4TH>u}5L?lmEeORhz6w+v*cc#?q`?tE^Ahsym0(3J1&weUo8EBKy{$ z*gDM;(r7Q8Jc4Kdr5E-vEWQaFVQqXo9L?mdKQ*h~ar0{H>=6upcHtS`imVO_B83!+ zD2mrt^@H=kBP6_yV{*=lngdklnxP<-fN$i?)%|ElTkNrfqq@(fr}b{la>3Cy=iIu* zT|+JgqB-yE=D0EDPJ|n*Y;gR@#R89M`J9kwV}d&#d)V=S9ra0G#1wqfB66baIaM{k z2c^xt0>>Ml9TOzH&jfYc-CO!!Uwt5$oGIUFTD*IsGH6h}curUaXk<4?<4+t>)LFKE za6k(Q2?@U`*=fuz#q7Vc}pC|86N)Fn8MG;pQ_|>g)NFoIyk1lg+?w@kq$kklDFb3h=zF~ z%#OKq5ouRV`gRZoO-+>YVF|-BMD*%eDw`j=!2B6t5BGAVyKW}9c>mUaYryg7%T%nu zPo_-qK$*YV8n-5TCooT2-F{KGea@HB6J+(Sm*bfxI*ZTpi2ekTvp$l7fsIA zukX`R`L!7r=qv&W1$iK^*>L{@$|33zx8lo=E{YcCrt+_C+Rf7wJ~}_Gazu)+zjBt~HzmN<9&#`Q9nTI@!NJ+ZLK_xgY<1TZKfuElglqYSWAAX= zlzicE7~f{qqixA)@xJr8$C5*^`GGiq>%#E-j@!xPmB+uuH{cds0N}qt;rh@j2?%zZ zf^7E-uF``D+$4{NzzC{`KvD91VM3BHStxdI1Tpi0Zr$lGW}@prh0KUiiK4>s?>b*HezQoFVa8|}6H(g8vd55(8&T8;k{ z!3Mu)1XYA7=c~Pe>d)J3h<}fkqYznZhW7)j+XJSc0n*7bgJd{+zk7Y_Ti#Kwm^KU8 zGWsuTle%RZK?EL1&l2)Cv2P$|(>+{xULCx7E8HjHihD9AnZA0+?tl!qkXxL4&zB(vSX8u1Dy)s z^XELJ;Ra1S^QE<;ZX<+D0d3Jv+{6kE5JW(aKAis+LkyY1%UOWkRMQHC>Jgw)M~b=E z?UY@!F^Bb*%>-$u?0|Y7S7U{EIjQk9xvf2x>7;aU*E)h55yb;6D*I6U-82TSwVA;j zL0Bw%slp{t;s@#rne!b2=Cf>ewRsGnn74L(ErpZt@TC!;WpU75TGYa)6b4M|L89~riSgF3f-KQtD^&3tG>SG5Lq1jwT;wY@QAx}<&Kepim!8_ zL-;~jD_0B`rdEAp?kDK50G(paIX^ZzONGbSZR{g647|GS zBDOb^(JG>!v1~kggPA!6{v`S1KJGSG!P8-3IPz}F1ljfi$^?8@lFVmli%Z3P?NR2d zOicINwlOxTN~5kT39YMCiJn2<%P)+me)0dB>;ql?svYaiM_9$a)7KfMiThxR5gWY} z=;jCBn)p?PM}_|$%sJaWc#I#XprUl4-6z>IPce^RxfK)})6^)N zTQ9#w>O^F~wv0ejpnw*ni=e6j9z`6A8}O8CR=^7^Q2-<{$37Qvrundj{t%IlBrGLn z)^aK(o5L6mm|y{!y`~3b21O8$2Lm=SgkCA2Zv8rJ&ZrE|!q=*eYk_B)dVb7Eg?^f~ zZ+Jn-vJp{7J?cvu>G<);3QvQT1Dv^NU#{x_ezYf!D(0iL4^0VNAG4m*|Lg~e5mAG9 zO8BY}Ol2qKL``lt6s5N+)NOH`l1cDf$|Kko@8njggdLG;wc#v4*exVgtRZ2`i7<|> z)FJ>jPgww09aqbVp`@L{`v^suI3qNQ1W%b!K-6H&8D}l=B{4J!7(l zi3*+)l%~KYCS)#UzrH{EL-#D93C3?F|jb3?OI>T5?jiC#?~@u9?<7`SkiP&|_epmZih) z$yvEqz;29NUR{nmDMwGkg!`;!p7#3G=nf!gAC2OrlZ^ZKFO)^+VQ_?CbE&tfa1l{n zAjG6G_Fs;CF%!{!IR+6=hj@YGPlgWR+`(OXI?cO@l00|w`~_g9VU%&r*&{UZVvW?| z9Tn3K4FY&LS^^tI&+`}xc2K+}CRkgK3q{`)GOgbX(-_5OqcZ?#(2Max7sinWU)0Gd zM^ALKDq-+X7nwR8yB$Y8W>{w18V^S>s+C)08$lptJ!rn9jo|<7t(pmS<{; zE?T4t`F<*uEy8uoRjD}NbF+>wFy|l+tH0@LrL=%^F!Ju73(TWPZJwb zwBO|3+rJve=vkfDApNc1kLMK3TF0GU-~hz!8_3#2MJm_o*&&tAdPQ%UGNR>x+E;Zu zp3Rd@J3c&CPi>5FneKGb>3I&fG+CyzgGJTo8AHMLoKniy9xq#WKY57i=QDqZ*l~uU zM(~U(<{?-KrBaanTKjaa#4GxnZ|yz!W}=BDZUD(}P;<3G4(ZG^pOnZ8tXbqMm12#& z*k;*I%x&?P7XW;kCOstni78H~pLt-C%bXPk5GhKogOKP!;{%s}BuI6mcSXG^FK~0J z7BRS~g;TLWhtWKvTp}ad*&I<5G^D?|j%zz~9X*xmqSyiv&>^LNtQ6Ta9wkDLU?+Ne$-!>oKFN-T? z32-)alj^}~Ftmg~duX+hwIv8vPAv{F8GUh9)gd#&^?ahvPZkSaEF(o$2u;TRu1{=d z2z}h)H;igM;V5AcJw-e4fdeMqV%o=#eec!2K8VvYo3c&S!LXPiV-LLOK(qW7z7uc)FctECEcvG8sjPlmq6n%^X1<=P6U zK@5#jzXW86tyC+L)Ob9M)oRyH*lDn^eI1d+3~4YVC$hp?>Mo-jDOj#0c?>|!ed^#+ z6RhEH+l=&*U257y?8=<86~v<#%PNH#G0GBrG!VWA;pReEQsiJDW&sA~MC$?m!i=?_ zR4X*1JrD#IOJXE!0OzeP@hvKX@SOba++8NQyBmY}Q<^3_=T?A_Fo^6>G`8Q~7aA7; z#*iG$DWVRJ+bfZB7mZgJY`&B$kMaEz1mT)_W_);5Qqp;`pp`mcfZ0e#WaR+wfO^{% ze?Ei%@}RjF-BD5B=v?%6t#HzDI!)O;>)q`3eb=w9&pljNKIm(WxIKxjYdQ^nIGJi` z2|8V`8zpiwi__17z*}S+Nd%Z26mPE!0V~o1;VHa4tKGIrM=URjM~q%?Vw%$Uv-7Y|u1>NEizOD9K2y3)4^)K$Z&xlnue! zCCQ7Fl((}}l&U+jGG5eE8qIMi4jzDAJ}jo4a^zr-Qc0!VBsnKvl=<*(<7GUR5)qbt zyPj20xpeuN>l!7?}HmdWMiMPyB>6C(xP zbMmQQ*hb>^=pg)7IS6zGQgg<OU|6di~+5eaT3sJk|NC z)EEcO-?3)0A3=88AE@M8J95G*D~3tfYxg6{kZ!`q%1*6A9 z=6>YsQzH-Gu~JqN*O**M;i&F)x#BC_eB&*-YD;zy%e->wl;hP1+$HmijfKNPZzCsL zQe?Y)MhRl*4;!v;o@aX5w!O^kmvs3baGR6;U(U&8c=&kN(J`&Azx@n-&MTG`wv^T$iVqe@mkJ5j_H4QKOA899P@wB)3bB3{9mA_XXj-4LwWxXdV0=( z+eY`V>FM=>^#4CcPY;R>X8gZNPY(vme zEj=x}uesu_3vYGaAmgN|dLV*mB+@oZzW9q2Xtw{~+5HzXCuVV7nR1aY_E{bKo)^S# zIjA;1yNf9K-;Zh9%--IkbAgPl4%v1Xj#+W{qW664X;tfnD92r|U-k&ej5znUYudJK_g*zl^nQVGdiW7!eV7q& zn^Wz3%X&##RU3;|z_2>a*qX~82a1gl>rGt)N zuRnomtr&Q{8()0=`1Ntl-v&m<@A=@(tlo2*4uF^bSpB;Ml8|bt!Yi#BjwMhyb)Sn8 zU_GaAz6)%-+w)50}KeJrvoorb#S_#RwI9$*peo3QZB!k{n&7ovlQ84{M$7F zs0PCNwGe$3Q&H-Ee@{u@=)|fNs6j_Y^-TD&>$%5kL;wg_=T+lEWHyQA00@XxXVWRB zy+d*j2uSEwgk87s%y4b@6~X&E>-+DB6d+aA{v|YZy2}BPfQC|x_W$N2{uBXgAoL=x zuil~>0M4RB>rDtJqZj<^wet^QF9q(X8!IH!!zVv-lpr|WQ@J&Xwm zUTkx>587pK|P5x-3g`<)k`+{}4hz zxc}q0d+IMC;F|LP>-fLqv6F!b&$`Mv3ID1BkOzKA3M`$Bs${$5Alm9>48r>22E|7P zCHx3m?td}%??2JIPs$br9c5(ymC1gl-{r(QOMxlgs5bnylbjVzL)-P&w`=K{>*0jX z*__W%O*4MCFykrl`zL?b0&=;kdH3HH0A%2<0LtJQ>|TLYAB?p%%SUWy=j#W4es9L; zPoRy&d+wqtni0rD&KX~Po=VrFm$rKT9Pzt(DA}!lVefCn46=A?2{#cQ0H~giZy7#r z;&q(3A3-#SU0ewsaC~Rtnz|cAzc!p-zDnrf>OrqMW4U(!+MJ0F{cBSHt&Uz!Pe5TxHy!7E7#JT z&lmU4mJo!xh?l5C{F#TZnXns94rqn)jP3^pl)J(sV}5yf-&?6J7#wz%fT{QN4s*&? z3jDL~e;yxtQe1ZNCmgm^Rf*rq$KpqpT=5H)`=!5~`!=$z9+;P|j8*3t!&cvFcS71@ z-@du?mNG8FFsM$oH=5B~7aMYi2XJ5C5(XJQd>) zaFa!4eH?0Q+veT}9&grf*OFY= zB=tq#K7ruv+0ry$mM^Ot2~gkhDqh}u7tQJpXLrRufnxdfv(g%F&IoMZs}Awf1|AKN z!hW$5{z_UR((~_6HmLZ;K&Ux)A7WNYrB^^rh^N#cRcsJ0QXdSqvDgbXk8W3{>48jB z4>WCWSZA)$ZZktysgEkWS`ln;aN&@I*s-~i<_jNBy zXy*m*HSnTpr%JBqYV*z_)OZ?|-4zdI$tMwpzcnf?DjqQ1=Fu@#ZM`KHsA^t~OG_Ke zlDTsKF+gCn1S>Fxd^AJX;g{DrmB&21-uGU703bY^^5?7fw?{w1X@}PidtBeKcE5pa zovQt@dwtr+^m6(tuFl27smooTE)hoL_oV7CRN^h1B{BnWNYeyD9dN1m^cN23rXY{zxr7kTW zfuvepGcjGN$X5khJHI#fcQcF8W-XOoV1)ZgK9#6hXO*o$k-1jwHO(9~)spB4sfzxK zucM~9%D(vj(N}fC11h0+x`n4U7g)RsUgRRDGR(P8KJvG>^D83zDbqE(u73W$bGy#i z=-F*`-8SFh=%d$$FsA7yx1Fa#-(9D3;LD1Ich#@Q>*aMz1#aCi6M8r(g&lb{Kj zCC~G{-}}6~`)zIg_1D%GUH43nbf0rLGt)iY)6)^9$ykuG``%BOx8c9h|0-)q4la(0 zzFV8^90fprSwS%#l)<{5%YnMNg@{bkQz?z@?0)C#(xbO^AKd{WX8Nw^<8U$HzNmi> z!1i|!H#UXNNAZ0nf&Mqp)e2dMYUt)`XqIVcRA6iTuOc;;rMd<|rvw0q(rO&aFM9HM zoVx%3_Y{WxL&9BQ}vS6^rzxhUTmBzs0RSic3QB^l(bHh5EEs4uS(uO*!?5PlTPU#WM3dbz!LEDdGls_q+BB(AjtmoMX-HFu*bd#?)%Y6 zua54fneVpzKbk?{%Q)rt-))p?9eedHle|+KYaBc3CirxPLSPlREGTLO;CYJ@8Q+z8 zgf1EIryb8P?Rs8a9-`EHq&;5Dg7yU{%};VF&^`a4`IaR7iq6-&tVWKK9wzGU1@k@x z06?+t^eXJgI}6~BCIVGCWSu|?|GN#e6~%Bk=Av`AR{jwjC}!}*PDp)&aP-~hqNenx z7wo3zxOOO|n~S|P^O$$Bdm;&~01`-s~=9#_a+o_3I9672M+x3Wg zl2+^WcCPo!RQkrwA+l}S?B}P0+s}0nHN%@m#Qa}GTB+6%p2t$rJu<7y{=o;LFtm!+ zYgfNv?N|0xIp)_6GbPrO@Hb#S8F>Si=#|95&W|dCyQAv>Ids-wxk~kU}$`ZuG+lo$t1u`Nh9Q>S!dk^ ze0S~=_x|P!CBL+3;Zx)U@l z-tTy&(^Q-*x$9C?@EcHSR@$=o(4L9`@sQ8;i1OZJnPs6ckn5)w$D;Q!@8Mh&`+xGq z3XXpbpH=03P0@IuPYw9b!vDh5^<4i>k;=eUiTUA<&2#yx)A7&i|85tZ|Lt zb{5Jf;s4D37gnubl_rlg`WFhBebGTDV?iZi^v*)=}B08P|?Tg&uFw;ay!8_;$;`uS752ylVQ$0Q(z&dMmC|N1#PWfBp<_-D>P(}-Lydx}_pD@}-Fe9pdAR4q8R z0Z`YKW9ZE(MmL1Rh5|C3+C5?|<+AGK_s-Gxfh5SREjo`A7J2_c)VifPIr_W05c5B& z|1*t9>T_0Z>}QPdm$r>+lDQu7spG(YxbC8`l0Cqe=d^zq-F`XUeO*hZDWoOW z|6vO_@9M7A`0M+Fz)Hzvx5TOQX@j&4L2k)uR$6&uH0GL%02fifKiEJ-N|b^M-2RdC zA4w=odKIK?)lyaAKiTM|P}@#gN2mURYu7f7ehAPI=p4mHMVS@-Dx`Fa+{X z8C+oA40!m0fat4G;zZ&_cF#+f}!N zkgi8>z6k!Z83jPCTz&K#(LHo$jaj4B z;W8a%RKv2vy_$Zx;G=hZv;RTx{}F+Tx)6rv+xtHL{B%_d{CUH`_rW>39{_-jANW|+ zlaLGg4G_tT>;8z#>vYqN22G-HIG)vgQ`fX}^j44FmUs~^|2`Ri4fI1q6LI?8aK!=KvHLKxKJ25st!8OBPYCWk{f~DJ&o*IR@kL0QW8dzMV2ke_TlY=th%Y*B zf3kTXS~_|}wdS43HZD(_x)olY?~IgC{63CVSF{MZUh&QCN6mnND{=i&*GaWH0yY5x zqYzO@v~IP^kjr(Ix-B`1I=h|cL$I`St7@L!4@6@M7u9kQmA0C#org+Qug5hU-69&C z&5(qo+PbSE_R_Aps@x7wty*U+Jw2lN>SM}cW;qzCBUHHcPIK{pyno5;?ETBO9ZH58 zw)Ok6T$a`Lvlw?Xr?{_9_A`ILyPcE;uV_RC@5enR4y7RYx!bY}#g~qEIMlK8O$ii+ zC>~!yR&r2=EpNtu31DFz&}atOoH6{73&SdnPg$6`-sCp`esvkd!Rea_4;Y*v*3JUJ zelhwV@96)J1#oXh8XmN_#S$n0JPZ^hEY#b13vY{DP|z^200=lVbPQ~q_avN{Sj@^s zq#VLzEI6&SOsCbBVgeUc?(=x718(sKcxL?j0rwoeQW zV2VH|8~?g`ZEq+tez;>2HM4hhjJl6)Q$z?1s_LiO;spl548&{|2yo0|LGa!;H9I zEaA2~`)DPROVP;6xVJ-8mKIEMP=k8_np-rLo|J|9N!aF!;k4~C;zmI$`nWNj$ooa9 zhGF}|0sM&a zQfP$c%rsdjb&*HTN0BWMfJGEEiL>&^WY>tm)JOYSW>tCF&T7a{lWgt0Oi$94Kql(? zL2PH*S#o7Z0{<$9cAk_ z=|C7QDYLJ4ch1q;W6CoXYmqNnnhd62gqzc8puz(r8+Bs^27?hDEPNbDG1Il6gKf*K zM{d6e*H#SGZqT=t$JkYUf$>0$yuGU={33qv;XA0z5-GUrHy~`U4lcu*P>WhUW**gl z{5#|MGg}#j5B&gm%jqz%Te^7zYKh(KkY$bM8z&?ya{wOdGuxp0DO3XQn}G-l>>M;0*y8FsMYMo05b zk`R_MJkz(ZOh`n>5!)n=D>x}>^1huJ%vp441ks~22nXkG!44QLHFBd~PU)4gG-Av~z zK`gC4x*U@*GUG9D?dn~!qee&$q%R*{Nj!yXKW&gLAErGQo+}Y_SB<2~N;#n58SHwa z+@|Yk&6~OB&+JP4PUDCyQ9P0In4KW#R*nTbXZc#hBhhs@>I1HR!gt9oKPW-^lrw~t z0Tb=2h=~S5M`%nL7m|Ia6+(~`ClMxc)c5xpEP_ReTyBSYc7~eOu*DP-Fy(0WXe&7L zKHBQBDk|+sp#1U{5qNrQUTA3vsb(q_5bJg|pR9WGlcsb_{xi!;@FGXn`%#Llc$U1q z(@z{O4LBXU!?Gzq2AkUxUu+Q`BJao}J1ZIWth5TgEv3vf>?lw~6az*5)4WG&n=a*-?OAm0AfD&G6g9PscMRL_Gp4{|qmmU?Y(ilTM2<^h z#dR42i4w-)^N9PEo6Z`S?X*8-9G!MaHpn0m)sw6D0O3KDvx~_%zZwh&M}GrW=5G7L z#M4q{qYhk6+7!TVkjPbRM<*#A>qO{+Dq98Nt4F%eEEyFoO2`UX1drKVc*}YotD2I2 zLk!8TWgy-9d^Upsh3zGxmE5h*e4&LhaBSxA+*2a|k&}rrMp` zeKX>S&$daQ9;QW={RAjT7aSzTpZHB%xzf%b@k0?vd zz6#1y8)x3)5G8oaUd$&7&f;FwYUrw_QM?MW<_hpbbO=OjZ*DF6()uJuMJ-rhoCs+L zLb^A7N=*3;_-TdG96is^C*f+Q_Zz?vU&2A~uHrklsfi9)2Ymw9bK%CwGq4K2zz|{7 ziyL7)cu!|^nnOCShqH_}k zjj%TR45QkBmT;4rzD{$-(oyplw`dz?bv-BH+8Je!Ad^b32-oyQSR~PTCY(r&I`)^`iyH@>O3^9FBO`i7{t!=1m=8)R4E0j)i&*e1?b_a8#1n>fB^jg z`zOSy0^KNVoa}-Qbs8ShqY?@)$pjy(A6>03vD7ofTAgO%jHu|+s0`HPzEISYM5a-x z+_cW@sePzJtzdoKwX*m&(04ye^0{f9;#9>QYuv0p`IKo3@!WdBm&z zkKV0U@o4071u?{uVrU+~_{#~`>jfl#oyKya_14LmPiZAj2{wd`*l~CBidp&^`zfFZ zNe@txSY!A>@7*|c5#+WUi_9Ng-8G$}4dtZdTd3q8C)4LR?gQP6SG?~Uo+DzK+3lxAg zkTkA!3X8Nhw#D^gIKVb+3HoH8q>AB2IEpkIkxbr3Gz~yjcCG{`S&mu=#*{;J0Fc(nP2Gm#!N6t~LIYFO4R`q{#iZ?0A*)I~ z>jPkO8B9oCC5ZwZ|CLACEYRS>5%$)bbqcCVb~*o7`Ee3vDg8%k7mfx>v{?jt09ry_ zz$7@DoB$@1p?NfNLm;gNyb}xyM{vO=MiVWeiD;7=UqhL9SNVLL24_d z8{RA|SX_molu2aik&i9;SXH~AQAu<|%*hPS(mdGK)#HpsxCLpB&jv*#V;RUbcPJ-? zek(~?nOl;Z)Nrx19D7(w*nrX^9D{WG5k0oyN!x2wR&;73YcS^v$}7z z^?&=sgX=p7bFzuvelU!4pkno8+pKDy=x;LKK&qm3-N=U?mTdWswh&XDzESdPTmNo_ z^3#C4xJBw`2D}uKltTZp^B5%HDo2U*@m;c7-PnxzJ;lVI;W9o){>`~JN&$9wo*W%A z-Ps5DILYJyUDraTy$J>?#M7=$+l@?3Nfi&4*?}s|x|4T(sM_P=S;WBf6kbG1;G&DS ztqC%uMZXeB$~;3W?wtl@gXIhi_Cid;LI#`Ya$Cs#?mp*6#5E-*?}bsSCG17Ynx(Nz zPrA5Ce@)9|iAq_`IHh=WU~*6*0Md*g%TK*-laOA5W(heOe0wh|IWqaiP{!&D6ok9^3WSD7sch-Q z>>7RptW_Rs99xi%*&cO})^wCYFUX}{%!7>(nHuz~cT(vt4D&YyrrttbBd<7!$0lI# zcczd@o6?rx?oXo0~=$9~5f5t1>5+AWzso z2I^``oGtL|@Vh~qJIBc2Cz__GG6c0&SVUn#vOZiaryU>{!`sGl>~ksoYLw(Lv$Isg ze{<2^<2I2osY=45C3z@jlrT=%v{8AVIAns5fk>a1Vn+)GxAQgXtX!=WiaPmWgwLbF zQlK!D454Az6v77n!uTAd!r|vnG+8N??D!Q<-W#1h?<=Dv{!bguooX~=VY9~ zwn?jo1c~9l*|Yb)dWtvGvh(95S8_1`@JxO+r+_SgE=C#nlA{R3`g-Bo3+Rc8jwzF+ zKT5Qd)n2e+hQ`d~(^qCk8n9Re>0^O7RK^X@i<_kVLl_gm3Pj`2wnYv>-=^=HkH0LL z^!a(CbhDt>kHj07*^-XZ+5?$Y@cd~H$fY;N#!+~ z7}ecNPjo^ksjs~uPkSCq_Q8BdhOg}>W-b=NH^nM(5LsM~B~dTPcrITs>tX3jKusDq zvQrB~J?2znDceyk309KI1FP86{I*t9E|a;g{rd{L?Qthp&8 ztoCZ@>@tX%6*Lyqv7f?z)Y`~=`kIn`%8;T19w|r@bO8%(HIq6u$b-JrL?tpajHN|$O-tl<5N!kZRBRqoH!MEvFqph!+0h|b#l#{Rm!-J$@ zE8RsybNYC`o%%s6>;4xMPRcU_aO3X&It#-ItN4R*gHX_IRLkG4s<%+`?llDT~8p~n2w?Xs&Jp!K8)$6BMN%D+DB{RT+%8EXX~)(f|UBiWG*3ba13ma}>miUENos{VgEr(hcAwSIzW z21+8Wd|`j3p?(MDHN@C^>G)1>mjdB-lGrc08O9Qn&7)W%7aMRR`l|*qj<7m4vd@Wm z!a3C+)J}uZ>qiRneT-t|-Nj`Cu_Y=2r_0SJOTt^DdR2YnMwFanxbr-yV~4#iqz#8= zI6n~RcghuHvm+9S%bC@o#@oa->J*iERcrvf&3DJ1K9YlA`Q4s3rS9YB$fx$V6JNna zqzFW;{%Zkx5ASz!?x>KTus*lsk*=D!8%y2-Bn|M-UQMkr`BU7;f(l5?u^^F3OR%QR z+ayP=y;(w8xlZ=1^(OSvXPdXel;umM!BR+pDJK;{XN;5~9R@96(aXFCV^U~Sf_uX+ zGEdep_r$eZLFrnR6ewOs8goG*;9HUnu2byhaAY4G3EYV=QK$;OV_6;89|=cCSA$NvT>{dtaP_ul{+n)`~S#YG=&P3~IM7bec7 z=?EX2c@J=NUFZ=9Ic3hZeBg#e5&IfLMYObv#v@XGdkGAsDvWS3f}A=`1hR~$g)Rs7 zpY`EYvzO-h*O6k1ZoYN>T05=dK_Ru5KW{*<^$|0r^^>sCI?6@G3+flmF0plk;DzD} zJ|&)VQugm)Gt^xQn($dW&4PI>1>81pN3N&m$GWZce8|tg>Y(+t%6mC?+ zLOFExhX$D^8{(HFS;LD*YlgC|7%snjA5`h{wo(VH=9U_?bGTV`BGF^#CwJ0|n(`V| zLbu61G9mt4U0`g%TD3$8eTCg?lyW*Pb<sUx-u9KDGl(s(&2 z>Yi(1nBHvUE1jIhM)=acU@PgZp4CD4=m!Jg$7@8oQR-Tfg07&be`k!{a;om7ZOes3hFR254EZ7KO#1l@dj-axpk;7t|c!gscU#Oi>o+D!A5ygtE(L3 zv_sg@;+XC(rM za3fDrwZ)e)!6`iE5wppQ)(kA>mQ0WAueT-`D1|x@-W<)M-V_VhHhyV!F7=1=dc4bb zvAEJ6n8*~F+)S2!8SGLb@5ijnnYOkWEO{OUh$0D>Cfh2VGXq~efb6}>Nu+b>0 zJvnp6cR)ZVVP82XA7Lhnn~SJ&1FENdYT{=N&}DVmq$>DbJLZFsAyMkjN%Duc{r%UOK{=?`j~`sW(nvJaZe4s{IWXP-ohm(H^#n%Voe^BgmJ}(bSc>y zi(yJK|B}iwhI$tu$tP1kF2#p6nzAXkVCCyNL67|vT?B^Oi9=(BWi7PHF)RNf)@iZf zMmHUk6O7T10*9sx-fwHh|HidXWm%7&x;*9^zj|%j*AVFf#iMfX;PZ8Mn>8G#Cv=zQ z7ZUD1_pxJ`i{X0;-~ft{2|KE+nz7Bsu!XoSybVyYH3(J;a(ngQhau2HdiMmO3LQ(H zwEIp?*PbJh45-oZ@d|BJFU$GuKo#Z;$VfV>h6!>&Ox;cx0j=xL5zT&Lz53G|lg8TK ziRfpa2F^f4YqTmr*8xVtf~l`16xK{?m? zmK78na&)Mn(2g}K_qL5B1oO9wg76dXdJf$QC|tvO!Xyaq_F)kwX!BZ^8f3z;(bQO# zD_G(njY@dUcCJ^MVWd{;eRSq% z!oSD?za=s6gr8Bk-fbY)v0ft`t0xzi=Q!c-F7$o7j}Dj5Gx$hxlDpks#P!M<4h`L2 z;52AYQ64e?fvr@?61OCA-d_B8SQRwlX~OgUfuYJNGV9Nx{#J{^6#)fxY-{AA&uNKR z>v{8`y(QL`_%i{syn<$fE%-EJmoe4R{A_d>=R3>2lol&qR(@>wH02k-xV(sGl<~(i z{P?BOuSTA+y$0uppvgtIuAj4avWcYl{?{b=IH`hjLz2LGDScD& zdjz`kQC3Payn@-dwR`?c(A%*0?R@yy2qAT|oFkwv z%|6n|e&yOWrA(EMfl-NnjznAC1Y@$UuuQ@kPo=aw*l1yGZ7=<}FAMozXm5XYM*|K!HOe5P71{)no=MnJ%4cn9+u}O^VlsZsFhMxLvP~cU z4Xhb0#JsCjJp#OiN>PSXDP`6JIrG`c8-_Dpe05m$Z^dEN`WL8fgcAxou$y8};tsh; zvdB4aIMIMk&1&3OwRkh=a^zFqOhY*?Q|(8xjW&7le_M%CxNAqjA(678Y2VsKs*cb5 z0>70*aT!PtKlRu5NN+wm|Fo;~i?5=9cQY%frO}e5MK^)Vr+*x&|6+dpw+grG-Mz(vI!r%;C>zanZ3;+5rxtb1w2(nZ#cv3Jd6W&_n2fAarUoj-7sk` z&~FyIGgZw_*D=8=?uY?6{D(A{hVMB%J}oQ$V>2@TxB{3Wb%K%aR<7RJd1r_`xVi=L zmo0uJ!VGsqRsk72cZm1#WdG1-ui1+Av%mT1ipNz*IjT9lH{;>7DH}p)oriKWy4#()AJT8tR1X4t6H53@0{V0}JE;Vaqk@ZlRw{!Yh^6eDL zF+$?y!~+`BAtr;IYP|MQ98L}j8CrX(tm(SF3@_k(T!zU)b^FI$a<8Iy2q0ZzHaTy$ zJul1B#d%QTFp48`VrSBl^@YXxC~V0}%no!{xrLerK?=nbIsDIdQ;;9T8%6eqol?_l zmrr3~?*-&okf+JXBZ;RoF=`C6Pc)rKsD{m@DJ)-M(qSsNh@Nng^A`+@3f9Jt6a3=Q z?zhrl^6W&S_R5PcGxEu>J|2XK*_q2h8q05{PAHBpg)xG$QHLsGMf<`EBe9CVCN3Z- zoB1zA-Z#;Fy^jbZjYxE*#DZ$fRk0H5_p~dD?aMynX23<0aypZxzDLvF=`a~R^>{!v zh$A<5ng^Oe$20E32eZi&0sD(Qvv9@dTA2450wfi`+EJ_4iLNOZ8&xf?&B8xfl2LL- z!6h5&jDPwnXHi|o`iQ!K>2(8e^_&^j#c&U8BgU75Rwg}e zlt=0+!EeAvt(P3bdpGunoFyw^{-U=PHj$Xv5qbh|H5^w)E76mgKe-Ilx+j?4 znsa4MAsAk7dgNagX;F*YvdLfQZ|FERblNX#Rd5q{0)pa%J&#zWZJgby>Kx_jTIeb7 z&GAYE9RL9d1qBBW2L}c7mv`733V=q3!C-+!!z3XUQ6^&*Rxx(U@591Y4NR<`Wo8pK z3IP8Q+quFaZbyt}Xy6^pVWGZuC@q1$~r zwwthMwG5fytyFapVC~E2Ih1}A-(Bzlf%ZS*rQ@lR^KBQ@k2P3_pZuV8%imH=6Fi`S=|RYH^1e-7{nn9E(G^$I-sJJRcM zSm&ooU3`%KL}63GSRMWxH%&@hA|2nJgF^v^mdg zaCK0$qTC#Q*J{Ch6Y)wNYha}$_y!c7)LGl)$HxDpI+m znDDpv5=$R(;QWlom}E2_mXp7Gg;{2jLI%fmcWPeYSKqXqtv53c&AvBDp4#SiT5b$f z5T(l@+<9Y^!8<}YdW6b*f1Do@YYv|u0_AgOgdr1PQ>6)wZ9tf=AX+~2V_KOdmdtxk zI=w6DOW<@zi@E0BM@#fGydxfn0gQGAo1TFEh2gl)mZTe~VYH<{(!vf*qczOWm*$2Y zyvdy6<0ZDu(7Mu{AS}+J7l9ur65g@sXV~oOg=r-6LHQr?&vd+Id zW+OqJ`F$OQZkA!pDmak+`X=OpgL(8>nap@*fX?+5O{t%r^43{Kz)b*eR>H!};ah4{ z3VlgwVzgw>#TDZzrLO222jV&ur^XuDydS4{eVI(fblS})SJJvQQQ>Gs2{n0Vo&n2f z#6^ip>UVdrL#W%|5wNfV@eD1!IdaVjo<`b%ou9&{eOYJBn_9SBKh{Tyfwtg}VW4r7 z+-K@jbYKjm>S~#ehS5{i04ifZgMr2a%+$MD%Tmb|WRm+u!w**&suyEXWKcQEt!143 z=}x6Dj0zrvKLmaZYpx+jH>$RFs`|DJJm_0?F^-Mv3s?*4k(Lmty=L$qCeHsL+9X2g zau}LeCqcpM@C0^ks`Gf5F=%xNf=?q@`~)09(xGh{D7-Y%bLgl%zDpS2L5A|!MWWa~ z4gim=a_J6}ljGAPB4JA#m^ld!oq+(p$tf5&_*zL#D%F$ddRc3>@V9#Rh$97+ge$#R z3(6(#j^9vkT&Rf5T{TQxsML3Ia-IRv>&TW#`0NpFWZ$BL7~$K1l0fnFS*rX>%yhqC zZl_IrdCU3tnD3!M=#CPDLxaPyEQRvWAv}p)j;UU1EMTXbAb`mia$p zFoFU4Tb;lV==p1;f`U3C63Ine$Sff;I;e~uk9{rXynr=vn)eDj4=~mpbPyui7HWaa zYY%SfhG=``ozh~-D@JIJU)3Q>iF{Dhc>(#M6<0Oh=}K?Cvu-gz%9;v )9MdjZJn zv{!3<4@Wpa%zKZQR8{qME!v8O4_GAI2Sq13Gm6;P=cD06-Tra;WqX@>pr9aNVW6O( z|2X`wL{Se0SOghf=aM2(n@1AuH!^{R>af6Xg1%~W)3Y&-)Nf8aX=V)T;Uq;ilRRW|8$a7n z2)m^8Z&^UBj$y4DOkDiG0Y$5ar8>U>O_Q4WU!3Qy1@lx^HLJxZ=cT+14cT*V#Z*Y2 zqHM1}jafCrD$zAGL#yW8jC9QnV!|~bk#>{6CdGp*CC6u#hL{K#1XLm;z{snZ@8PSrDT8EucnKXMtCi9Xd^M~%7iAw||% zMG`K{IE-y-CV*kT7t+Ua&gWe4nKO8RO6Ggr(+^M$?Sbw^Qqj*9zxyNufK|(z7lrZ9 zl}plCuxswqyN)tNeg)cmY2VTZBM?AbErPincFlL}mcF)dY6hXdejCaCd#Fu#tEo|C z0PQfU8P%^rz&fVAmf@k|q7+{JWQDQq#vUJj|1+>W2q>R&cOhhrKjS<^SU))?5Q9RQ z8wHdtd=Xz+Hc0GAzF64V=o}GytX79vBIEcv`>pcGL=E;C!A11cO%!KzX5kvAN zVrpXov577G>QtUKf+Lj2D_fkSAdF}v&r8YC9`e_bA?uS=C~Zp?_* zZ^KLOX5d<<0`*eQv9WyW#gBWiYkrBu(Ofjm*GVi6IBLC9+)C_~kU)!oGQewGAv;}D z;D#tIv4?}{0|nMXub!j3`3F0l=mj>yXa0cFZ!~j57N(tNIqj3##hAD z72Lm%Quo;1)pXYz?}U=8i$I>zxD-!H);H`mWoMTpk=>t(tQG1bNNi9{`bEd48WSgY z0yf+i3aD?zf9p}_w&vrKUet@mDuZVgpNYIeMDSMdrEC4dD?_g^tT72JOV*$--#)r& z6wz9!I-hf%KaaO|?y=(X2t|O(ch0kNNqNrwz1pqPS0%OL&b!;7R#cYZN>Wwo$Gf*- z0)+NQK!t{aML|V{goJn#QvW5OlCogF4G?6k#!i7~BtT|14$-$UqJDNx*~rA%#Wfh5 zT-4CF`vVr6oLyKfC@H0&u(5wfP2Kd00!RFoQ_}3eHxIxHy=@+N-pq&`nPr^0Om*2M zP{MK_d1UlvrX)W^XP#XOPQ}h&ahfQS1TPqST+ie%%~q32i@t?}6w+Qd3GWvPg*{JU z;MfAcAP}aRBEby&IGXumMd*CmJC=MLqB%%^LQ7(yV4v@p+gvPiS@0ss?^GyCpj)h1 z`B9OOMxgA}96hG0AVNfzo9>3pp1t9urONZIosM~7!f3N=u0PbP+fUHYw_++yHCP1l zxE;hZ$r9ZO&h}U|q^I2V#>>YhcR3qBe%vh+02**%dpi|REacJVv&O1_O0GT zdPkJ0BWq%U7a4|Ss@{9)GmV63lQjomE(M-omPkv6*$-UCuhN}pdY@=W@5VV7Z%s2h z%v)7Rx5p5%)zX5xw0IPbl4RAkVu(PaWBD1@ab0sGHKQuJTwyWW<+~z&-9b8K7ZK@}jB1-sR07unEWHbVB8eqtX!q zv3w*|2h9bjti+5(aW<8qgfT1v12k6&vwi~%F3H=9J3{pt@?o26gZQvUhLm!J@KpYsfs_zu&sj!QLI8LGq( zL8ZZ$4Z5!X#K`sRE%y!LO#+><1RD9`-4;r4uQQ^^ipr|zifLDEA4DJ&h?I5ig%5qE z&G0HkFPy`y1mS?}7AM;pS~Ww0xC6M2m1v^qWJkZJ#&Z}mu~uHt0cE}Kau8vtT_HPhWfC2RvJJ+4CPr?pFLZmxIcNy$(HeVI4d)r&iPrqYuNBF03RAGSK53 z1cPKmCp;EH5wVhDc`DBq53yyr!I_D=PQ7n_;Hnt0b)FrjYHkQ$`{+{)@Z)-dyhz}g zNpcfJ50)8II#St>J%8eE_Bw4%PoHguTe;t%kahARYUT$7+m+&g6)7qAzk|mq?sHeKDF_EuT zb-&SMk;IsWvS6gH#2muCHn(T<9^8}}#Cf+wQCg~(=Jg7xVIZ3m9CLLyJ-A-_8vuUW zLb2PqzB-rTc4nc|4+gn*F+MT;xS}QCS59_G=l5eh%;nNCGE@m7*OpT_RlQP&Y{hr) z9tR6nh)tGPBkvLH#&#u?JPbm|EE49hck%>Pd2tNx?}7@n=je^~zM*_rHq?>zHa|RA zRYDlia0BL|?b*o1RvF07S;Mc-X@5p}MK|@C{G7*oUfVT)yFBaFLaF07tgx)S)*ppB z&VXT z{7Tj6=AS66$h~J*gQo!kTM(Uec=Og8Zskg`nI(Uff}z*Rc4{7oPP=B`&Le}qonOje z_l%upx|r&*baq?s8=Hd{SqRi6Y+krgTVh}Q%xA?$HrN=)I{93uF@ur0Ta545iwaKiqA`|V)l1-dh*ePXkc-Ll>E$`%=al;%UgyCS@<7bJKln+B)q>gO_)=$B$;2dP5n^W!?5 z6)CJQWj_{oWVj(^AUY`)QH8h#hJT>ccqa3j+bu3u4!^b9*SF;SE)^g?cT{b0U@+N4 zzpYYExo1Tc#IhXXaW7g+v7FGf>8Q`;(Ohk#L|o=R1)6sTpYxlq&vP^8LAh??8mPuq zT`!O+nha&iuUWIlVdg{mGHZ87dGVvg_hqrcbi2Jvuq?(l+v2UqJ}6niZ1^0iX)|Ai zLSxk$Bu%2_nP;uw+$)i9+11UyQSg(^J{N}zQr$iAQ*QPZ8w;CVaeJMW(^S=UFO;u! zei(@+m3FSeI*T;9z7wrzc3DBdS7ZIm%9+N4427S$sdi12P34UA@Zx7oT))QXWRvLU zj*G6g$A1XQ?>x{PVeEg+Qy4*Py)2BeDZ#yp^BbWmM1p6eQLKoReoDl!wmKZl(A8kw zV{+r5!Y?Y?RiKmS7`SJMdTfQUcViPT2f{E|%6ZD+;yqLF|^v_D(! z-;M7JvjEM@w~Wu6rBojPHWlO*$CAq2*dCTR^4aZ)MOhaQy2v= z>AFzR4b-oG6xc83kb1XX#)bxv*{KQ;B4M~=kcItmuDuCk{->IUuh8Or*jC%9 zY;r<-Q7FJu^fXQo0^{qK$KipPTFVkp0b{Lq{$A8=ni^udt3$tyhnf5|Pmk9!svvh& zzv}UK?Dwn5=1AXzoQ{>ofpuM*yKv5qLjKyjSGYAGeVU3Ov~2Zav&5#MEHb9nk8r93 zra;krFHi}_x)n-Gpc{>J9@G-;hLe?D6VkYDEP%ko!h5tuHMD$)))=9%|BB}jz8sO? zyDrf9i`#H+x)@`lcX>s*6y{ec>gi}V9uG-EJ49NInS>J6ti|1GuL4zFReuAki#fuM zfk0OXTHJa1!N2=dqafx}Mf||D*YpebXA5f+1I3T>?~DAbByQ&c2vf;g!+RkdANBo@ z#S7(R>)bSibjv5T|LQWs6f(23Ym}E9TUsBW#3ikg6Xu>?BE%`d4>Xi#Gc%7 zX0Yd1GbU@WZ|^AhCU#U2ILJ5nnX~5yievc9i3JfoCugC4}E&FqueV<7S>R zM-C}Y@=?Pkmn#)Y7JW=tRA1I^u3B|0N1|^d&`W}Yss4&lWI)wb!=u`1VlmUmP-3wn ztri;!9g-aXoK`-aMy@n5)l;7HRatp2ta96+jLJYC3DNujWS-2tyC^#Y_kVErmT_%$ z+qyVKinKs+iWLp+t}PCMAi+woLW=~76STC2BE^flCxM^^f=gT6C0Oy|Qe0Z3@ZRiq zpL5SX=f6MQ-~Y?KU)D^r=CU!@9GT-8;~67GS7^d`0ie!)k^!vdcBnY%6l^t?EVl0! zD7CKaTn~BXx$%ZV=7$Ozn!?ME#7RYd=zhaYJhRm4IpZ`KH4Uj$XrsCT2sm_3!nI)P zG~IY!k=<`7UNrsV?}nV0U%Qk8wN7=^H0WUAY}JEGef62rukGa0I&BdXIBN|yb<_AVH{oEA)?$(52LI&Y*uF|d9BdNteY1TA;!*a{^!L{p&?n1 zs>rS!eXYTHu93mj*QiC8D2AW4ESZ_!`ZB+XgV^_a)J*Ckne0dvM7uO2q{j*sPL$#P zHxxNsLXDRlqxT!-5dmvoy+04?RFW7XoKh+%gI_8NoVwSZK5zj+4Ln3GdD!@#xFntZam;m%pMX=~LjO|F#X)3L zl@fzGa&ppdKQqloOE61Gdgpl+^`Wf_BoH(cl-e3VqA;cOJZmZ5Z6LEjhis|LAccie zGe4Q9GS^9L{Z;P%I1evF4NY}4S0(XP!xoDJT&E$rfZwpqd*M@G5~WRB_ri;aEyl4= z2Q+;n&kt5c-Yx@URb5`~4lHg#ffVl@VN#?8n{-41sZN8VHE1=dFmlT9-~nTVhb@Knn5}Gx2~hO0v(iX%VyV+azWz zvBTr4fhhM+qpw?bep$2c!J+ty55RGM7ybEX@0INjAaG!XalV=7&Fq)QI)`JIRm?2G zcL724HJr#wwZa?4de%w-Ym!PH@yGa>mNhTEy96JxhH6ZsJBg_vCxlFA_;3g%C?(9k zQw5`+Iq6IkImlE>O9EM>1>cWa`*PQI9HZ>}A=zEhie4vBVvR_$dsd0Zq;2suS|?t< zd1|KqgVlv^`71s1gQm0`p9f{8CL|=+1we&0%M6QXSmy`hSpgA-_b2C8>7-JviahEw zmg*Ak$5RPhN908Y8FQ1oZh&7ubSfX|KY3mg+42`oq-I%dq+*K;4drVxjc!9$&ezNU zneP5#(0QPC zE*?s3{r1bB zwh_GH5h>EyPeYCK!3t{r@zq2T+plsuFrQhEKLt(pO@8NaUc@FNK~qTd`#fy;Shdaf zYe*zT>QfjuPRfSdNS^=fog#-fw*KR~i-!arD;0#QA};Z&vhW5S=h_0wLD>qSA@Dym(_hCzF*~w4Uff$J6 zEZ)p;ZQI9f**t^zHzm*y&2$Qv!1QFJxsu9kSEx#Ze_@<`m9K`$USwx;0Cf)5h=E6=g_AikzXJ-SHI_Qlk%gJi>W*X;ajJ)N5sV0#r|Ou?St8P2vA+ ziN&SrTosqtki!44tl8XT-MJdZg?XLR3h>;?Xarf;ll%FbFz05*N9>+)7wd{*l+DpO z34yYF0f9jbz-_yG3m2o;yZRd^cQG6XsTV#`X=wVThls#u*_$$Jl3p1Hju%Vk#r65K zewg@4>@9F`w2@dLr^UX;|KYsSCYEe#TCo#~=tXy0<>L@wYlc6E3bDuZ7 z{H;z>bFK;4zqY#fq6+nxhHJ>=Wr~PYp5lj`lXmBMBOytF`l$|$+w}_W7t@vz#^0yl z#oBgOg)kz$s@jzw=WTTZ+B}d{Rr64PUacAaKV8vOiV7*s&J|t}_rLX_&&ZVW27d#- zv{colIB{~Hp zsW)M>{SrKFA~ed;w5GhU-^Qeku8f%CoRW)e2kLb6?=woBIz%j}Sh(Wu86-ZtKZ>3l zvafF&@p0po1oP*TRn@%;%C=cD)Bo%mOQ;hsYP>l)_~cLIz^ub76F;rOfYkD4k5^t> z3Tj;qx`&BKWEvw8Sl{R^ddS2}##z5ovS|&o;6#^F&wwMwvg><-rI%nW zs-IGAbx>DSvgdJ*T$NvQ&s$+8Y$7LM3FICX&kW7V+nKk5)@ZBjY?y!!T3FC|`bo^I zM{BQ^o|6Ir>FFRBCB@JjlMm7|7MbXgXJ8pp@|RYQ?$W|L4f@UXx6?ia>V)PT$n@Xu zPDEebOjKhHxbCoVL)%qVpYgaCm$qI;eHw$a%}D;x;Fyd_Qkdd^5}HO-;o9PBinP^D zjyA*DBd)CWV#6}7(D~6yIPZ@I0G558_|Ux?5`jS2Ye{ zY7W^(! z#ntS4wkc2GafW#~)QEPLupH2y5KCMv>H4<5DUumLOSz0AIOx8(ZaABH%RcN=s9ZY< zeSpM|q%mA)VM!rtNX87^G+hG(@&hH$39SRoH&*O7XlJr81wUS1M3~p#U4;Ady)jGf zq4G`EtA!U?wqT|z*G8n<>LreQP^}KXjcc9i5UU91BVTU3NG{3iA<87%=4{>Zl*my-&-g(NDl!Ox|U>!V!lHA9_A}Vm|%XOJ9w7M|eB&*7RC=mRv{R>FKS8z?|Qt z=PyLI%4Cf)d%ORj-WUS)9yc17y2Wc;<-kSGHZy(WUReg%m^OBbc#ZLhjK1p^;}E7= z_xtPSsPS#(et3x@a4l@)0b-z!y4G#{J?VJX&;I=RiJJ>@UiHZ zpPNr~Id?3_+C{%FUPj0>=0ECt>Agn3@AgKOId1IZ%Np5}hrZlOZ1LUO-J;)fuwAII zUF@)36t%It|8cl4of2<+=XQ_icgss8=OZ*PT}oXCBk%UlBYomX1h*wIf$EzNx_m|h z5q5YOA#o|V?9`Bu(;_2H9PjW;O+}vbvNEtlRDp?j;p_;dm*07IZi?jFly)C*M=kAo zjE-x8HF(MiXMv=yB9{XkT^exlqD13cjgojzrBqy_P&&)=J+K?H5YM@HSeznT&owuKyIWOGXDSV{`NnLuQandX zgyI=nh4Wdy^#MB_OOnzBP2vr{ewX=`XWRFaEhyg0+HL#6vmL8tNZ>awU)WF_Hx3~& zwltf^znK(^rh7Tw1j8tau68_woBfgslYdba-=1X}pS^!?#FKqpZn5};iGqt;7?2cg z@~Y*tZ){|=FlhLTOiLCR6i-) zWY7)s1e<~y?@2!!08A8quu=~K?#gC<6ZR2MQV!4k2>GID@?zG+<3#;xAbpz#TtHhE zHY-PJInhzXURKs@7j=&#TByQUeZzg>RE0~BnR7EM#p;B6m+8p+UH=e=mkls46=b4F}Vf(c_@l+duDv^A2j z1G4uh*ZOnH`OwHvZ5~y8*`B5XFXd0K34d$q7w&vgrF-(~w(MijR#6V|59P84)JRCZ zBi%N@CdWjZZrUJgTlv#g+zC;v-*&tts|J6YFF-D(E@oZCr}F+}IZKp<{Ip+7Ebjof zkGe6LM2&F;sakNrI-Osw_cU@7vZv1ww6DNY$v0B7sGXy|H%U!G8bpCUm>WtGbg}LG zhjI@=_-cn>7XnX+`ve}cHH@b%JZnkeG`LqcgPWHb(Cll}={aqswH?lG2g* zsWHv0=~O|%8S#2+kEj46ED$B*Umz=Ta~2=sdsEKO`Wh8FAJ<8sYbTs1gDRq;wy&4% zW893;=rkhy4Rw5&=HvF`%FLyy6nKzy>hh@>upx{1+-j$cD zYZoEB{Em0J=@f8r^?PRZmNe8|c%!mi$=*UEG6ds|IeZdxu_izq&zFy_l?FvRpKR&vGt6Mx}YolL z2R341evsPk{qTkYF{1&J2=R7hMug61}H@6!jr<+V5NIbGUo{Z9G8D z7Mo{P%#$fGj&6wYJjH*l)WD2eS)G@-J;&pSIjUD^=RKpIheb+SAoQy+wOD8!s7dXE zw_ohM{Q|kQ$@<%!D!G%3!~Nl*!Zb!2@HB}o;?vKAJ#cPIH4fnr9XFgMxf=)0uML84 zu2pau=@$O%-}44BU(#cuXGE*|G6vWAWU~K>MVM(LO8;!O_)6lKl2?m#B?s748~tE|s1C$Bk3Q*(Y!>%US;E zk_F39HXFCe8T*Q{;R((w4!Y?%68a=>=1cQ<@yl95$0d0KC|MvJ!1ufI$@9kt%{*|i#Hi97kWco9H_&&`_Oq{Fvnl4;TcJ9@?x47*X)Y|--V@@n{kX5VcHg4oLy zKA6WG<>G${Xprz47_u&14s9(H<@X9zSYOdQ2gJiCx5V^|n{+0TEv^bly2|Womy%?fpD?jj{tDaU)d`1} zdL8k+)O4Dw5-Z3(%`|bYc7`gC(Y@Nvf^|AE%1`I;f0H@4Ovh^VL<56SZPU(bNm~XT zHm%n=#_4;|p7!vk0K|ic80au987QrOE)bKFe7Qd3! z_(QDNDcDDBr_gj#YmmhF6FhJ8`A7bg-HG)i)Au$@JFcd%aec}rUMeqS zW!#@!CZ{W4%RSuJe#G})pNSIZk%EXm5c917%4fdbnQv1H2D@>McWG(0Y!jH5rd);x zCs32B0QP@_ftd(n7^Mhr)GlG>l5TP^vEHxpucp6-+M3B^DkfXwm2Jv#_sFb9od=t~ z3c*K&T{8XI*R^zTT2Yx{-Xn>XA^0`i3Dk&4FcB*l@v8m*%ipjJ#nZhU+ zu15Nt41E*RhIlh0^vV8uzr09TyLjJ6eNI6LUrn%9(FqBjB@pl&M%-GN5=4{b|FK%S z{F?5_s`3Ze^FDLBci4y3(9(?^%S?NrLdF-=LoYv98a%?_IWZ4vYShGEOnmbaYS*w} zo_4X;Y8m9MhYWi?W5zGe`L>JPD#>_g(~|Z`@A~jno}~h_`-$`>L$K5~X6HKh4=UHY zOPE$su=16{REs@AqLF$YbO!sHXz72wxUo3`*tU0DtQ5AQfkWhLP`0zWK+Ys85W_Y? z!jnC3d}(J$N>!ZloXb}FeRGH8_VR4Pxg)ouWfR5&$0IFhqK|ZRKsFfhLV1<-cS!(ZB^J!&~|7-4WQICHQHfwfAj3M}^SK%&nhvZpWwp4oGkU$pHP z(7*-60sP6Wrh?ZuQ7cD!MLtI6iI@=dWUM1j@%t~-d?YO-*58q%shjYLXD{r)Zd(a@ z7^`N;QfZ}}d5n-VNI61XchC~0sCP^UZG5;2suHr(ZctxG1QZaJl6s9z^06Jw-7@=<;PiALBG8;Or_X3?O~6AJ!( z|LXZ0udnpW$}mPRr>$9NbqLE)^CwW>H+JBxezh@(qwZ@=rT2#2VPgC+j&!*s@W8o1 zd^^JUPX)%tfXlT`JU8v<<$lxi{GPp%|Y7cvE}N?|mz%$&pkiWdyiOy2QV$r4pcJ zEH5p!_dMOn8Zuq>R1*EvH$hJ@s+k7mdZ?LH03Sy{k1Y*4+~ znh{id;fg%h{W{Q0ExOUK%1Vmu9Ft=R7igKWw9fZWN=>j9F0#ot;YX=Lny|Og7KhB;*NmC@-$(P?wz2mO}YMquS#_^8QB?-hET$(mqC(J zsa_=`bQ=fM9U9sJ()y9~mKA?cu4~zq9bO8s{>}r|AA!yRbU3o2}B@c@m-i`ZBgg~wntZf29Ic>ja^bLMkf z(>>~q;rBBb>ArW~Tt=2+Ka-==joz25H4LWYX!RaI(~}-Fyjk$(Wn#^v4A6MVLE7k~ z#}&y$mlRWGh+M=chPr6iD^!tK0<+u8LXT+_3;}ZxtVe}}s0t^wtfX7vQNuJ8jsomr zAp-?AnJy!*c*K>T`i7v~UpShz3sdO!wPqa8b8I|8pv%%;;61Cof{(Z|qZ9-9=XK>% z7;yEr*7e#bKRC^)#)RPqZGoIw#cw7fP>W%J_Grla>N0_gxt(!wk#O8;U=2tVrPS}w zHkbAxCO^H|JiD*V6 zS+VuABpPwbY+{oSpwu%W)(U%yg!K6;xwg$Pc@MsWbpz3ohR6dbz=-pPOL}~~hzUPz zvphTgVfSQN@F``|TAf5j!3j}neoo4gk?<~`rFj7jPXS(XT8(qFz1(@l@L7}!t%-lE zKkuB{N}rNKA#Hu3(BgWvAcV8ILj}y2W0dM*)lvv*2y2)JY$g4}rqUFNLh+VNg*8j< zkzfeiq#@+EP#Xd5QS;$Lx5^@jFt1q|9~n1^l@k3Q>bj)uzi=EDyW*C9;jqrGe@*fQ zWln$cNhX&PF3s5q%Hs?0Oz0$r3If7s99UY`%6%&_A7Y5IE%z432N(B1t8eRv_m?lv zqBJX}n)wCxgd0>-Th{a>W|#BcCJrgy3e@R0z)?oVDnv;3V^ezN#LobhY|WQs<)p^e z91`0Jcl|^R+M#mrZ}exL>XdTopKqYB)M#E3dU~DxW#8UR6Oy2=x-`l)(hVMCifV+L zo~})P#y3_!5thJ&dHxcDFUDe>S0A)K@lo5z%&u05#oQw+0}8DecDV#m7Gi_DGq@2z0*NtC5~S=L z0SfM=F~P12O;sm(Eyy2rPT`i8MK?ej;AH%LX)JY%o*=1R^-XTM`?wvYwhtdinKbH* za`~Y%P3vd#jK>5GW`FFXiWpj9Bvy}%jr=Q4IZrmAIb2?tDn+UF0jRi8oBP9Qh=(3- zrsm4sFkm7-Gl17Wmy)ZW8t0R{G4so#GUtH@Mk5ui0wA~OBDm1eetsO)OgQ|=(ABmt zTU*jz@K!#uDOeArDDHfJ3OPP9CH?l0 zxK9DLIzl^S?>qrV7exOc{$jMoLO!ui5X7xH9)99O-C=uAQ7lJsZbxQ$f|z7u#}mNY zh^%LRTIq>2I;p0w3mu0u2u!GC(3Hlfx-CvD1ADzCEmK_rJ)(@t3Qim0GBcbUGPE>)1I^C-% zdA60epev?`_AA~Ex4(U}FSUx2GBd+lqMhkESbXwAa&=oAz{nw;*JX$FOyoR|mQw9? z6w+8YwBgT$WXg`fI8`m4w_da_({clB<29)?TnP4sf=g^b1${VSv|J@XtGnvU$tBBlPtC zfkw95enqxZu(?n)Q0O#zcHOH}cR059sJTPcc!I`jroh{_?@2h>Q$VJ}T)K}0+BA%I zx_zC4JXVB4QH*LjCvyU2GR(!A0Jj@()cDa9NeAcfck#pVjp-1@$UAcZtONRR=wyUS zw+;KLVH$^!z_u~Ms3%7wI6jk<`lRb9M9^eu_fo3(htnAL9FxAj&0X5Pkw+o^8QF~h zbV&Y%nSsH>Zsb^zz=Y zoqD#?`A}?9`=mN2C)1>A-m^2$j6W z_Azi=n?nm76T&;&IecQ@M+s^Oms#67fJb}!Uv>=&8q9Wofyx%5C zef2hBKN&IbZ*gH5fO2`0Gmj%NeA+VHgLYu>UGg&wFZ)?bvhB(x~|K`$8;VpE;i)-usm!5)s{R$>|maT4bLNJNQQA_7hnq}rCMZxM4!LLMFjDA zG(XfHek+u&QwtlnR3DEEc!)I-yOIS4hU&yN-P;zP37T|IeRXp)&qRJ}dvuE1nYjYMJX=+AR{$HnrE%r(zMJcu2O~_R+dkofZAoj!`&sl{X^k6gvr(AwJf2U$jA$# zM$2%t$b|t`d}n!F9f_r!Q{YsfrVO`{tYGhlN~9xfC>50DwG`;{AlQ}t-i*uYGwIpF(*6lvBOUoT@(TYJMCJDK{P65rT^YDfkGVohjr$~#pbmK zf?BwRORZX*Meb*Ixj`tQ!M#0GRi{bNIy^G8K*M3HPLGbEDI=+~Y$2@*98<1%|CE8x z^n9kCq!O0@@U4KG6;I+snh$SRp!Z)mi^S%{K0`I&@?wTuc+UDsYZBB7TYrl$rT8QD z{R8N@YpaHdIPvRc4K7aak4ELS3&2zq0)@V$d=|pbCY0&RXX5kH2%VhsR(5gaPx_zP z>E)$C^iaWqZ)}+Z1VP;2|q=7L}yTv-_-sM8f)g4Zh=J{PJiALRy(v3HigEto0h zaRwX0YlOyI!nlofA!3+$*@2jOGvU(ZHfImO|9nJT2gr!4Fn4GPb&1f=(l!t|)Bjg0 z=PZA$1e?#NzI*|f11H6M-)Z_?c+fKYaTI%)MY00&!ZZpF?QMe#$;>#mKQZL)N<6u&rubn7zK&U?!{z&mqMNOK30+chc){NcZQF?U? zQQJIb%@;nUV)7RbV~CB}ETuTjejNO=1tc*QZM-`I<-$M3;J0NH+ZHaC6tni$x0(HT z;wJX*jhR73&-9CHt(~k*y z@`8nb)B-){T*=q4X&Hu`-chjR{JVoJ-1q`|XM|8B=zI9DSG!#2A0qw%LB#PHLmTmk z@>4v)wXYeJew7gZc>_CftV1T|g4Vbec?^iFNwW9$eoX!<0(&r^wCUO#n(*zhV9RNh z1O_8}UJ&=w^nr=YY%d3YnVV>sGQT<>DCqm2z46;M zMWX-H#vm;(2YR^awgl0XButa{JF{tIZoR5rh+q0Md(h{0=kja4@tx$2=fan)+orz* z1$~dUzPSBg*s&8p=i(NbYt{Sxp;gsnSAVb_pS!4|L}1-baJ2uQJd*R|Nf3Uzxvd+g zFkjd#eWuwR#J^=gRi#?Wy})%X3i=qOX^~}TPlmE^yY*zhOtowa%e#43v3)_7PVxLl zAHEMjVvg5w-9I?Sc_(z9W5soJ2bqArqqdlAfuaa!-F0>%h zhU@aU0}Or}*@$#LrClKO9+hq`g!+*i;;tnj|AD z(nkEm*wX#YT9X^oG#T$1jQ_RMz^~%l-o#B#5?do`(zYM-iQBPO7KDG{@F`4iu(4Ol zhYzNfu#w;s7#n=3qLXx(-c|S2ewnb6MoEd~RLa(#l)V2L>sL~Qit76Sosvg*-Xn)p zm8i1zUZgeauh7>qHG9Q5VNHMO`jf!V4T~z4u6BE$3Jo;+|C_-e`L|HQgKFD8oU7j$ z(e{1)3n#zSw6UG}`aYKQRlE_cEB)oMOb#`Bnrl_TGIEiVyh2^tg*$#vksdx$Q>^_L z&d0|I*A68?N_wMMA}6^8|Yro zm+A;vwM?p-t^C}rWq!N@rS}o8&y>}|>SjXl-N(Sn)YF!4 z3=9B9>~lESSevbuncolk=(uydFv*a;cCqMO{d&&J_z{y3Nj4GeD{SO%tNQsvI!fyA zkyN6w5`F?9*{xi8z4E_r*?RKl?lDD&5)oD*_;Y+R_nd|B9ixYUo?o!T_Q=2C02mN6>pSetR@?a9$z zcwQb;@JqD)wHdURBzsx7+m;GkHlY+tqE7%l(wiVk^>MS%+tdl}%61EYZX$xU>f3jY z#zlgsZOpXf=389+78>u~7DAp9-gbAVqj$?HS_0|Uc1zm7y;JKR>zF>Lm?h57bFeZd znMgKCgcx($*=p5s=46^)LT#iex}Oav#N4kNOmQoS*p$l^S?E0JCF+94mv+4By})hN zHR-`W&Dc-f2!)%bA{9vlyqFW?ub9u>EIi$G#oxO*kyJ7?E@-rD4-t9RBYJ0qxuBBx zt``h5zl*;->%5(_R>tsL4Ei)|H~h;OLNCtiWno$Ba^_>6Hvb&Q_}ctls>&ghIR}lf zwX}xB*L4#0Ou)uqV;AtMDW3iQt2fUjbB&8(_|m*nyAjKD@zTY4az$6kj8h?fOnkXf z@$jDe(><0MEmG{#vpGury%*?sx5U?#(saw^mNYdd9Ho4JP*&UaX5Vaz{4XOsN;c9e zS6do#zB$bq_U-+Lq6=QUqPo7f>zdrC{x1T(z6L&HcH(!}kvs&Rs{Jj{$zk)_BwjDu zf~>aF#(D__iabK6_jL*zMVbUCNm`5oeNKJGHwi{v_gQN;#;JRKWI=D=w}I{#{^RqE z{461XVZpn=<2$Eng3)V+3|r^)45ww)s0f503~B0vcLgj>%Rw%mUw&RMDNPG&} zd&ovS4+OFOxZzK=&N+Ibt^A{esW@yUtdIB$aXi&qD(XGQoU7uCcl7^l^OkBWVfs=( z>#5nQlGCkCSl`|sz*Cb|(d%mBglT_W)5=R-kL=@&Rq0jHPWMjRwWU6$Cbt59@mg*G zV8OCw%lK28C5Rf=B_Z}w=3i$ZoZHc2W7na5z*;Nw_k2gF91KEfM4X;$aIah5A|Cvn z;kQh%0b^d8m&xcxPHKN)$SBWFbuBh%BtEpgQH!5R;__vff})g+fQLz~1eN@(BtN(a zOBb=$xc$P(4xYeZbFZpT;fKIo?4{z26^sWz0XUJ2nXi6p$-4Z5O+7PReEe=vSKEt! zmnAv9G7&R!lk_L?@AW7wTwLTIc#YKGNRQC>u|sui!QnTl(&bzZk_TJw7x(LuViYL- z`8H&kx(z38RERn61zEZ)TiU9fYW}35nZQbfFhc%GtOn8ZUp3J)ifH#xGsa`X^|-ap zW;r@j{)=bI=2ns!Wm8l`GncP%)^n37M=>448PzD0Rblm|{?B@uZA+f#Yx;JTj;8eP z)!WDF&P(YG*hW|g37O1i;lq=_6~3?Dh*0JX!_>__YFyy>5bDHeZ*|IL4F-5dhb^zG z8ERa9Fa5#ytN-gxUrmTG&vKUSvrnlqDa#vep6|=S<60nna0*Rn$(xFrwXkMxK<+pW zW8q|Q0Jv!rl7rgQ$*%Hj7khf+JF@Kp4DmBldbF80T#HzkNNxBzic>;_{B;y*U2P12 z+fRkH9n8~_QiXlsGHPk)u~Gz4gOf<9YYg8@NGP(PhQmfp8%U1i6@80U0*f{2K7%2X<}U!M(=j-r#& zpaX#1D9x=*0(o5`AYE+z#?S#`W|9$nj~|(MPo2}u#I00?$rbt!@;(Hl%oyyjYXzE8 zqBL;HX!aX?$fi3OmB#y}#czF#wzwPy5&OIbZaWzUKdG0%g_zIsq|D0g$4s@CNl&Yp za8mS)m*^P1kCvXMS&O66wkUgA?)1!Pvsvv%+{7PW^732JdF5gMGVo?U5|Cx!K{2&k z2?^5y?tZeyEu(8Kj*7BqNh%2N0bcM@g1NN@>6#I{(ZR_XW~4CYeu`ILgs9>D_jnMN zWidX>sr(-kNY0h=w}~O3<_lrV z`Xf{^r-Mcyez4E`^FbB+IXVmbwxT^o(sBmR42x1%KSl{i)sH;?GL_FW8O5Q;^Q>vq z!YAK=;j>1ay4H}Yk9#oN_#5*W)LzW{NiB;ZS*Z|4l%Vve$~AE&$N2oQdI9jmI)u6}!4|3w>FD%5))=mV9pFau#lJS|_1g;hc6u z(x29%z41y9l#62A=wLdWx5FeJ&xZBFNm5oOW$ttmhc=r~v*5-J|Z72R9XW`COcjwTdTWpq(AS(UnGB6Q2>CR9-E4l5(t85to8-a!0Ul5gA@LtI0b;NZ$(9FLY^z zJnJw_&l8r*s$c9_A-q*#!Yk({cV!6JTsB3nYkcR`{>mkrp)(UAR`C~3uZ-geegg)g zr%b#m(CK(!f$;49;5eCk#28#E3#r> z_u1Jn&Vn3hD?0Q&1L^V580E~(A+7y_@2_k&wY=VtI?^|qY-u;=%lv@U4o zahrVoU=o}#W9S3Scfu9#Jk`_0jM4ipqEj5`-uas?@w-b^U(h8GozsbOh_p&hufY-0 zi9e?CU<(f{tkyvWd0w_+Ng$^z`jgTFMe<&+qWwR4cc6elPxWad-ql+3%@7LH6N|#QG54OUw0bMjpGG33* z@>uO0rak#u`6OIlIGI+QtTD9bm)B7mv7ZSS6k1xojCI6XhcG#5OXKXRHn1rvrRIUH z5lZu%QL5iL8s;)dp=!8T%mVXghZr*5H`22X0e=K)aON5Y>Wu|@Szjz+D%YJAG%`Bp zCLWukW9HeNiPjVunA9LMdLYxAmoa7^FI(ts$1`{(EOK?R5P4a5wsCQM9N(4xb+ixl zdNh$MZW*{17Z>q*7Rfc`lo=VAMR(xQOPj(vG$O@^G6GzE0q2ts zd0f%~UkvAKHihLDYg!DJebFuRJJ#+aY}g>x$Z8_RviNt`f^ZZtjxZ_2OS zVz>lSKhHnvSuPcqR>zn04rQ>q0|x9))H*U4x=y9W>`HL3D{5q;ndy=``TaU%?~OXK zEtop|M5P04r+GQv?3L?EzBG9|R(>YN*9tdi8=PKj5|j02VYhP_^aQp_NW|GW(dHbl zGu%e*kSGmsT;tNpk?FL(U)KZdCBZ&Ejah;2dU;^7%O0&CRSN6N2qoo_-2aBrDtLIL<;RE{ZQ;sZ0_mU zt*DV&%Lw*yC6!0B9*sOBv?rX53NVS*tuFg=Fj{f(LS*jeJ@M1@?8!u_`NJRSE*)bE zek=8qXSKc9*Go{rQZv?mc0Wk3SltKbeo)WUEgLcGG~euupo^JQxo2I^rxS7}Sz$+s zR7(k=>b*F&Om!)0?h(>KeTfvoQM`}+ox4%)W#rX8SbVuG)J-_$MPN^&eWjYDF`K%n@*g)y zC$se0)yu#@4@+V_s9xPzidesv7i`hZ)fj5y;=cvRDrT5Xk~VJKD0QJVZg-4kuB)Uy z)R)c;s;OeBMbc#Qd-KxnfCp^vfc5^cW%ow0tKv5@)Goocci0H$2LpR z;2bFmqN$fVPbnQ*fY(s6qe{-(S|^@s_3CfMbHGKR;*wHX<1t5Iw(C!%GbJJtDRcmTezawZGfNd_CBu9x~2ClM&l1jy0UA90VDs zb6fWCnt4(Y3>yh#u?Ao1@@uIt|9)+)o6>&JNT|}6oWXX>Ts)}xSAiy;b%)1^Em6`| zgT+U+TpRhhp3VV9Kc3G&6ty3mkMY!NgcCgHbPN|gvZeY3@7;lQ;A$AE(pjlPlOl;l zwWZbeOK)|un%gG4eATb)f3_xk#7K_{DpY3dIR&im8*P6OxAFW@1tj-QbvE#Eb!MgjpNV zGpU4l_pRS>5u;K99C7Zk$Iu{Yh$W8#FaBwZobvpIBf4X#O~Uxl%&X4En?j9~(~~T1 z6n&U9NZK=Lwv2pAh)k5532(608LTD@3J+M_-3_b)o42B@#5?oNcSR}GN#Y{udrcCS zh|0JYw14s7igW^GqThask*RbxFX}ONc@KHdLT>oPwd5dvI5m;z~pL zWK{v?y$-YH#A(BLtiyH9leNbWM@yy&FzH4R&e>Gev|RfefPFad^Fp+vub{up{fs!3 z`rcNt>4}uJ9Q|=it(&BGYPlOvwA6Et^B2u*4o31%;Q{N7Qtt*6x8oP*u*jZf-hXhK zNt>N(5fnkCp*zQL`oF^tU;Z5-8ISFyyrO}doe}71g6K78jaR(jII~dw?R38WZ=1i# z$@BWT!5$tSR zJbzRP4X`f4J`>by{>+uQ(&;|ljJRn<{YesH#4rQByDvmbVXaS}{bTwu*>(c}2Di$ly>jzQf9-7G& zFE~V*c!o7ND)eq_D*h=R&41%WdFI)@plv`G7{l-6Pl^BU+#W{a^0l_99@)OZeA-)I z2=v^{B~8;=eBmcY$_b;`#o)5=`2TFfqB3`-G7rk2) zt5E?K+PC7n1CMu%P&Bjp7oT=?f)1W4d$Ju8T`NjapwFlE2ut#Q%hYvH-9%q(i`tnF z8oe$^+sf;&`1x#Yp)pw;Ixm0_uZl04kGM+txxw8ts;Tk6M|@%zO3iF{Jci8s%|Ue! zn{_#=9v|0>&cI`vdp3XF>g)317dXZk^E=p&@60hlTkr^dOVAzJ#4&(5xhRsulFR=S z5RGr?9?84g4lv?lzP@xjyHyB2Siq0rv|%IVYWS#{#hju}pFhe6%05M_Jz)S~GBMb}#Zwb^xR z!@=FXcnI$9?(P&VZpGbQgS)#!(L!-|hav@vyHm7Cf&O`(bKY~lZ|46pnaLzGxwCWc zz1LprTGzUk-QEd1r*&V)me!;JLpxr?GO2$k(^_^{SMi!Vvn8!S+$|Y;o8>!8_Qs0? z^V^=bzEOpF+{;MD<4*`#S#ksG;FMorRhS79`>;;ni2V6DFRReO?}=wK-D-2VyeYvG zyShJv#>;EPpkpKx>%(f?F{apL*?jz0slLGQ9kx#HkvfximhYQ>(w$t(JN)_Uy<_%*v`<|g+umJ4%5G}7JNe1Ljm@N) z+V#WFh~6<26x}38g@U=|?)%@ACpp4rg2YSW@P-+{LvVq(3f*`K|8OH_RR2jSC zGFn-sh=BC=2#cfL{etb|qvvLYzxHut9nGeKCH_{%%Mx#x(Pi4o1Qfo1X-14+rB)rb zPa~~kF}fnlv`YlM&c3bf48tZpUOU|Pc*dQ`vcCWVN5w=0r_+WrU>;U0Q!c`dXUg4A z=I<4iXwz4lzYTn`dtV_(g}gkkCH?)>RO^pq)s1Q-z^?mw1UxG{&nn!67v~|dwDX+~ zS&~vL>m(aaU=5`mL?7yG`ZK?T)J)30(xam7pEHsrGF?Z<&z1tb5qfA&vF#uIj;F9t z&{ii6JhrMexj?Q)QGJNimKsy1lmY||^ukHBLX08H4^q7uGmEoMEh_}2_U1iZgS3bq zNR}F@4k%NWitr^Jm5w#L^;is%Uhcai4%A-m=5h1;BkwhfIG(;`xz6EHVY}j>g0mtu zml5#w_AWB^55no0e3x?pwHTW9e+}>X{yyjshtG1-(>c9C*1ERy7#q% zM@n>zo)6^PD>poN?;|f20xF1PckQPbAO!;xF39CJ5=KCpI=#r;fCJ$Y8@`y6Q|V76 z-U$jW!#!0)NM;UhA81j`LM9^^${ecZ5=5cjj^ELwi(J1-_XcUU*0x8-GAHfka3S`8NxGSI(C&`yZSpHx!3c|N!!3t7Q_U>AdJ)~w z8Tc|!aGxt`g4$cku0ASE8uc00=V(5^sx|Ws7G`8PDJnQ2pRq)E&+wHfSSeQ=CUZr= zaV)Tu;VzQ-4GoMf2wS)BvRVxZ-7@8Ezxud-^0+#g(ux4q99hQxJ zzi(_%_1G6Ng-puc5vH|}W~lBHg_JMU$I!{wt#>h`?k5hy|0{`MN)OQk_+YV%I{hzc zF*WqhObhg~R&7q!*CV~uOe@O?o`!$vf^syK#f-m(A%;Gb7q&B%n`tpIq7|>4tEac# zyTB&NN?a>FM<3dNfwsEcF|9yS-#W$Am6fbyZ=I1?LJyg$AT4-3L#ajs?W!am>$)PD z(L|d`UNM~OC-GKzo9jyzM;+UghM5OgUPjlUWFZMVFFk<1$EannV+_LEX8)`-MdNB_ zK~K#IU`8w%-->ZTG%WjeRKCd0G1Fh#59N;FC^>*1(ID(;`Ww+1j`raTX#1%6`bJVk zRj!$1UkbNQl7!nO&XrFZ!bNv?P|Orx(PoG`K{QOQh2-g_Npgi#x-_@m&UOFqS^3mB z1g1yI$dde0-y{*ozXX)sh>|PlP)YIIh$FxkR~kC^z+GZfO{Xo(PIIo}`SaOUntwh< z>YyH+dj;jgQdW%)HK4CT67-3^>k_)8Ey7?Bj987Uif6aK@()utN@6b8v>bw0I16B= zD2M~L4hYbNlCr(*TV|9qrW~se<3BtWeWI`6=C1K~aaz@6=KFD$LAf|!;9i4RO!T0N zD@w&Rn;qel&Y~^FY99S@+jQ6j+ftL+nqx|3#(Fm#Wd)zx@sN=StS-mdv)7qKa~~T+&ML5z>e9GXfi+^mY?-&`^Zz{D(1&wRfX~~#_5$-? z>v>26GO*d=H29wyA4}C>9N{5K`}LwPp$nE0MhGe-9UdsU14ydWd{2DGZ~|VuqC>=k^Es%o>j4MqOhT7bSL#|Sq#2}bCu&m9X}>Z53mIetymQf z=8)vOl|SvHHV%UVZdr+=ts;f9%&XR2@@~{iXodZAaM7w}8hT0BqP}xvH+TLwu&p9+ z%-WsLal^xMeG8>!1-ti7b8KYAc$)(R+IC*fOz6&*fi|EB26vU8p3T8BP+ zi1W`Q4^CM55J-zLR|X_V2F%T1*B8f3Qre!W(iAgMENvC7B={~X+~?MHAZaNteNoBK zAkfUNWpUt`u7I!@wh;-IcyOkLFe|L|9RG<1Ja|)liqZb5`hi<21_q<$<6ZId`zXFL z!-x}f*dlJGxZZj333!HH-RcmzJX;yNr23S%2bYAk*pIs#EOM;>N z>`E~93|jq;Mx(WBok5Ck7^s)IVX_bu2=bPW)8`q6vbaGHrvtm z@hcmjGg}e`oAO15eCPj@-tm8{F|qOuH#70wbf2w@$?N^}JPI(aZo?*l+{Bb(H7V-W z1N%DfI8w6kG-# zTM_{}nEK6!#2NCtxYy~EZv2IiDk5@-NHsGiM7tgu3K|w38qx~|>K`q8EJ^^oxVkBY zOGq*%TXECCwVH|8_nY1SQJsborTh!H^8)28q%jc(+cJ`)0X^1J!qNJvC6o)$CE$3H z+i%^v;`yNr!)o@Yn5M=!X6Pj%`7#7L?z@%jVdki=GczMV)&+QI`UzxR6a5;|TXF_J zu2F|Mq@r`lVYPf2Bw=g5VHoBG!y93@S@%6wP7c;G@E~e>3`6NxH!PW!dn#rjeT3Tk zOz7sre`5pf*iOe}W|#`(TMQ0!XEY&Z^+6tNStdtgy9U*@iWx_42?lT@vCuBh?Gpo z)N7r1@Dfb^G|TAEp8ZFTU@7h^nvMa+MKNnDxrTKJ5(F&dqlY@3gs)xz7SRSo! zBF_NxYKlpw2W|4JmxgL+v?f&%5qy&vHUw!O}Bed{%?+jS3`)jw6OvC#D3P7w8w-u1il!OZ~IGIfgjSGBx~c2Qi6(3E@O%A zl0V(pUeqxFIjDC zZ@X@h5hwuKX5w=rTGaFGiF$8XcbqutuWsL}%no+h&S_qR0LpE8LTKvXsPbKUzBcm2 z)PteHkZ+5qAX-q2!>yfXYV~is`0N z!TS9KQP|+L;2{FZYw^g~qrhyaIlz>RoPi#li;~OOPD}q{lF-oOd%s2znkkOgc7(8l$36ii4U;=VQsM7kW4_JrxpPua{O92fkkGrk`0u zsNUn{e*r;cj-q$mF}UuoKsTrU{RBn6PZk34iPT5Q+CS-%rt?eb=k859Q)|-(uQwWR zLX5x}3kAbP`3AB>f{M}p;~Z2ar`I0FO=A7fVHseaMgQw++*Ztj!RZE03TV6xxz!vP zXws9ZXqItA$ziIUZx!y6R%XhY%_TT8Gp*CjQj$nakvJ?7G?eR<6nq7vz!mx$B3)}k zyw4!`cCfi2WxO_=LMGQOj1g4QPpMUkCjA?ni5+!D45^;L&vw_a47nWujz>DMbe75L zrX6k1x&>wlkB)7wA^h$dCPnaI8?`v+Lk$%_V+R<%KdwqYg^;>r%enlkh9-Piu+EUl z=!tfBiVrG=VEs+W1-3~B+^X8IvJO>V8ePmXeI$z(9_VvS!!>={WJV+FR#&l{+3yt% ztbr~GkEkV6K8mH|(I2FgF;A(BPuT8KzgiV*i_vj#DmR5A{*kJG##PyMT&B!qz%EK% z=uJhurDhr?&Qq7ZF~yRQ&Q(M5P&pkH*Q{q4?tf40#a=ag+x~c(y0{5V=Iwtj9+f)QFL|Fgb=B?+YOp5G z^)TDp&qY9qSX7@@ijo*9am`fy%-7F}Ie-bU5iRL8iy=&B2|h+@AH>I`us}}9k_4g- zVB>gO*aah+%Y1yKW`=oF-WT(NE-5qcyyAK_Qhce;`#g~%!UV4sk9jsuD=pX(3s9wx zvJgedf#Fb3i>p<@l;WAeb4J(5`67$!l44*MsI8&@gQU?Ni#P#>V)&FcCFjY|%f zI0VzzCCv`#07WO)ZZpT??u8;=yGG9rl?fxE2*QUn2+#~ubGKxH{?V3BZSPLm(kqN@ z{)(M8n20Rp<^F`K-k8h=`!gQRro%sUJ`2&AN!3e@{cHb|r_|pnghTpHmmLt=?&zumiiFTr~!{t~hMVSz0p_HG%8&>0#^~Duoc=);Y z=T*P6g&`tbQAGV#!@V6+Ib~7Gr1u1;Av6<>G%@nzL5o>6>wIJ~l-K?cOU!`(X{Gu2`B5#Y#_)SYQeOSPh zP9?fr2^K(^2+E`;EAV3f8@Z?GU5y!K$~p*iMa4Qey+aTjdU1vN;My7|u&jKARJ33w zZ8^bloVm{@+^AGBMZYiry-4G*#%-EGqr3Rg$RRtKw~^ij<=_lO51WuTU%?ACHC+$N z>RJROUGWjaGt8^0{50om=qn%FEe-tq!h2S@=WI%{YLVc>V*q(_4`8x93P-M@03M zo4q(T$ud;ofy*Q}KV^deLfBX<+2>jF0uZ<{D|O=u=#W&`W2_%my#{LupY${COQa_? zj6m>4}n+Z=Q^VY7=fKrRCDJE)6 zR*^*XQY%mDb;BprOT18Z7W_ZE5g+_$7O*`v`@-;<|#B=SC%)|r$Hc8Oo zW8_ImuU{BiYx+PzaD0G{%_B(X34nrb+hO{>e4tc8jVSfJ)Gu9Ee9wZl+C-{236{SA zitQKiJNIZC$!d+BU>o+vz+Da9M;bg#)d!>V6R}C5h!1K~>3Qrt{j^q?~^j-PY)nJb*^-CYB2~4kq1&Y93^{c%B&;7Idc|DsE}l?YXB!L zIqDFky6XX>z;p2zpzlzX7@WvdC4@gXvaj$8tt;x||>5{G%a%`0CGIyCnF{ucMv`aR$ zF9yyG$Bq_++`w!t!nC5Nv_ZO1q#wbVB!Lo=x3x7tA~CrY;5{A{>gt+bbXFV z%8-qc+TPLf%djjIIvj8xXQaZAV_~th_?BDtGPM+l)cM*5f< zN)+E{2RNrw@!8q_h|c@w(L2kglY0akhTvZrdL_Anb>Vh$?J|C86i~MsxQmwl=hu_O z>H0kp<8iY+l$3qihPpzFj4}m=j#VPuhPc#_1+1ymeV*jXY;j$Kt~tWaa^&f;Uf&M0 ze;`sv=bk`Q33x5(7&r-9Ds-_hYIExP54nBeeRX`otcvquF}zmig3_za80$%#aVFRz z=7AERmYRvE&$lZbim8JX29o#-;Dm>nrTj6msgu_X*~Zm+uH#)u_>$A=l9+&bk|42Q z)BXvQbm`*rJXkWB5-i$Og0e}Zi7_c66nCRfM--9@p{pk8kF&RfqF$LuOMd}|c@$I7 zzr_oE)!!aQNfaK{n0J?&8NG`+1Qro6mnkfyT1;g4#kFDq_VL7o5bL9xL^FK+9Pl#! zfznm8{G@%WHyjl_uKo>nK=(aVu#y&Cn|j>gbf;GILjk@|#|KR! zN{M3y0zOguJiq2e048{H`|wSV@S1;83wh)QF1punh!?AAaga3Ft(4N74NAJP9mNtK zvp70~vl&wGAyGW;YG;gl-7GOSv#sj(JV;COMr%)?X|D+eRD=pMHfU*w4D!yHs-y{uJu8fXd;dDEh4N zXTJul6r7i>e^_|+id7l%Yy|arAk1{+`$u*!p+3UMrhd3mRAign`Wji-5K!e(NcIMw zxVUuHd~l|>P+X*6LhmZXN*7X zQL{K;)p(1v)9C$Y8;*zpy`2h?ti*&yn=(o(0k$PC>8y?1@cWKbS!&(mh$cP7$(e>c zR}=aX_wipc{$ZYg_-}Y{a4rL>Z|;o=t=q&QtJ}?v@0^8BNC@ui zQOj0l8fF+vvl?7mdOg}W^)27`V`-tO8m22a6Eu#>XI}6j(j#=}b(5eYFcNkv`lV2n zcjy1waU3KS7h@H|dJzrv{atJv3MwF7!gflhq>FqR@#5qo*vKQ!m{+BQ{cR16z85fT zAu}xVj)D!p(xE|_#QlZ3G&yuV{Kr}Thfczh9ktLNhx#|R6voZ~_Ud>!rJ7c4z1bB^ z+ZC8bYMgp%nrLK?ZcjT}JvOV^Q^O_)(}69dMG+fM1y*ln3R_bUV)Oy9AaMjf_6D1)ZJ6%#D>B^?1U?li}Q^R66@Zfdw1; z04Z0m8<|foP9g2Ch^xOn%}+Hs#2;qlfdI3EgZ<u2|cNOGW~3H;CV1h;Q1_r#Ro z_)(t{TZdcLl@TLDne;O8QrF+E+D~vFUpT&hRGaopTS*OH)PN4s*?j9fwnhx<5_*O- zSH)_fg!bJXy_aR(c=0h$D5w-B5xsCFP7vd5@#|o!dPOTP-Z*eledL zgq>N*`_DD6BiScYkY-D+JJiO_Vi2*x3p9xBq4Pl^YSKcFlHl5Z+<BNw*VQr43M(q!sFBk zktmp`QM|T2QpY}Hr>;T$It|N309ShczkV5LY;NG#B}+6At=S!-}t zdrd6u2X`2v+L`&k45nk_!=WWOqtpt2=uj@P!kd*SHg!i^s4WpZ*=_jD@*Pl?Us0By zP2KiAjg1#Ngb~*tq-Dp?hh~WZ!uy1MeVQXJ*MtR~Z%NEWVZ(wT*F-;m;OX`QdR`e0 zs9Tuu2K-S0rdS&lcld1y`!A%P<$1CIJme0Pl}~#)ztD6=WP~On-c?FU;ng zi6HU0^+hmCs!)Z-w>K;>CzFIBL@JQ>EI!t_ozPF||0(Y@6x7iA7Z3u<%2&~(Q$D5_ zbYUXVfp?~~WNLj&@~8ex70g$MZ_C7&Y!bUzdSek6yQ-t;6<47t)M((iKKZ%ewh_LJ z2Nw(r^t`d3!7b^L#kPgf10zv(Q&@0@wMU?ep+SvGo~Rb%fD`1;9`y7d`;y)OtW$+I zubVz5{!fE4ccGMy!pNO#(kLFJF*H!%%$mcMExVubWtibYuzImL%iTxpoGeS+2*Ys& z=W1#4%0JrJ8HSa((odp^#IO|EfQIFQ?w)>!uwIAPpO__3ZLFa(ui*>C`TBqBvrd#rFapSX{h{CQbl0 zw8yur)ZNoLa6e*n2$VWQXPj$Eqbd#dc)mRQ*dSW8I3A2&mQbGJ{`w&7?S*^+Jx_Si zEU!UYE_=lL&FE*Oh2>mPhh{#mRJ}Nhqo$Jv?L624&y8bg5~!=U}y!43jz9?9_Bc z?e$O1bP6tFD>im=TWu6YSR9CMe_{5821602D`3Eg1}6*Pu97Ypgm&Idt14FYOUWZ@ z+<`6_0a@v{`(FTgqw!S#Bcy^E!O4_W-jQ$rx`+c{L?-(_H`IgabCXBU5Y_ND z#*oK(p7!>NK;j~KJNQ%A3t^QVgRPpLU=S!2{S@F_;4a=Ji$ieJVa6s7dgYmtiQtka zl1(1`F%0fdA~B7pi$T<8oM0Lu@elA#V-F#wl;*ui-O0(s)&!vn<7ggXzzxfMp%B;3 zq9c(G^OylcOSg-k>(QV1?kP2!B0~DeLoH}{QCyVC=2BAE=2}KvQJfo-8?2_(50Gil z<+!gVC#wM;(9JqHPSQn_kOmbi3JD@Yl^9 zh9`we9bYyBbw#Z0wnqXeDE%>9qUdavHxMdUuay~mDX1rA8yX#iir5JgyoN2*R8=b7 ztd#d0NX-Ssm492NRC)&E;>VV{4EOCQGC!BsIRe|IZ;z=J?!)M5VC##yI6!*v6mlum zG2zPC+OiGH7rDd+*eW0GQ7= z@5*CS@+gWV-{|fMb!xU(>Q(t|#zU&8XOH?|5{ClpMYmX5pz+av#Ii4Jn(9-nh5c5jN zlv3Roz#$$5L!AMK-_X#HlN)l*fT^90kUaF3goHAvmP`dqYR)Z;;g(ROXSz!|wwcBb zX*c*4l~oc+0ae8J1pLj`>GwhFGl$_NQLq{TR6uj7SwW@;Y=@fMSlDOz6-e%jz;UCB z@-!4e{UOCZcT=XJUjhib^yR|X7=|yRkjJ>BUn{Aw z((VR8^qraT0k@yyoAWS|WVXPj846ooIHe&)^5G31Fv*4IT$Q!pa+@y1#*=^c?KWB` z(=P8XpbpYEf;6FHyKj~|0?GcL)1g9MUVv1Q*oC$xGA;Fa4QKkGIJ2Xi9! z4$KrJq71#Xnr1#_+!6T}Je&0S50FVS3ASPeMA9R8U0W(j|CB^#TS`SGMGf^)MwG@~ zfya?%*KmN-r*?-A6NSWJ2@elX9OWgKlo5oV4mohoSAG;i%=O z^8N$a96SC6@NL0{l#=?1duCIEPCS?##+mVgA)S;F@jYhW-d$?x6s?Ee+x`O5JR$n4 ziPn+Bxc}fpIo+bM71Xgbg8Mn4WCJSu*!%4p29@{k6Ii1`DI7e;7`Rg8qVdeQcS)BYs zHm&+Tm9!SB@K=NSa&kE{38G@GK8u2OHw{M^s`DHQRmLf9o|C=(yuRW{NuRJv#&y79 zkF9eLYgePmh5h_O26M9q0@nLS2uzH8O?$;bpYM0VNZpqHwU{KKT(3=bQ*!Ad+FOtA z;n&NumOcxlkdudQvUbJbQ?n% z8@)n%9i0r60%L>Z{vR)mbcVBaxy=V-tr(SP_dcxPSjh4rzl?1Wd=j=4pSg0s7j>W1)=r{pL4~^KrkB?`u*0>ea_bEf`NO~)*QYPN!&Z99}L_L z7Qt%%)RdBzXr=Jz9FR7#y%9Tn`QrAtLXT~uS|GAd${~xJKd%2o;c1e=K7HgqbN{S; zzS8ii$M<1}Oe2PeE9A|8eRi2wb0HDA=MvXb)Fu@f>fRN}bx^Z{R8@8W^zSkr zys7Ag3f;kRD0#_RChjl2;sY!6VLD4a!FKQz5r7qZ5z3CymTELqsL!{#a1>O1M5I${ z2s*H{YO_vhqrS6e#}R}2Y=j%3wnYN@RH$@WCb;;lBVLu8r|>8;HC}6Vo6JUH@tNey zhGVBvE>$tcZql{?{~k!S*w4*0=;DpldA>X1%#Lr(^BmXLaT@J)gPGVCq#qYVe;xF* z`%X|@7+3Hl(87GS*K3U>*Dtp^&r9>E?7tk+&xmX{odPafCiU4qrb>jxA1u$O3J0`M0oSJ>%AU7AQrifKcqV^Kfd(x6!Bf zRGjU(P#vPCM~UTD`s!;=X4HH(x5(NcCFgnexE~jjh$4{K-s_)T)+m6+x%NVFz~yku zFAD=L)PORI`xx{_HWX7boebJ&0x+5=yqmhlv4QE`#hC}V&QTR+LUolkgfGqi2O8|9 zPkJC{#7-B?0t6?f;+}~rB~R;W*k8>#&AnFGR4|}XFj^#}E&S^!|C2}P<^8}A#-}#X zoTob`%#&#q!2X90LBi0>_Rp%)hV#+d&;Ax468i;^#%+AZ<=Uhr*M-7?-xhaaSS!Jd zbdJdGSi-z|Z@yb|xXS}!i+c*W9+8T3l#w5Tzh{pgj9O$)Z?>pKEm$fn;OHwG=z+}gM%E4g3vJDRba z0X7~9J=s*MW81kXIcRrWk#u2S@-!iy@&c>e&s0W0$&8x`v#aAq^w>nE7xOPbbm=_| zQFYDpM(axkdilfg2%*L3d7TKAH>G<}*zVo+U%<#M|%?A)9N|I_;vU)niah>uZV@Q5Xb7gRB(UhuDz9f8oEXk zuAWprt?ne|zX}ftGm`e-yP}%+B_RBnd&R)|=*}_o2oReTPc?MdxjLxAQ684@B$S9g zBa-)9)Q&6nrBFF{^@1-<|42|h$y52t)$YmxEK5&nj;26-j@T#SPey$CVB6J zsfigjIHJ!D5d|(HTZv7jp0RopDXc|LJm$KC53!sW>C8IuCN;UJcAbBr-_T*71o~QI z75K8nk1XZgmHsyv0BO>QHD@;<>hSCeQwhqLysi!iJihi0^6MJ<-mr3z+HGYZ1Vk|I zcvhooB(?bT_`~7@7aLF7j{&3Hs>oq9L*>JfjfQ(kiJ(+G$Ohi z0r9Snb0%{qYxar!+FR?np{sw7=Le>Mh?eQm_4cFFErqDXO0;C7v>&Osf4X5Kf@8^e z2GGs>S%qwU{^&|rwb$sSA%gW5lfN@j^VfBZfOj}&uONHU6DuLJaPeG0;HAPnSZ;xC zht{?%oWX&nJ3Q(-xBD|Jg`#wa@p63*jCr56sNAddDR~?u{S#)5AVNQet7q-U+4HB% zI_S}J7SfgV60+}>*9H5&v=Ydw8=uTAh!VZX?nAz1$^jQ@R#ar{#m^JL|8;_1f~1yw zV6d{Ez`>Zs<*X3n%J*Fg$(V$uh*~@bD+a%Y*24qEl~9REiElpmjgg}7+x6Pn`&bAV z;5GgiFh7I+>>Yuw=GiPeJ&F+6LC>pM$fF3>!BnpGiol0WRweBahjB(yOSOJzH+-V{ zcJ>_bLx_Vc{^2zX6P_>YUw4;twiHH1#bZ++x#>M%dvyB*$l4XirL7@E71eZ=J?3(`Uq{clYg;?rmr;RoEIS zF0reN3R4v^P!A(K9j1OHSVFz;+`0Ppm1HdWj>_njwC>NZ)KCE;JjzgQ{iu4{Kh4A5 za)NQzLHuHA(Q2JQpHw{PPdc!8Q7$&(;b~`Vjg$8QcNRuw#+YIf^4t8jONyr%HSS-q zv(RlJXN6lc9qv~g+zxc*KOM7s1k8K4nPsh3VLrUHnxL@v^! zVb3I9LqWzpn*tOY$BlVT+tL zv>}HG6ekEvMEv6A=5ZP~>tUM-ii}PNeaT6_3_lzjEFqljheT>2JMHg zMruZ-`G?x?$g|0(YRau0(UpUt?Nx#*+R}d$#r@Ig%{oD@TCcL3=#ERu&Y?fU7Vx#a zjMbY|pUv=C#2ZMKo&=L#%-+(g4pJ}g!i({AfQ&9pXu`{12pb8=%e-8CU+hoGUw$Qv zHW*e3J>AXFHEFB1?`%+Kzto7vgg7ecTqUKlwWc)rRlvf2pa`q_j$>VX4#tlUFLf1h zx}We}lP3oL5KGBln#FH3P8DWPP=;z;R)9qRdW3V(zJA~C$A#3)zB~8KHOI9hMYIseul*X|vkEFJ ze{hV5M7@x&6Iqsix>aIqRKrLaI(WOK+^_ehn#(&Et}*;2ZRE7~SzYFJqzEcM5mc@- zZWLAun-Idv_Zl9xODNR@J8{WfHf&knlXz4_5>lrD%PcX-_)2X`sDnnhTXw^V-mHVl zGQr1UF{y|25u1~~6Ck4H`NLI>szG3b7C4;F%KC@DpQT~_y|;rm;!Q&6{CtSu*Y7Z= zC%#&(;Iao*4q5sMpBxb5+?VFiM!OHBH){TYiAppTFHnC0*+LpK#zE`rqWrG$4tFlg z$7YxAf|tMDn)ITke?ITBiKs^Clo|8!|4>UT{R_ysO!pk8LUguia$Jy7N=nH@pFT7) z%tm+$DEWYSF2!h;L-GlUP2PPOY?71p?iNq>c84AU#p=ixu2Z}!h(yUUUU==;O=5Ar z&4F1QmAuWmSXG1!EQLdQ!U%Jhk*nX6JTY&T!mhx*!@AfN^{@9qn!4@`zhf%!753dL z#tuLqKl!zSxe7@Hn*0%JA(6Cw=A2rc{ObN5h0)*-_yYB9T&?%h76wFxAlml@&lc@h$7x`9vGvTY=s^EG*X;Bqun*>iK@Gj$p^-po zjq_sADaTp~c1-Rm43L({zpdF`dLIN!2UC14H;?gPqFwaKb2|+~2^tsIpEU48u!Es# zFVpbWTrpljtz*!pR97D2~RasLKiK_#i|;H zv4oLV&h4IewW8S5k}uYwD7>alDbcg9>zxb}szMkLcU8k8_Z4;p`bsS!?*59y0mIDB zE%tk?89h90!3IOL`%DJtiv?V6FvVA<1E>4pe+(7vwXL+$PU?_-+`NIB;!J8$rV<^} zLE@129DwAVvnP^CIKOF>g(EH%&SeZjMw5nPqJ-{RD^n|xg2~e|-wDAD3EvgS^SZ_Z zQLBC)YylTh5=+&d-#E7HL?A^b*uRAXDQ)A|jpKK+x?=C0g(~EpBCSP1S59!B>L=Ea z&iqWu=kXkS#y;kp-t4gnCH@XV-A2fz11Y3$hE}LmLMxOG2kZWkD7Baj;dy`0*lwO}}j0-EMCg3;+2Wb$q1twAfj7~3jAz9~M zzxMj_iay+N`QA_P@XGV_#0ZYcaP@Y-2$S^Pj;_&cEU^^6-1pbwLL)wXhLG&112cdL zJ&DePG!>ivGSwe;z_M`|Q_?3nJ;WQw(=iz+>Y)kH@8mD%$U%L{KIz=y(5h4At_QL8#gK8nTs7oE9jM0=R z_JW+a;sNbijvly>efmOZ<0CQK0oh8! zu7r=}Bzk}90R>6Nt&+ObGJdFo=Hd%p_(IaWyrqztzif?o0s#Vby#JF)Pr%sFMP4@N z8OmP($>n~@wG*s|9TfzExBMF%=1T*n`%a4~pQ z-@fAKL6XrHA4~uOfP64e0byNt7($a~2cSWX-7AOC$)!lGLGg-f3unrXs)WXIF^lu8b zq4FT9L31r(l8<^l{&|q7y{1N)hC;_M)zLdJkgrK>eSIBTBSmxBMEjrHqUb>K7a#-1 z8WLP)RFJ3}$_!P?AZ?)`0`3LM`jdY`IlEKxGkI~|mQ8sgffm*1qw*g!)ET0M;3Ld5 zPHgA52qjM^b}J3=py-SGWG5GqE#!yu=y`YO2?n&V)8H&%LeZ|-%Z%MXEIw$#O4?GA zXFqCxNL$Nh0+?-+hBMsj1fle4sQRF<^}tuz4M4yfp^{6w6I+}3}jsyIS zqd8v(2qIfzO7ZF(SXerOE7HTUEI1d9A+|d#msG&2M_&E5KuifIV_wM=I{{Xq+qg;n zUM>|%6E%i#{vyOi`(+U=oSdpy`B6ynzH{s|d`ic>T>ZyCg=bo=UKJ2-&yMDwhifMa zbe-4w4Et;F^Fm0gW{M+4#ampF{(?S5$(9iNfn1y6A$+O^w!jQWUNSo@@0In{tl;8r z>;I&4QFkTaVyF+%tMSyD}g7?yjn$KCy9v~Ht`Kq2@aQ9a?98+jWF;}J4jRMTSJMff=xjuNE2{Elnf?m& z9(sHbrNel(nmI*Oyv~m#r#L|tth5UJtmtzKJx?F8XjJB*!Y;l`+07_#=%thxtQv9} z+@t~J6b)>e2f-h%kP2Y|;@z^lf|Q(!=8ZW%;sU}jc_zVzdY5M;jLAl*&msRi9yjS# z&=4wpS^2geJ610Aon8RS6?=e}A_a?l2!aOe6AExJYnLK=s^u86h*uZxXFM$K@ByI` zxax`;ou*PEl1QHRoFx@5!~`r~b(u1qkA*F{rL8*(I74J(l2=#IN)r=)mmtzNAtJK- z#@nGu+X2N{-0D=yLM7PL*5>4a3DTRuR5m;YqBasy!e29|c@@L4GK2E}J3wa+RLo}g zgo&abKkQW>F~=kqHUY=$l|-H%gmJQRWjC)#1N+m`}iz5)gO$*>nXY!IJmF?-*+KGWjM7kh~hG_ zgd(se03LooBBJ#Luc2SOjtjb8>$q|YJKOnnhX_5Y6v~qPfhmp+nX@lLT6A`{@u{DT z^c;T!w`%_}UAiDn_c>@*a9GWTO^gEFvjG~S`@GK$dnz|GJS{L9c$+c_PlzaAAFepB zKY`5?E?-u0bJuQB);VWA7FF!@zA zg`)zGd}J*`F=>*Yh%WBtD;OoR!WGt*w=u7*2V$Ijgp|1Vqz5TAs|Pf+tlJ}I1W{Or zIKTxBIrJP;+SpTj6mbqX;(od4;wRsuWcsCRKL((d*!U*0oYEDY~*?mpgAyaLwbw6?#Jxa}B=`8QFVPEa=`!uB;q{xD?#Ir(T0 zdJ{KK!pVaiNmhx+BcbH2{fidGqWvq!7@;k6>eU59BZOFYGzlWj?8CT zlK+prw+xGGSsI1c3uB3`LjWDe5j@s<(E>9*szZ2=u74ZeBYk1Cmd zvUw*Zy~S`m4dvIZ@2lWqCN~&fa@)f!(dg9jcv-#pyUVd7kX=q~m7zrAnqPTSGC#Iw z+v46m*$^es%*I48ZzLFz{V`3=NQTejBxtsDv;Q!4pPe!IEj~-dZjyv@kSexNQYnNA zi+-J{+cqFIiM#MFzIFNgogSn1ReV5El(YqKi+%g?D8I;0;8e56FY;n^2IZS6 zV;aJIUkX|jmA>t7^T55mxZuK+dzAGZETxf8H!W{TtCn<3wka^h8X-^Bd8Hf{;e$J$ z)5Sz+nPz0!=TNhg#h*i+%MS`iK~2&V#w(-wXE^n0w@Y_2F%jW)(~!$hq97lyH@W>u zOc%R>y*Mom3z661Sl0auzufYBjnh8Q^PDm)@2iK)b^HQu{G==Fn$3~#z!6$|8vkC& ztEFV;!zNWpf_elqwKmk+^f|tCJ3OH}VN}Ofqv;JiA%4)!>dr#`Z=u}oG3~5a0j-Oe z=%gmax!}kzQpiZlP~7g--y5k=L5}wpR+0J)vKrWXwT+Dp$uY_@yl!`?|6}J&cYK;c zyG5!R?8>xh)+7QDq(MhI((nssbIeW2sP%1tJ$$RiIOfkR88)erb$4UGfM4?fHVSe> zCV+z6h>3qP3jhDh|8fWJs}FnI`(FP)-KCwA=%;N+pVioE-T%YQ-AMVF{N($4@cH8Z zgD~!u;4YP+<_)`h|I2qc8Rh+r9saG%k$iZ(!_s$1J|sEA|H^bSDEQAR zhyC~ekQV<7sQfL8^?wnCL^b@T`J-rF{6ooK!06o{AlAwMMdSeSKiQBpXD3Jw%Xv!V#^=^^HH_J{QpMqpWq`9q7Xxuc26tK|AhUIx*>tlq_9!XRZ6?R={9_{I`U~V zp8s#aKWkuLp?)f(-%OdF`B#D?EnWZL&r^~v_ut^vzv;4&^?trJ>M+ir$e_>y4PXq1k>Oul$A134#PqXkP=QfS$6j~?@-GsF%(Olt`mD3H@}JLx zw+s8v608Z|C+#obZH0f$Sw+Hef1{2x;q~h9A8TLaM!64>pL_qM6;jpTMKpO7?;owW zQuD_z;7>Fo674NjZfN}0?ylwEH{{QYLHNmt^lwhVQRHpgclb-a1IRbWU%(G!3 zzxWr#KV|*_Swx27A-i20(!c8R7x;1LZ?0AmB12e?W@w{*dqs(D?=2 z{uNj3a6^O~nvu-E!ISr?Nbaluy$c~XULi&P{zWb<{KHQCs{&S}O47f9yT5?*o0C46 z76|`*5qnbeFW;ayMxYD(uy;uMFDjo5h}{08N@UF0EiL?blo$2{$~4M0`B$P*_91+y7Hs(OH?rk_ll}eTpXT>~_GI*SBIxGH-?4w!=g$fS{vdmz3GcUgb}}OM zSF+>(T7#(0Z2j#IlX*R#Jlss5{wzi|D7 z=4h1kZWP(duBYyX;j3|iU7E0?VZoCa#s?aLCnLYdzyDl1{r}l)e@Y)|atg%5`BA6> z72u8`f+%vtCZYdTgTqD6E99N|gly_A{ZvPTaHKss8O280ljB~v%YT#h|4}$Hod_oZ z2mqmg&>>)CIuYa?7C@#G0qFQ-@U^r}oe~RSh``q-9pi_*jseTaxh@n*3X(=H?B};v zr3Fn#O*1E!G9jL+KVVf{Ct#0AZKHSF2szDZiL&#}|LjzrC_BqW2lWb`iy~m0ui@)Z z+0ROU(S57+hF&Wrd_!|ugl!0euSbAt)wi~6m4YsPIqoDVsb#Ez2$*o?3V71ZTfeK4 zb(DD#9I7cV-8PT_TNQqZ?!dE=ROecHAn0@yeX0)O3uoN;JkSJ?U~T_ zd8v`Xm<}y6oVrW!Bje|(?8HvI+k&3V`CmX$zK3n%W1HfA2Jw{SzJ%s)*NaI;`J%_v zRbzwxD-l3ZNtFQ=Ah-ERrV|J#eWpppEs=(wVy-e-PIPvIKCxUXM!hG}qN8CsDGaL$5P1sb;mOj1gJ}wIlQxMXNcemf z^xaA(h0554DBD+h6tc%?x$kj=tRIu56Eh|WWjzG%7G9fd8t^%vig)v!a5q(8I2$jY zsj<2ERgF^eu~7lvjm4QCmD_;upEIt#d&e_6htOc_u~Jf93ojS0!hS{FHZRCu8f=4LR9;V`JAkN0-E)uUz^Y zsU3L80gJWp%DcW{%2bqz)452UEOpnJYI6<U^0e@c>O<~1oBq8EkerTgR{c^1j%$!XJcWL${FjhnzK7KP7(M-X zGJ7|pviQ|1+k-QXz6&l{(4N`v3j^~+a=I52$EOy*0AlY5rYI=G1cOcQo52|qRZMJ2 zLaqUH#Hp)h^{$$zmvq~u_d5vt~UF$Vad5;XM8h1)1CsjOt75$42A(W_j5@r#)3r%DTK z9We@+ves1x-b1H;e3f)p-4CQxW{b);I1xF(LvVAXs`7imUtI^ka6ynQ)IRT;@mrcD z{0t%3=EKSOaDWqbSL`$w?Uxx^Yl(*AHuLm%8C#p-Pa*#W1R%$_Zh!-6d69ktq~%50 z)PGoBfB>J44<_^5^cErl6JK|Xn*X zE^x|4=|*K@PlsJLO6vn$dzU%G__NDkjuYO?=#3R=j-1lgm)EOiv5Ab^_mA@{QxNa# zk@4Rb(Vp^!pM2G#m?PrY%j+h&b6grNf2f@H<{rl#et93Ljpp#$x`FSy&4&6(vHr%| z)G5|Qw57*}ws?5j=JmV<)rGgj;SLJd!3v*ZSjj`IK8-^}gFkotfer!MoaL8hDp#Wy z$*d!Y##AYuZb3|OIXl96M3gnEVC?+CG^F4Zwi_=cQEpK+X^nJgeG^R)Fdqz%JOqy} zQEK4Ob4BO3ljh(?&AW?UAq?E;*fhpaId>2P{_i1>!S1HCYy)k)o4#tHQMgVlWV6kvN=_0jnG3Oji(V4B+)GzHfsct^SV7NZ0c|O#nlz)>c`q2MU z@C=@>^jbE|alR^9-;Ko@IUD{NSTOju;9Sz9s&Ce!frV*wjUE5~5>L$sVYdQWF`14W z`%DF&cbAzWk|!9Tuf42ZjGUiUN6c(d-xcHNwLix7UeFv8k$0csuW@OMS#9)nvR;+$ zwx+k09iYQG-YhS4cUE#Ijg4-n=75}k!_Df`Xq-OKcR(;tWFM#x{hTgsB4-s9f{C!P?K{a5LR*t7s?|9n;8&?$0@gVoc*Hy0NW6l9FJ&a0(d z2gt4m%aacA?-*YWHQJ_jZxy-hK`3aI+CKr z;zxCDrz$;v(018l5yg3O0>Te_RNf+n@M3GL-5Y35BEcJgBS+r$4!9?#$ZFbH5vM+C zr;o#8piaWg`c?Fx+#V3@>3J5NV6EyAPd&X~Ux-Y^EG|Jq)a&LnN$}9{AF0}qT^s~PK}SVq zYWqj3w%>CrWcLolhw&yBb{rzKOkR&KAN?g&8**}W@)G?;n9*C*;0IXQP9rzC;i!^@;xtqRM{ynHzK=+=nRM0P zz_g;my_;#`JEjjKJZrE&1WFgQHciCKNCnS_#P?};jFey;&w7c?K8W?j>cggzxYztn zokc;#`P+nTzsfrWkvD_Gyc zFEj*qo@Y*GOytgReCCPo0;^L<2E<``20~p#35fB-IkmB#db;U@K1C;0s8M{p};K?scHisi(8uof0WT=mH;H8@lcLg-)(u_GR33`=9R6+&lmA^&#& zf!?g}4yeP7O<}7>g~#Up4z5^s`4Tlii56a5{u*j#5ohp4R$(m=(kRZ2oQ_Z>`tsd)VVs znh(aKw5E#Ryp)zt2A(O>@X%`hKw}owpm@Spq`j_*(z_>GED=odvs)ur2N!Q6I-xN7 zxbiWjFug?Av-ljbc0w|{3cwt-V-a+DI?QD2&52p#FM#1kJSk`6j}S7y3fqoTnvTN;6uGSof%E~G)FqXq zvZPVIL*5f?(y>fM65e#yx&;DJMDO!>K>pBz-#~`8^L| z!zvHmNK=JVKLCXY+xvOk)vJB~cy)8s-;veYax0J>K12u#$S?MJUh;xPy!zVkc1xipcX{~L@Jv`Rc*b2u>xfGj_VF@>Wk1kHs`r-ss2UzmKSB3qWazd?jB zd8)vXKRrq$xtLPvbeDL$n@Q+3Hfem0uGl!2M(lXX) z#|dF6l(B5`PB<0V*8EmX`eO##dgUP*!c+5^*OC*_m}J_?Y~2>xbu#oBwk-?GY;K=P zu`<#?0cef9Ok~iXR#upY=H^8VQ%j*ZeXb*$C2okWk}HSzsLRc$L9X|Ube;)d;I5*` z9S$x2%pm-lU^LH=z=Tr}JNOlmlvd#xMM1D>nV#(kmS%@`u(6{&D#(;@P3h2ok+OzX zl8gT~^8yOV(R0#)BvbQH;!?i`;%9e@BJtP|?BIRu6_20fZ28ZtDll9~bu8_Hy2xXV zZF`NlSVlK?fP{Q0iRZpNsSEDt!6sT_ffk)2_qGh9a}n4^*9JM79%+3E&@XjYI+|VCk?~PD!>eC6`E~5MK#2yY(l*-xbOe~2!OX#ar?MdA0SZ% zYFSEtGREVg5wP;sRw|WRcJrF8Cj<`h6*0L(Lo1AxxhY11AwrPwx6fOdJSfv`-YbsT zV}#C;Fbq-PV_T6yfqTtMiRu!A;`@+sq`5aUtyU(SbXbqRrRcxcm*lud+mVk z6gxIM3ooV*OVnoAQo#`RGQEJY6#7UzhBM~IKYE=&1aFYH0=g_a+>Ahf`2y3iF&O0X zP!h#YJ2u!Fu(%^=Th{0~im7zmD-kmUMdVW~q6JhFAY7k*Fb{+4QCg={r8{j1>QGwT zR1S}=3x%f1SLP<&U(X|fE>6aI7$1PHOo7}$?Pc9deuj1G*1WtJMmwhtdeLY_(+>(z z7;01;HJ%aZRR!#AC63AVJE$yUSmsl)9++c^#upv#cO!6WQaTd}fIS?-eEl|HZatl& zuZX5>RQqH^nbm}PYSwd|SdW_Z<_OaXnHlQ?>BD97ZoyBZbiGlgojE+-4^d8V{tI}zuD=!hV2XXP3gv&ab>J)USWJ5Yf7{VjV($Sh@c5Q-Fp{hk^ zfy!FNjQXT9b*1>qLCqOA1X8Zt{g$2s1d4;NQ#0rgf|!GExP zIiz_#I4APyDrx?>X#G$guh?E0m_;jGqM2Tz(f*#T*6}JYT^^ujZBGGB^fKaK#gB@+ zS8kwU7DV5lr5np3+u_W7gI@|@5k!9nr6R`UZ20#2Mi)F=?6JoHCQjt3&oF-xgeh@$ z3S;t|ASKP{9X$W)sk__Lj+rWC#G0J>nRYIX-g1nBTcB3$k^hL9|A@wJ&FgfJt@e?1 z86w(rKeszJeh130*shRHSfaq8{N-3PXUe89s;EhCKOJZ-qnM7D4j0QF1?Q=Ptjaio zI@s0(OR1g%60i_RQlnYnHq^)fhROyu+`K%P!sqIOdDBcx%H02u8*0CI7m5OT_vJwm ztM-oqIL~y4QxW`AtS)kZ#9msap7a@V?4%1XJYd^zZ!+g<09X&I$FW{5)3Y+acoC@+ z8Z$~Dr^W9kLcQ3SmC%AtYkqXcAvUcR~Z!il=Cw@k`pb2_6Mphxv+oit0P8Uah@{fdzCfeiEa)k61a86EB1k5-zaa zm_M{Y*_q;$4aW$Oo{w~m8R-_JwIOCz3Q;wI0A7#cYSG6n==5C8zLG_>e$N$mn=gPp zw~7ra>rA|QW5@~U!N84c^RjXv2l8ZP=L+Wfcg`y8;}6?zri`b~m>R+;{Zfr)@BCK} z+zw;j5y>dzrm!^qXmotNERaQjNt1?BxPOgg)~YHi#7O05kW z7;TyULmA(hJdzKur#rHU@q))?${WTz?C4qIKfdVmr{#nxQGzg< zbkQhNJAJ$(w6xC^si1@hO1hZK3fb)#9RyiKEhzMXMP*awrX9-=U%EEZoleFr6KjmxPDWeN>M3k5U; zF$i*TMQfX&m|)kk`sL8z5N*UL6O~8$R`rgjH#EJU_kmvo|3~qj{ zmA*MWQ{xY`NTCmqwa~Q=4QRhb8|R1gL3_<=9xyQk2lG`xa^f5a6?_NH7r$rmrsWp^ zRYFcf>wzi+s!QSEH8_Mfftg${D#Ny*C<|&JB>hOE+9_1ZhMnRY-bAHdV`sh~3C@e~ zqjZGD(*OV!K?vxQ*{XJ6zO4?o3MFF|W(G&WN_6jt7E?*=dLFwvBE$K|Z!wuUY+FJB zd{`~<;}#%?fV^;e4!C}Y1<+0Sqe1*?W;g)M65t_TQq}~b+Qfoa#6S<%d*0RaHNGE_$OX+}mM3Vzg|6I`-DA;{b2x8Qv_K{he@m4oVzj7b|Jfet?sYgd&- zL45QNEIzYpdh~}qfroqvKz)Kj7m^br?m&{3h%9j*tqnBUePwN&Fu(NC=ItIRw^Q9;Jxh)d??+U3AelSbI

65cfG3+ln8|$X}=JTDqM#L*;)gtL4Lbnb2TX7=M(iZ+49~vV7tm)BjMq2+}O+ zS)PYW%qZ280#li*p?SS}Vo;TmtoQorbEU?j;nu5J(h%69axYcfZLI>LQXKAb`f)(0 zM-HW-NhgTUz@(B!zxI+tsH z$bPWvX(sc<+-Ng=8P>$J7z?mcZ_ckbW$X0iUZm;3dbBi^_p)2F*b zE>yqoe|sS|7j~NbaXZOUhm} zYKi_pWD+JREm|wMZpa>zZ$yA2=|BNkCUb5XgP^3a)r_C`0VvSXO%U+G))cCP+t{qm zD+4vqc=-Bh&MLXO1$9_q<>b5Bbfb~v1MMOobG+~hpY8r=y9XNwkvI{|Mp`1kEpscE zg4}TduZ31O1i3K{wqnwi2HVt-w;10>UTZUgROhRB#Wn+mI}PHlTIUKeUjgCA5#)8q zVPYbqlOvgyuAe{ph%s-L4WBrKeyG735@FU&$zEeV|&! zL8fs9Sc74lIa=}#14%M%hR;g7LW&B^=ul7>dZUWVm~Y(N&{hMZV-!RW8!s4c$0Nr4 z_gdiWA3Uoy#h1oRuZ)bJ=pdV~XRZMxFnZDEjCzdj%T-eIH3s0MZe;=s@6_`gxRnDJ z-e}!&Oo|<+Bc(<@rNMJx$r+3M2nnemGGblRcJWQus?sa8Z5w;Ku5fFXUne(VRNu6X zkZM93=d`7Y7TjJ)Y+^e(QoxGiZ+4vr%PoT}X4z3exJJ3k}zl zKE8PB6r3QO`CHQf)*ob5VQGeI9+^^Y6Lv@Bb6!{9ie|=XYA|qbK>0z3t3u^HCp&!ChWwdW+|i;{ zaT7ZY^%Ef; zjgUO2u9##5Z|IPDQG8fC5h-T;ch{i0bR_cSeFq-s-Ld9B3g&8zmVq6(&O95aW?{4?9p3%`(%Y0~cwo(-=q=2psIFfKzF zKkR^R$pX68U(;5=JiwK`C!2iFWTyf;$2xz1@Y(E7m8;>ptTvSMjZzA^WYv*O+eA`y zS6J7+osVVj+cF4rg9I8K5^|zQl8?YI0CSs>)g0no^h^Y^aY6(Pn?a&OSbfP@fycMU z9_I~?EQaVqghH%Y-a{||i1{?>wTkMY}RF1 z!%p!F%#DvhEcydM!My8UIM`p<#(tvg0ig@>YGA7q>0YP)WOBD*J(&L&VAog2`D3{X z=xqHjz(a4f^S+KJSOpsDHIk&rv}PA39DT6qeBk^K2*b$cmdf~Q@KdY#x`Nomx+-ni zJrs05j@`W=y8!@?>bjzYz}?3hSw(V^W6kvA?*SPzU0=E^_oNrniXkY;f=$oXOzauI zPe!MXfwgK_-%?2D+ayg?KFCZu{E>6|-$_4i&!F>Vuz zhI}U>g2Wm$zfK5icmHddxRmqM%CUH$os5*;m$eke;J=rkN zR#)=Gv-p69&$(J{^O*B*pKoHn^zO2 zvygXYyvuZ1A9w8+GQq%=2ix8ESHa^XrX%|32|kuOZ-;l5u$*kpiNPvOo?qL_5f~;X zDydE29w(knLbSUtpU__7+1jzRz|>9LOSWeP6W;LtA>I<+Eo*G7qE+de^0m(bhK|KV zezGgnRv-s)%kjo74-b87hIoF}<($s%2ncksgi*}!4^mF18EMP%VZUM~baqqm<5{sk zozAEQ9hxp8P@Uy5PnXdv7!UwxNFQk>soAo_bI7-TznpinvOdUix}*QI@$f(f@!`c! zp=gHbnYc?N+Hijja&q%u{;uRlv>5@m8r|Lj@iaSF~0j@GJ&-$9^1n>CGIhsk3J$UbV$66mmE zy)TQoVJ4=$2H_B)hHSB?8;wCHAj^J)h=(%*m1F}z#1?pRyx&9(4>s^_DazClZMj>~ z`sQMk$JcyJoa`+a#e5aL3$Fr<*+N-M^l7SIqwSSLeq>gmV3_^0V>IKOVb}=BU-|z1 zn|jMg7bI-FP@XCa*D-3gehLjXW1Kqcq#}Z0roCXoxD?(CteK&OGKT@3S~ICK5vHDI zc4{VdD5NOMcTMG)PstpS`-nS8N-#LZBwP4e;0q@$RurETZUVg`nRka)DJsHD=jD^L zgWcj|i@j5Qv+fSBY28~{Gs-4P1hG$gsVgjz53)*`{WHwaFe_L$n4PfKi(KH7RYNI1 zC)9X2z8<6xqfcKcnjlgq&2r}Re`>a3FE7AXHZL!T%?Q0-`+Ie?ibfKy+I$z&;Sg6` zx}_{G@2nSm#t9vQEz`C{B2NO-Q9aVpfeT|!IxjA^$iNu1GH0q17xBVL5vXpq2Jc~B zd9#o?TI^Bfo?&Ot_m}#K^$`!{EMY?dy9*9D`3tJ`2_kHAHCkdV*|ajL@zbp7p57eo zE1L`tLv`pT9-X>%Po)_}U@xQ1F91%`!q-J+ju5FAm66epr|Ok0hO1`DgDJUtN)8ey zZ*i?~4NpI0wnX;0} zSVx$q%+zK=UV{^dYWEqEMVSkt%2}4T%TUK%1zU$Dq0%10-b_g^T2X2<>Cd4Jf_vK^ zW5tT7TQ!&rbT-!dM<4%)+0`h=jz1Dr!Eb6hCBX<)DQux$#?+ND@h=~3z?Z+EMGp*K z=C^8#*YbM!dnM<=fmD@ zb0`uJpYSdEuoKv+n0WLP1R7L4Jm+|2mj>O{+ad28MHGcxRlyZ!a5`m^Pjd0U1}^EL zq1yD;j4zUWX~Fo+t7A{QHn}gKS`KH>ry{QXyD>%ny7+t41K4X%c(=NL|K}T`GG^7`kQDW@Kv;3TO}Am#&G z8`QMCrCV9Q0C-{%(?mPj7^J@dEG1FuLE~-t7-R={ra@`}LEParPBJT>!(P<`D#pEw zxzP-}*2mZ>Xw{?U4kFhsj@iX%)=6|sGM;t^RWhC*YU;Z<;Ex-tfSA7??+Y9|gWUP( zTRR_sN$VyfnXZ#&3xIMq4LE}kkELMT+dn(ST1LHI1-c$2%|Y-244U=Tt>0MENL_O& zZ6%oP0C5?F&hut@ucmdvHUR>b&gw-;tGH6qE@N@sHf6%gQ7D+BlVSIKRKsdBW20D- z?gfJFc+3pJe!uSX=~M=s?pp7T!4-v%Nd@VQL@sd4w^&JghXUj^Kig6=Bc3jD)y)}=|8JCm$uPe+X_POFFjs)T`t^s@$Bi<7WEeav~T(k3Vg zQh68*v5|GFbsSfO2o4?yFR`%M!3XR0M(5Y~g2j%VXjoP_&+R%}t*K=T32a$|W?1(8wIAPv}^kwL<$6??U^dMaNof zLg{uUnw@B^T~1#Ezr>T}F97tDJ2tH023vxaR+7O``GyuksPAHk?z&HNJI!W>k% zQP(V0l?^TT=L@ux^l=t`0buF~7%FK)l|~$OG_HHvJgEq!)Kl#5HR>KM!v+mdQp&G$ zwhm~i(1UwnBvIZ*_bnYgSe zR73)NLP$a4X>jS-(l%(AvQ&*Y^EVp4UckY{><4`}52W&@Auj2$SjSSHQaQ+;2B9$d z5Vh_(;bQvGHSG_>qN6NloIh>y5+6wBU?*I-y;AZLE5-HgR^wHy ze3T$gt{XKwd{!yfY^={jl2nO}T3WM$ZMoXd3qcTiQNN_Q&%?FVhE1vJ-Y#cae({jm zv_&Ior%{7T)|4fJ2@7JjpuUxAK)+q%EGxwd!$}r&(()8(79{*hRcS#hMaw@OW`d5H zinSvEpkosBQ;`N{t1br)E@a=oiZbw)<%^`cPMi1JL?2Z;a!R~|fv27Q1M-AGlhkTHN zG2+U~df{iiWYgrFrzy<>rVW?lQA|wiDif%9V{M6qafgg?HeOZc&tXCXQ9`N)YmuX3 zq|raZMB_Z*uu-VErLh-pgM^TrtG=2({zfD9!${ZlncLn^22$VH5f5;lp-?B#5-Lc*N{i1BmA9TM085E;ztyToO zSwJ)2GA0akzJmTU{bw||XEv>NfncBq4FaH@r<+HGNd*h_u&P;&(P?Ny9SsHJBi~jE zgPa*AGU?S$dw6Adpl$$q+j@17^5eb6b^Z+A*5`)Z>VCEp znn7ZwZ1})6{PGxedCU$GFaRBS!MJ(!q-Hv*$ft* zIhDXrLovR37Cyrk4g#jf_Zq*7ub$Kd&II=y`8{GG{u^(iYi}io?{z_S_QI1_ zSuJ*FM!x+DL$RMbPQ%NHZFn1>U-Yju?(QEUj&xZ%*FSIp|7rMhPWf}* z0udraHzC%m>xnY$sAg)ddDsiZ%2}#fRG3`N5?Cwnt-KP;`G#gAmQ^Vh>8n+*Rr`iD zSKkuNc{QCJPc9n$_c|JPUN0_``O|R5tQjtEgsS;Q=hJLq%NLy@9b~}~)256w=Z8Kc z5gUehcd#7QwYoK6ASvto@TgMR@WGS1eB_X_8^d1n5BWA=<`_xJLF`>cS_iw~3Hyy3 z@(#nyyNadT0H6OY3lE0KSt9L-0=z(=H*a2_QEG+xSWE0uOVti|2p_ata_TqZd($a- zlE4#u=jNeUzm5qf>+9Xj;HGkE=%^HPuc_M1jNs;UXhuMjNeBrCyU@|*793;`sp0Cp z*U>$-1xh8IPu~k~4KY@ceR|9-FvdxXPy@^FU?|ZRPM{wlDy}|35qup|UZsLYDp{Vi z78*Zvob*OJ>`wp%rxiTz<=QA&zPwTM*6)Mqr2^x06c7kz4=fm&_z^IuvxE!8MsZwW z@mys#RGrT~i&h0;&Q^))DpUx(?il0>Zqe_y$*_jAoNr|8+ z*r!~vBBWihV1gtau{!e$V6f8?1xXHj8=c=j2s^j#6lmiq4`^O2IYt|oO(gBJDPON* zd97|HeGXhznqRcY*<+0`Ws^cbj%Us;RS$y+DSxAy*HX%% zsp7x2>MDH`a;X;=GXU2Yp*)HzGr3QT;&SL?|AOPvXo-W*9w!F#OwJMVB@l-NXKSmY z5MIl1iGAejRD^A)Z2QG8z=+Hb^(A^1Ob@pUndx*n(hr}@kDSY)Z4K~0WX9C@UX9|T z2O-HxakEHEOZIjqu!302F^5F;<&eD}9Yt+8*;TlJe2&gflb=pkC@w`?M~()ESCPd| z_PrpGT*2qSCi?}TP9~PR{Fz%g>p{G99V>E4`nyr3&GD5YSXR*(3-j(msiycBmy; z?HcRlID z0;eQnP`>~QPYdWKU{@%9*LjKGX3DtwWnPcFbk_zeW775fuBx3@&b6?{q+X9!-P@N4 zpS*xKtuDgoq#R;y=;dDIt55bH(o{PXB#lx3VXx8_hgcEWol{Cl9#xz8YCcS6dzC|N z>I+=SWQ2;ptf7}}|GNhMZ#~Jwv&h8PFtS&#@%bVE4&>H+rZ>fKTNkoaHK$D6Ulsit z^%I6&nT86JHEu_37fH(>pm18dVq`zdeJ>L@r$i@{MjsrFoWymH47$VVZg-9_whrz|xUU1X~71sX&4YOze5!HS2YetU8k;bD`hNgGYzu);alaw3^P1b4BEirb&ZjjXR1~{{O)gv(y~8iSrU_XG0iQ6pu{PuVqgk+14W8Bd z=G$PR@Nk)#bQH1@t;e{0qs@8`A;#RQY+0z|#eAtMKLO0P_Gys+OXrYZH=fK_-t?L7 z#}cDHF-v^J9`pOM(wLlIfSper*CQ(mkR_CLD)Yx?5;k2IO?|il+h-*CVA|2FHq_Mg zk_x{7@mk0T12X{lK&nXVn|?Jne@$jt)D|J$__ze47z9>}CVa)Cb8I*&JgJAdT@wei zx|&A#c%(g7eb>1RuwgPY=|SpalZVeSBm+%e3iE4fs#$ZbsQ64nY)pfH%NQ9jV-YaS zvW2eYLB>PrmuzIUdn74r4aynVtTyPBv4SR-1TZ_=r~bh{>$|Mg1m#Ji4dX_fTzwNT z1*5|8T}A=JAylgrl1|0S##!(g;xnVbf`LcYCBqO)6>A~(tl(kx8Ojk(Kr@47wp39` z_-HuPRw7Hw(*Fv%0$r_pVsU4n61c@cz`uf`?JQF-3S26&!V*=7|K58kZF({-(`}3Z zgsAYduyoH?b>BW|+H_O1jCpmp^<$Xf#c58&=5D^9j$v%D942f(MQ@nX4&pgk=r?}< z=pD&gikm8*1@)$*7hdK&@eA;#^7Y!wMNK?x$F!*{V||J0Mlq1tC&&+3%~h9)EmyKA zVH8>Yi_I95$&m747&>~T*o2)gX@+gB8q<@&i)SzFvGO!g$_%m*#`$@1GZVpdNlpGy zWN6OlJbTEs_}c1SMLl@*(!FxdC)+yf%VKkO+C8wML!OW`)9M;ql~>J+Q#(&I7}dEr?ko4BIe;fVOS%VajzK%4yo#-5W{jK_sQc1xM&RyLZT1Z&}row?dx} z%HedGW^HBxLVn@rm5YH#tR;&mgAi5m{9Vx((s;duyQ(y3AK6(Unoabl@4}f$?eAYW z7o|5OF_zY{hKkI}IuoCBeVoUZg(K7G=4}``h^HTXTwM67zkQFaw=igFcCQZypMh%HS=gKsq( zNoZOGa%!}XvNG32Lu&$+tqai^nULGQ0Rj8oRk3^UJEdgJ>=22T8cNS@d#)<%&!LNx zI(+7+1zoaCq!X!gr-iAf`ci`Dj&AkMp~Rws<(}7yeURZw>9u|c+%;Tk3rEInLQUJzg&uYTjIxhG%;}3{Y+v!?Qwge|Dl1^x@h_<|{ zl5{x=wUi3ljQu}rQaeZ_YqplKO!_ACDi;WPo{xF%!ZYsS8p(_gxs|^ZdB!|9wzt!u zC$A;QazuTd$>V7eOhSI}i&j6!t}P6i8^uMVZeMY6Be?jUqfV;sdara|&>B9JI-GDO zuhDi7>z*Rs80Z_TnqfoxWIxv3`4a7nKHg1;-a(r%RE(B1wNBG%Pw8HE7(v!*q3Ym( zrodm!?Jlu*7u(T6AxSqJ^+}x7pJ7*9&`~f8(teIMY_N3dQ73}kkRdV>peE&u(pP zy){)mHQil(rsbUT?d$tF*Kt}>`E>o%;lNhCy*!%3wx+Mgipiw=JxIE>`Apt)ecSG9+AphRh|hT-bkOPYm?h{VedXhhx@Q@_Ke_U{z@$-YfZcH&GO9-4*O{rp)g+xX|tQohl{ z!^w2j6Ef^F2$B~6#VP$Q=YQ|`zc0@}ABx820Dyu~iSh__W9ahv#rh}nqEEj)&36m# z20l>e*7p?BW-YrAZUJAW9g$wOpTc!0!hL22FSmB$B;dNJnV#?>_% z@-Aa^^E1jvRA!5Sa=19~?fg`34ST{ihN;5Og`q&FyAC18DWGPc)%)&h2Ng2+M7Z`@ zkvgTF={u_6;Zk+#3<_Ng3s(-_GQ*KQcykOSN(9yICUs)M= z=vKPmFA5pOBHM2s={K_+3Pvl2%585yOw_(G54D)V5o@?94FR0G|qfQ z=YvnAlkI1*ZQl@r#2nk?FBJPU@|HoXqKf38N^wZd^Gnfk=FqDG2SYwOn3{Mn6!6@$*g07vca1@Rs!z z%FN-}PQ}3nvwEwk^n*s7R!FbiT==wN+ij4#ni<2#BD;=~y5dS}ESubf zSL_4_o384Yd@Pb=!#nlbo@f8sRLXs-JWPW!8WWy_3OXZtWHYAFlyK}zi zXO0j(E(aVXu`ws6MHdh&ysMKPw|v%oMtOQOC(m8NUrV}@9q;wJx?dHy{fj9M0b#9> zAo)y&w||2h^6fYpT*R+bO5MaxIRPS4Hum0*fQ329^Vt4HDJ?qwtrcU%GJm1Y%91G= zo4FKyBu1(uZ@=zlK*{(Sy+T1Aq}zn+$CwbA)5K@W(F$IkJP*`#aWX25X9bC$UKBR9 zR|pv~w!G=LSgo}2R4@HBLwHq2ET*Gu8#~_UO07g3n1W98_0lMWQ!067$cMVg$`t~3 zfvnnOzAzu6ELJ*SsM%I8T3n_`T9LR<|Xz-4qC8>C{R-_=@*kBPx~_c@c) zT|GU2EzLY$RdxUM@%J{7qL)gN5-@ z>)KxwD1gCc5V0Lc-*z->2jSsij`w`F1Iykm&h_ixKZI_|Ko zh>#6Lblj~B&tl~f-b`sc?olW0$Od!4bR1X}n>t#9l9T1vuL<(YRtcv<&{`*}@w^TL@53B@ZwSjj(51|D(r~Z8 zOKcnw?73D9Kt(D$A>NDS#1P)RWIeaCQ=yqUu%%;|EUT}?D#O<4PA(aoN8WohF7jot z=`*&PSOTUdC@jZV*6!Uo72wJtP`9H#!)Vah2X_1Bf3%r%6k1%cx9J67BT-R!thYfK zxG2R7G#a;g?8gX8obgD)@}Uk(rLf6>4!*sL_cB%I?(A2h7N+L%GW@hu5u4C+PPtL$ zTFA^R5h+4Wy7>luqBJhiSiUJGS#+MfIE=dpWVL=0M|#icM19-9 z**Edir!Fh#z-_p3L)ZZv*2*||UzV5B$dSptkYEB4#= zO@X2H1#=gX?9-3J<~->7C(#uXEB8JlNK1@COn9r9`H;s2nh_V*S*XmasRbj+N^H=3 z;t3aKw{IPN%@7br31UCscaXSG(yX2yl_fCzK`YnTM>&3r$xF$NImq^;3VwDzco%JC zkt>#~$pyCszMQNn2r*N(z){T|4;kvQy#%gcEE;+f++9Xl6CZ! zimvg9>m-k9h;Q#bYAhBNV(X$N5tz)VY8OR`z6hw-?hTaCbSloWv;tQI<%gd~6@}jT z=1%j0V-(l)|Dwnd9)rMN64s_j5A+=)y@TUjMVZJLN8D;`jk6o_Q5xYd>8?GfRq&i@IqMaSE+)b77BqrJIZ$DWu;TJUtv8~ZGk?+|y2HiSdWCw5@3{SY! zI=ogX`qBYzr`$=rsL5D0iDGSC*@4UEU-&Ex+-DCL+7RANxwHiJXfhYMgvy($mJur+ z*SEAMFcZ=BQs8`^#}G_zkKC|UxAHTUqpmEhHqiCTFXrY_-cWZ8DFr-wO&c3EG5e^q zgPFbD+j{^%RD6vPYQz*0OCOYi0_@Xy>}61kIcFz=^h z3nV}GBOvjn+!4=_5e_BElvi!{<9@JEE#P#AAOPj(Ap*T{fXT}a0WIDRn4>1G%BYgF z{_jih)?y9#OQ8$*!Gd>$^4#ZcmL|cQwg5L*$OGzxr+kzjZNZ9F+}pB8NRm&rXB$FQ z;#QT}56l0$HTuU2)4j~I7o4%)ag1$d%4h0h=5RF|W%k7>3g>l$vT@cNqeaJlj0uZO z_bSZ0X2z!m>Z5FAMB#QXMMsY0DO%5kO94Nz|2l%Gg^?KT286MXvXro)i)@~ix{pv7 zf-Db1N=^#Oz^F0KtP47oTuwhIDYFw-6xCH}E#SJjtCMB@2q+lWc}J5*T>jW|X9_H4 znfN6zi^6#|h;p|mRG^1|rG{!%oo|>F^`yMSisg$%9-iGNhXdvG0|}7g?z+cAg^@W= zBuQoe>oUggw>UqL!=&zyc9nCty%_+X$o%9(?)aRV`-hb%w8Kx2%hgue5jIV8 zIgiT|R<@QK{RTl0ldb}KUcp*~+rF0U83L-E)Ctj*p^a@r?ftYk$*wAu6cc;A$?c{FnOt~RJ6ap8YI3TjE&?YACjqD^9ONz?VOf2^TV}Ghr@a z58>o6`pGHpG#z3!r|)HWhpH=WO_u0V8NSACans?{3z_d~(g~NV zPn7+OlI4T0P9?W{z()^I1b~uNmMNP>Cm-A<6p4ruOG0u5-}y~A^h=1?<;XC%J&gx$ z&Sfu*4ZcJuZJvrvys~eg=1<1^W7hTsm8+b(?q05Y;h|#v2kSf1 zuMAE#%H?OVu8Zhb@kE>6=jT6hIi_#HiwYCDr03K+m+Rs-+%4 zQW|H1FJ2p2Ek}))Rk@ZTCE*fcOmwTQtVn zv;i``%gwak{GP~Ybtmh`pk7=u)}joAC%^<#%7U577i*810B?@NFm5P$@_SL)E9@*Y zEZ?3odi%v=cD)8Hyo}RL5$Z^20C8&g?(Tx&8B_39hn<&^XXt84hHBy3F_=1{Te9j=!ekk$T>`j)rLkmvV?qZjs5EMl z0CCNnKG@714TH8cr`&Lj(~E^3N`GC7n!t<48Mcl^asVcmv;+<_-}C*}EI^cC4Z)Tx;|-lvO`0(hl_pFvPf-_Vd~@R>=GSAdFuuL^ zJcJMCZWP#I%CNDsd`?^r7%*Y@Y}edEfmNGL>$;=6na-kOoou+gZhuR+cD(zer`V35 zme|Wj#LHBUuA?0r`b|255=r*t(pTvPvM}^x0qw6Z86k^PhF~ML8)2EP^U5-eA_!R2 zq*8qmBhcUB@}r>=9GlqLg;hbFHgT|S%sG+2V^t#7B7A_dKwAhFT@4KtVG4h$)L(a# zVaba8;+JY_?bVn|MmNS11+M<0RZCm9QF%9iWxtwX#ohtO>Z+z4$m^w)>lTj>G}$mQ zCO3)_Csrf7-OXF+eVQQU#+)b`KWg~RHm#V2T7cf;dr|C&; z>SPouoD}$5P+Sq92<*j!@W>n=J!UpTXCN_+CsVZW6cLr8cU8s)fM?8*yX z9dF?92!TPyNM#D+nO)`q<=~wZaL~$4BOch5au)iQyO zW@ z68pwR6{U4-0C)Je`igm*$ob8@faK%^JvOVfT{g(c3SwiomdG9z9_!L0y;yxpimwIH z$^Aq4GJNOV6!Ca>-S^;6WRF?SQP!WOL5o4Hm7mn#ultU5LdQo96&9cQH);Q94~Wns z3?cdc%q_U{%gZA(5l2_&SHwSn$e7*gq@LYtv8Qb}%97f}^xX@Gv;hBk<281LWE%p}# z8sepZzbIkmPBk~@b_^<*Q_5Q#T^Ymo0gd?{E0nu|hkt_Ne*Iewe2HXq*MnXjIvYo=w<~x3AurbJ;#stZes0n-p0G&_rkzh(2Qe`+qquJB9D`V z(KDm3js6#o0|h$O%$fVr%1GL_nfyrNn`bL{3mxdHgr-2&EBluDXznjc<|QH%EF2&S zxZDGk7xFP*sG<07!DvNwM;B*!mrq}a_uJ-HQG2H@%D?ooNJ9xa!>nP1hAr5s6E+8$ zwr&Ko?YfXZ8Xr#D z#l>B+p0Dc|GPl2iu^PPu-+EIx;R7e-2#GWPnOvZvcO z=R+Kl%=yHYtMzf!-0klpxrM0kyb+$nNz`4CCbj;>$KoQ)+*Rp zla;^bazmJQx~ed*SS)GiSE1f`6U@sdFIh2Tmk3aj49qzxdvEl+yhfVRhstR2eCDr| zsm9%ZpwQYusP@FIKsX$YaP%GB!Qx5uqZAsNdc^}R>yy*I&vD~RMwI!j>-n9g*W$wh z#43#hQzfN#ge*}v7U+-#MwwKLskKnISVDMahf4#bxiUOa#Nux*ni8?o zR%2j_v9Um|#f#dz4^;bX#~+!-M8d|E~o8vDIVh16@5QGtrf&tT4lG$xxTe6rTOa_fJEmH$%tcthEl!(6BG zJ)&ROl@V0=pS)!#@d(%2nk)!MPvf3P!P}crfB#O{C)hLdLmAPKHeP;s;IAB)S4}l% zn9Z?-F=MYzeCqz9Opxjb((N0`5yI6OvjKL1_M;R{{gz4;rORsZwzj5if>n>&fabyk z(c3vJr*N>64;Vl(Z?fOS#w0k3lVX)bCG+HYl0Y`hjDeO(W3$vjCx*`2kdxCjHv)d^ zQt~m}7G5nEBo4wRm>7B={^V)1lm;G>gxV}E0pbG6#%gPP0@^EevvWx^Lktg2YX8(H zP8QCDjxCs!iI(rSntpwfkIBP{j8f*qdv!({N}GWxTcwSx@WEwP-~v@bebSoe#o@}| zoJ5{~@g3SP4maFeLm_&lCQ|8TpD7&m7sX}}9~+vJ2!7T1i7eIr7yA&gz(rmKE=dp0 zoS-I&k2w53iqx?}NnBqERH8^}Bg)k4e9toD*2Z)naH&ZeQz9>JNZ-Gcn5g=ENtb>{ z#odY#%QE`$OPmzCYyD%~Q$2$n9a2Vyn^OEP>#A4kb^G%v5hzKQ{H#k)hu~Rq&x7c1 zuA0mR=e<_Dk;HTki;LsLt~P2HvNcsNSO3+l(>@sLUlf023UJ=#(3D~ensuiKgoRP6 zh(Vf8jzcy|VQZ!@F^2{%lAe^OhX?#SP4C+si}sVY2F-92N&VMD;$XA^>=RG`b}HO= zUW3uue6hwQQa!kJxk44nz$1F?v$v#X!pw5aW-a3awQP@)a8NC63gt9NvD8m2a-!d# z>xKg-!5tq8x|UgB44@%r&LVDTeunKFN-KBckT(!nJ}cg$8-f_Sp~|>2Wbd*vtDL*K zuvwimf*fCGv(ex}OY!dveyM6wpw%yH*yxmIK_dgp#z zpl*nKY198|Fj8-vu47=b$D(8$Z)4u4$Q?SUA5f^cp9w|A9mXK4efb1f(vS}tAu6!< z132kefx~?!DBU(Mpnb5T`O+?ziQ!e8)Dhyheu1a1r5|ZksH8*iU6ae8=yWvsnhMB< z*-dke2_E?*S`+aiRV2yb1r#0KX2=!adsXFTyyjBF%xvcifB03ql%h^YLh zsK71@J00-fI%ehvJ#CmSb-N@vI$SSF@jlG-8Or|lb{(&1CXym!2-%i$%& z*g!|{4L;y@zLU<*vZ8NWG0w*68_>)1<0Y3Whi7Qt8ovLhpd*RlSCTYGpx z^s9|%lVmK5HABik2c$0F|oKo4$j+WGNql=3h6r2W^_XblJfA zeyWjmT-x}3-Sld2C#Hv&$vpR_3qP;rzSi1)T3t*fkJ!R-X1#Slcj)B zGxq%#zf?2xIZC|k-H-fTSA1u&pyHJghFxWD`jjvFM8H+2VmSW*k#F`Ccfrd5u>*$0qH1Bb+V2!PZ1$Qe~t-=6|@IRrnX+_ zunNOYQZ$m8tn-;2WJw-8jCDU&L^6NLU=@v*+ zPZzH&d(iJ!{q${aAjJvMBc0mPZ5J-X3KWo2jB?n?r;rxdB}jJZ%1MYdB;Cza>) z#h!Btem}I=c$oK)oUi5zm}zo(Z;)wDIftBtJU%2p-y*Dc*w;eu!#P@$UGOwXMBY`fwVltTky`inc$hnL_*a$5n7!FMSqyOA5c=($#-m-gGR zuSoEvJ)_0#(;3-f#=6Th@?Gqa-v(r|Db4@!r~p;$LD1tEjqKa(C7GVZL}^G>DA4AFzP={mJFoDheS{f<$38NS3Wr20 zGCrUA2t$&CocU)qsXOmRI8XB_2^Y6Dd_Ll92JX5_O!$RBO~NodqQgP?U;4c~3T;#G zF1NZRwY#b@!e^L(3F-}#)g{%doy(=GcA(tm8nMdnM%FmoHVl}O3qlV&XEo1ug~yFQ zvH+rJ1C9>>j>6$8toP(?uvNB~b-wW5OKQfa`F_ucou_G-U$n0PDLmweOe++v$lE40 z-Oo^f>Z`ptpckt7M*M-fqumKcg=28Oz}&G4@zS$}fu>lz-_)_%ct^+kT{I^}tj2n+ zxnhjCkZOvbmF?Yin=EzR%JjnF6uoo>I zo?`7K%dBqN^cQ813tX5y@Uy{yCK6ICE;&h^DhuBahHkun2_c;BsgSGhz1usfZm$CKpQi?yPBv3AJ6CHfUyAq(v;SIuC-leAqwDkFKCP>bs2~EC ztb1lvb=?VNUhSH84KyC0lCU(jJ9iYTb~vrx#MgXgs$R(nMtv17Fc}-ggk+1WKfk|$ z)KV_wJP|4Gvfm+=u3(qNU~st)dM+s)Wo3K^!5x285pnLDvO~BIUrJ7nuub-{=;Qo9 zve)tdEinJ<97|KS?5Gnu1iIn~l!C%Ve?rtSLCJB+@n;|QUc{0lZ?7GCcT(Q^y7Lx_ zj(O)ECxFmxSB-U1ySFrhTjWB$V)Y=Uob*CO?wFv)FF60ABidr!`Q;TK>NnI$;}TO4 zR&BWgMfTJgBggQr3=xzLJt2IbOe>PsT%3$5bZG8K}}XVs9_n0NKzF( zPuQeJCJwWT$6pl9z-P(S(c$Ys9(VsK>cX!c8H;cMoY)k~gezTzDj`@MX1s|b*2gv$x&wcD1N4~g%TVfa>GO|F>R&8DnM z9_ajfVRG>8m-Rh+$@I!EN+=F)3rsMY0aFkS5{xJ`log?FQvpibr^~Q5mu%cUDx+q88-7L9_;hkgJ)qD9=7)riBYy zU{K3AF;REq7)>ZasDI&?#8Fq6)@FL^yNbf`4U*8>gIT#SF)KR0l1<{iF{Hf?dls!A z^WSI$ZRB{Q+-HUl?U?z=>^DD7WwxsnMdk_lYhy8-P6f{%lQ#_Rg}HB3v*!d8!7wkq zi>aEfK?)Vhy)yvE`}*Cc`E2fpY1aeoG_~;r>y#W3<$#El+t*g)virW1`nHj`^MgQ-poD5zPROMbmNyHz-E&?Y^7=Prv@z99y` z^so7xY%BoB=Y6FrXc+tLDpS72pm|}9BeA`!pf%dM1(q1?sHI5hZ82|fX$4{enPh8a z>3PVT+f`63gr8Mw;zhU4C6z+nuT9aW?)sr&dJd836mTjNtLNr*sK3hGnCGvw(?C4t zt~Nl%XC?$b%ql~FY=y+#wT1~P*9}`Ol`g3XyQGLpnqkHW^0U#5a5x<7ugNNenQrRl zP918iFl4ZLi$Qid_?Bf5)h_>8nv#cWn#`VoMLEG9`c1qIcB}@Y#7m8Hh^hny-{f?e z9}`L_)^%l+X|rojW{ef=EZ*-g3dKJfu;>os_DJ>QxDLF>4=3o|y>=L#>)s80XEsWK zxm6b~=3br#Z{W?B0Z8m)0%AN!_;2i^M3LeCxR1FNrt)v>1LNP=hx)&<4{%3pNP8qh z?EUd~-*GqCP0Sd7pKG3t&%Y?@A_{71<0g*(#6INyjeXb)MvO}P1zvk4qisn}t|9iU z@me-QpYNR1n;#$)14DiXcGDg{0@)Om_Rx~tc%Mqh9 z+r=}{6$$T zu-ZKWtce2@a-x-e>9%I8@;Y)SpEK$%hU=`gz?m~`T2e`2sVmj+<*ueL-ay4))-X4Y z!71iB%;VS_^s^@+=XPVgD8+OwWhy3fQ%@%vLr9M-tNnk`A2&9ZF(dKztFmP~s{TAX z%XLo5@!5g7(m95KU6o%`WjCDbuwLGlw1TczvE6CCf;R>W>RXPU7iX$g2Y~%knFp^l zYuoamjrK*&@r-P{U-=|YHyaInfZC^Ec#10EMTjbz5?NS3AYDa^ZTVXCyHSMZA+12-zK(Z=C-$sKq&M-Lm=ItuD>k3-K~YhoaFJYzIb z6u>`I)ZML@-;-toz}W_?Z9Ur-pwj`TYUk=Lhx{{I)kT*p)OC){VZXt9zsGLRfQX;} zvogj12D>WH2=k?sqyjH9VkVO>_g>vmw7_J`B5 zr=jp?6OB^@b)|plF_`uu;srqlb)Ut$4vHr0Hjc|G?kJLoO{lVGe6jESh|Cz=wWPAn zGY;g@CnDBo7MR@7fv?e6liRvk9L z$nCuY%*svz*vgbNuSN!IUgLiz!qN z^j&sN_C211)`MnR+j2Ff09@)$ ziDbzX2Ri$D6nwk#4wq~eahuLv+HdHfH>v1T-DE-WbOkpp zUoWu$+B>gbkFxi> zx2iriU%k~a7G7Ze2$7=(uF30HN{&Fz3=4Rs0FMF3I%PPD_rmVmD1pC*E7}&IAbvKn zGn(6lcEwm{dOKOkVEwTuM$^b`Yt#G3?!lr3;`L|vUsdMmX_W$*6Z0LzTUKIyKogF$ zf?#1IJi_-y_k^#aMGW0&LEO>11`POr;2O>MyQV$4Tjmcw|4<9`63!QAF`qnOR! znv|1fV5^m`=GVs4C<^@910G^ooxkQ6t%lD^%D`d&Neg?8bxGr`r5TLR{%G4?0E*h$bRp$ ztxWs2J`#c)1=Gw+5|KDfiyw zy)B1qRy0Q*FVIcSpPg=u7Pm$wW~fDL(hGsP+vqY?;RF%hX7zMq9k!+cOgJTyaEOY# zUI#u;C#xG{A!?SI4<~=v7q+>Lwi*h(XzMl-O!VNb2av1xl6b?M(=TiP`{PyFDQL7{ z>_Dm8P)&_RWD3y6cV3p1N9z3Xco8+nt-bziE4oR1g(XyyTJQ|~csV`A55-#zSaZL1B^VKQKsH)g_tIvlsR z^ny3YKkmj_Nm(|6VXNX*|00~Hb47x^I?H%~xyCefCp6n4PTvo=(dj@P?QK`bMQNbg zrM(xH#^Xu!C5S9tqSP$+)w__E+d1RmE08LrB1MzSivBnyyhE^2I(c~{M8}l<-ZZI~ zQbJ}fT>25|WE}s`uB|PNXjImfOHQd9BF6}|0_S9=Z7!cy#$-@$(Cc=FC(EwLyB z3bNg`Z|9fKhuTbmH4d!R(_m;UE+li087^OT zNd8lJcS~WOpbv?g*j`d3j{OKUs5R4YIL2qyn~Wv&7MQFy*cHQlU(cTR$N1-GAdNcI zV_ghH&r1NjarD8-+%%YOu!uNgY^I!-ccIVk53tSX8;)><9=~Msp-wokRSZO0nsDnz z=n&h?Eu3y;Cap`%lyo{=W{Y&y%pqt;^&&jFeFAZ#C<8M_hgOG>*6Nz)g#T#L^!LV` z(tK3*D@n>RPl>R)gU*Bgu~jdYd!r`uxNENR{AK6kKhEiYrRb0;pO;;9|1WGJOP{3E z2!vWESLXBrD*h!PbhLD_rueyi)a1C@{hh17KX55gITo|)2TY^*epSo!CTicz#GGXG z|JmL8k%dmm{qM#9cdtRk=*}j8qDGu-ayBMbTgUoelzS!dpGa8>L3?bJz-us+a!Q7D znBXKr+V>zmCXkbVAnhekk%m5~C`jKh8SM{lL`a*kOAChj-kG;r7rZUqIug{UjSfuBlyX#}-%|t`bECu5W-m#5&wHu4deI_Gj z`o1&&;^gZzy<1m~yG+X(gh;66{JZ%qOmZWk9xdBMX&e7V=8`}rlf9xeo9ko>wsg9k zT`Cl+z2%<92q`N1Zx2zt6lAPuIOw$L0cfrM6C||ng_2L+>@IvLwT{`ZC(05F%dPcr zRktA%Th35%SIiA>oO>8Zi9IZ>L0Q7Ft0Xoz+B=-uZ_Ovcq^R09JB<;vI0e5?{0L=C zdK(%+eZ-{yg2Kf&DFmOnvt>WzC#gsA?A;W-FaTfqD?XmktC{cD0ZSjdV@Sh`^xe(n zijKIIBqP<*mP+*#y9B?g&>npt{fm8-5TI;Ownaesqg8>YP`sqqBnUp1R{#m)zu)T5ki?fEKa1&7PPyy0+0oKUDX zjDmhB)iGV0E*fl9?zSAGV=H#~nEspW2SM`OszeA-1h?wl5P!ONHPRFSKe4u64`1t- zE?pxD&bF$VSlDCMfG;K2$1@!9010^zY2O9;*wIdAAUN|+8u2fp=@(>6*r<+8p=lP+ zW9U756%wsRj=LWL7xdCAf)2NiUv|>15njM)+~CvxfrfX!VlmQv3ybADCo9NXrO|MH z=VY7Nf@9#RaG_+mUofe3O+wzYD3Lw)WhG{X4;3BQov?36>x>+XWE<}e`1Nzsz8d}D zFAB3_XzC#zMj9a@Zmjgf#SNNMv!EY>^2_s8xeyz8tH}GD$b#^}M9voli6G3O?5ymM znOH_k8w;{-hRr9$v;+F}S`~(9KG^dit~U;J3~cCRjqlKlFI^MZ1=v;K$Cek&#QF|Z z{4PYqr4~Iro`aRkSh5nhCh+}qyL2d4!kAOjr~W3IQyz5WoP4pQ$EoSazy|Tm5KeV@ zXC*q(qi^@+7TuTHRlP3#(TJ7=UV_W@h;GAB=ZY9|3I?d0y) z0S-Fdw}^D~VYdkW@~gGiw-g>Cv_F1YW7O@$aq!X+&v9Of!a_|Kd&wJw1|sUR{iZLr zjg8-w@}hAk3d{BVxR@wWl6{FC(w?fDN|x-3ZZM{Y-oCe3w4MJbxg@x z2R(O<(h*K{$KkP^cB5-VuS1vSF=v&EGJ!VIgVdAUpPu^gT{=oE7egnZB}DHR$2^+e zpRlz?Q3$UQpRv_srF?jFEb=TXptJny3&0d=WvjO18K7+jPhP}Er*f9+h*OUD<5NAe zOo!Iwl`DRu&WwIddiI_XKM;z+lTIsK{S~V>veAGa^KOv{Bn3;=w zE+5KvZTC6(!uqo~-+cX7=eQoReJz0-^_7XGgT=d1+hMK+L-PhPr0~yvYEaH>%@Ir6 ze(DT&?%2?Jl$zH0_dyZ2`Xbf3Ds{cH??dZGLIFVKo*#&_(}9|0XT#czH&1#?*i zpQp_hze_pN;^06dvpBUtA*Ewjxv={h@GgaeXb<}QH0;OVG&Lde7qIxo9pk^1mg+)+4YKTPencl9*e(=BFHk3L);=^&3Pxy5(zqf$pFcl6z_ za;@KYMec~LAmpL+Y87M0aY!3CfV0JKYwt)~&;I;HIfNY!{e=IyeE9wJF-S`K+smo= z|NpKa`r$FpoZ}ab!#ml_Ej{iE`SD`=tdAfJ|K+XJmldA`vr70X3PCAp<+Urg)y>Ix zJd5tzkAM$p{CJcnwF(ApUOz`4Jv7N+J*WnDhSs{_L&_wT^dG!ZN_Ak__}lyf?3N$t z;_3ld>{ikFojvJk?i(BtRl51EJizSy%PoU~RlF9= zimh^kcX}i~n)5J9T`m#qAJe>Td*5ACk}wvK^FjD(GPfQjWO||OcC$0>ga! znp@%6x8lb`)8jVyjG;YR;>GR;qaAWU&8;rM21#js^*KBG9+Qo`1D!` zIC;!o(ZY;>bujVkiI(Y9>YJ?NA8dPB{Ka(tPcUw6s-A6f{qCoJ;Vc=Tx=h1Ns&gx? zGe~Vzf1xa=EroIRMe!fCJFD;XqfJYgQ_T4bkpxZJ*t}M+JS| zupbFFs z8&4`h4rXH^U<6Yhjea(Xh}--AWd>!hMDBZc9m8yB1EVa0`|NP|&VmZ3Dd4yx{hT}b z7T)Xgz^k+zDD|aZ-{FSPYcP3JXQ772)-zbh`ZywyCT0<%LTDF()%&3c>RXzQws*<# z$z6er`YXKhg*ETTH^0~n5?|0{tnqzTw~wH=GAGWh?8&1!$7$q=IktigrBjUk_><@+ zsejK~(4R2nLPy$l0Yua{q6)yC{|?po0>f(Rs{0%SBQ+qvFuaXv4>83(rjsO^IpSQvd@sVwW#`-bmC2B(=;Eyj}sxsF~(7a@erb{ma>Y+W^*2#7#;t4 zVR;kt)|`w0y$zIT#z$hGv1M>7@BblcDmla=#g@0J@_WIXRv3?)s~rWQvsb3}P+&Xw zgG0dZuy*(%dH^J#KUV<^12Q@ z%hZ@Z@GJL6L0R-q=7mUU9QkuWk3h;px=in^LujMy-3Pw&jA2#BEu4u|BOh`0f0(igjHFUboSffch*{&XH806`s-O_Fo@f{7vd&K*Z-gcy# zyUhc6-9^s60WhhhBU?#et=MYyq+=j zW)bP3W`+SCPaP%MufV*%yrNp!u^P+IN0yS9^RC`$aHPo{bu$FZKA7>Uhf2xfKybF1 zw1tz>*Mt46B%FtccZly$op+$iV#jmb85ASMXzEJkwm!wE=WILFrYjQn^<6Y)waH-K z!UWmPC|YZ;(AyRt*IVvGp=ffgVwS$F^Z>8) zS(1%BWBo&jD5t9fuIdC^Ky3Lq!|j{%0Zhe57;2;JGS*D!5Qv~7B3w+ERPbK-FG zCl7zkhC!x3tte3yQV*Aiza>Dh+rcaz@1tDhQOKP$-PIL8JK^`Z7*nEazcnN^V9R%n zm@skl{_HG_D6^zPwaR-b=04Q*yiv<|ait$61Y_gF<~i)KF23%LfuAF2hNm9k8J`jV z2KdSDFG>p1(2j_K+~>2>zjp|9IS~C<`|x#PS=0~KCK8oPKuRsN*hs8rSpw_`hm)Q|D= z)b3IIf*ITC&7zcLeEBWdBUA(^?nC~*X(;gV*SxC}E4pX&mq9TY+@rBp>5=PXDe4nV z!O6=JuNndbB6fcNN2j3SxKnw7qWP0s2{s?`JHiQ$$G!J+d{Ejx-==dI&v0HJUj)xq zXMkLW{4g&}Gh5abPoywny_?$3;GO)T{8Xr8PFQV+4~5Y?9o_$fwzmL^q}jHG8+T`L z26uO#Y20macXx-u8h3Yhhr!()26y+tT?U7FeBZg}UHMO(xDkImqJ!$H%AJ|r)!nuC z+B?^(%g+l>y!v#2oM(?xdUs7X>w##V!yGhX-j_`9>&rAYm%e%06c;8nRtudUV423g+bu#~d?d-0&H(^i zs{wxPqGn~et_O{nVb#8!zh!(Gdz;?fJxNHUXmMs{?!W*Ya@G zH&`QLTMXC{Qvp-xp+*qZ#uJ5+8unQB5PN6~N;9dAR&MOm#Gi~vWbZ9%fpBQyfPp&T zNOCt(y^vQl$1O-2K-Tp9F`{p#Xa7KqoRZ&j%g{g1r$)?aNQZJG={#Ncu^#VELhZeH z+Zxy9q)OcVJZTIDoAWbGOsS>o${;Kh(XQc~pA9ACZh>Iyn>3)Z=!B$zx;#~ha$LDW zfWEv&eG81QAlMC_q0fOj%h;-rho6}aP{z*I0N_OvyiTMA=&Gw|Du=E1bRIA!!ycj+ zIpgo*Dg`Ju1*i5MvEtguB9N}w3vm14iAy0m+d|~k{oZ$mZb(CO5Ufcs=qRd)3rEDAfjv{qOwt) z<1JeGNPceC-Ox@=Hqv#loM~aXBn=AdlTj4qO=7SaLrsxqg~HK8<{vMWa*e|=Tsz<7 zcgh{kkPnSiMMCPIP{Ywzw(zeGL{LlT9$$t|RG3r8yWEeE&-=a%*j}9NLaa)P5@RcW zNUAwu;!~e^a|`V5XiA1eN|D6Q!Jw^M2}v*EE|U~dRbW&7ts=6Vc9kB1Q(>_j$XGig zxg}|TrF^DjHMEjZg^xFC@{&1DvFs{th})^4VhIIT9#LrSqQWBSs03ZB()E-jBw2?n zU|SoE#`5&DBXFr7;d&)_M=+NilCuRpB)?#n7n!D2#XzOY?Ag^!?GphSbibiP-J!hk z?X<36e&@&98`u|=lDX6~q#-L}O1e+F*EDm}>>_!;^ulEPlIYSS+O(pakbXUV-(Ju+ zF$b#WhqM}{Wzl8!R>IbmwT!M~%uVi`s&4fkDY~p{e1f#k8p1hm zcV8^hPVa}3KE1L&?PQRQql#POpnkCQ@@Xl1PMLQ9{>d;GDPC|+uElqhJ(@+1!Zv4 zOUlkX9LCaICb|x3n(K1XbZw<{;7H($U*hR4>*F(i4a2X`wc3T}6-{=sK!Fi`i2Mhj zfw%-RfUiD%4<-J7Ha;62jde{s&qXeF7dB5vusan=nlj}S9$KC36%9=;BrHyaP9Cm~ zC3rf&iTYS0IjLZ~t30w6S7U-fyNQcn?-6TpNiAQuS;bvFam&oUDN#tGnxt|sRj9#0 zi=gu<^S(uB@WHWj>t*M|MbyK-{VTGFlICb7_YW$V+vSGD6E`d8bOEy*&=-cie#7CN zU^HJlzGB~f*1J*s+o`k&JdIP{HCT}^Wy}~a`gszH*VfoYaqNcG*W^5)`z{5fl9_bI zQu*cD%w}J74r0HA^riDT;FC#H1}M4GSwy#&tpyD_F&Y{E0g%>w=2fN04x48qxtp`r zH__-M+~oo0Cne4AQD~JZGnIx5jvAPD9XK|6C;3po$W-F1Gf$`fT>gdU-0=05W=Yz% z*F|f+S(3FJMrw1P2JAbUcf`9H5A1Zoe(sdJixLjL13%A0w5jrY}H=Zs<8!S?wsWn8r_RYWP7USqt!e+C)MhxQI+_G-&uTEol;si)eWb zHucMDFj8Pt8kH7XssjUtx{y#g$-W47vN-c|U3}SKAA8H42%J>Y$Ii`;~Oxz%sQ z^_`MtRCX3jzJ5vW^F9LOqEQ(UoC1To#d_^z$JgmTxMeay%!J4tuA=}7^BpX;E;3Xz zV|)Q~RoM#vE$5i;{k>$XQ!-wgyO>%fb}zMmf1tp*0vDNy-ZlJtSI~MP{BzTg_Pu20 zKQ99yEj$#aUb|WiAdG(e@@9dC^=kjlQo6_q430$I&T0qxEnJ7Q-W|gUE~EgqG`iBH z0-CNSI)fTp*Q%%`X`G!scQnJE&qo@|ApB$}+%27PkDy1UlZ22q zTg7czsX}iSU5k;^RsxEc3ZGf#h~I;VSsr(CC5aLx5X;0`##Zs;B(^9DuUks@V1bYr zO|tQzNvWDpA_(ztK0fzvW%7m}V0A^EP-}*gSx9Qq@u^uL)8LHZ2C{8DXhEu2u31Kv zj|Jr3FAP<8?2u7YSIS5eCoz=>eh{{T-z1Ls2@^(JYu%S0+N^gr9W*ZXl-io3Lmk)%Gsv9k&EBQyvUsk9dA zHgjHvnG`Q6<4)#^k(iWEU(=}I)d1+HY0HuKwE|?4+&nbdxK(&lVhxzsI6i0CEcL2i z+p{oyH=H|BCe|H6DP>uY8H?hpp&@Px0A-CEZT#xUgcoJetftb|0zOwm-)lWaoQ z!{RaH{YkuEcXr8?a&N&MARWM+c-R^`Baz0SNqCf8xc|i}^uW5EHw(AHXSJayk5XUx zW@vy^&O62NKqZFkq^p*caKG*~V7xmF@5hwxjlVz~Mq1rUanrpS>r6JOi@;0o(VBC# zPPHj_wU}kD?h3B%;GAHtD?F(Og9cLG8PHpQrnkObgnN4#&=ewb_Tw24^?0 z)S(SNlbtj+$J0&Xy`$*9?V(&5N?R|T-^95{p+&jR7}d0~1ZM}KMlSqgd6A?+{i{q} zL{6w`^prj`6O$R+D?M2?k@k=yT+|&z-Mw;a0)bkK`MSc~x36SLwX66>5amT$Bufo7 zO*tYlLQr9S2`=9aemiw8;9L)|$EKDsd?pZd={yx`$!}a`;N^~poxzs3>92jv(|hen zZI_37ZFkY{nD5 zaTkVZyUB3L0#SGRncO3SB`II`mgP!|fVTYgdn-J>Y{J(Of=dB?7#4;zypqsgj)P#g z9D`VwKlh_LYdZZ;OM*^cmH)aBA%EXpbA+thN0?Nu&jHGEG-@Y(A&$E%R-9VDOP-1J zNqz`J^PbKa{8)Y3_bFQQ-`G~DV5{td+^L<_)P@PwF+HB21i{$j6059g!o23|#?W&Y zwy%SQ*%}ooZVEu>BB)*()2BuD4s8&pdwnotAH%0wUe?jSnk|$zLTf{)*v(I5D=WFl zH2sCVLJUmXx9vpkRB(y@g}i!+lYcO;ECB059zlP9WkZT3;G|VuxRz#Fo~&N_Q*{Kh zsjpqExx+E=J~Lxn1X- zP5FDBcZ7bpr`uFQXx`3pUa4jaXY|*yoJ?{#uV@R=waF~@IA>o4MyLP@+Dp+L13R4< z_v^(?=ISR5x*DNS27Akx)H0r;qi{g_CGoca8vq6`J${WPW!3fv>Ke^21qWV0Vej;t z!PF0l`@DaykTP^gEu)x2^8m6d_b=ELBRBxg<-79NW+Cw1{!#ZBy+V+urgR$1YU*F8 zE8C%gKKaqe>jd<%q9gQ>PyXBvCBN%o<>&c{k_NHzyNi6yHIV++x3kTPf5et>)lm6) zuw0r3$1ib>iu~^^CR%?0XC)SWw8y2S8mtpbWKk1_8d7bI5PgYdSUEeNi+SkV3~>$D z`1{S`p&j!Bs+4UZQNuTIGRjFhiVW=mIXJ^?##nPBa5T{#VmGn7|$&24SkZEs-|!fxQzhlSbZeik#p50O~M z*DN}A0YCMLC_2PUDNHH%*SNjcYpZlx)$Ek6eZ>Y4W%r$gnIe<2r8Xzx8S}f5SXu!I z67%_`*FcPk1peeB7arAw+tA#RgBwTE6RzVsJoy4b^?19fofbCTsQ0*rS>a9J=%9Gu z5oVcF#b}cs(p*6yCT+|GI^u*WTIV?a#61Ym)ea}h1%@!mjS$d-lLVBtE3Nh+)&?SX z%>%Sp0j9m)j3uakYm^}c01Z$N1Hy&$(jnA1k--<_x;A{o*xG$tS_kk8KBmeJ3<$%B z1gfTj_BQ3Oc;c>ZrVHUJm~EiC$?uym-7|JX5C2FK0Ad`0589TU`wW`9Cc60xf5E}n z7nC~X!h@^G{sEHaBM2M_2?GVA(3r}WO3{@f9DbNzr*jGFof%CWQU}>9bw1!=G!W@; zea;U!7?pHUxOq6cV_X**ft8W0yxSC2k=M>PYxbqj!8fd=C``>#|u7k;3@--S4h(JO~G>`-$& z_X%1Ddus0F47VV=lOA``Ti`#d6T0}|a zloDBS@aC3Uy)<;lyz~934bQ-y$H#M@8a+8gvyOX}W&g?7#NJnbet=e%Yl5{lBwS04 zjPSIf1}xMM$cLbSj=25d8O?C0j&QOHc!7-`M%oCzS+(6PlOFiOs`&I=K`XF zE}!id_u!LhN@AqnBT`O%=Sk2CLr02L4xeqwlx$T0ud&hJIIT?8vl_N*2Z2STkR;eI z-NRI!l{hTuF&=kNX(g61`{R^G8;>)6oeRe-8C~qocTKJ3v^)M~w}h_ghegJ&`(5N@ zD8eEOFIhbka?TP4cRv(VgzuWLAf!?F*?O0*E2Z;+1Cg=9nePlW;EeGRP~rCK7VZ9| zqK-v`nW)*k(!U&v+a}kn$6OcMO7FyR{Pgv@2X;OIXsI;%ifDBz`R2dpqX*8miSt}z z{$QXj5*OWg6_!$9tu-&v8YnI43d%6+fDAEn-Dw zz4$FG>I`G%84Nu>MGQ`txy^*>7v5BTcMUCNIFd3dZv8AM@uMmybXPZeVb-uIS0Q;! zuC@h-j~IWUtUm#fPY%X1H(i}?-IY+$wA^tg#O4;oXxoy|p6-;fl1r9n9(Ea(FI*{G z-(>8D9kSp+9j%o}D91#Mnc4mbD#VlmHoz%zAqK{Yl+)7uYz-ryO0Ge{ERI_cL8?y-^WgLmqVF!G;vot+x?4W4+O_b&(`UmQ)!EIZIG^w?aa6b zXRU8NLuuLk)ww%PF0E_)mT1I6oI^Uwc!Cj_-N;10@iO?IOWB)#kwA(VRTjs=3#45B zgkRg{A-Z3)t6qGHJIba%rz%u~R|#t}UmOg#ToS!XF}h#n9P^>xqMb>mtk&n2-FjJD^pk&~Wqhs(g&m1OYL5Dxd7K%FrLV+GvbtBlvRtuAF zZGLzE`%apmj)0Sk@&Mw`iTnn0pZrnn!f+c$hVvLxsq-enDuo34-5;ivjufZID>vQY z(be$np@R(~D}rz;&G|UA%1`-JE7*gJ8dTCzg>djl5r32U+qU4xegORh5#`1%cLFzy zwOs`|=chW@fXJ9u!#ltR4~jgm*fI#%|B*(2N1AxI1an zKOE#gBP6Hu+X}gY8QN<%AJGcEKXmq_Hl@|xcsVFX&=I}A z2Ges0M5Tl4icscB)cjd)IVBpIn_sm*#VK>5)OAadzF*?{L&)JaloP?{AZ0KsFDNX| zI6k1C^#l(ckuQ9w%snq;!SwS*rq$%S>XBEN(JY-4*Q(5+G zul&O42oEm+-unlD@(lKOIBll$-G$cT_!4D6N2yS72^E%o;naM;U%&_o0v<+nFG8Q+ zkUhhGw`!cD6zs60IozZokV%HVh8(>Jvp>(V72DXg_S1{Ks;jeox*n-kuY>}i8#{#{~MlTdkMMDC-KnUAEUS_3AVH!+w!mrYbh7>%$@YgiHRvnteRR_-_OFYf%9IvHOpM z|L#9M2286JUhy7Pm=wyAVdg*k`IjcWfVtz29$96mgk}^q0~YU&e=~{#B4hjhmkc}p z)?xmd8v?T&glQedwBD?LVKRvLUk}!Q3_bkUG_L>E9F%riXO~)Io_N&9f2C^v+u05x zZkvpM09JvSAH}07F7}5H|8WS*vPpsR4p-MXYe>D1!-9fh!M~ zDG;p74+8SUEwUaPTl!_W58vDm zH$Kj_F7bQqU9{|NJ`T%1{FnX}p!oSteLh61{ukF`5Wx0dEdO)7e|1m+<$uxPKMV)| z_un=C|3}@T{^x9o|NZN_K>>V}Xw##8hya2^!h9$?gZ=$01OP)L0sK{>9p~WpA@?_P zwR4S1tN>)z2mM{6{g~YW=`yEm6dAJt;ql$>=Iy}#>M<4D12w*jp%q@U4oZ!;;*D%dd7=csbJe5@-=oJex zee~Bj{0_~+iDQD^zejUZct$&Gn39Xn6tK4#hQTFpDK*InkfdG25h|9jMK=mo79v;2 zXYw)fHiw2vm${zGg2J%I)zU&vgpU))aJT?rYOXl4b(RM9sL^*`Drqhu77QqICc4FtMLY2&NI6zBrSx zcACR%{x0a)jnlo=nb_Z6hpJ2@i<%sM%b&N&=}cXA{+2vz1z#!I@PYoVy%3HtX7{`K zb?~ep*{+~A>AZxP!;IYlNYLTrFs2BSyi$+8)gXzXJNnfUE-9MeJ&T&))AvfVZa| zGZ2uX3ZkM%rlxsXmBPH(t8H0^8c&vmrkL0)L#fP#7c!Cqc~Y^7Kn6=UmySWm_$Q-e zrqF%CH15Q<(?X{%#B-*2vd;xZlI22_Vhs7|Y4f$h@|#l|tmQ&DRs+#|-$bZj^x5e* z8Sh-S;jl;aTg>YXzUB1<&exO2A&H}9F+-qZlq(ht#egf7ei8gEL#EgpC^CxRCrri; zwndlZyw2@)T--woTTi+l;V%h}@Td3uVKIxr?W0Qw4z?z|OhX4a1I2g$(aT3D)G72DXz0mYMA}EJx z-3&QeFmZF9Sm!5jQ#+nsw&!uMOw+(B_ds_D(c3?7#O=B0I<<-F-){4Wb1J=&hGIVJ zJNnu$r$A$46#;PHE2v6hyg5PoODbpQHOAm9!f860*R!GMkz&I?m*-kvP?peCG49|9 zqzNb^(QohvTV81bciZ2et$+i*vCKpo4>8U=r?Z}n?kd%3D=5u7O7l-TZF7_>aU)uu z${6F;Z+d$|;#*e27!S*iUq3+inf$NnKIX;Z>n^E64h0U+htr#hei_%7Md+>3*5a%4 zkYPG@M|Kk6VJ~<1Gvu5h?pG&5iOAb|Ed>VXeupN#`|gXe!G*5kRVa*`M-oKdS7j`N z_c0ye=oC&zL{xS!9A8&k1@kPWWMFU#;BV9*L(-C!M!dmt5%bx?9QecZ11D7x*`|Gz z4VW8~`G4;YC1LhDGV$}8GU(IlSA6ApEc=8j1A&dz8DMoQk~^;+*LQ%8DtieONr~H` z7YU%~EX{vm9BiVgM2IS_+_;|kQFdxc49#5p?1UtOuJR!Rz9bpnT|Yga6MQDh`GJdz9)iF{&y7djSn|uUezn+V zZ0x&Au#Y~n=;$nN0c077XLwVVT!BRuQSafg5@tDR=3|u#-ad>NnAJ_rWGE$6*s;L% zE^EFd{U3l*5h`4UkGIO&v&h-gYGmBlrAzRd$aSX%!js@{w1U~hE`3)H7>C9!9&>c} zcbT&gHlc$`obJo(Z-O2dYNC_jaP7$5;e&(6639Nk!a0Th0J;%=L<3&*2GzlCpSi)_ z!6aFLfqrqX%u81iVCm!te*op+5~zr**74IFHOidKQpSZK1Gs3K%?L2vqGH48)W-SE z!iW$yQ$ILI1} z*a6L<(D=eaS195h;@IBKYLVS#7)(ix{KNzt-9pG$F_{og#gzsWlM-8H#$fVzcyR8+ z!m`|6ViLa|WNy-ITZDohh1I4!PjGa4d-i5rJrE{v1is;2@|$@O%(KNiB!-e0hHmx# zk)qII92f-K@{c#_fY5})8a_XDRG+rX*`SDLl-i~x{^k9zCO;s`y&pyg#=Ewh3saar zN8iEm49;A{V3|XsO@Bsx$O^&_AB!7K=qq-4{qD7(PBNyCO+M7%FdZVV0!Xq_mGN~Z zb^q-HzrOKJCL(9#R*=MBAg0E{8vFp#1?tUKDDD8FHoMEVY{!r+jocczuPV&cJ{{BI z3#!Zy$MHGEeLn4kg?jTfvM~bF7hG;bgzdiE5+s2XhJ=Mom_|WaK!>AZmD{0>d!a?$ zG7$Lc2iY+!_D})!LU*YP`YwEkVk1fM2ax7Q;=9ouX{+=OfUGI3a(_nvgR}w;LJg5& zHXAs6q5(^MYgsqbl>VY==Fl?P(BxG%qm}Cc6%2!K7X*ew(N}|0P%8dfHULhqFGF#V zCpF4|VGn--Mh=ag8`PilD^U@$1RWh$K@@$(lrdbZoV@)*bc2}o3o3C6sg0rIPipN7 zZ5_JvBuD@hf-5p4E*W#_L!=*9AXG8^#?b{iP<0Tj76F!lOJwM&nL+qY-E6DuIj~EmEn0B4*F7-h$kt*e+x)sp6gw zgiI&)mxiA@?N%v*d%0X!h!27T8fkuDZ^R7d&1@A9cQXpa>pFUk7;I@LTSB5JZ8

HJSq5O|JsR4fKjQZ3Uk2B<>9kwio-_@3`PrvUx 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
&mkq9ik>N;~+V*@3X)A2qUO@&zVK++*xB6md z>3Frn*SZQ&@04<;B*=PvOV0kNjzS;KZ(6U{QQFZkm8^NW5H)K!ei9LW*aSy9Y2(#r zxo94h>Fsm3=%J%yA&9&eeXU3~6ZOfMW17;$&_GD}zWSzH5mF%+28OaV?VBm;GF(Wd z&K>32dfNz#61EW*g*S|lp_H7T&Wxk+NaAHx8Crqbrnidy;%2AqpO+B5W&Y$oXsp&0 z2i_DH^F>YcWQ3K&`(S+a%B;SMFV$&vIHMHA5%{h^(g0J82eLtCJ$-``DSl?H19;_| zYJN+D?Bz$ha+O=d^Ciu&$$SVnDK}W~to{W4rOWy>n!BL8#!~rpLmOQQ9%n>c9b~^` z#A&Yo8qD(bFE9U@Tz8UJjtJ&@&k^djo4mp!x)Vc!Dp*i)P# zsBAnHaMpq@DV5@T(jQV-ak==MJyj0BLNq;)-o92xGeF`JT3>11A4^pvhwW&s`?NR&U209BWzGwnql8m*)sMC$zQiJPLw)N ze(O1#itiN)$}7iRwd;a8(sP3^r`?;#j>!cegUY!Q0{0ZMHU2JRDm~pZ-0-B{cTC8S zf1?s=*|}CK-t26l3=sN$b1nsG{I^W{Q-bsWtLy>KUV8Zt}`RYE>sdT1re=IB4sUYryiHbU)ZcJ>>`&l zl*=SrE!_&Lnu~Zs?pmw4_eR%b)>%E|^F|W--r%UA_3sDQ1LdQX-rSELGuqh#F5bG- z>=97yKKC%!rE$m0E3PS7$EOA|4ktvFAwbeQJ15mf{;r}1il8Zcf`uIy82gQms*~R` z@pQlMOr2bGV_zS3fnZ=#T}wdyPb^4<6@T8ecV|<}!QF!*9fiU0VIr-m2Ggf%zjL%7 zjFj~oTs?6c^i~0A`~^T=Osw^;d_h^Q!+GsY`)yYLsP~I>eq`C2I@&rr>JI0u=jD7% zk54w+Y3Tq88f-~5w0agb?M$@hB?(oK}j6VYp zv{q@7h`2NKr1}i@#4p$iggw_KFA_m_6{`*|w&r`Ll2jC9d@No+em1)6NKkfGEuLNK zI3<3Z!z<8RbMFxO?HrO;+R?TdTEUgz@VBec|sFJDvd_5wTJ$9;3MD zwbzu4g+x+9S@EdlqK}=PoNqmhs^S7t;6?{1ZTp%jpTcq&NY$SlXe9e`)IS)SzUr`e z+-5O*!b{L2uXu4&!K=PE*Xo3=7BQO?T3RcPwbOBs;U6akOFa?m>Zp2a&N@#L*T{%s zF>vU%ZIt7XB>JygEokDYir086)bk}wK?*aQiq_VHhubq)1eSV~EJ_ny`~F3ljPDQ2 zWGwA^On*h0EMk77X+YR4n$2l(%V&qey?qbHEE~)3SCCUY14!8w&GCAI^60*tVjvg3 z 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 literal 0 HcmV?d00001

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 }{qNkSv`V5r|hz}Lg%4w-k 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 Blgt1B literal 0 HcmV?d00001 diff --git a/EinfuehrungTesting.pdf b/EinfuehrungTesting.pdf new file mode 100644 index 0000000000000000000000000000000000000000..eb2eb84c68c6639732e549abdec364e35f39f10b GIT binary patch literal 58311 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 z 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 RVSIjj*D?Nv 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 +#include +#include + +#define MAX_RAND_TRIES_PER_WORD 10 +#define EMPTY_CHAR 0 + +//TODO: Spiellogik implementieren: +/* * Wörter aus der Wortliste zufällig horizontal oder vertikal platzieren + * restliche Felder mit zufälligen Buchstaben füllen */ + +// Creates the word salad by placing words randomly and filling empty spaces +int createWordSalad(char salad[MAX_SEARCH_FIELD_LEN][MAX_SEARCH_FIELD_LEN], unsigned int searchFieldLen, const char words[][MAX_WORD_LEN], unsigned int wordCount) +{ + +} + +// Prints the word salad to console +void showWordSalad(const char salad[MAX_SEARCH_FIELD_LEN][MAX_SEARCH_FIELD_LEN], unsigned int searchFieldLen) +{ + +} diff --git a/Start_Windows/game.h b/Start_Windows/game.h new file mode 100644 index 0000000..95346af --- /dev/null +++ b/Start_Windows/game.h @@ -0,0 +1,11 @@ +#ifndef GAME_H +#define GAME_H + +#include "input.h" + +#define MAX_SEARCH_FIELD_LEN 100 + +int createWordSalad(char salad[MAX_SEARCH_FIELD_LEN][MAX_SEARCH_FIELD_LEN], unsigned int searchFieldLen, const char words[][MAX_WORD_LEN], unsigned int wordCount); +void showWordSalad(const char salad[MAX_SEARCH_FIELD_LEN][MAX_SEARCH_FIELD_LEN], unsigned int searchFieldLen); + +#endif diff --git a/Start_Windows/graphicalGame.c b/Start_Windows/graphicalGame.c new file mode 100644 index 0000000..fc648b6 --- /dev/null +++ b/Start_Windows/graphicalGame.c @@ -0,0 +1,455 @@ +#include +#include + +#include "graphicalGame.h" +#include "raylib.h" + +#define MAX_MESSAGE_LEN 256 +#define MAX_SOLUTION_WORD_LEN 16 + +typedef struct +{ + Vector2 startPosition; + Vector2 endPosition; + int isSelected; +} MouseSelection; + +typedef struct +{ + Vector2 position; + char character[2]; + int isMarked; +} CharSquare; + +typedef struct +{ + CharSquare *squares; + unsigned int count; + unsigned int squareSize; + unsigned int fontSize; + Vector2 position; + Vector2 size; +} CharSquarePanel; + +typedef struct +{ + char content[MAX_WORD_LEN]; + char *solution; + Vector2 position; + int wasFound; +} SearchWord; + +typedef struct +{ + SearchWord *words; + unsigned int count; + int fontSize; + Vector2 position; + Vector2 size; +} SearchWordPanel; + +typedef struct +{ + char content[MAX_MESSAGE_LEN]; + Vector2 position; + unsigned int size; +} WinMessage; + +typedef struct +{ + char text[MAX_MESSAGE_LEN]; + Vector2 position; + Vector2 size; + unsigned int fontSize; +} HelperMessage; + +// Creates a helper message to guide the user +static HelperMessage createHelperMessage(unsigned int screenWidth) +{ + const char *text = "Please search below for the words located at the bottom \nand draw a line exactly on the desired characters ..."; + HelperMessage msg = {"", {0, 0}, {screenWidth, 0}, 18}; + + // Copy text into msg, ensuring does not exceed max length + strncpy(msg.text, text, MAX_MESSAGE_LEN); + msg.text[MAX_MESSAGE_LEN-1] = '\0'; + + // Set the vertical size based on font size + msg.size.y = 3 * msg.fontSize; + + return msg; +} + +// Creates a winning message when the user wins +static WinMessage createWinMessage(unsigned int screenSize) +{ + WinMessage winMsg; + char *text = "Congratulations! You won!"; + + strncpy(winMsg.content, text, MAX_MESSAGE_LEN); + winMsg.content[MAX_MESSAGE_LEN-1] = '\0'; + winMsg.size = 30; // Set font size + + // Calculate x and y positions for centering the message + winMsg.position.x = (screenSize - strlen(winMsg.content)*winMsg.size*0.52) / 2; + winMsg.position.y = screenSize / 2; + + return winMsg; +} + +// Frees memory associated with a search word panel +static void freeSearchWordPanel(SearchWordPanel *panel) +{ + for(int i = 0; panel->words != NULL && i < panel->count; i++) + free(panel->words[i].solution); // Free solution strings + free(panel->words); // Free word array + panel->words = NULL; + panel->count = 0; + panel->size.x = 0; + panel->size.y = 0; +} + +// Creates a panel to display a list of search words +static SearchWordPanel createSearchWordPanel(const char words[][MAX_WORD_LEN], unsigned int numberOfWords, unsigned int windowOffset) +{ + const int maxStringLenInPx = 200; // Max width of each word + const int fontSize = 18; // Font size for displaying words + const int rowHeight = fontSize * 1.2 + 5; // Height of each row of words + + SearchWordPanel panel = {NULL, 0, fontSize, {0, windowOffset}, {windowOffset, 0}}; + + unsigned int xOffset = 5; + unsigned int yOffset = 15; + + // Allocate memory for words if any are present + if(numberOfWords > 0) + panel.words = (SearchWord *)malloc(sizeof(SearchWord) * numberOfWords); + + // If memory allocation is successful + if(panel.words != NULL) + { + // Loop through and set up the words and their positions + for(int i = 0; i < numberOfWords; i++) + { + strncpy(panel.words[i].content, words[i], MAX_SOLUTION_WORD_LEN); + panel.words[i].content[MAX_SOLUTION_WORD_LEN-1] = '\0'; + + // Truncate word if exceeds max length + if(strlen(words[i]) > MAX_SOLUTION_WORD_LEN-1) + strncpy(panel.words[i].content+MAX_SOLUTION_WORD_LEN-4, "...", 4); + + // Allocate memory for solution word + panel.words[i].solution = (char *)malloc(sizeof(char) * (strlen(words[i]) + 1)); + + if(panel.words[i].solution != NULL) + strcpy(panel.words[i].solution, words[i]); + else + { + freeSearchWordPanel(&panel); // Free memory in case of failure + numberOfWords = 0; + break; + } + + panel.words[i].wasFound = 0; // Initialize "found" flag + panel.words[i].position.x = xOffset; + panel.words[i].position.y = yOffset; + + // Move to next position for next word + xOffset += maxStringLenInPx + 5; + + // Move to next row if needed + if(xOffset > windowOffset) + { + xOffset = 5; + yOffset += rowHeight; + } + } + panel.count = numberOfWords; // Sets total word count + + // Adjust panel size based on last word's position + if(numberOfWords > 0) + panel.size.y = panel.words[numberOfWords - 1].position.y + rowHeight; + } + + return panel; +} + +// Creates a square for a character in the search grid +static CharSquare createSquare(unsigned int rowIdx, unsigned int colIdx, char character, unsigned int squareSize) +{ + CharSquare square; + square.position.x = colIdx * squareSize; + square.position.y = rowIdx * squareSize; + square.character[0] = character; + square.character[1] = '\0'; + square.isMarked = 0; // Mark as unmarked initially + + return square; +} + +// Creates a panel of character squares (the search grid) +static CharSquarePanel createCharSquarePanel(const char wordSalad[MAX_SEARCH_FIELD_LEN][MAX_SEARCH_FIELD_LEN], unsigned int searchFieldSizeInChars, int panelSizeInPx) +{ + CharSquarePanel squarePanel; + squarePanel.squares = (CharSquare *)malloc(sizeof(CharSquare) * searchFieldSizeInChars * searchFieldSizeInChars); + squarePanel.count = 0; + squarePanel.squareSize = (double)panelSizeInPx / searchFieldSizeInChars; // Calculate the square size + squarePanel.fontSize = squarePanel.squareSize * 0.75; // Set font size relative to square size + squarePanel.position.x = 0; + squarePanel.position.y = 0; + squarePanel.size.x = panelSizeInPx; + squarePanel.size.y = panelSizeInPx; + + // If memory for squares is allocated successfully loop through grid and create squares for each character + if(squarePanel.squares != NULL) + { + for(int i = 0; i < searchFieldSizeInChars; i++) + { + for(int j = 0; j < searchFieldSizeInChars; j++) + { + squarePanel.squares[squarePanel.count] = createSquare(i, j, wordSalad[i][j], squarePanel.squareSize); + squarePanel.count++; + } + } + } + + return squarePanel; +} + +// Frees memory associated with CharSquarePanel +static void freeCharSquarePanel(CharSquarePanel *squarePanel) +{ + free(squarePanel->squares); // Free squares array + squarePanel->squares = NULL; + squarePanel->count = 0; // Reset count +} + +// Draws all squares of CharSquarePanel +static void drawSquares(const CharSquarePanel squarePanel) +{ + float fontOffset = squarePanel.squareSize / 4; // Offset for font positioning + + // Loop through all squares and draw them + for(int i = 0; i < squarePanel.count; i++) + { + CharSquare square = squarePanel.squares[i]; + + Vector2 squareScreenCoord = {squarePanel.position.x + square.position.x, squarePanel.position.y + square.position.y}; + Color squareColor = DARKBLUE; + Color fontColor = LIGHTGRAY; + + // Change colors if is marked + if(square.isMarked) + { + squareColor = GREEN; + fontColor = BLACK; + } + + // Draw square and its border + DrawRectangle(squareScreenCoord.x, squareScreenCoord.y, squarePanel.squareSize, squarePanel.squareSize, squareColor); + for(int i = 1; i <= 3; i++) + DrawRectangleLines(squareScreenCoord.x, squareScreenCoord.y, squarePanel.squareSize-i, squarePanel.squareSize-i, LIGHTGRAY); + + // Draw character inside the square + DrawText(square.character, squareScreenCoord.x + fontOffset, squareScreenCoord.y + fontOffset, squarePanel.fontSize, fontColor); + } +} + +// Checks if selected word is valid solution +static int isSolution(const char *solution, SearchWordPanel searchWordPanel) +{ + for(int i = 0; i < searchWordPanel.count; i++) + if(strcmp(solution, searchWordPanel.words[i].solution) == 0) + { + // Mark word as found and return true if solution matches + searchWordPanel.words[i].wasFound = 1; + return 1; + } + + return 0; // false if not found +} + +// Updates the marked squares based on user selection +static void updateSelectedSquares(const MouseSelection selection, CharSquarePanel squarePanel, SearchWordPanel searchWordPanel) +{ + unsigned int wordIdx = 0; + char selectedWord[MAX_WORD_LEN]; + unsigned int selectedIdx[squarePanel.count]; + float radius = squarePanel.squareSize / 2; + + // Loop through all squares and check if selected + for(int i = 0; i < squarePanel.count && wordIdx < MAX_WORD_LEN-1; i++) + { + Vector2 center = {squarePanel.squares[i].position.x + squarePanel.position.x, squarePanel.squares[i].position.y + squarePanel.position.y}; + center.x += radius; + center.y += radius; + + // Check if square is selected by mouse + if(CheckCollisionCircleLine(center, radius, selection.startPosition, selection.endPosition)) + { + selectedWord[wordIdx] = squarePanel.squares[i].character[0]; + selectedIdx[wordIdx] = i; + wordIdx++; + } + } + selectedWord[wordIdx] = '\0'; + + // If selected word is a solution, mark it + if(isSolution(selectedWord, searchWordPanel)) + { + for(int i = 0; i < wordIdx; i++) + squarePanel.squares[selectedIdx[i]].isMarked = 1; + } +} + +// Handles mouse input for selecting words in grid +static void handleMouseInput(MouseSelection *selection, CharSquarePanel squarePanel, SearchWordPanel searchWordPanel) +{ + if(IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) // Start new selection + { + selection->startPosition = GetMousePosition(); + selection->endPosition = selection->startPosition; + selection->isSelected = 1; + } + else if(IsMouseButtonReleased(MOUSE_BUTTON_LEFT)) // End selection + { + updateSelectedSquares(*selection, squarePanel, searchWordPanel); + + selection->isSelected = 0; + } + else if(IsMouseButtonDown(MOUSE_BUTTON_LEFT)) // Update end position while selecting + { + selection->endPosition = GetMousePosition(); + } +} + +// Draws selection line on screen if selection is active +static void drawSelection(const MouseSelection selection) +{ + if(selection.isSelected) + { + DrawLine(selection.startPosition.x, selection.startPosition.y, selection.endPosition.x, selection.endPosition.y, WHITE); + } +} + +// Draws search word panel (list of words to be found) +static void drawSearchWordPanel(SearchWordPanel searchWordPanel) +{ + for(int i = 0; i < searchWordPanel.count; i++) + { + Vector2 wordScreenCoord = {searchWordPanel.words[i].position.x + searchWordPanel.position.x, searchWordPanel.words[i].position.y + searchWordPanel.position.y}; + DrawText(searchWordPanel.words[i].content, wordScreenCoord.x, wordScreenCoord.y, searchWordPanel.fontSize, WHITE); + + // If word has been found, highlight it + if(searchWordPanel.words[i].wasFound) + { + int xOffset = MeasureText(searchWordPanel.words[i].content, searchWordPanel.fontSize); + for(int i = 0; i <= 3; i++) + DrawLine(wordScreenCoord.x - 3, wordScreenCoord.y + 5 + i, wordScreenCoord.x + xOffset + 3, wordScreenCoord.y + 5 + i, GREEN); + } + } +} + +// Draws helper message (instructions or tips for user) +static void drawHelperMessage(const HelperMessage msg) +{ + DrawRectangle(msg.position.x, msg.position.y, msg.size.x, msg.size.y, BLACK); // Background for message + DrawText(msg.text, msg.position.x + 5, msg.position.y + 5, msg.fontSize, WHITE); // Display message text +} + +// Draws the entire game content, including helper message, squares, and search words +static void drawGameContent(const HelperMessage helperMsg, const CharSquarePanel squarePanel, const MouseSelection selection, const SearchWordPanel searchWordPanel) +{ + drawHelperMessage(helperMsg); + drawSquares(squarePanel); + drawSearchWordPanel(searchWordPanel); + drawSelection(selection); +} + +// Draws success message when player wins +static void drawSuccessContent(WinMessage msg) +{ + unsigned int textWidth = MeasureText(msg.content, msg.size); + DrawRectangle(msg.position.x-20, msg.position.y-20, textWidth+40, msg.size+40, GREEN); // Background for success message + + for(int i = 0; i < 5; i++) // Draw borders around success message + DrawRectangleLines(msg.position.x-20+i, msg.position.y-20+i, textWidth+40-i*2, msg.size+40-i*2, WHITE); + + DrawText(msg.content, msg.position.x, msg.position.y, msg.size, WHITE); // Display success text +} + +// Draws entire game screen, including game content and success message if applicable +static void drawAll(const CharSquarePanel squarePanel, const MouseSelection selection, const SearchWordPanel searchWordPanel, const HelperMessage helperMsg, const WinMessage msg, int hasWon) +{ + BeginDrawing(); + ClearBackground(BLACK); // Clear screen with a black background + drawGameContent(helperMsg, squarePanel, selection, searchWordPanel); // Draw game content + + if(hasWon) // If player has won, draw success message + drawSuccessContent(msg); + + EndDrawing(); +} + +// Checks if all words in the search word panel have been found +static int allWordsFound(SearchWordPanel searchWordPanel) +{ + // Loop through all words and check if any is not found + for(int i = 0; i < searchWordPanel.count; i++) + if(!searchWordPanel.words[i].wasFound) + return 0; // Return false if any word is not found + return 1; // Return true if all words are found +} + +// Main game loop where game is run and updated +static void gameLoop(const Vector2 screenSize, MouseSelection mouseSelection, CharSquarePanel squarePanel, SearchWordPanel searchWordPanel, const HelperMessage helperMsg, const WinMessage winMsg) +{ + InitWindow(screenSize.x, screenSize.y, "Word Salad"); // Initialize game window + + SetTargetFPS(60); + + while (!WindowShouldClose()) // Keep running until window is closed + { + handleMouseInput(&mouseSelection, squarePanel, searchWordPanel); // Handle mouse input (selection) + + // Draw all game content including helper message, squares, and search word panel + drawAll(squarePanel, mouseSelection, searchWordPanel, helperMsg, winMsg, allWordsFound(searchWordPanel)); + } + + CloseWindow(); +} + +// Initializes and starts game, setting up necessary elements and entering game loop +void startGame(const char wordSalad[MAX_SEARCH_FIELD_LEN][MAX_SEARCH_FIELD_LEN], unsigned int searchFieldSize, char words[][MAX_WORD_LEN], unsigned int numberOfWords, unsigned int windowSize) +{ + const int windowWidth = windowSize; + + Vector2 screenSize; + + // Create necessary game elements like helper message, square panel, and search word panel + HelperMessage helperMsg = createHelperMessage(windowWidth); + CharSquarePanel squarePanel = createCharSquarePanel(wordSalad, searchFieldSize, windowWidth); + SearchWordPanel searchWordPanel = createSearchWordPanel(words, numberOfWords, windowWidth); + WinMessage winMsg = createWinMessage(windowWidth); + + MouseSelection mouseSelection; + + mouseSelection.isSelected = 0; // Initialize mouse selection to not be active + + // Adjust panel positions + squarePanel.position.y = helperMsg.size.y; + searchWordPanel.position.y = helperMsg.size.y + squarePanel.size.y; + + // Set screen size based on the panels' sizes + screenSize.x = squarePanel.size.x; + screenSize.y = helperMsg.size.y + squarePanel.size.y + searchWordPanel.size.y; + + // Start game loop + gameLoop(screenSize, mouseSelection, squarePanel, searchWordPanel, helperMsg, winMsg); + + // Free up allocated memory when game is done + freeCharSquarePanel(&squarePanel); + freeSearchWordPanel(&searchWordPanel); +} + +/*gcc -fPIC -c input.c game.c graphicalGame.c main.c +gcc -shared -o libwortsalat.a input.o game.o graphicalGame.o main.o*/ \ No newline at end of file diff --git a/Start_Windows/graphicalGame.h b/Start_Windows/graphicalGame.h new file mode 100644 index 0000000..cacdf24 --- /dev/null +++ b/Start_Windows/graphicalGame.h @@ -0,0 +1,8 @@ +#ifndef GUI_H +#define GUI_H + +#include "game.h" + +void startGame(const char wordSalad[MAX_SEARCH_FIELD_LEN][MAX_SEARCH_FIELD_LEN], unsigned int searchFieldSize, char words[][MAX_WORD_LEN], unsigned int numberOfWords, unsigned int windowWidth); + +#endif diff --git a/Start_Windows/input.c b/Start_Windows/input.c new file mode 100644 index 0000000..ed77805 --- /dev/null +++ b/Start_Windows/input.c @@ -0,0 +1,12 @@ +#include "input.h" +#include +#include + +// TODO: +// eine Funktion implementieren, die ein einzelnes Wort aus einer Textdatei (words.txt) einliest und als C-String zurückgibt. + +// Read words from file and store in 'words' array +int readWords(FILE *file, char words[][MAX_WORD_LEN], unsigned int maxWordCount) +{ + +} \ No newline at end of file diff --git a/Start_Windows/input.h b/Start_Windows/input.h new file mode 100644 index 0000000..032ec28 --- /dev/null +++ b/Start_Windows/input.h @@ -0,0 +1,11 @@ +#ifndef INPUT_H +#define INPUT_H + +#include + +#define MAX_WORD_LEN 100 +#define MAX_LINE_LEN 1024 + +int readWords(FILE *file, char words[][MAX_WORD_LEN], unsigned int maxWordCount); + +#endif diff --git a/Start_Windows/main.c b/Start_Windows/main.c new file mode 100644 index 0000000..03da755 --- /dev/null +++ b/Start_Windows/main.c @@ -0,0 +1,54 @@ +#include +#include +#include "input.h" +#include "game.h" +#include "graphicalGame.h" + +#define MAX_NUMBER_OF_WORDS 100 +#define SALAD_SIZE 20 + +int main(int argc, char *argv[]) +{ + int exitCode = EXIT_SUCCESS; + + // Check if the correct number of arguments is provided + if(argc != 2) + { + fprintf(stderr, "Usage: %s \n", argv[0]); + exitCode = EXIT_FAILURE; + } + else + { + char words[MAX_NUMBER_OF_WORDS][MAX_WORD_LEN]; // Array to hold the words to be used in the game + unsigned int wordCount = 0; + + FILE *file = fopen(argv[1], "r"); + + if(file != NULL) + { + unsigned int placedWords = 0; + char wordSalad[MAX_SEARCH_FIELD_LEN][MAX_SEARCH_FIELD_LEN]; // 2D array to store the word salad + + // Read words from file and store in 'words' array + wordCount = readWords(file, words, MAX_NUMBER_OF_WORDS); + fclose(file); + + // Create the word salad by placing words into grid + placedWords = createWordSalad(wordSalad, SALAD_SIZE, words, wordCount); + + // TODO: + // Check if all words were successfully placed + // Start the game if successful + // error message if some words couldn't be placed + + } + else + { + // Print error message if file couldn't be opened + fprintf(stderr, "Could not open file %s for reading ...\n", argv[1]); + exitCode = EXIT_FAILURE; + } + } + + return exitCode; +} \ No newline at end of file diff --git a/Start_Windows/makefile b/Start_Windows/makefile new file mode 100644 index 0000000..146a8c6 --- /dev/null +++ b/Start_Windows/makefile @@ -0,0 +1,46 @@ +CC = gcc +CFLAGS = -g -Wall -I$(raylibfolder) +LDFLAGS = -lopengl32 -lgdi32 -lwinmm +BINARIES = ./windows + +raylib_folder = ./raylib +unityfolder = ./unity + +# -------------------------- +# initiales Spiel bauen +# -------------------------- +wordsalad_initial: + $(CC) -o wordsalad_initial $(BINARIES)/libwordsalad_complete.a $(BINARIES)/libraylib.a $(LDFLAGS) + + +# -------------------------- +# Normales Spiel bauen +# -------------------------- +all: main.o input.o game.o graphicalGame.o $(BINARIES)/libraylib.a + $(CC) $(CFLAGS) -o wordsalad main.o input.o game.o graphicalGame.o $(BINARIES)/libraylib.a $(LDFLAGS) + +main.o: main.c + $(CC) -c $(CFLAGS) main.c + +input.o: input.c + $(CC) -c $(CFLAGS)input.c + +game.o: game.c + $(CC) -c $(CFLAGS) game.c + +graphicalGame.o: graphicalGame.c + $(CC) -I$(raylib_folder) -c $(CFLAGS) graphicalGame.c + +# -------------------------- +# Unit Tests +# -------------------------- +TEST_BIN = runTests + +test: input.o game.o unit_tests.c + $(CC) $(CFLAGS) -I$(unityfolder) -o $(TEST_BIN) input.o game.o unit_tests.c $(BINARIES)/libunity.a + +# -------------------------- +# Clean +# -------------------------- +clean: + del /f *.o *.exe diff --git a/Start_Windows/raylib/raylib.h b/Start_Windows/raylib/raylib.h new file mode 100644 index 0000000..a26b8ce --- /dev/null +++ b/Start_Windows/raylib/raylib.h @@ -0,0 +1,1708 @@ +/********************************************************************************************** +* +* raylib v5.5 - A simple and easy-to-use library to enjoy videogames programming (www.raylib.com) +* +* FEATURES: +* - NO external dependencies, all required libraries included with raylib +* - Multiplatform: Windows, Linux, FreeBSD, OpenBSD, NetBSD, DragonFly, +* MacOS, Haiku, Android, Raspberry Pi, DRM native, HTML5. +* - Written in plain C code (C99) in PascalCase/camelCase notation +* - Hardware accelerated with OpenGL (1.1, 2.1, 3.3, 4.3, ES2, ES3 - choose at compile) +* - Unique OpenGL abstraction layer (usable as standalone module): [rlgl] +* - Multiple Fonts formats supported (TTF, OTF, FNT, BDF, Sprite fonts) +* - Outstanding texture formats support, including compressed formats (DXT, ETC, ASTC) +* - Full 3d support for 3d Shapes, Models, Billboards, Heightmaps and more! +* - Flexible Materials system, supporting classic maps and PBR maps +* - Animated 3D models supported (skeletal bones animation) (IQM, M3D, GLTF) +* - Shaders support, including Model shaders and Postprocessing shaders +* - Powerful math module for Vector, Matrix and Quaternion operations: [raymath] +* - Audio loading and playing with streaming support (WAV, OGG, MP3, FLAC, QOA, XM, MOD) +* - VR stereo rendering with configurable HMD device parameters +* - Bindings to multiple programming languages available! +* +* NOTES: +* - One default Font is loaded on InitWindow()->LoadFontDefault() [core, text] +* - One default Texture2D is loaded on rlglInit(), 1x1 white pixel R8G8B8A8 [rlgl] (OpenGL 3.3 or ES2) +* - One default Shader is loaded on rlglInit()->rlLoadShaderDefault() [rlgl] (OpenGL 3.3 or ES2) +* - One default RenderBatch is loaded on rlglInit()->rlLoadRenderBatch() [rlgl] (OpenGL 3.3 or ES2) +* +* DEPENDENCIES (included): +* [rcore][GLFW] rglfw (Camilla Löwy - github.com/glfw/glfw) for window/context management and input +* [rcore][RGFW] rgfw (ColleagueRiley - github.com/ColleagueRiley/RGFW) for window/context management and input +* [rlgl] glad/glad_gles2 (David Herberth - github.com/Dav1dde/glad) for OpenGL 3.3 extensions loading +* [raudio] miniaudio (David Reid - github.com/mackron/miniaudio) for audio device/context management +* +* OPTIONAL DEPENDENCIES (included): +* [rcore] msf_gif (Miles Fogle) for GIF recording +* [rcore] sinfl (Micha Mettke) for DEFLATE decompression algorithm +* [rcore] sdefl (Micha Mettke) for DEFLATE compression algorithm +* [rcore] rprand (Ramon Snatamaria) for pseudo-random numbers generation +* [rtextures] qoi (Dominic Szablewski - https://phoboslab.org) for QOI image manage +* [rtextures] stb_image (Sean Barret) for images loading (BMP, TGA, PNG, JPEG, HDR...) +* [rtextures] stb_image_write (Sean Barret) for image writing (BMP, TGA, PNG, JPG) +* [rtextures] stb_image_resize2 (Sean Barret) for image resizing algorithms +* [rtextures] stb_perlin (Sean Barret) for Perlin Noise image generation +* [rtext] stb_truetype (Sean Barret) for ttf fonts loading +* [rtext] stb_rect_pack (Sean Barret) for rectangles packing +* [rmodels] par_shapes (Philip Rideout) for parametric 3d shapes generation +* [rmodels] tinyobj_loader_c (Syoyo Fujita) for models loading (OBJ, MTL) +* [rmodels] cgltf (Johannes Kuhlmann) for models loading (glTF) +* [rmodels] m3d (bzt) for models loading (M3D, https://bztsrc.gitlab.io/model3d) +* [rmodels] vox_loader (Johann Nadalutti) for models loading (VOX) +* [raudio] dr_wav (David Reid) for WAV audio file loading +* [raudio] dr_flac (David Reid) for FLAC audio file loading +* [raudio] dr_mp3 (David Reid) for MP3 audio file loading +* [raudio] stb_vorbis (Sean Barret) for OGG audio loading +* [raudio] jar_xm (Joshua Reisenauer) for XM audio module loading +* [raudio] jar_mod (Joshua Reisenauer) for MOD audio module loading +* [raudio] qoa (Dominic Szablewski - https://phoboslab.org) for QOA audio manage +* +* +* LICENSE: zlib/libpng +* +* raylib is licensed under an unmodified zlib/libpng license, which is an OSI-certified, +* BSD-like license that allows static linking with closed source software: +* +* Copyright (c) 2013-2024 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 RAYLIB_H +#define RAYLIB_H + +#include // Required for: va_list - Only used by TraceLogCallback + +#define RAYLIB_VERSION_MAJOR 5 +#define RAYLIB_VERSION_MINOR 5 +#define RAYLIB_VERSION_PATCH 0 +#define RAYLIB_VERSION "5.5" + +// Function specifiers in case library is build/used as a shared library +// NOTE: Microsoft specifiers to tell compiler that symbols are imported/exported from a .dll +// NOTE: visibility("default") attribute makes symbols "visible" when compiled with -fvisibility=hidden +#if defined(_WIN32) + #if defined(__TINYC__) + #define __declspec(x) __attribute__((x)) + #endif + #if defined(BUILD_LIBTYPE_SHARED) + #define RLAPI __declspec(dllexport) // We are building the library as a Win32 shared library (.dll) + #elif defined(USE_LIBTYPE_SHARED) + #define RLAPI __declspec(dllimport) // We are using the library as a Win32 shared library (.dll) + #endif +#else + #if defined(BUILD_LIBTYPE_SHARED) + #define RLAPI __attribute__((visibility("default"))) // We are building as a Unix shared library (.so/.dylib) + #endif +#endif + +#ifndef RLAPI + #define RLAPI // Functions defined as 'extern' by default (implicit specifiers) +#endif + +//---------------------------------------------------------------------------------- +// Some basic Defines +//---------------------------------------------------------------------------------- +#ifndef PI + #define PI 3.14159265358979323846f +#endif +#ifndef DEG2RAD + #define DEG2RAD (PI/180.0f) +#endif +#ifndef RAD2DEG + #define RAD2DEG (180.0f/PI) +#endif + +// Allow custom memory allocators +// NOTE: Require recompiling raylib sources +#ifndef RL_MALLOC + #define RL_MALLOC(sz) malloc(sz) +#endif +#ifndef RL_CALLOC + #define RL_CALLOC(n,sz) calloc(n,sz) +#endif +#ifndef RL_REALLOC + #define RL_REALLOC(ptr,sz) realloc(ptr,sz) +#endif +#ifndef RL_FREE + #define RL_FREE(ptr) free(ptr) +#endif + +// NOTE: MSVC C++ compiler does not support compound literals (C99 feature) +// Plain structures in C++ (without constructors) can be initialized with { } +// This is called aggregate initialization (C++11 feature) +#if defined(__cplusplus) + #define CLITERAL(type) type +#else + #define CLITERAL(type) (type) +#endif + +// Some compilers (mostly macos clang) default to C++98, +// where aggregate initialization can't be used +// So, give a more clear error stating how to fix this +#if !defined(_MSC_VER) && (defined(__cplusplus) && __cplusplus < 201103L) + #error "C++11 or later is required. Add -std=c++11" +#endif + +// NOTE: We set some defines with some data types declared by raylib +// Other modules (raymath, rlgl) also require some of those types, so, +// to be able to use those other modules as standalone (not depending on raylib) +// this defines are very useful for internal check and avoid type (re)definitions +#define RL_COLOR_TYPE +#define RL_RECTANGLE_TYPE +#define RL_VECTOR2_TYPE +#define RL_VECTOR3_TYPE +#define RL_VECTOR4_TYPE +#define RL_QUATERNION_TYPE +#define RL_MATRIX_TYPE + +// Some Basic Colors +// NOTE: Custom raylib color palette for amazing visuals on WHITE background +#define LIGHTGRAY CLITERAL(Color){ 200, 200, 200, 255 } // Light Gray +#define GRAY CLITERAL(Color){ 130, 130, 130, 255 } // Gray +#define DARKGRAY CLITERAL(Color){ 80, 80, 80, 255 } // Dark Gray +#define YELLOW CLITERAL(Color){ 253, 249, 0, 255 } // Yellow +#define GOLD CLITERAL(Color){ 255, 203, 0, 255 } // Gold +#define ORANGE CLITERAL(Color){ 255, 161, 0, 255 } // Orange +#define PINK CLITERAL(Color){ 255, 109, 194, 255 } // Pink +#define RED CLITERAL(Color){ 230, 41, 55, 255 } // Red +#define MAROON CLITERAL(Color){ 190, 33, 55, 255 } // Maroon +#define GREEN CLITERAL(Color){ 0, 228, 48, 255 } // Green +#define LIME CLITERAL(Color){ 0, 158, 47, 255 } // Lime +#define DARKGREEN CLITERAL(Color){ 0, 117, 44, 255 } // Dark Green +#define SKYBLUE CLITERAL(Color){ 102, 191, 255, 255 } // Sky Blue +#define BLUE CLITERAL(Color){ 0, 121, 241, 255 } // Blue +#define DARKBLUE CLITERAL(Color){ 0, 82, 172, 255 } // Dark Blue +#define PURPLE CLITERAL(Color){ 200, 122, 255, 255 } // Purple +#define VIOLET CLITERAL(Color){ 135, 60, 190, 255 } // Violet +#define DARKPURPLE CLITERAL(Color){ 112, 31, 126, 255 } // Dark Purple +#define BEIGE CLITERAL(Color){ 211, 176, 131, 255 } // Beige +#define BROWN CLITERAL(Color){ 127, 106, 79, 255 } // Brown +#define DARKBROWN CLITERAL(Color){ 76, 63, 47, 255 } // Dark Brown + +#define WHITE CLITERAL(Color){ 255, 255, 255, 255 } // White +#define BLACK CLITERAL(Color){ 0, 0, 0, 255 } // Black +#define BLANK CLITERAL(Color){ 0, 0, 0, 0 } // Blank (Transparent) +#define MAGENTA CLITERAL(Color){ 255, 0, 255, 255 } // Magenta +#define RAYWHITE CLITERAL(Color){ 245, 245, 245, 255 } // My own White (raylib logo) + +//---------------------------------------------------------------------------------- +// Structures Definition +//---------------------------------------------------------------------------------- +// Boolean type +#if (defined(__STDC__) && __STDC_VERSION__ >= 199901L) || (defined(_MSC_VER) && _MSC_VER >= 1800) + #include +#elif !defined(__cplusplus) && !defined(bool) + typedef enum bool { false = 0, true = !false } bool; + #define RL_BOOL_TYPE +#endif + +// Vector2, 2 components +typedef struct Vector2 { + float x; // Vector x component + float y; // Vector y component +} Vector2; + +// Vector3, 3 components +typedef struct Vector3 { + float x; // Vector x component + float y; // Vector y component + float z; // Vector z component +} Vector3; + +// Vector4, 4 components +typedef struct Vector4 { + float x; // Vector x component + float y; // Vector y component + float z; // Vector z component + float w; // Vector w component +} Vector4; + +// Quaternion, 4 components (Vector4 alias) +typedef Vector4 Quaternion; + +// Matrix, 4x4 components, column major, OpenGL style, right-handed +typedef struct Matrix { + float m0, m4, m8, m12; // Matrix first row (4 components) + float m1, m5, m9, m13; // Matrix second row (4 components) + float m2, m6, m10, m14; // Matrix third row (4 components) + float m3, m7, m11, m15; // Matrix fourth row (4 components) +} Matrix; + +// Color, 4 components, R8G8B8A8 (32bit) +typedef struct Color { + unsigned char r; // Color red value + unsigned char g; // Color green value + unsigned char b; // Color blue value + unsigned char a; // Color alpha value +} Color; + +// Rectangle, 4 components +typedef struct Rectangle { + float x; // Rectangle top-left corner position x + float y; // Rectangle top-left corner position y + float width; // Rectangle width + float height; // Rectangle height +} Rectangle; + +// 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; + +// Texture, tex data stored in GPU memory (VRAM) +typedef struct Texture { + 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) +} Texture; + +// Texture2D, same as Texture +typedef Texture Texture2D; + +// TextureCubemap, same as Texture +typedef Texture TextureCubemap; + +// RenderTexture, fbo for texture rendering +typedef struct RenderTexture { + unsigned int id; // OpenGL framebuffer object id + Texture texture; // Color buffer attachment texture + Texture depth; // Depth buffer attachment texture +} RenderTexture; + +// RenderTexture2D, same as RenderTexture +typedef RenderTexture RenderTexture2D; + +// NPatchInfo, n-patch layout info +typedef struct NPatchInfo { + Rectangle source; // Texture source rectangle + int left; // Left border offset + int top; // Top border offset + int right; // Right border offset + int bottom; // Bottom border offset + int layout; // Layout of the n-patch: 3x3, 1x3 or 3x1 +} NPatchInfo; + +// 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; + +// Font, font texture and GlyphInfo array data +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; + +// Camera, defines position/orientation in 3d space +typedef struct Camera3D { + Vector3 position; // Camera position + Vector3 target; // Camera target it looks-at + Vector3 up; // Camera up vector (rotation over its axis) + float fovy; // Camera field-of-view aperture in Y (degrees) in perspective, used as near plane width in orthographic + int projection; // Camera projection: CAMERA_PERSPECTIVE or CAMERA_ORTHOGRAPHIC +} Camera3D; + +typedef Camera3D Camera; // Camera type fallback, defaults to Camera3D + +// Camera2D, defines position/orientation in 2d space +typedef struct Camera2D { + Vector2 offset; // Camera offset (displacement from target) + Vector2 target; // Camera target (rotation and zoom origin) + float rotation; // Camera rotation in degrees + float zoom; // Camera zoom (scaling), should be 1.0f by default +} Camera2D; + +// Mesh, vertex data and vao/vbo +typedef struct Mesh { + int vertexCount; // Number of vertices stored in arrays + int triangleCount; // Number of triangles stored (indexed or not) + + // Vertex attributes data + float *vertices; // Vertex position (XYZ - 3 components per vertex) (shader-location = 0) + float *texcoords; // Vertex texture coordinates (UV - 2 components per vertex) (shader-location = 1) + float *texcoords2; // Vertex texture second coordinates (UV - 2 components per vertex) (shader-location = 5) + float *normals; // Vertex normals (XYZ - 3 components per vertex) (shader-location = 2) + float *tangents; // Vertex tangents (XYZW - 4 components per vertex) (shader-location = 4) + unsigned char *colors; // Vertex colors (RGBA - 4 components per vertex) (shader-location = 3) + unsigned short *indices; // Vertex indices (in case vertex data comes indexed) + + // Animation vertex data + float *animVertices; // Animated vertex positions (after bones transformations) + float *animNormals; // Animated normals (after bones transformations) + unsigned char *boneIds; // Vertex bone ids, max 255 bone ids, up to 4 bones influence by vertex (skinning) (shader-location = 6) + float *boneWeights; // Vertex bone weight, up to 4 bones influence by vertex (skinning) (shader-location = 7) + Matrix *boneMatrices; // Bones animated transformation matrices + int boneCount; // Number of bones + + // OpenGL identifiers + unsigned int vaoId; // OpenGL Vertex Array Object id + unsigned int *vboId; // OpenGL Vertex Buffer Objects id (default vertex data) +} Mesh; + +// Shader +typedef struct Shader { + unsigned int id; // Shader program id + int *locs; // Shader locations array (RL_MAX_SHADER_LOCATIONS) +} Shader; + +// MaterialMap +typedef struct MaterialMap { + Texture2D texture; // Material map texture + Color color; // Material map color + float value; // Material map value +} MaterialMap; + +// Material, includes shader and maps +typedef struct Material { + Shader shader; // Material shader + MaterialMap *maps; // Material maps array (MAX_MATERIAL_MAPS) + float params[4]; // Material generic parameters (if required) +} Material; + +// Transform, vertex transformation data +typedef struct Transform { + Vector3 translation; // Translation + Quaternion rotation; // Rotation + Vector3 scale; // Scale +} Transform; + +// Bone, skeletal animation bone +typedef struct BoneInfo { + char name[32]; // Bone name + int parent; // Bone parent +} BoneInfo; + +// Model, meshes, materials and animation data +typedef struct Model { + Matrix transform; // Local transform matrix + + int meshCount; // Number of meshes + int materialCount; // Number of materials + Mesh *meshes; // Meshes array + Material *materials; // Materials array + int *meshMaterial; // Mesh material number + + // Animation data + int boneCount; // Number of bones + BoneInfo *bones; // Bones information (skeleton) + Transform *bindPose; // Bones base transformation (pose) +} Model; + +// ModelAnimation +typedef struct ModelAnimation { + int boneCount; // Number of bones + int frameCount; // Number of animation frames + BoneInfo *bones; // Bones information (skeleton) + Transform **framePoses; // Poses array by frame + char name[32]; // Animation name +} ModelAnimation; + +// Ray, ray for raycasting +typedef struct Ray { + Vector3 position; // Ray position (origin) + Vector3 direction; // Ray direction (normalized) +} Ray; + +// RayCollision, ray hit information +typedef struct RayCollision { + bool hit; // Did the ray hit something? + float distance; // Distance to the nearest hit + Vector3 point; // Point of the nearest hit + Vector3 normal; // Surface normal of hit +} RayCollision; + +// BoundingBox +typedef struct BoundingBox { + Vector3 min; // Minimum vertex box-corner + Vector3 max; // Maximum vertex box-corner +} BoundingBox; + +// Wave, audio wave data +typedef struct Wave { + unsigned int frameCount; // Total number of frames (considering channels) + unsigned int sampleRate; // Frequency (samples per second) + unsigned int sampleSize; // Bit depth (bits per sample): 8, 16, 32 (24 not supported) + unsigned int channels; // Number of channels (1-mono, 2-stereo, ...) + void *data; // Buffer data pointer +} Wave; + +// Opaque structs declaration +// NOTE: Actual structs are defined internally in raudio module +typedef struct rAudioBuffer rAudioBuffer; +typedef struct rAudioProcessor rAudioProcessor; + +// AudioStream, custom audio stream +typedef struct AudioStream { + rAudioBuffer *buffer; // Pointer to internal data used by the audio system + rAudioProcessor *processor; // Pointer to internal data processor, useful for audio effects + + unsigned int sampleRate; // Frequency (samples per second) + unsigned int sampleSize; // Bit depth (bits per sample): 8, 16, 32 (24 not supported) + unsigned int channels; // Number of channels (1-mono, 2-stereo, ...) +} AudioStream; + +// Sound +typedef struct Sound { + AudioStream stream; // Audio stream + unsigned int frameCount; // Total number of frames (considering channels) +} Sound; + +// Music, audio stream, anything longer than ~10 seconds should be streamed +typedef struct Music { + AudioStream stream; // Audio stream + unsigned int frameCount; // Total number of frames (considering channels) + bool looping; // Music looping enable + + int ctxType; // Type of music context (audio filetype) + void *ctxData; // Audio context data, depends on type +} Music; + +// VrDeviceInfo, Head-Mounted-Display device parameters +typedef struct VrDeviceInfo { + int hResolution; // Horizontal resolution in pixels + int vResolution; // Vertical resolution in pixels + float hScreenSize; // Horizontal size in meters + float vScreenSize; // Vertical size in meters + float eyeToScreenDistance; // Distance between eye and display in meters + float lensSeparationDistance; // Lens separation distance in meters + float interpupillaryDistance; // IPD (distance between pupils) in meters + float lensDistortionValues[4]; // Lens distortion constant parameters + float chromaAbCorrection[4]; // Chromatic aberration correction parameters +} VrDeviceInfo; + +// VrStereoConfig, VR stereo rendering configuration for simulator +typedef struct VrStereoConfig { + Matrix projection[2]; // VR projection matrices (per eye) + Matrix viewOffset[2]; // VR view offset matrices (per eye) + float leftLensCenter[2]; // VR left lens center + float rightLensCenter[2]; // VR right lens center + float leftScreenCenter[2]; // VR left screen center + float rightScreenCenter[2]; // VR right screen center + float scale[2]; // VR distortion scale + float scaleIn[2]; // VR distortion scale in +} VrStereoConfig; + +// File path list +typedef struct FilePathList { + unsigned int capacity; // Filepaths max entries + unsigned int count; // Filepaths entries count + char **paths; // Filepaths entries +} FilePathList; + +// Automation event +typedef struct AutomationEvent { + unsigned int frame; // Event frame + unsigned int type; // Event type (AutomationEventType) + int params[4]; // Event parameters (if required) +} AutomationEvent; + +// Automation event list +typedef struct AutomationEventList { + unsigned int capacity; // Events max entries (MAX_AUTOMATION_EVENTS) + unsigned int count; // Events entries count + AutomationEvent *events; // Events entries +} AutomationEventList; + +//---------------------------------------------------------------------------------- +// Enumerators Definition +//---------------------------------------------------------------------------------- +// System/Window config flags +// NOTE: Every bit registers one state (use it with bit masks) +// By default all flags are set to 0 +typedef enum { + FLAG_VSYNC_HINT = 0x00000040, // Set to try enabling V-Sync on GPU + FLAG_FULLSCREEN_MODE = 0x00000002, // Set to run program in fullscreen + FLAG_WINDOW_RESIZABLE = 0x00000004, // Set to allow resizable window + FLAG_WINDOW_UNDECORATED = 0x00000008, // Set to disable window decoration (frame and buttons) + FLAG_WINDOW_HIDDEN = 0x00000080, // Set to hide window + FLAG_WINDOW_MINIMIZED = 0x00000200, // Set to minimize window (iconify) + FLAG_WINDOW_MAXIMIZED = 0x00000400, // Set to maximize window (expanded to monitor) + FLAG_WINDOW_UNFOCUSED = 0x00000800, // Set to window non focused + FLAG_WINDOW_TOPMOST = 0x00001000, // Set to window always on top + FLAG_WINDOW_ALWAYS_RUN = 0x00000100, // Set to allow windows running while minimized + FLAG_WINDOW_TRANSPARENT = 0x00000010, // Set to allow transparent framebuffer + FLAG_WINDOW_HIGHDPI = 0x00002000, // Set to support HighDPI + FLAG_WINDOW_MOUSE_PASSTHROUGH = 0x00004000, // Set to support mouse passthrough, only supported when FLAG_WINDOW_UNDECORATED + FLAG_BORDERLESS_WINDOWED_MODE = 0x00008000, // Set to run program in borderless windowed mode + FLAG_MSAA_4X_HINT = 0x00000020, // Set to try enabling MSAA 4X + FLAG_INTERLACED_HINT = 0x00010000 // Set to try enabling interlaced video format (for V3D) +} ConfigFlags; + +// Trace log level +// NOTE: Organized by priority level +typedef enum { + LOG_ALL = 0, // Display all logs + LOG_TRACE, // Trace logging, intended for internal use only + LOG_DEBUG, // Debug logging, used for internal debugging, it should be disabled on release builds + LOG_INFO, // Info logging, used for program execution info + LOG_WARNING, // Warning logging, used on recoverable failures + LOG_ERROR, // Error logging, used on unrecoverable failures + LOG_FATAL, // Fatal logging, used to abort program: exit(EXIT_FAILURE) + LOG_NONE // Disable logging +} TraceLogLevel; + +// Keyboard keys (US keyboard layout) +// NOTE: Use GetKeyPressed() to allow redefining +// required keys for alternative layouts +typedef enum { + KEY_NULL = 0, // Key: NULL, used for no key pressed + // Alphanumeric keys + KEY_APOSTROPHE = 39, // Key: ' + KEY_COMMA = 44, // Key: , + KEY_MINUS = 45, // Key: - + KEY_PERIOD = 46, // Key: . + KEY_SLASH = 47, // Key: / + KEY_ZERO = 48, // Key: 0 + KEY_ONE = 49, // Key: 1 + KEY_TWO = 50, // Key: 2 + KEY_THREE = 51, // Key: 3 + KEY_FOUR = 52, // Key: 4 + KEY_FIVE = 53, // Key: 5 + KEY_SIX = 54, // Key: 6 + KEY_SEVEN = 55, // Key: 7 + KEY_EIGHT = 56, // Key: 8 + KEY_NINE = 57, // Key: 9 + KEY_SEMICOLON = 59, // Key: ; + KEY_EQUAL = 61, // Key: = + KEY_A = 65, // Key: A | a + KEY_B = 66, // Key: B | b + KEY_C = 67, // Key: C | c + KEY_D = 68, // Key: D | d + KEY_E = 69, // Key: E | e + KEY_F = 70, // Key: F | f + KEY_G = 71, // Key: G | g + KEY_H = 72, // Key: H | h + KEY_I = 73, // Key: I | i + KEY_J = 74, // Key: J | j + KEY_K = 75, // Key: K | k + KEY_L = 76, // Key: L | l + KEY_M = 77, // Key: M | m + KEY_N = 78, // Key: N | n + KEY_O = 79, // Key: O | o + KEY_P = 80, // Key: P | p + KEY_Q = 81, // Key: Q | q + KEY_R = 82, // Key: R | r + KEY_S = 83, // Key: S | s + KEY_T = 84, // Key: T | t + KEY_U = 85, // Key: U | u + KEY_V = 86, // Key: V | v + KEY_W = 87, // Key: W | w + KEY_X = 88, // Key: X | x + KEY_Y = 89, // Key: Y | y + KEY_Z = 90, // Key: Z | z + KEY_LEFT_BRACKET = 91, // Key: [ + KEY_BACKSLASH = 92, // Key: '\' + KEY_RIGHT_BRACKET = 93, // Key: ] + KEY_GRAVE = 96, // Key: ` + // Function keys + KEY_SPACE = 32, // Key: Space + KEY_ESCAPE = 256, // Key: Esc + KEY_ENTER = 257, // Key: Enter + KEY_TAB = 258, // Key: Tab + KEY_BACKSPACE = 259, // Key: Backspace + KEY_INSERT = 260, // Key: Ins + KEY_DELETE = 261, // Key: Del + KEY_RIGHT = 262, // Key: Cursor right + KEY_LEFT = 263, // Key: Cursor left + KEY_DOWN = 264, // Key: Cursor down + KEY_UP = 265, // Key: Cursor up + KEY_PAGE_UP = 266, // Key: Page up + KEY_PAGE_DOWN = 267, // Key: Page down + KEY_HOME = 268, // Key: Home + KEY_END = 269, // Key: End + KEY_CAPS_LOCK = 280, // Key: Caps lock + KEY_SCROLL_LOCK = 281, // Key: Scroll down + KEY_NUM_LOCK = 282, // Key: Num lock + KEY_PRINT_SCREEN = 283, // Key: Print screen + KEY_PAUSE = 284, // Key: Pause + KEY_F1 = 290, // Key: F1 + KEY_F2 = 291, // Key: F2 + KEY_F3 = 292, // Key: F3 + KEY_F4 = 293, // Key: F4 + KEY_F5 = 294, // Key: F5 + KEY_F6 = 295, // Key: F6 + KEY_F7 = 296, // Key: F7 + KEY_F8 = 297, // Key: F8 + KEY_F9 = 298, // Key: F9 + KEY_F10 = 299, // Key: F10 + KEY_F11 = 300, // Key: F11 + KEY_F12 = 301, // Key: F12 + KEY_LEFT_SHIFT = 340, // Key: Shift left + KEY_LEFT_CONTROL = 341, // Key: Control left + KEY_LEFT_ALT = 342, // Key: Alt left + KEY_LEFT_SUPER = 343, // Key: Super left + KEY_RIGHT_SHIFT = 344, // Key: Shift right + KEY_RIGHT_CONTROL = 345, // Key: Control right + KEY_RIGHT_ALT = 346, // Key: Alt right + KEY_RIGHT_SUPER = 347, // Key: Super right + KEY_KB_MENU = 348, // Key: KB menu + // Keypad keys + KEY_KP_0 = 320, // Key: Keypad 0 + KEY_KP_1 = 321, // Key: Keypad 1 + KEY_KP_2 = 322, // Key: Keypad 2 + KEY_KP_3 = 323, // Key: Keypad 3 + KEY_KP_4 = 324, // Key: Keypad 4 + KEY_KP_5 = 325, // Key: Keypad 5 + KEY_KP_6 = 326, // Key: Keypad 6 + KEY_KP_7 = 327, // Key: Keypad 7 + KEY_KP_8 = 328, // Key: Keypad 8 + KEY_KP_9 = 329, // Key: Keypad 9 + KEY_KP_DECIMAL = 330, // Key: Keypad . + KEY_KP_DIVIDE = 331, // Key: Keypad / + KEY_KP_MULTIPLY = 332, // Key: Keypad * + KEY_KP_SUBTRACT = 333, // Key: Keypad - + KEY_KP_ADD = 334, // Key: Keypad + + KEY_KP_ENTER = 335, // Key: Keypad Enter + KEY_KP_EQUAL = 336, // Key: Keypad = + // Android key buttons + KEY_BACK = 4, // Key: Android back button + KEY_MENU = 5, // Key: Android menu button + KEY_VOLUME_UP = 24, // Key: Android volume up button + KEY_VOLUME_DOWN = 25 // Key: Android volume down button +} KeyboardKey; + +// Add backwards compatibility support for deprecated names +#define MOUSE_LEFT_BUTTON MOUSE_BUTTON_LEFT +#define MOUSE_RIGHT_BUTTON MOUSE_BUTTON_RIGHT +#define MOUSE_MIDDLE_BUTTON MOUSE_BUTTON_MIDDLE + +// Mouse buttons +typedef enum { + MOUSE_BUTTON_LEFT = 0, // Mouse button left + MOUSE_BUTTON_RIGHT = 1, // Mouse button right + MOUSE_BUTTON_MIDDLE = 2, // Mouse button middle (pressed wheel) + MOUSE_BUTTON_SIDE = 3, // Mouse button side (advanced mouse device) + MOUSE_BUTTON_EXTRA = 4, // Mouse button extra (advanced mouse device) + MOUSE_BUTTON_FORWARD = 5, // Mouse button forward (advanced mouse device) + MOUSE_BUTTON_BACK = 6, // Mouse button back (advanced mouse device) +} MouseButton; + +// Mouse cursor +typedef enum { + MOUSE_CURSOR_DEFAULT = 0, // Default pointer shape + MOUSE_CURSOR_ARROW = 1, // Arrow shape + MOUSE_CURSOR_IBEAM = 2, // Text writing cursor shape + MOUSE_CURSOR_CROSSHAIR = 3, // Cross shape + MOUSE_CURSOR_POINTING_HAND = 4, // Pointing hand cursor + MOUSE_CURSOR_RESIZE_EW = 5, // Horizontal resize/move arrow shape + MOUSE_CURSOR_RESIZE_NS = 6, // Vertical resize/move arrow shape + MOUSE_CURSOR_RESIZE_NWSE = 7, // Top-left to bottom-right diagonal resize/move arrow shape + MOUSE_CURSOR_RESIZE_NESW = 8, // The top-right to bottom-left diagonal resize/move arrow shape + MOUSE_CURSOR_RESIZE_ALL = 9, // The omnidirectional resize/move cursor shape + MOUSE_CURSOR_NOT_ALLOWED = 10 // The operation-not-allowed shape +} MouseCursor; + +// Gamepad buttons +typedef enum { + GAMEPAD_BUTTON_UNKNOWN = 0, // Unknown button, just for error checking + GAMEPAD_BUTTON_LEFT_FACE_UP, // Gamepad left DPAD up button + GAMEPAD_BUTTON_LEFT_FACE_RIGHT, // Gamepad left DPAD right button + GAMEPAD_BUTTON_LEFT_FACE_DOWN, // Gamepad left DPAD down button + GAMEPAD_BUTTON_LEFT_FACE_LEFT, // Gamepad left DPAD left button + GAMEPAD_BUTTON_RIGHT_FACE_UP, // Gamepad right button up (i.e. PS3: Triangle, Xbox: Y) + GAMEPAD_BUTTON_RIGHT_FACE_RIGHT, // Gamepad right button right (i.e. PS3: Circle, Xbox: B) + GAMEPAD_BUTTON_RIGHT_FACE_DOWN, // Gamepad right button down (i.e. PS3: Cross, Xbox: A) + GAMEPAD_BUTTON_RIGHT_FACE_LEFT, // Gamepad right button left (i.e. PS3: Square, Xbox: X) + GAMEPAD_BUTTON_LEFT_TRIGGER_1, // Gamepad top/back trigger left (first), it could be a trailing button + GAMEPAD_BUTTON_LEFT_TRIGGER_2, // Gamepad top/back trigger left (second), it could be a trailing button + GAMEPAD_BUTTON_RIGHT_TRIGGER_1, // Gamepad top/back trigger right (first), it could be a trailing button + GAMEPAD_BUTTON_RIGHT_TRIGGER_2, // Gamepad top/back trigger right (second), it could be a trailing button + GAMEPAD_BUTTON_MIDDLE_LEFT, // Gamepad center buttons, left one (i.e. PS3: Select) + GAMEPAD_BUTTON_MIDDLE, // Gamepad center buttons, middle one (i.e. PS3: PS, Xbox: XBOX) + GAMEPAD_BUTTON_MIDDLE_RIGHT, // Gamepad center buttons, right one (i.e. PS3: Start) + GAMEPAD_BUTTON_LEFT_THUMB, // Gamepad joystick pressed button left + GAMEPAD_BUTTON_RIGHT_THUMB // Gamepad joystick pressed button right +} GamepadButton; + +// Gamepad axis +typedef enum { + GAMEPAD_AXIS_LEFT_X = 0, // Gamepad left stick X axis + GAMEPAD_AXIS_LEFT_Y = 1, // Gamepad left stick Y axis + GAMEPAD_AXIS_RIGHT_X = 2, // Gamepad right stick X axis + GAMEPAD_AXIS_RIGHT_Y = 3, // Gamepad right stick Y axis + GAMEPAD_AXIS_LEFT_TRIGGER = 4, // Gamepad back trigger left, pressure level: [1..-1] + GAMEPAD_AXIS_RIGHT_TRIGGER = 5 // Gamepad back trigger right, pressure level: [1..-1] +} GamepadAxis; + +// Material map index +typedef enum { + MATERIAL_MAP_ALBEDO = 0, // Albedo material (same as: MATERIAL_MAP_DIFFUSE) + MATERIAL_MAP_METALNESS, // Metalness material (same as: MATERIAL_MAP_SPECULAR) + MATERIAL_MAP_NORMAL, // Normal material + MATERIAL_MAP_ROUGHNESS, // Roughness material + MATERIAL_MAP_OCCLUSION, // Ambient occlusion material + MATERIAL_MAP_EMISSION, // Emission material + MATERIAL_MAP_HEIGHT, // Heightmap material + MATERIAL_MAP_CUBEMAP, // Cubemap material (NOTE: Uses GL_TEXTURE_CUBE_MAP) + MATERIAL_MAP_IRRADIANCE, // Irradiance material (NOTE: Uses GL_TEXTURE_CUBE_MAP) + MATERIAL_MAP_PREFILTER, // Prefilter material (NOTE: Uses GL_TEXTURE_CUBE_MAP) + MATERIAL_MAP_BRDF // Brdf material +} MaterialMapIndex; + +#define MATERIAL_MAP_DIFFUSE MATERIAL_MAP_ALBEDO +#define MATERIAL_MAP_SPECULAR MATERIAL_MAP_METALNESS + +// Shader location index +typedef enum { + SHADER_LOC_VERTEX_POSITION = 0, // Shader location: vertex attribute: position + SHADER_LOC_VERTEX_TEXCOORD01, // Shader location: vertex attribute: texcoord01 + SHADER_LOC_VERTEX_TEXCOORD02, // Shader location: vertex attribute: texcoord02 + SHADER_LOC_VERTEX_NORMAL, // Shader location: vertex attribute: normal + SHADER_LOC_VERTEX_TANGENT, // Shader location: vertex attribute: tangent + SHADER_LOC_VERTEX_COLOR, // Shader location: vertex attribute: color + SHADER_LOC_MATRIX_MVP, // Shader location: matrix uniform: model-view-projection + SHADER_LOC_MATRIX_VIEW, // Shader location: matrix uniform: view (camera transform) + SHADER_LOC_MATRIX_PROJECTION, // Shader location: matrix uniform: projection + SHADER_LOC_MATRIX_MODEL, // Shader location: matrix uniform: model (transform) + SHADER_LOC_MATRIX_NORMAL, // Shader location: matrix uniform: normal + SHADER_LOC_VECTOR_VIEW, // Shader location: vector uniform: view + SHADER_LOC_COLOR_DIFFUSE, // Shader location: vector uniform: diffuse color + SHADER_LOC_COLOR_SPECULAR, // Shader location: vector uniform: specular color + SHADER_LOC_COLOR_AMBIENT, // Shader location: vector uniform: ambient color + SHADER_LOC_MAP_ALBEDO, // Shader location: sampler2d texture: albedo (same as: SHADER_LOC_MAP_DIFFUSE) + SHADER_LOC_MAP_METALNESS, // Shader location: sampler2d texture: metalness (same as: SHADER_LOC_MAP_SPECULAR) + SHADER_LOC_MAP_NORMAL, // Shader location: sampler2d texture: normal + SHADER_LOC_MAP_ROUGHNESS, // Shader location: sampler2d texture: roughness + SHADER_LOC_MAP_OCCLUSION, // Shader location: sampler2d texture: occlusion + SHADER_LOC_MAP_EMISSION, // Shader location: sampler2d texture: emission + SHADER_LOC_MAP_HEIGHT, // Shader location: sampler2d texture: height + SHADER_LOC_MAP_CUBEMAP, // Shader location: samplerCube texture: cubemap + SHADER_LOC_MAP_IRRADIANCE, // Shader location: samplerCube texture: irradiance + SHADER_LOC_MAP_PREFILTER, // Shader location: samplerCube texture: prefilter + SHADER_LOC_MAP_BRDF, // Shader location: sampler2d texture: brdf + SHADER_LOC_VERTEX_BONEIDS, // Shader location: vertex attribute: boneIds + SHADER_LOC_VERTEX_BONEWEIGHTS, // Shader location: vertex attribute: boneWeights + SHADER_LOC_BONE_MATRICES // Shader location: array of matrices uniform: boneMatrices +} ShaderLocationIndex; + +#define SHADER_LOC_MAP_DIFFUSE SHADER_LOC_MAP_ALBEDO +#define SHADER_LOC_MAP_SPECULAR SHADER_LOC_MAP_METALNESS + +// Shader uniform data type +typedef enum { + SHADER_UNIFORM_FLOAT = 0, // Shader uniform type: float + SHADER_UNIFORM_VEC2, // Shader uniform type: vec2 (2 float) + SHADER_UNIFORM_VEC3, // Shader uniform type: vec3 (3 float) + SHADER_UNIFORM_VEC4, // Shader uniform type: vec4 (4 float) + SHADER_UNIFORM_INT, // Shader uniform type: int + SHADER_UNIFORM_IVEC2, // Shader uniform type: ivec2 (2 int) + SHADER_UNIFORM_IVEC3, // Shader uniform type: ivec3 (3 int) + SHADER_UNIFORM_IVEC4, // Shader uniform type: ivec4 (4 int) + SHADER_UNIFORM_SAMPLER2D // Shader uniform type: sampler2d +} ShaderUniformDataType; + +// Shader attribute data types +typedef enum { + SHADER_ATTRIB_FLOAT = 0, // Shader attribute type: float + SHADER_ATTRIB_VEC2, // Shader attribute type: vec2 (2 float) + SHADER_ATTRIB_VEC3, // Shader attribute type: vec3 (3 float) + SHADER_ATTRIB_VEC4 // Shader attribute type: vec4 (4 float) +} ShaderAttributeDataType; + +// Pixel formats +// NOTE: Support depends on OpenGL version and platform +typedef enum { + PIXELFORMAT_UNCOMPRESSED_GRAYSCALE = 1, // 8 bit per pixel (no alpha) + PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA, // 8*2 bpp (2 channels) + PIXELFORMAT_UNCOMPRESSED_R5G6B5, // 16 bpp + PIXELFORMAT_UNCOMPRESSED_R8G8B8, // 24 bpp + PIXELFORMAT_UNCOMPRESSED_R5G5B5A1, // 16 bpp (1 bit alpha) + PIXELFORMAT_UNCOMPRESSED_R4G4B4A4, // 16 bpp (4 bit alpha) + PIXELFORMAT_UNCOMPRESSED_R8G8B8A8, // 32 bpp + PIXELFORMAT_UNCOMPRESSED_R32, // 32 bpp (1 channel - float) + PIXELFORMAT_UNCOMPRESSED_R32G32B32, // 32*3 bpp (3 channels - float) + PIXELFORMAT_UNCOMPRESSED_R32G32B32A32, // 32*4 bpp (4 channels - float) + PIXELFORMAT_UNCOMPRESSED_R16, // 16 bpp (1 channel - half float) + PIXELFORMAT_UNCOMPRESSED_R16G16B16, // 16*3 bpp (3 channels - half float) + PIXELFORMAT_UNCOMPRESSED_R16G16B16A16, // 16*4 bpp (4 channels - half float) + PIXELFORMAT_COMPRESSED_DXT1_RGB, // 4 bpp (no alpha) + PIXELFORMAT_COMPRESSED_DXT1_RGBA, // 4 bpp (1 bit alpha) + PIXELFORMAT_COMPRESSED_DXT3_RGBA, // 8 bpp + PIXELFORMAT_COMPRESSED_DXT5_RGBA, // 8 bpp + PIXELFORMAT_COMPRESSED_ETC1_RGB, // 4 bpp + PIXELFORMAT_COMPRESSED_ETC2_RGB, // 4 bpp + PIXELFORMAT_COMPRESSED_ETC2_EAC_RGBA, // 8 bpp + PIXELFORMAT_COMPRESSED_PVRT_RGB, // 4 bpp + PIXELFORMAT_COMPRESSED_PVRT_RGBA, // 4 bpp + PIXELFORMAT_COMPRESSED_ASTC_4x4_RGBA, // 8 bpp + PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA // 2 bpp +} PixelFormat; + +// Texture parameters: filter mode +// NOTE 1: Filtering considers mipmaps if available in the texture +// NOTE 2: Filter is accordingly set for minification and magnification +typedef enum { + TEXTURE_FILTER_POINT = 0, // No filter, just pixel approximation + TEXTURE_FILTER_BILINEAR, // Linear filtering + TEXTURE_FILTER_TRILINEAR, // Trilinear filtering (linear with mipmaps) + TEXTURE_FILTER_ANISOTROPIC_4X, // Anisotropic filtering 4x + TEXTURE_FILTER_ANISOTROPIC_8X, // Anisotropic filtering 8x + TEXTURE_FILTER_ANISOTROPIC_16X, // Anisotropic filtering 16x +} TextureFilter; + +// Texture parameters: wrap mode +typedef enum { + TEXTURE_WRAP_REPEAT = 0, // Repeats texture in tiled mode + TEXTURE_WRAP_CLAMP, // Clamps texture to edge pixel in tiled mode + TEXTURE_WRAP_MIRROR_REPEAT, // Mirrors and repeats the texture in tiled mode + TEXTURE_WRAP_MIRROR_CLAMP // Mirrors and clamps to border the texture in tiled mode +} TextureWrap; + +// Cubemap layouts +typedef enum { + CUBEMAP_LAYOUT_AUTO_DETECT = 0, // Automatically detect layout type + CUBEMAP_LAYOUT_LINE_VERTICAL, // Layout is defined by a vertical line with faces + CUBEMAP_LAYOUT_LINE_HORIZONTAL, // Layout is defined by a horizontal line with faces + CUBEMAP_LAYOUT_CROSS_THREE_BY_FOUR, // Layout is defined by a 3x4 cross with cubemap faces + CUBEMAP_LAYOUT_CROSS_FOUR_BY_THREE // Layout is defined by a 4x3 cross with cubemap faces +} CubemapLayout; + +// Font type, defines generation method +typedef enum { + FONT_DEFAULT = 0, // Default font generation, anti-aliased + FONT_BITMAP, // Bitmap font generation, no anti-aliasing + FONT_SDF // SDF font generation, requires external shader +} FontType; + +// Color blending modes (pre-defined) +typedef enum { + BLEND_ALPHA = 0, // Blend textures considering alpha (default) + BLEND_ADDITIVE, // Blend textures adding colors + BLEND_MULTIPLIED, // Blend textures multiplying colors + BLEND_ADD_COLORS, // Blend textures adding colors (alternative) + BLEND_SUBTRACT_COLORS, // Blend textures subtracting colors (alternative) + BLEND_ALPHA_PREMULTIPLY, // Blend premultiplied textures considering alpha + BLEND_CUSTOM, // Blend textures using custom src/dst factors (use rlSetBlendFactors()) + BLEND_CUSTOM_SEPARATE // Blend textures using custom rgb/alpha separate src/dst factors (use rlSetBlendFactorsSeparate()) +} BlendMode; + +// Gesture +// NOTE: Provided as bit-wise flags to enable only desired gestures +typedef enum { + GESTURE_NONE = 0, // No gesture + GESTURE_TAP = 1, // Tap gesture + GESTURE_DOUBLETAP = 2, // Double tap gesture + GESTURE_HOLD = 4, // Hold gesture + GESTURE_DRAG = 8, // Drag gesture + GESTURE_SWIPE_RIGHT = 16, // Swipe right gesture + GESTURE_SWIPE_LEFT = 32, // Swipe left gesture + GESTURE_SWIPE_UP = 64, // Swipe up gesture + GESTURE_SWIPE_DOWN = 128, // Swipe down gesture + GESTURE_PINCH_IN = 256, // Pinch in gesture + GESTURE_PINCH_OUT = 512 // Pinch out gesture +} Gesture; + +// Camera system modes +typedef enum { + CAMERA_CUSTOM = 0, // Camera custom, controlled by user (UpdateCamera() does nothing) + CAMERA_FREE, // Camera free mode + CAMERA_ORBITAL, // Camera orbital, around target, zoom supported + CAMERA_FIRST_PERSON, // Camera first person + CAMERA_THIRD_PERSON // Camera third person +} CameraMode; + +// Camera projection +typedef enum { + CAMERA_PERSPECTIVE = 0, // Perspective projection + CAMERA_ORTHOGRAPHIC // Orthographic projection +} CameraProjection; + +// N-patch layout +typedef enum { + NPATCH_NINE_PATCH = 0, // Npatch layout: 3x3 tiles + NPATCH_THREE_PATCH_VERTICAL, // Npatch layout: 1x3 tiles + NPATCH_THREE_PATCH_HORIZONTAL // Npatch layout: 3x1 tiles +} NPatchLayout; + +// Callbacks to hook some internal functions +// WARNING: These callbacks are intended for advanced users +typedef void (*TraceLogCallback)(int logLevel, const char *text, va_list args); // Logging: Redirect trace log messages +typedef unsigned char *(*LoadFileDataCallback)(const char *fileName, int *dataSize); // FileIO: Load binary data +typedef bool (*SaveFileDataCallback)(const char *fileName, void *data, int dataSize); // FileIO: Save binary data +typedef char *(*LoadFileTextCallback)(const char *fileName); // FileIO: Load text data +typedef bool (*SaveFileTextCallback)(const char *fileName, char *text); // FileIO: Save text data + +//------------------------------------------------------------------------------------ +// Global Variables Definition +//------------------------------------------------------------------------------------ +// It's lonely here... + +//------------------------------------------------------------------------------------ +// Window and Graphics Device Functions (Module: core) +//------------------------------------------------------------------------------------ + +#if defined(__cplusplus) +extern "C" { // Prevents name mangling of functions +#endif + +// Window-related functions +RLAPI void InitWindow(int width, int height, const char *title); // Initialize window and OpenGL context +RLAPI void CloseWindow(void); // Close window and unload OpenGL context +RLAPI bool WindowShouldClose(void); // Check if application should close (KEY_ESCAPE pressed or windows close icon clicked) +RLAPI bool IsWindowReady(void); // Check if window has been initialized successfully +RLAPI bool IsWindowFullscreen(void); // Check if window is currently fullscreen +RLAPI bool IsWindowHidden(void); // Check if window is currently hidden +RLAPI bool IsWindowMinimized(void); // Check if window is currently minimized +RLAPI bool IsWindowMaximized(void); // Check if window is currently maximized +RLAPI bool IsWindowFocused(void); // Check if window is currently focused +RLAPI bool IsWindowResized(void); // Check if window has been resized last frame +RLAPI bool IsWindowState(unsigned int flag); // Check if one specific window flag is enabled +RLAPI void SetWindowState(unsigned int flags); // Set window configuration state using flags +RLAPI void ClearWindowState(unsigned int flags); // Clear window configuration state flags +RLAPI void ToggleFullscreen(void); // Toggle window state: fullscreen/windowed, resizes monitor to match window resolution +RLAPI void ToggleBorderlessWindowed(void); // Toggle window state: borderless windowed, resizes window to match monitor resolution +RLAPI void MaximizeWindow(void); // Set window state: maximized, if resizable +RLAPI void MinimizeWindow(void); // Set window state: minimized, if resizable +RLAPI void RestoreWindow(void); // Set window state: not minimized/maximized +RLAPI void SetWindowIcon(Image image); // Set icon for window (single image, RGBA 32bit) +RLAPI void SetWindowIcons(Image *images, int count); // Set icon for window (multiple images, RGBA 32bit) +RLAPI void SetWindowTitle(const char *title); // Set title for window +RLAPI void SetWindowPosition(int x, int y); // Set window position on screen +RLAPI void SetWindowMonitor(int monitor); // Set monitor for the current window +RLAPI void SetWindowMinSize(int width, int height); // Set window minimum dimensions (for FLAG_WINDOW_RESIZABLE) +RLAPI void SetWindowMaxSize(int width, int height); // Set window maximum dimensions (for FLAG_WINDOW_RESIZABLE) +RLAPI void SetWindowSize(int width, int height); // Set window dimensions +RLAPI void SetWindowOpacity(float opacity); // Set window opacity [0.0f..1.0f] +RLAPI void SetWindowFocused(void); // Set window focused +RLAPI void *GetWindowHandle(void); // Get native window handle +RLAPI int GetScreenWidth(void); // Get current screen width +RLAPI int GetScreenHeight(void); // Get current screen height +RLAPI int GetRenderWidth(void); // Get current render width (it considers HiDPI) +RLAPI int GetRenderHeight(void); // Get current render height (it considers HiDPI) +RLAPI int GetMonitorCount(void); // Get number of connected monitors +RLAPI int GetCurrentMonitor(void); // Get current monitor where window is placed +RLAPI Vector2 GetMonitorPosition(int monitor); // Get specified monitor position +RLAPI int GetMonitorWidth(int monitor); // Get specified monitor width (current video mode used by monitor) +RLAPI int GetMonitorHeight(int monitor); // Get specified monitor height (current video mode used by monitor) +RLAPI int GetMonitorPhysicalWidth(int monitor); // Get specified monitor physical width in millimetres +RLAPI int GetMonitorPhysicalHeight(int monitor); // Get specified monitor physical height in millimetres +RLAPI int GetMonitorRefreshRate(int monitor); // Get specified monitor refresh rate +RLAPI Vector2 GetWindowPosition(void); // Get window position XY on monitor +RLAPI Vector2 GetWindowScaleDPI(void); // Get window scale DPI factor +RLAPI const char *GetMonitorName(int monitor); // Get the human-readable, UTF-8 encoded name of the specified monitor +RLAPI void SetClipboardText(const char *text); // Set clipboard text content +RLAPI const char *GetClipboardText(void); // Get clipboard text content +RLAPI Image GetClipboardImage(void); // Get clipboard image content +RLAPI void EnableEventWaiting(void); // Enable waiting for events on EndDrawing(), no automatic event polling +RLAPI void DisableEventWaiting(void); // Disable waiting for events on EndDrawing(), automatic events polling + +// Cursor-related functions +RLAPI void ShowCursor(void); // Shows cursor +RLAPI void HideCursor(void); // Hides cursor +RLAPI bool IsCursorHidden(void); // Check if cursor is not visible +RLAPI void EnableCursor(void); // Enables cursor (unlock cursor) +RLAPI void DisableCursor(void); // Disables cursor (lock cursor) +RLAPI bool IsCursorOnScreen(void); // Check if cursor is on the screen + +// Drawing-related functions +RLAPI void ClearBackground(Color color); // Set background color (framebuffer clear color) +RLAPI void BeginDrawing(void); // Setup canvas (framebuffer) to start drawing +RLAPI void EndDrawing(void); // End canvas drawing and swap buffers (double buffering) +RLAPI void BeginMode2D(Camera2D camera); // Begin 2D mode with custom camera (2D) +RLAPI void EndMode2D(void); // Ends 2D mode with custom camera +RLAPI void BeginMode3D(Camera3D camera); // Begin 3D mode with custom camera (3D) +RLAPI void EndMode3D(void); // Ends 3D mode and returns to default 2D orthographic mode +RLAPI void BeginTextureMode(RenderTexture2D target); // Begin drawing to render texture +RLAPI void EndTextureMode(void); // Ends drawing to render texture +RLAPI void BeginShaderMode(Shader shader); // Begin custom shader drawing +RLAPI void EndShaderMode(void); // End custom shader drawing (use default shader) +RLAPI void BeginBlendMode(int mode); // Begin blending mode (alpha, additive, multiplied, subtract, custom) +RLAPI void EndBlendMode(void); // End blending mode (reset to default: alpha blending) +RLAPI void BeginScissorMode(int x, int y, int width, int height); // Begin scissor mode (define screen area for following drawing) +RLAPI void EndScissorMode(void); // End scissor mode +RLAPI void BeginVrStereoMode(VrStereoConfig config); // Begin stereo rendering (requires VR simulator) +RLAPI void EndVrStereoMode(void); // End stereo rendering (requires VR simulator) + +// VR stereo config functions for VR simulator +RLAPI VrStereoConfig LoadVrStereoConfig(VrDeviceInfo device); // Load VR stereo config for VR simulator device parameters +RLAPI void UnloadVrStereoConfig(VrStereoConfig config); // Unload VR stereo config + +// Shader management functions +// NOTE: Shader functionality is not available on OpenGL 1.1 +RLAPI Shader LoadShader(const char *vsFileName, const char *fsFileName); // Load shader from files and bind default locations +RLAPI Shader LoadShaderFromMemory(const char *vsCode, const char *fsCode); // Load shader from code strings and bind default locations +RLAPI bool IsShaderValid(Shader shader); // Check if a shader is valid (loaded on GPU) +RLAPI int GetShaderLocation(Shader shader, const char *uniformName); // Get shader uniform location +RLAPI int GetShaderLocationAttrib(Shader shader, const char *attribName); // Get shader attribute location +RLAPI void SetShaderValue(Shader shader, int locIndex, const void *value, int uniformType); // Set shader uniform value +RLAPI void SetShaderValueV(Shader shader, int locIndex, const void *value, int uniformType, int count); // Set shader uniform value vector +RLAPI void SetShaderValueMatrix(Shader shader, int locIndex, Matrix mat); // Set shader uniform value (matrix 4x4) +RLAPI void SetShaderValueTexture(Shader shader, int locIndex, Texture2D texture); // Set shader uniform value for texture (sampler2d) +RLAPI void UnloadShader(Shader shader); // Unload shader from GPU memory (VRAM) + +// Screen-space-related functions +#define GetMouseRay GetScreenToWorldRay // Compatibility hack for previous raylib versions +RLAPI Ray GetScreenToWorldRay(Vector2 position, Camera camera); // Get a ray trace from screen position (i.e mouse) +RLAPI Ray GetScreenToWorldRayEx(Vector2 position, Camera camera, int width, int height); // Get a ray trace from screen position (i.e mouse) in a viewport +RLAPI Vector2 GetWorldToScreen(Vector3 position, Camera camera); // Get the screen space position for a 3d world space position +RLAPI Vector2 GetWorldToScreenEx(Vector3 position, Camera camera, int width, int height); // Get size position for a 3d world space position +RLAPI Vector2 GetWorldToScreen2D(Vector2 position, Camera2D camera); // Get the screen space position for a 2d camera world space position +RLAPI Vector2 GetScreenToWorld2D(Vector2 position, Camera2D camera); // Get the world space position for a 2d camera screen space position +RLAPI Matrix GetCameraMatrix(Camera camera); // Get camera transform matrix (view matrix) +RLAPI Matrix GetCameraMatrix2D(Camera2D camera); // Get camera 2d transform matrix + +// Timing-related functions +RLAPI void SetTargetFPS(int fps); // Set target FPS (maximum) +RLAPI float GetFrameTime(void); // Get time in seconds for last frame drawn (delta time) +RLAPI double GetTime(void); // Get elapsed time in seconds since InitWindow() +RLAPI int GetFPS(void); // Get current FPS + +// Custom frame control functions +// NOTE: Those functions are intended for advanced users that want full control over the frame processing +// By default EndDrawing() does this job: draws everything + SwapScreenBuffer() + manage frame timing + PollInputEvents() +// To avoid that behaviour and control frame processes manually, enable in config.h: SUPPORT_CUSTOM_FRAME_CONTROL +RLAPI void SwapScreenBuffer(void); // Swap back buffer with front buffer (screen drawing) +RLAPI void PollInputEvents(void); // Register all input events +RLAPI void WaitTime(double seconds); // Wait for some time (halt program execution) + +// Random values generation functions +RLAPI void SetRandomSeed(unsigned int seed); // Set the seed for the random number generator +RLAPI int GetRandomValue(int min, int max); // Get a random value between min and max (both included) +RLAPI int *LoadRandomSequence(unsigned int count, int min, int max); // Load random values sequence, no values repeated +RLAPI void UnloadRandomSequence(int *sequence); // Unload random values sequence + +// Misc. functions +RLAPI void TakeScreenshot(const char *fileName); // Takes a screenshot of current screen (filename extension defines format) +RLAPI void SetConfigFlags(unsigned int flags); // Setup init configuration flags (view FLAGS) +RLAPI void OpenURL(const char *url); // Open URL with default system browser (if available) + +// NOTE: Following functions implemented in module [utils] +//------------------------------------------------------------------ +RLAPI void TraceLog(int logLevel, const char *text, ...); // Show trace log messages (LOG_DEBUG, LOG_INFO, LOG_WARNING, LOG_ERROR...) +RLAPI void SetTraceLogLevel(int logLevel); // Set the current threshold (minimum) log level +RLAPI void *MemAlloc(unsigned int size); // Internal memory allocator +RLAPI void *MemRealloc(void *ptr, unsigned int size); // Internal memory reallocator +RLAPI void MemFree(void *ptr); // Internal memory free + +// Set custom callbacks +// WARNING: Callbacks setup is intended for advanced users +RLAPI void SetTraceLogCallback(TraceLogCallback callback); // Set custom trace log +RLAPI void SetLoadFileDataCallback(LoadFileDataCallback callback); // Set custom file binary data loader +RLAPI void SetSaveFileDataCallback(SaveFileDataCallback callback); // Set custom file binary data saver +RLAPI void SetLoadFileTextCallback(LoadFileTextCallback callback); // Set custom file text data loader +RLAPI void SetSaveFileTextCallback(SaveFileTextCallback callback); // Set custom file text data saver + +// Files management functions +RLAPI unsigned char *LoadFileData(const char *fileName, int *dataSize); // Load file data as byte array (read) +RLAPI void UnloadFileData(unsigned char *data); // Unload file data allocated by LoadFileData() +RLAPI bool SaveFileData(const char *fileName, void *data, int dataSize); // Save data to file from byte array (write), returns true on success +RLAPI bool ExportDataAsCode(const unsigned char *data, int dataSize, const char *fileName); // Export data to code (.h), returns true on success +RLAPI char *LoadFileText(const char *fileName); // Load text data from file (read), returns a '\0' terminated string +RLAPI void UnloadFileText(char *text); // Unload file text data allocated by LoadFileText() +RLAPI bool SaveFileText(const char *fileName, char *text); // Save text data to file (write), string must be '\0' terminated, returns true on success +//------------------------------------------------------------------ + +// File system functions +RLAPI bool FileExists(const char *fileName); // Check if file exists +RLAPI bool DirectoryExists(const char *dirPath); // Check if a directory path exists +RLAPI bool IsFileExtension(const char *fileName, const char *ext); // Check file extension (including point: .png, .wav) +RLAPI int GetFileLength(const char *fileName); // Get file length in bytes (NOTE: GetFileSize() conflicts with windows.h) +RLAPI const char *GetFileExtension(const char *fileName); // Get pointer to extension for a filename string (includes dot: '.png') +RLAPI const char *GetFileName(const char *filePath); // Get pointer to filename for a path string +RLAPI const char *GetFileNameWithoutExt(const char *filePath); // Get filename string without extension (uses static string) +RLAPI const char *GetDirectoryPath(const char *filePath); // Get full path for a given fileName with path (uses static string) +RLAPI const char *GetPrevDirectoryPath(const char *dirPath); // Get previous directory path for a given path (uses static string) +RLAPI const char *GetWorkingDirectory(void); // Get current working directory (uses static string) +RLAPI const char *GetApplicationDirectory(void); // Get the directory of the running application (uses static string) +RLAPI int MakeDirectory(const char *dirPath); // Create directories (including full path requested), returns 0 on success +RLAPI bool ChangeDirectory(const char *dir); // Change working directory, return true on success +RLAPI bool IsPathFile(const char *path); // Check if a given path is a file or a directory +RLAPI bool IsFileNameValid(const char *fileName); // Check if fileName is valid for the platform/OS +RLAPI FilePathList LoadDirectoryFiles(const char *dirPath); // Load directory filepaths +RLAPI FilePathList LoadDirectoryFilesEx(const char *basePath, const char *filter, bool scanSubdirs); // Load directory filepaths with extension filtering and recursive directory scan. Use 'DIR' in the filter string to include directories in the result +RLAPI void UnloadDirectoryFiles(FilePathList files); // Unload filepaths +RLAPI bool IsFileDropped(void); // Check if a file has been dropped into window +RLAPI FilePathList LoadDroppedFiles(void); // Load dropped filepaths +RLAPI void UnloadDroppedFiles(FilePathList files); // Unload dropped filepaths +RLAPI long GetFileModTime(const char *fileName); // Get file modification time (last write time) + +// Compression/Encoding functionality +RLAPI unsigned char *CompressData(const unsigned char *data, int dataSize, int *compDataSize); // Compress data (DEFLATE algorithm), memory must be MemFree() +RLAPI unsigned char *DecompressData(const unsigned char *compData, int compDataSize, int *dataSize); // Decompress data (DEFLATE algorithm), memory must be MemFree() +RLAPI char *EncodeDataBase64(const unsigned char *data, int dataSize, int *outputSize); // Encode data to Base64 string, memory must be MemFree() +RLAPI unsigned char *DecodeDataBase64(const unsigned char *data, int *outputSize); // Decode Base64 string data, memory must be MemFree() +RLAPI unsigned int ComputeCRC32(unsigned char *data, int dataSize); // Compute CRC32 hash code +RLAPI unsigned int *ComputeMD5(unsigned char *data, int dataSize); // Compute MD5 hash code, returns static int[4] (16 bytes) +RLAPI unsigned int *ComputeSHA1(unsigned char *data, int dataSize); // Compute SHA1 hash code, returns static int[5] (20 bytes) + + +// Automation events functionality +RLAPI AutomationEventList LoadAutomationEventList(const char *fileName); // Load automation events list from file, NULL for empty list, capacity = MAX_AUTOMATION_EVENTS +RLAPI void UnloadAutomationEventList(AutomationEventList list); // Unload automation events list from file +RLAPI bool ExportAutomationEventList(AutomationEventList list, const char *fileName); // Export automation events list as text file +RLAPI void SetAutomationEventList(AutomationEventList *list); // Set automation event list to record to +RLAPI void SetAutomationEventBaseFrame(int frame); // Set automation event internal base frame to start recording +RLAPI void StartAutomationEventRecording(void); // Start recording automation events (AutomationEventList must be set) +RLAPI void StopAutomationEventRecording(void); // Stop recording automation events +RLAPI void PlayAutomationEvent(AutomationEvent event); // Play a recorded automation event + +//------------------------------------------------------------------------------------ +// Input Handling Functions (Module: core) +//------------------------------------------------------------------------------------ + +// Input-related functions: keyboard +RLAPI bool IsKeyPressed(int key); // Check if a key has been pressed once +RLAPI bool IsKeyPressedRepeat(int key); // Check if a key has been pressed again +RLAPI bool IsKeyDown(int key); // Check if a key is being pressed +RLAPI bool IsKeyReleased(int key); // Check if a key has been released once +RLAPI bool IsKeyUp(int key); // Check if a key is NOT being pressed +RLAPI int GetKeyPressed(void); // Get key pressed (keycode), call it multiple times for keys queued, returns 0 when the queue is empty +RLAPI int GetCharPressed(void); // Get char pressed (unicode), call it multiple times for chars queued, returns 0 when the queue is empty +RLAPI void SetExitKey(int key); // Set a custom key to exit program (default is ESC) + +// Input-related functions: gamepads +RLAPI bool IsGamepadAvailable(int gamepad); // Check if a gamepad is available +RLAPI const char *GetGamepadName(int gamepad); // Get gamepad internal name id +RLAPI bool IsGamepadButtonPressed(int gamepad, int button); // Check if a gamepad button has been pressed once +RLAPI bool IsGamepadButtonDown(int gamepad, int button); // Check if a gamepad button is being pressed +RLAPI bool IsGamepadButtonReleased(int gamepad, int button); // Check if a gamepad button has been released once +RLAPI bool IsGamepadButtonUp(int gamepad, int button); // Check if a gamepad button is NOT being pressed +RLAPI int GetGamepadButtonPressed(void); // Get the last gamepad button pressed +RLAPI int GetGamepadAxisCount(int gamepad); // Get gamepad axis count for a gamepad +RLAPI float GetGamepadAxisMovement(int gamepad, int axis); // Get axis movement value for a gamepad axis +RLAPI int SetGamepadMappings(const char *mappings); // Set internal gamepad mappings (SDL_GameControllerDB) +RLAPI void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor, float duration); // Set gamepad vibration for both motors (duration in seconds) + +// Input-related functions: mouse +RLAPI bool IsMouseButtonPressed(int button); // Check if a mouse button has been pressed once +RLAPI bool IsMouseButtonDown(int button); // Check if a mouse button is being pressed +RLAPI bool IsMouseButtonReleased(int button); // Check if a mouse button has been released once +RLAPI bool IsMouseButtonUp(int button); // Check if a mouse button is NOT being pressed +RLAPI int GetMouseX(void); // Get mouse position X +RLAPI int GetMouseY(void); // Get mouse position Y +RLAPI Vector2 GetMousePosition(void); // Get mouse position XY +RLAPI Vector2 GetMouseDelta(void); // Get mouse delta between frames +RLAPI void SetMousePosition(int x, int y); // Set mouse position XY +RLAPI void SetMouseOffset(int offsetX, int offsetY); // Set mouse offset +RLAPI void SetMouseScale(float scaleX, float scaleY); // Set mouse scaling +RLAPI float GetMouseWheelMove(void); // Get mouse wheel movement for X or Y, whichever is larger +RLAPI Vector2 GetMouseWheelMoveV(void); // Get mouse wheel movement for both X and Y +RLAPI void SetMouseCursor(int cursor); // Set mouse cursor + +// Input-related functions: touch +RLAPI int GetTouchX(void); // Get touch position X for touch point 0 (relative to screen size) +RLAPI int GetTouchY(void); // Get touch position Y for touch point 0 (relative to screen size) +RLAPI Vector2 GetTouchPosition(int index); // Get touch position XY for a touch point index (relative to screen size) +RLAPI int GetTouchPointId(int index); // Get touch point identifier for given index +RLAPI int GetTouchPointCount(void); // Get number of touch points + +//------------------------------------------------------------------------------------ +// Gestures and Touch Handling Functions (Module: rgestures) +//------------------------------------------------------------------------------------ +RLAPI void SetGesturesEnabled(unsigned int flags); // Enable a set of gestures using flags +RLAPI bool IsGestureDetected(unsigned int gesture); // Check if a gesture have been detected +RLAPI int GetGestureDetected(void); // Get latest detected gesture +RLAPI float GetGestureHoldDuration(void); // Get gesture hold time in seconds +RLAPI Vector2 GetGestureDragVector(void); // Get gesture drag vector +RLAPI float GetGestureDragAngle(void); // Get gesture drag angle +RLAPI Vector2 GetGesturePinchVector(void); // Get gesture pinch delta +RLAPI float GetGesturePinchAngle(void); // Get gesture pinch angle + +//------------------------------------------------------------------------------------ +// Camera System Functions (Module: rcamera) +//------------------------------------------------------------------------------------ +RLAPI void UpdateCamera(Camera *camera, int mode); // Update camera position for selected mode +RLAPI void UpdateCameraPro(Camera *camera, Vector3 movement, Vector3 rotation, float zoom); // Update camera movement/rotation + +//------------------------------------------------------------------------------------ +// Basic Shapes Drawing Functions (Module: shapes) +//------------------------------------------------------------------------------------ +// Set texture and rectangle to be used on shapes drawing +// NOTE: It can be useful when using basic shapes and one single font, +// defining a font char white rectangle would allow drawing everything in a single draw call +RLAPI void SetShapesTexture(Texture2D texture, Rectangle source); // Set texture and rectangle to be used on shapes drawing +RLAPI Texture2D GetShapesTexture(void); // Get texture that is used for shapes drawing +RLAPI Rectangle GetShapesTextureRectangle(void); // Get texture source rectangle that is used for shapes drawing + +// Basic shapes drawing functions +RLAPI void DrawPixel(int posX, int posY, Color color); // Draw a pixel using geometry [Can be slow, use with care] +RLAPI void DrawPixelV(Vector2 position, Color color); // Draw a pixel using geometry (Vector version) [Can be slow, use with care] +RLAPI void DrawLine(int startPosX, int startPosY, int endPosX, int endPosY, Color color); // Draw a line +RLAPI void DrawLineV(Vector2 startPos, Vector2 endPos, Color color); // Draw a line (using gl lines) +RLAPI void DrawLineEx(Vector2 startPos, Vector2 endPos, float thick, Color color); // Draw a line (using triangles/quads) +RLAPI void DrawLineStrip(const Vector2 *points, int pointCount, Color color); // Draw lines sequence (using gl lines) +RLAPI void DrawLineBezier(Vector2 startPos, Vector2 endPos, float thick, Color color); // Draw line segment cubic-bezier in-out interpolation +RLAPI void DrawCircle(int centerX, int centerY, float radius, Color color); // Draw a color-filled circle +RLAPI void DrawCircleSector(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color); // Draw a piece of a circle +RLAPI void DrawCircleSectorLines(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color); // Draw circle sector outline +RLAPI void DrawCircleGradient(int centerX, int centerY, float radius, Color inner, Color outer); // Draw a gradient-filled circle +RLAPI void DrawCircleV(Vector2 center, float radius, Color color); // Draw a color-filled circle (Vector version) +RLAPI void DrawCircleLines(int centerX, int centerY, float radius, Color color); // Draw circle outline +RLAPI void DrawCircleLinesV(Vector2 center, float radius, Color color); // Draw circle outline (Vector version) +RLAPI void DrawEllipse(int centerX, int centerY, float radiusH, float radiusV, Color color); // Draw ellipse +RLAPI void DrawEllipseLines(int centerX, int centerY, float radiusH, float radiusV, Color color); // Draw ellipse outline +RLAPI void DrawRing(Vector2 center, float innerRadius, float outerRadius, float startAngle, float endAngle, int segments, Color color); // Draw ring +RLAPI void DrawRingLines(Vector2 center, float innerRadius, float outerRadius, float startAngle, float endAngle, int segments, Color color); // Draw ring outline +RLAPI void DrawRectangle(int posX, int posY, int width, int height, Color color); // Draw a color-filled rectangle +RLAPI void DrawRectangleV(Vector2 position, Vector2 size, Color color); // Draw a color-filled rectangle (Vector version) +RLAPI void DrawRectangleRec(Rectangle rec, Color color); // Draw a color-filled rectangle +RLAPI void DrawRectanglePro(Rectangle rec, Vector2 origin, float rotation, Color color); // Draw a color-filled rectangle with pro parameters +RLAPI void DrawRectangleGradientV(int posX, int posY, int width, int height, Color top, Color bottom); // Draw a vertical-gradient-filled rectangle +RLAPI void DrawRectangleGradientH(int posX, int posY, int width, int height, Color left, Color right); // Draw a horizontal-gradient-filled rectangle +RLAPI void DrawRectangleGradientEx(Rectangle rec, Color topLeft, Color bottomLeft, Color topRight, Color bottomRight); // Draw a gradient-filled rectangle with custom vertex colors +RLAPI void DrawRectangleLines(int posX, int posY, int width, int height, Color color); // Draw rectangle outline +RLAPI void DrawRectangleLinesEx(Rectangle rec, float lineThick, Color color); // Draw rectangle outline with extended parameters +RLAPI void DrawRectangleRounded(Rectangle rec, float roundness, int segments, Color color); // Draw rectangle with rounded edges +RLAPI void DrawRectangleRoundedLines(Rectangle rec, float roundness, int segments, Color color); // Draw rectangle lines with rounded edges +RLAPI void DrawRectangleRoundedLinesEx(Rectangle rec, float roundness, int segments, float lineThick, Color color); // Draw rectangle with rounded edges outline +RLAPI void DrawTriangle(Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw a color-filled triangle (vertex in counter-clockwise order!) +RLAPI void DrawTriangleLines(Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw triangle outline (vertex in counter-clockwise order!) +RLAPI void DrawTriangleFan(const Vector2 *points, int pointCount, Color color); // Draw a triangle fan defined by points (first vertex is the center) +RLAPI void DrawTriangleStrip(const Vector2 *points, int pointCount, Color color); // Draw a triangle strip defined by points +RLAPI void DrawPoly(Vector2 center, int sides, float radius, float rotation, Color color); // Draw a regular polygon (Vector version) +RLAPI void DrawPolyLines(Vector2 center, int sides, float radius, float rotation, Color color); // Draw a polygon outline of n sides +RLAPI void DrawPolyLinesEx(Vector2 center, int sides, float radius, float rotation, float lineThick, Color color); // Draw a polygon outline of n sides with extended parameters + +// Splines drawing functions +RLAPI void DrawSplineLinear(const Vector2 *points, int pointCount, float thick, Color color); // Draw spline: Linear, minimum 2 points +RLAPI void DrawSplineBasis(const Vector2 *points, int pointCount, float thick, Color color); // Draw spline: B-Spline, minimum 4 points +RLAPI void DrawSplineCatmullRom(const Vector2 *points, int pointCount, float thick, Color color); // Draw spline: Catmull-Rom, minimum 4 points +RLAPI void DrawSplineBezierQuadratic(const Vector2 *points, int pointCount, float thick, Color color); // Draw spline: Quadratic Bezier, minimum 3 points (1 control point): [p1, c2, p3, c4...] +RLAPI void DrawSplineBezierCubic(const Vector2 *points, int pointCount, float thick, Color color); // Draw spline: Cubic Bezier, minimum 4 points (2 control points): [p1, c2, c3, p4, c5, c6...] +RLAPI void DrawSplineSegmentLinear(Vector2 p1, Vector2 p2, float thick, Color color); // Draw spline segment: Linear, 2 points +RLAPI void DrawSplineSegmentBasis(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4, float thick, Color color); // Draw spline segment: B-Spline, 4 points +RLAPI void DrawSplineSegmentCatmullRom(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4, float thick, Color color); // Draw spline segment: Catmull-Rom, 4 points +RLAPI void DrawSplineSegmentBezierQuadratic(Vector2 p1, Vector2 c2, Vector2 p3, float thick, Color color); // Draw spline segment: Quadratic Bezier, 2 points, 1 control point +RLAPI void DrawSplineSegmentBezierCubic(Vector2 p1, Vector2 c2, Vector2 c3, Vector2 p4, float thick, Color color); // Draw spline segment: Cubic Bezier, 2 points, 2 control points + +// Spline segment point evaluation functions, for a given t [0.0f .. 1.0f] +RLAPI Vector2 GetSplinePointLinear(Vector2 startPos, Vector2 endPos, float t); // Get (evaluate) spline point: Linear +RLAPI Vector2 GetSplinePointBasis(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4, float t); // Get (evaluate) spline point: B-Spline +RLAPI Vector2 GetSplinePointCatmullRom(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4, float t); // Get (evaluate) spline point: Catmull-Rom +RLAPI Vector2 GetSplinePointBezierQuad(Vector2 p1, Vector2 c2, Vector2 p3, float t); // Get (evaluate) spline point: Quadratic Bezier +RLAPI Vector2 GetSplinePointBezierCubic(Vector2 p1, Vector2 c2, Vector2 c3, Vector2 p4, float t); // Get (evaluate) spline point: Cubic Bezier + +// Basic shapes collision detection functions +RLAPI bool CheckCollisionRecs(Rectangle rec1, Rectangle rec2); // Check collision between two rectangles +RLAPI bool CheckCollisionCircles(Vector2 center1, float radius1, Vector2 center2, float radius2); // Check collision between two circles +RLAPI bool CheckCollisionCircleRec(Vector2 center, float radius, Rectangle rec); // Check collision between circle and rectangle +RLAPI bool CheckCollisionCircleLine(Vector2 center, float radius, Vector2 p1, Vector2 p2); // Check if circle collides with a line created betweeen two points [p1] and [p2] +RLAPI bool CheckCollisionPointRec(Vector2 point, Rectangle rec); // Check if point is inside rectangle +RLAPI bool CheckCollisionPointCircle(Vector2 point, Vector2 center, float radius); // Check if point is inside circle +RLAPI bool CheckCollisionPointTriangle(Vector2 point, Vector2 p1, Vector2 p2, Vector2 p3); // Check if point is inside a triangle +RLAPI bool CheckCollisionPointLine(Vector2 point, Vector2 p1, Vector2 p2, int threshold); // Check if point belongs to line created between two points [p1] and [p2] with defined margin in pixels [threshold] +RLAPI bool CheckCollisionPointPoly(Vector2 point, const Vector2 *points, int pointCount); // Check if point is within a polygon described by array of vertices +RLAPI bool CheckCollisionLines(Vector2 startPos1, Vector2 endPos1, Vector2 startPos2, Vector2 endPos2, Vector2 *collisionPoint); // Check the collision between two lines defined by two points each, returns collision point by reference +RLAPI Rectangle GetCollisionRec(Rectangle rec1, Rectangle rec2); // Get collision rectangle for two rectangles collision + +//------------------------------------------------------------------------------------ +// Texture Loading and Drawing Functions (Module: textures) +//------------------------------------------------------------------------------------ + +// Image loading functions +// NOTE: These functions do not require GPU access +RLAPI Image LoadImage(const char *fileName); // Load image from file into CPU memory (RAM) +RLAPI Image LoadImageRaw(const char *fileName, int width, int height, int format, int headerSize); // Load image from RAW file data +RLAPI Image LoadImageAnim(const char *fileName, int *frames); // Load image sequence from file (frames appended to image.data) +RLAPI Image LoadImageAnimFromMemory(const char *fileType, const unsigned char *fileData, int dataSize, int *frames); // Load image sequence from memory buffer +RLAPI Image LoadImageFromMemory(const char *fileType, const unsigned char *fileData, int dataSize); // Load image from memory buffer, fileType refers to extension: i.e. '.png' +RLAPI Image LoadImageFromTexture(Texture2D texture); // Load image from GPU texture data +RLAPI Image LoadImageFromScreen(void); // Load image from screen buffer and (screenshot) +RLAPI bool IsImageValid(Image image); // Check if an image is valid (data and parameters) +RLAPI void UnloadImage(Image image); // Unload image from CPU memory (RAM) +RLAPI bool ExportImage(Image image, const char *fileName); // Export image data to file, returns true on success +RLAPI unsigned char *ExportImageToMemory(Image image, const char *fileType, int *fileSize); // Export image to memory buffer +RLAPI bool ExportImageAsCode(Image image, const char *fileName); // Export image as code file defining an array of bytes, returns true on success + +// Image generation functions +RLAPI Image GenImageColor(int width, int height, Color color); // Generate image: plain color +RLAPI Image GenImageGradientLinear(int width, int height, int direction, Color start, Color end); // Generate image: linear gradient, direction in degrees [0..360], 0=Vertical gradient +RLAPI Image GenImageGradientRadial(int width, int height, float density, Color inner, Color outer); // Generate image: radial gradient +RLAPI Image GenImageGradientSquare(int width, int height, float density, Color inner, Color outer); // Generate image: square gradient +RLAPI Image GenImageChecked(int width, int height, int checksX, int checksY, Color col1, Color col2); // Generate image: checked +RLAPI Image GenImageWhiteNoise(int width, int height, float factor); // Generate image: white noise +RLAPI Image GenImagePerlinNoise(int width, int height, int offsetX, int offsetY, float scale); // Generate image: perlin noise +RLAPI Image GenImageCellular(int width, int height, int tileSize); // Generate image: cellular algorithm, bigger tileSize means bigger cells +RLAPI Image GenImageText(int width, int height, const char *text); // Generate image: grayscale image from text data + +// Image manipulation functions +RLAPI Image ImageCopy(Image image); // Create an image duplicate (useful for transformations) +RLAPI Image ImageFromImage(Image image, Rectangle rec); // Create an image from another image piece +RLAPI Image ImageFromChannel(Image image, int selectedChannel); // Create an image from a selected channel of another image (GRAYSCALE) +RLAPI Image ImageText(const char *text, int fontSize, Color color); // Create an image from text (default font) +RLAPI Image ImageTextEx(Font font, const char *text, float fontSize, float spacing, Color tint); // Create an image from text (custom sprite font) +RLAPI void ImageFormat(Image *image, int newFormat); // Convert image data to desired format +RLAPI void ImageToPOT(Image *image, Color fill); // Convert image to POT (power-of-two) +RLAPI void ImageCrop(Image *image, Rectangle crop); // Crop an image to a defined rectangle +RLAPI void ImageAlphaCrop(Image *image, float threshold); // Crop image depending on alpha value +RLAPI void ImageAlphaClear(Image *image, Color color, float threshold); // Clear alpha channel to desired color +RLAPI void ImageAlphaMask(Image *image, Image alphaMask); // Apply alpha mask to image +RLAPI void ImageAlphaPremultiply(Image *image); // Premultiply alpha channel +RLAPI void ImageBlurGaussian(Image *image, int blurSize); // Apply Gaussian blur using a box blur approximation +RLAPI void ImageKernelConvolution(Image *image, const float *kernel, int kernelSize); // Apply custom square convolution kernel to image +RLAPI void ImageResize(Image *image, int newWidth, int newHeight); // Resize image (Bicubic scaling algorithm) +RLAPI void ImageResizeNN(Image *image, int newWidth,int newHeight); // Resize image (Nearest-Neighbor scaling algorithm) +RLAPI void ImageResizeCanvas(Image *image, int newWidth, int newHeight, int offsetX, int offsetY, Color fill); // Resize canvas and fill with color +RLAPI void ImageMipmaps(Image *image); // Compute all mipmap levels for a provided image +RLAPI void ImageDither(Image *image, int rBpp, int gBpp, int bBpp, int aBpp); // Dither image data to 16bpp or lower (Floyd-Steinberg dithering) +RLAPI void ImageFlipVertical(Image *image); // Flip image vertically +RLAPI void ImageFlipHorizontal(Image *image); // Flip image horizontally +RLAPI void ImageRotate(Image *image, int degrees); // Rotate image by input angle in degrees (-359 to 359) +RLAPI void ImageRotateCW(Image *image); // Rotate image clockwise 90deg +RLAPI void ImageRotateCCW(Image *image); // Rotate image counter-clockwise 90deg +RLAPI void ImageColorTint(Image *image, Color color); // Modify image color: tint +RLAPI void ImageColorInvert(Image *image); // Modify image color: invert +RLAPI void ImageColorGrayscale(Image *image); // Modify image color: grayscale +RLAPI void ImageColorContrast(Image *image, float contrast); // Modify image color: contrast (-100 to 100) +RLAPI void ImageColorBrightness(Image *image, int brightness); // Modify image color: brightness (-255 to 255) +RLAPI void ImageColorReplace(Image *image, Color color, Color replace); // Modify image color: replace color +RLAPI Color *LoadImageColors(Image image); // Load color data from image as a Color array (RGBA - 32bit) +RLAPI Color *LoadImagePalette(Image image, int maxPaletteSize, int *colorCount); // Load colors palette from image as a Color array (RGBA - 32bit) +RLAPI void UnloadImageColors(Color *colors); // Unload color data loaded with LoadImageColors() +RLAPI void UnloadImagePalette(Color *colors); // Unload colors palette loaded with LoadImagePalette() +RLAPI Rectangle GetImageAlphaBorder(Image image, float threshold); // Get image alpha border rectangle +RLAPI Color GetImageColor(Image image, int x, int y); // Get image pixel color at (x, y) position + +// Image drawing functions +// NOTE: Image software-rendering functions (CPU) +RLAPI void ImageClearBackground(Image *dst, Color color); // Clear image background with given color +RLAPI void ImageDrawPixel(Image *dst, int posX, int posY, Color color); // Draw pixel within an image +RLAPI void ImageDrawPixelV(Image *dst, Vector2 position, Color color); // Draw pixel within an image (Vector version) +RLAPI void ImageDrawLine(Image *dst, int startPosX, int startPosY, int endPosX, int endPosY, Color color); // Draw line within an image +RLAPI void ImageDrawLineV(Image *dst, Vector2 start, Vector2 end, Color color); // Draw line within an image (Vector version) +RLAPI void ImageDrawLineEx(Image *dst, Vector2 start, Vector2 end, int thick, Color color); // Draw a line defining thickness within an image +RLAPI void ImageDrawCircle(Image *dst, int centerX, int centerY, int radius, Color color); // Draw a filled circle within an image +RLAPI void ImageDrawCircleV(Image *dst, Vector2 center, int radius, Color color); // Draw a filled circle within an image (Vector version) +RLAPI void ImageDrawCircleLines(Image *dst, int centerX, int centerY, int radius, Color color); // Draw circle outline within an image +RLAPI void ImageDrawCircleLinesV(Image *dst, Vector2 center, int radius, Color color); // Draw circle outline within an image (Vector version) +RLAPI void ImageDrawRectangle(Image *dst, int posX, int posY, int width, int height, Color color); // Draw rectangle within an image +RLAPI void ImageDrawRectangleV(Image *dst, Vector2 position, Vector2 size, Color color); // Draw rectangle within an image (Vector version) +RLAPI void ImageDrawRectangleRec(Image *dst, Rectangle rec, Color color); // Draw rectangle within an image +RLAPI void ImageDrawRectangleLines(Image *dst, Rectangle rec, int thick, Color color); // Draw rectangle lines within an image +RLAPI void ImageDrawTriangle(Image *dst, Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw triangle within an image +RLAPI void ImageDrawTriangleEx(Image *dst, Vector2 v1, Vector2 v2, Vector2 v3, Color c1, Color c2, Color c3); // Draw triangle with interpolated colors within an image +RLAPI void ImageDrawTriangleLines(Image *dst, Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw triangle outline within an image +RLAPI void ImageDrawTriangleFan(Image *dst, Vector2 *points, int pointCount, Color color); // Draw a triangle fan defined by points within an image (first vertex is the center) +RLAPI void ImageDrawTriangleStrip(Image *dst, Vector2 *points, int pointCount, Color color); // Draw a triangle strip defined by points within an image +RLAPI void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec, Color tint); // Draw a source image within a destination image (tint applied to source) +RLAPI void ImageDrawText(Image *dst, const char *text, int posX, int posY, int fontSize, Color color); // Draw text (using default font) within an image (destination) +RLAPI void ImageDrawTextEx(Image *dst, Font font, const char *text, Vector2 position, float fontSize, float spacing, Color tint); // Draw text (custom sprite font) within an image (destination) + +// Texture loading functions +// NOTE: These functions require GPU access +RLAPI Texture2D LoadTexture(const char *fileName); // Load texture from file into GPU memory (VRAM) +RLAPI Texture2D LoadTextureFromImage(Image image); // Load texture from image data +RLAPI TextureCubemap LoadTextureCubemap(Image image, int layout); // Load cubemap from image, multiple image cubemap layouts supported +RLAPI RenderTexture2D LoadRenderTexture(int width, int height); // Load texture for rendering (framebuffer) +RLAPI bool IsTextureValid(Texture2D texture); // Check if a texture is valid (loaded in GPU) +RLAPI void UnloadTexture(Texture2D texture); // Unload texture from GPU memory (VRAM) +RLAPI bool IsRenderTextureValid(RenderTexture2D target); // Check if a render texture is valid (loaded in GPU) +RLAPI void UnloadRenderTexture(RenderTexture2D target); // Unload render texture from GPU memory (VRAM) +RLAPI void UpdateTexture(Texture2D texture, const void *pixels); // Update GPU texture with new data +RLAPI void UpdateTextureRec(Texture2D texture, Rectangle rec, const void *pixels); // Update GPU texture rectangle with new data + +// Texture configuration functions +RLAPI void GenTextureMipmaps(Texture2D *texture); // Generate GPU mipmaps for a texture +RLAPI void SetTextureFilter(Texture2D texture, int filter); // Set texture scaling filter mode +RLAPI void SetTextureWrap(Texture2D texture, int wrap); // Set texture wrapping mode + +// Texture drawing functions +RLAPI void DrawTexture(Texture2D texture, int posX, int posY, Color tint); // Draw a Texture2D +RLAPI void DrawTextureV(Texture2D texture, Vector2 position, Color tint); // Draw a Texture2D with position defined as Vector2 +RLAPI void DrawTextureEx(Texture2D texture, Vector2 position, float rotation, float scale, Color tint); // Draw a Texture2D with extended parameters +RLAPI void DrawTextureRec(Texture2D texture, Rectangle source, Vector2 position, Color tint); // Draw a part of a texture defined by a rectangle +RLAPI void DrawTexturePro(Texture2D texture, Rectangle source, Rectangle dest, Vector2 origin, float rotation, Color tint); // Draw a part of a texture defined by a rectangle with 'pro' parameters +RLAPI void DrawTextureNPatch(Texture2D texture, NPatchInfo nPatchInfo, Rectangle dest, Vector2 origin, float rotation, Color tint); // Draws a texture (or part of it) that stretches or shrinks nicely + +// Color/pixel related functions +RLAPI bool ColorIsEqual(Color col1, Color col2); // Check if two colors are equal +RLAPI Color Fade(Color color, float alpha); // Get color with alpha applied, alpha goes from 0.0f to 1.0f +RLAPI int ColorToInt(Color color); // Get hexadecimal value for a Color (0xRRGGBBAA) +RLAPI Vector4 ColorNormalize(Color color); // Get Color normalized as float [0..1] +RLAPI Color ColorFromNormalized(Vector4 normalized); // Get Color from normalized values [0..1] +RLAPI Vector3 ColorToHSV(Color color); // Get HSV values for a Color, hue [0..360], saturation/value [0..1] +RLAPI Color ColorFromHSV(float hue, float saturation, float value); // Get a Color from HSV values, hue [0..360], saturation/value [0..1] +RLAPI Color ColorTint(Color color, Color tint); // Get color multiplied with another color +RLAPI Color ColorBrightness(Color color, float factor); // Get color with brightness correction, brightness factor goes from -1.0f to 1.0f +RLAPI Color ColorContrast(Color color, float contrast); // Get color with contrast correction, contrast values between -1.0f and 1.0f +RLAPI Color ColorAlpha(Color color, float alpha); // Get color with alpha applied, alpha goes from 0.0f to 1.0f +RLAPI Color ColorAlphaBlend(Color dst, Color src, Color tint); // Get src alpha-blended into dst color with tint +RLAPI Color ColorLerp(Color color1, Color color2, float factor); // Get color lerp interpolation between two colors, factor [0.0f..1.0f] +RLAPI Color GetColor(unsigned int hexValue); // Get Color structure from hexadecimal value +RLAPI Color GetPixelColor(void *srcPtr, int format); // Get Color from a source pixel pointer of certain format +RLAPI void SetPixelColor(void *dstPtr, Color color, int format); // Set color formatted into destination pixel pointer +RLAPI int GetPixelDataSize(int width, int height, int format); // Get pixel data size in bytes for certain format + +//------------------------------------------------------------------------------------ +// Font Loading and Text Drawing Functions (Module: text) +//------------------------------------------------------------------------------------ + +// Font loading/unloading functions +RLAPI Font GetFontDefault(void); // Get the default Font +RLAPI Font LoadFont(const char *fileName); // Load font from file into GPU memory (VRAM) +RLAPI Font LoadFontEx(const char *fileName, int fontSize, int *codepoints, int codepointCount); // Load font from file with extended parameters, use NULL for codepoints and 0 for codepointCount to load the default character set, font size is provided in pixels height +RLAPI Font LoadFontFromImage(Image image, Color key, int firstChar); // Load font from Image (XNA style) +RLAPI Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int dataSize, int fontSize, int *codepoints, int codepointCount); // Load font from memory buffer, fileType refers to extension: i.e. '.ttf' +RLAPI bool IsFontValid(Font font); // Check if a font is valid (font data loaded, WARNING: GPU texture not checked) +RLAPI GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSize, int *codepoints, int codepointCount, int type); // Load font data for further use +RLAPI Image GenImageFontAtlas(const GlyphInfo *glyphs, Rectangle **glyphRecs, int glyphCount, int fontSize, int padding, int packMethod); // Generate image font atlas using chars info +RLAPI void UnloadFontData(GlyphInfo *glyphs, int glyphCount); // Unload font chars info data (RAM) +RLAPI void UnloadFont(Font font); // Unload font from GPU memory (VRAM) +RLAPI bool ExportFontAsCode(Font font, const char *fileName); // Export font as code file, returns true on success + +// Text drawing functions +RLAPI void DrawFPS(int posX, int posY); // Draw current FPS +RLAPI void DrawText(const char *text, int posX, int posY, int fontSize, Color color); // Draw text (using default font) +RLAPI void DrawTextEx(Font font, const char *text, Vector2 position, float fontSize, float spacing, Color tint); // Draw text using font and additional parameters +RLAPI void DrawTextPro(Font font, const char *text, Vector2 position, Vector2 origin, float rotation, float fontSize, float spacing, Color tint); // Draw text using Font and pro parameters (rotation) +RLAPI void DrawTextCodepoint(Font font, int codepoint, Vector2 position, float fontSize, Color tint); // Draw one character (codepoint) +RLAPI void DrawTextCodepoints(Font font, const int *codepoints, int codepointCount, Vector2 position, float fontSize, float spacing, Color tint); // Draw multiple character (codepoint) + +// Text font info functions +RLAPI void SetTextLineSpacing(int spacing); // Set vertical line spacing when drawing with line-breaks +RLAPI int MeasureText(const char *text, int fontSize); // Measure string width for default font +RLAPI Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing); // Measure string size for Font +RLAPI int GetGlyphIndex(Font font, int codepoint); // Get glyph index position in font for a codepoint (unicode character), fallback to '?' if not found +RLAPI GlyphInfo GetGlyphInfo(Font font, int codepoint); // Get glyph font info data for a codepoint (unicode character), fallback to '?' if not found +RLAPI Rectangle GetGlyphAtlasRec(Font font, int codepoint); // Get glyph rectangle in font atlas for a codepoint (unicode character), fallback to '?' if not found + +// Text codepoints management functions (unicode characters) +RLAPI char *LoadUTF8(const int *codepoints, int length); // Load UTF-8 text encoded from codepoints array +RLAPI void UnloadUTF8(char *text); // Unload UTF-8 text encoded from codepoints array +RLAPI int *LoadCodepoints(const char *text, int *count); // Load all codepoints from a UTF-8 text string, codepoints count returned by parameter +RLAPI void UnloadCodepoints(int *codepoints); // Unload codepoints data from memory +RLAPI int GetCodepointCount(const char *text); // Get total number of codepoints in a UTF-8 encoded string +RLAPI int GetCodepoint(const char *text, int *codepointSize); // Get next codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure +RLAPI int GetCodepointNext(const char *text, int *codepointSize); // Get next codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure +RLAPI int GetCodepointPrevious(const char *text, int *codepointSize); // Get previous codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure +RLAPI const char *CodepointToUTF8(int codepoint, int *utf8Size); // Encode one codepoint into UTF-8 byte array (array length returned as parameter) + +// Text strings management functions (no UTF-8 strings, only byte chars) +// NOTE: Some strings allocate memory internally for returned strings, just be careful! +RLAPI int TextCopy(char *dst, const char *src); // Copy one string to another, returns bytes copied +RLAPI bool TextIsEqual(const char *text1, const char *text2); // Check if two text string are equal +RLAPI unsigned int TextLength(const char *text); // Get text length, checks for '\0' ending +RLAPI const char *TextFormat(const char *text, ...); // Text formatting with variables (sprintf() style) +RLAPI const char *TextSubtext(const char *text, int position, int length); // Get a piece of a text string +RLAPI char *TextReplace(const char *text, const char *replace, const char *by); // Replace text string (WARNING: memory must be freed!) +RLAPI char *TextInsert(const char *text, const char *insert, int position); // Insert text in a position (WARNING: memory must be freed!) +RLAPI const char *TextJoin(const char **textList, int count, const char *delimiter); // Join text strings with delimiter +RLAPI const char **TextSplit(const char *text, char delimiter, int *count); // Split text into multiple strings +RLAPI void TextAppend(char *text, const char *append, int *position); // Append text at specific position and move cursor! +RLAPI int TextFindIndex(const char *text, const char *find); // Find first text occurrence within a string +RLAPI const char *TextToUpper(const char *text); // Get upper case version of provided string +RLAPI const char *TextToLower(const char *text); // Get lower case version of provided string +RLAPI const char *TextToPascal(const char *text); // Get Pascal case notation version of provided string +RLAPI const char *TextToSnake(const char *text); // Get Snake case notation version of provided string +RLAPI const char *TextToCamel(const char *text); // Get Camel case notation version of provided string + +RLAPI int TextToInteger(const char *text); // Get integer value from text (negative values not supported) +RLAPI float TextToFloat(const char *text); // Get float value from text (negative values not supported) + +//------------------------------------------------------------------------------------ +// Basic 3d Shapes Drawing Functions (Module: models) +//------------------------------------------------------------------------------------ + +// Basic geometric 3D shapes drawing functions +RLAPI void DrawLine3D(Vector3 startPos, Vector3 endPos, Color color); // Draw a line in 3D world space +RLAPI void DrawPoint3D(Vector3 position, Color color); // Draw a point in 3D space, actually a small line +RLAPI void DrawCircle3D(Vector3 center, float radius, Vector3 rotationAxis, float rotationAngle, Color color); // Draw a circle in 3D world space +RLAPI void DrawTriangle3D(Vector3 v1, Vector3 v2, Vector3 v3, Color color); // Draw a color-filled triangle (vertex in counter-clockwise order!) +RLAPI void DrawTriangleStrip3D(const Vector3 *points, int pointCount, Color color); // Draw a triangle strip defined by points +RLAPI void DrawCube(Vector3 position, float width, float height, float length, Color color); // Draw cube +RLAPI void DrawCubeV(Vector3 position, Vector3 size, Color color); // Draw cube (Vector version) +RLAPI void DrawCubeWires(Vector3 position, float width, float height, float length, Color color); // Draw cube wires +RLAPI void DrawCubeWiresV(Vector3 position, Vector3 size, Color color); // Draw cube wires (Vector version) +RLAPI void DrawSphere(Vector3 centerPos, float radius, Color color); // Draw sphere +RLAPI void DrawSphereEx(Vector3 centerPos, float radius, int rings, int slices, Color color); // Draw sphere with extended parameters +RLAPI void DrawSphereWires(Vector3 centerPos, float radius, int rings, int slices, Color color); // Draw sphere wires +RLAPI void DrawCylinder(Vector3 position, float radiusTop, float radiusBottom, float height, int slices, Color color); // Draw a cylinder/cone +RLAPI void DrawCylinderEx(Vector3 startPos, Vector3 endPos, float startRadius, float endRadius, int sides, Color color); // Draw a cylinder with base at startPos and top at endPos +RLAPI void DrawCylinderWires(Vector3 position, float radiusTop, float radiusBottom, float height, int slices, Color color); // Draw a cylinder/cone wires +RLAPI void DrawCylinderWiresEx(Vector3 startPos, Vector3 endPos, float startRadius, float endRadius, int sides, Color color); // Draw a cylinder wires with base at startPos and top at endPos +RLAPI void DrawCapsule(Vector3 startPos, Vector3 endPos, float radius, int slices, int rings, Color color); // Draw a capsule with the center of its sphere caps at startPos and endPos +RLAPI void DrawCapsuleWires(Vector3 startPos, Vector3 endPos, float radius, int slices, int rings, Color color); // Draw capsule wireframe with the center of its sphere caps at startPos and endPos +RLAPI void DrawPlane(Vector3 centerPos, Vector2 size, Color color); // Draw a plane XZ +RLAPI void DrawRay(Ray ray, Color color); // Draw a ray line +RLAPI void DrawGrid(int slices, float spacing); // Draw a grid (centered at (0, 0, 0)) + +//------------------------------------------------------------------------------------ +// Model 3d Loading and Drawing Functions (Module: models) +//------------------------------------------------------------------------------------ + +// Model management functions +RLAPI Model LoadModel(const char *fileName); // Load model from files (meshes and materials) +RLAPI Model LoadModelFromMesh(Mesh mesh); // Load model from generated mesh (default material) +RLAPI bool IsModelValid(Model model); // Check if a model is valid (loaded in GPU, VAO/VBOs) +RLAPI void UnloadModel(Model model); // Unload model (including meshes) from memory (RAM and/or VRAM) +RLAPI BoundingBox GetModelBoundingBox(Model model); // Compute model bounding box limits (considers all meshes) + +// Model drawing functions +RLAPI void DrawModel(Model model, Vector3 position, float scale, Color tint); // Draw a model (with texture if set) +RLAPI void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model with extended parameters +RLAPI void DrawModelWires(Model model, Vector3 position, float scale, Color tint); // Draw a model wires (with texture if set) +RLAPI void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model wires (with texture if set) with extended parameters +RLAPI void DrawModelPoints(Model model, Vector3 position, float scale, Color tint); // Draw a model as points +RLAPI void DrawModelPointsEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model as points with extended parameters +RLAPI void DrawBoundingBox(BoundingBox box, Color color); // Draw bounding box (wires) +RLAPI void DrawBillboard(Camera camera, Texture2D texture, Vector3 position, float scale, Color tint); // Draw a billboard texture +RLAPI void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector2 size, Color tint); // Draw a billboard texture defined by source +RLAPI void DrawBillboardPro(Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector3 up, Vector2 size, Vector2 origin, float rotation, Color tint); // Draw a billboard texture defined by source and rotation + +// Mesh management functions +RLAPI void UploadMesh(Mesh *mesh, bool dynamic); // Upload mesh vertex data in GPU and provide VAO/VBO ids +RLAPI void UpdateMeshBuffer(Mesh mesh, int index, const void *data, int dataSize, int offset); // Update mesh vertex data in GPU for a specific buffer index +RLAPI void UnloadMesh(Mesh mesh); // Unload mesh data from CPU and GPU +RLAPI void DrawMesh(Mesh mesh, Material material, Matrix transform); // Draw a 3d mesh with material and transform +RLAPI void DrawMeshInstanced(Mesh mesh, Material material, const Matrix *transforms, int instances); // Draw multiple mesh instances with material and different transforms +RLAPI BoundingBox GetMeshBoundingBox(Mesh mesh); // Compute mesh bounding box limits +RLAPI void GenMeshTangents(Mesh *mesh); // Compute mesh tangents +RLAPI bool ExportMesh(Mesh mesh, const char *fileName); // Export mesh data to file, returns true on success +RLAPI bool ExportMeshAsCode(Mesh mesh, const char *fileName); // Export mesh as code file (.h) defining multiple arrays of vertex attributes + +// Mesh generation functions +RLAPI Mesh GenMeshPoly(int sides, float radius); // Generate polygonal mesh +RLAPI Mesh GenMeshPlane(float width, float length, int resX, int resZ); // Generate plane mesh (with subdivisions) +RLAPI Mesh GenMeshCube(float width, float height, float length); // Generate cuboid mesh +RLAPI Mesh GenMeshSphere(float radius, int rings, int slices); // Generate sphere mesh (standard sphere) +RLAPI Mesh GenMeshHemiSphere(float radius, int rings, int slices); // Generate half-sphere mesh (no bottom cap) +RLAPI Mesh GenMeshCylinder(float radius, float height, int slices); // Generate cylinder mesh +RLAPI Mesh GenMeshCone(float radius, float height, int slices); // Generate cone/pyramid mesh +RLAPI Mesh GenMeshTorus(float radius, float size, int radSeg, int sides); // Generate torus mesh +RLAPI Mesh GenMeshKnot(float radius, float size, int radSeg, int sides); // Generate trefoil knot mesh +RLAPI Mesh GenMeshHeightmap(Image heightmap, Vector3 size); // Generate heightmap mesh from image data +RLAPI Mesh GenMeshCubicmap(Image cubicmap, Vector3 cubeSize); // Generate cubes-based map mesh from image data + +// Material loading/unloading functions +RLAPI Material *LoadMaterials(const char *fileName, int *materialCount); // Load materials from model file +RLAPI Material LoadMaterialDefault(void); // Load default material (Supports: DIFFUSE, SPECULAR, NORMAL maps) +RLAPI bool IsMaterialValid(Material material); // Check if a material is valid (shader assigned, map textures loaded in GPU) +RLAPI void UnloadMaterial(Material material); // Unload material from GPU memory (VRAM) +RLAPI void SetMaterialTexture(Material *material, int mapType, Texture2D texture); // Set texture for a material map type (MATERIAL_MAP_DIFFUSE, MATERIAL_MAP_SPECULAR...) +RLAPI void SetModelMeshMaterial(Model *model, int meshId, int materialId); // Set material for a mesh + +// Model animations loading/unloading functions +RLAPI ModelAnimation *LoadModelAnimations(const char *fileName, int *animCount); // Load model animations from file +RLAPI void UpdateModelAnimation(Model model, ModelAnimation anim, int frame); // Update model animation pose (CPU) +RLAPI void UpdateModelAnimationBones(Model model, ModelAnimation anim, int frame); // Update model animation mesh bone matrices (GPU skinning) +RLAPI void UnloadModelAnimation(ModelAnimation anim); // Unload animation data +RLAPI void UnloadModelAnimations(ModelAnimation *animations, int animCount); // Unload animation array data +RLAPI bool IsModelAnimationValid(Model model, ModelAnimation anim); // Check model animation skeleton match + +// Collision detection functions +RLAPI bool CheckCollisionSpheres(Vector3 center1, float radius1, Vector3 center2, float radius2); // Check collision between two spheres +RLAPI bool CheckCollisionBoxes(BoundingBox box1, BoundingBox box2); // Check collision between two bounding boxes +RLAPI bool CheckCollisionBoxSphere(BoundingBox box, Vector3 center, float radius); // Check collision between box and sphere +RLAPI RayCollision GetRayCollisionSphere(Ray ray, Vector3 center, float radius); // Get collision info between ray and sphere +RLAPI RayCollision GetRayCollisionBox(Ray ray, BoundingBox box); // Get collision info between ray and box +RLAPI RayCollision GetRayCollisionMesh(Ray ray, Mesh mesh, Matrix transform); // Get collision info between ray and mesh +RLAPI RayCollision GetRayCollisionTriangle(Ray ray, Vector3 p1, Vector3 p2, Vector3 p3); // Get collision info between ray and triangle +RLAPI RayCollision GetRayCollisionQuad(Ray ray, Vector3 p1, Vector3 p2, Vector3 p3, Vector3 p4); // Get collision info between ray and quad + +//------------------------------------------------------------------------------------ +// Audio Loading and Playing Functions (Module: audio) +//------------------------------------------------------------------------------------ +typedef void (*AudioCallback)(void *bufferData, unsigned int frames); + +// Audio device management functions +RLAPI void InitAudioDevice(void); // Initialize audio device and context +RLAPI void CloseAudioDevice(void); // Close the audio device and context +RLAPI bool IsAudioDeviceReady(void); // Check if audio device has been initialized successfully +RLAPI void SetMasterVolume(float volume); // Set master volume (listener) +RLAPI float GetMasterVolume(void); // Get master volume (listener) + +// Wave/Sound loading/unloading functions +RLAPI Wave LoadWave(const char *fileName); // Load wave data from file +RLAPI Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileData, int dataSize); // Load wave from memory buffer, fileType refers to extension: i.e. '.wav' +RLAPI bool IsWaveValid(Wave wave); // Checks if wave data is valid (data loaded and parameters) +RLAPI Sound LoadSound(const char *fileName); // Load sound from file +RLAPI Sound LoadSoundFromWave(Wave wave); // Load sound from wave data +RLAPI Sound LoadSoundAlias(Sound source); // Create a new sound that shares the same sample data as the source sound, does not own the sound data +RLAPI bool IsSoundValid(Sound sound); // Checks if a sound is valid (data loaded and buffers initialized) +RLAPI void UpdateSound(Sound sound, const void *data, int sampleCount); // Update sound buffer with new data +RLAPI void UnloadWave(Wave wave); // Unload wave data +RLAPI void UnloadSound(Sound sound); // Unload sound +RLAPI void UnloadSoundAlias(Sound alias); // Unload a sound alias (does not deallocate sample data) +RLAPI bool ExportWave(Wave wave, const char *fileName); // Export wave data to file, returns true on success +RLAPI bool ExportWaveAsCode(Wave wave, const char *fileName); // Export wave sample data to code (.h), returns true on success + +// Wave/Sound management functions +RLAPI void PlaySound(Sound sound); // Play a sound +RLAPI void StopSound(Sound sound); // Stop playing a sound +RLAPI void PauseSound(Sound sound); // Pause a sound +RLAPI void ResumeSound(Sound sound); // Resume a paused sound +RLAPI bool IsSoundPlaying(Sound sound); // Check if a sound is currently playing +RLAPI void SetSoundVolume(Sound sound, float volume); // Set volume for a sound (1.0 is max level) +RLAPI void SetSoundPitch(Sound sound, float pitch); // Set pitch for a sound (1.0 is base level) +RLAPI void SetSoundPan(Sound sound, float pan); // Set pan for a sound (0.5 is center) +RLAPI Wave WaveCopy(Wave wave); // Copy a wave to a new wave +RLAPI void WaveCrop(Wave *wave, int initFrame, int finalFrame); // Crop a wave to defined frames range +RLAPI void WaveFormat(Wave *wave, int sampleRate, int sampleSize, int channels); // Convert wave data to desired format +RLAPI float *LoadWaveSamples(Wave wave); // Load samples data from wave as a 32bit float data array +RLAPI void UnloadWaveSamples(float *samples); // Unload samples data loaded with LoadWaveSamples() + +// Music management functions +RLAPI Music LoadMusicStream(const char *fileName); // Load music stream from file +RLAPI Music LoadMusicStreamFromMemory(const char *fileType, const unsigned char *data, int dataSize); // Load music stream from data +RLAPI bool IsMusicValid(Music music); // Checks if a music stream is valid (context and buffers initialized) +RLAPI void UnloadMusicStream(Music music); // Unload music stream +RLAPI void PlayMusicStream(Music music); // Start music playing +RLAPI bool IsMusicStreamPlaying(Music music); // Check if music is playing +RLAPI void UpdateMusicStream(Music music); // Updates buffers for music streaming +RLAPI void StopMusicStream(Music music); // Stop music playing +RLAPI void PauseMusicStream(Music music); // Pause music playing +RLAPI void ResumeMusicStream(Music music); // Resume playing paused music +RLAPI void SeekMusicStream(Music music, float position); // Seek music to a position (in seconds) +RLAPI void SetMusicVolume(Music music, float volume); // Set volume for music (1.0 is max level) +RLAPI void SetMusicPitch(Music music, float pitch); // Set pitch for a music (1.0 is base level) +RLAPI void SetMusicPan(Music music, float pan); // Set pan for a music (0.5 is center) +RLAPI float GetMusicTimeLength(Music music); // Get music time length (in seconds) +RLAPI float GetMusicTimePlayed(Music music); // Get current music time played (in seconds) + +// AudioStream management functions +RLAPI AudioStream LoadAudioStream(unsigned int sampleRate, unsigned int sampleSize, unsigned int channels); // Load audio stream (to stream raw audio pcm data) +RLAPI bool IsAudioStreamValid(AudioStream stream); // Checks if an audio stream is valid (buffers initialized) +RLAPI void UnloadAudioStream(AudioStream stream); // Unload audio stream and free memory +RLAPI void UpdateAudioStream(AudioStream stream, const void *data, int frameCount); // Update audio stream buffers with data +RLAPI bool IsAudioStreamProcessed(AudioStream stream); // Check if any audio stream buffers requires refill +RLAPI void PlayAudioStream(AudioStream stream); // Play audio stream +RLAPI void PauseAudioStream(AudioStream stream); // Pause audio stream +RLAPI void ResumeAudioStream(AudioStream stream); // Resume audio stream +RLAPI bool IsAudioStreamPlaying(AudioStream stream); // Check if audio stream is playing +RLAPI void StopAudioStream(AudioStream stream); // Stop audio stream +RLAPI void SetAudioStreamVolume(AudioStream stream, float volume); // Set volume for audio stream (1.0 is max level) +RLAPI void SetAudioStreamPitch(AudioStream stream, float pitch); // Set pitch for audio stream (1.0 is base level) +RLAPI void SetAudioStreamPan(AudioStream stream, float pan); // Set pan for audio stream (0.5 is centered) +RLAPI void SetAudioStreamBufferSizeDefault(int size); // Default size for new audio streams +RLAPI void SetAudioStreamCallback(AudioStream stream, AudioCallback callback); // Audio thread callback to request new data + +RLAPI void AttachAudioStreamProcessor(AudioStream stream, AudioCallback processor); // Attach audio stream processor to stream, receives the samples as 'float' +RLAPI void DetachAudioStreamProcessor(AudioStream stream, AudioCallback processor); // Detach audio stream processor from stream + +RLAPI void AttachAudioMixedProcessor(AudioCallback processor); // Attach audio stream processor to the entire audio pipeline, receives the samples as 'float' +RLAPI void DetachAudioMixedProcessor(AudioCallback processor); // Detach audio stream processor from the entire audio pipeline + +#if defined(__cplusplus) +} +#endif + +#endif // RAYLIB_H diff --git a/Start_Windows/raylib/raymath.h b/Start_Windows/raylib/raymath.h new file mode 100644 index 0000000..e522113 --- /dev/null +++ b/Start_Windows/raylib/raymath.h @@ -0,0 +1,2941 @@ +/********************************************************************************************** +* +* raymath v2.0 - Math functions to work with Vector2, Vector3, Matrix and Quaternions +* +* CONVENTIONS: +* - Matrix structure is defined as row-major (memory layout) but parameters naming AND all +* math operations performed by the library consider the structure as it was column-major +* It is like transposed versions of the matrices are used for all the maths +* It benefits some functions making them cache-friendly and also avoids matrix +* transpositions sometimes required by OpenGL +* Example: In memory order, row0 is [m0 m4 m8 m12] but in semantic math row0 is [m0 m1 m2 m3] +* - Functions are always self-contained, no function use another raymath function inside, +* required code is directly re-implemented inside +* - Functions input parameters are always received by value (2 unavoidable exceptions) +* - Functions use always a "result" variable for return (except C++ operators) +* - Functions are always defined inline +* - Angles are always in radians (DEG2RAD/RAD2DEG macros provided for convenience) +* - No compound literals used to make sure libray is compatible with C++ +* +* CONFIGURATION: +* #define RAYMATH_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 RAYMATH_STATIC_INLINE +* Define static inline functions code, so #include header suffices for use. +* This may use up lots of memory. +* +* #define RAYMATH_DISABLE_CPP_OPERATORS +* Disables C++ operator overloads for raymath types. +* +* LICENSE: zlib/libpng +* +* Copyright (c) 2015-2024 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 RAYMATH_H +#define RAYMATH_H + +#if defined(RAYMATH_IMPLEMENTATION) && defined(RAYMATH_STATIC_INLINE) + #error "Specifying both RAYMATH_IMPLEMENTATION and RAYMATH_STATIC_INLINE is contradictory" +#endif + +// Function specifiers definition +#if defined(RAYMATH_IMPLEMENTATION) + #if defined(_WIN32) && defined(BUILD_LIBTYPE_SHARED) + #define RMAPI __declspec(dllexport) extern inline // We are building raylib as a Win32 shared library (.dll) + #elif defined(BUILD_LIBTYPE_SHARED) + #define RMAPI __attribute__((visibility("default"))) // We are building raylib as a Unix shared library (.so/.dylib) + #elif defined(_WIN32) && defined(USE_LIBTYPE_SHARED) + #define RMAPI __declspec(dllimport) // We are using raylib as a Win32 shared library (.dll) + #else + #define RMAPI extern inline // Provide external definition + #endif +#elif defined(RAYMATH_STATIC_INLINE) + #define RMAPI static inline // Functions may be inlined, no external out-of-line definition +#else + #if defined(__TINYC__) + #define RMAPI static inline // plain inline not supported by tinycc (See issue #435) + #else + #define RMAPI inline // Functions may be inlined or external definition used + #endif +#endif + + +//---------------------------------------------------------------------------------- +// Defines and Macros +//---------------------------------------------------------------------------------- +#ifndef PI + #define PI 3.14159265358979323846f +#endif + +#ifndef EPSILON + #define EPSILON 0.000001f +#endif + +#ifndef DEG2RAD + #define DEG2RAD (PI/180.0f) +#endif + +#ifndef RAD2DEG + #define RAD2DEG (180.0f/PI) +#endif + +// Get float vector for Matrix +#ifndef MatrixToFloat + #define MatrixToFloat(mat) (MatrixToFloatV(mat).v) +#endif + +// Get float vector for Vector3 +#ifndef Vector3ToFloat + #define Vector3ToFloat(vec) (Vector3ToFloatV(vec).v) +#endif + +//---------------------------------------------------------------------------------- +// Types and Structures Definition +//---------------------------------------------------------------------------------- +#if !defined(RL_VECTOR2_TYPE) +// Vector2 type +typedef struct Vector2 { + float x; + float y; +} Vector2; +#define RL_VECTOR2_TYPE +#endif + +#if !defined(RL_VECTOR3_TYPE) +// Vector3 type +typedef struct Vector3 { + float x; + float y; + float z; +} Vector3; +#define RL_VECTOR3_TYPE +#endif + +#if !defined(RL_VECTOR4_TYPE) +// Vector4 type +typedef struct Vector4 { + float x; + float y; + float z; + float w; +} Vector4; +#define RL_VECTOR4_TYPE +#endif + +#if !defined(RL_QUATERNION_TYPE) +// Quaternion type +typedef Vector4 Quaternion; +#define RL_QUATERNION_TYPE +#endif + +#if !defined(RL_MATRIX_TYPE) +// Matrix type (OpenGL style 4x4 - right handed, column major) +typedef struct Matrix { + float m0, m4, m8, m12; // Matrix first row (4 components) + float m1, m5, m9, m13; // Matrix second row (4 components) + float m2, m6, m10, m14; // Matrix third row (4 components) + float m3, m7, m11, m15; // Matrix fourth row (4 components) +} Matrix; +#define RL_MATRIX_TYPE +#endif + +// NOTE: Helper types to be used instead of array return types for *ToFloat functions +typedef struct float3 { + float v[3]; +} float3; + +typedef struct float16 { + float v[16]; +} float16; + +#include // Required for: sinf(), cosf(), tan(), atan2f(), sqrtf(), floor(), fminf(), fmaxf(), fabsf() + +//---------------------------------------------------------------------------------- +// Module Functions Definition - Utils math +//---------------------------------------------------------------------------------- + +// Clamp float value +RMAPI float Clamp(float value, float min, float max) +{ + float result = (value < min)? min : value; + + if (result > max) result = max; + + return result; +} + +// Calculate linear interpolation between two floats +RMAPI float Lerp(float start, float end, float amount) +{ + float result = start + amount*(end - start); + + return result; +} + +// Normalize input value within input range +RMAPI float Normalize(float value, float start, float end) +{ + float result = (value - start)/(end - start); + + return result; +} + +// Remap input value within input range to output range +RMAPI float Remap(float value, float inputStart, float inputEnd, float outputStart, float outputEnd) +{ + float result = (value - inputStart)/(inputEnd - inputStart)*(outputEnd - outputStart) + outputStart; + + return result; +} + +// Wrap input value from min to max +RMAPI float Wrap(float value, float min, float max) +{ + float result = value - (max - min)*floorf((value - min)/(max - min)); + + return result; +} + +// Check whether two given floats are almost equal +RMAPI int FloatEquals(float x, float y) +{ +#if !defined(EPSILON) + #define EPSILON 0.000001f +#endif + + int result = (fabsf(x - y)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(x), fabsf(y)))); + + return result; +} + +//---------------------------------------------------------------------------------- +// Module Functions Definition - Vector2 math +//---------------------------------------------------------------------------------- + +// Vector with components value 0.0f +RMAPI Vector2 Vector2Zero(void) +{ + Vector2 result = { 0.0f, 0.0f }; + + return result; +} + +// Vector with components value 1.0f +RMAPI Vector2 Vector2One(void) +{ + Vector2 result = { 1.0f, 1.0f }; + + return result; +} + +// Add two vectors (v1 + v2) +RMAPI Vector2 Vector2Add(Vector2 v1, Vector2 v2) +{ + Vector2 result = { v1.x + v2.x, v1.y + v2.y }; + + return result; +} + +// Add vector and float value +RMAPI Vector2 Vector2AddValue(Vector2 v, float add) +{ + Vector2 result = { v.x + add, v.y + add }; + + return result; +} + +// Subtract two vectors (v1 - v2) +RMAPI Vector2 Vector2Subtract(Vector2 v1, Vector2 v2) +{ + Vector2 result = { v1.x - v2.x, v1.y - v2.y }; + + return result; +} + +// Subtract vector by float value +RMAPI Vector2 Vector2SubtractValue(Vector2 v, float sub) +{ + Vector2 result = { v.x - sub, v.y - sub }; + + return result; +} + +// Calculate vector length +RMAPI float Vector2Length(Vector2 v) +{ + float result = sqrtf((v.x*v.x) + (v.y*v.y)); + + return result; +} + +// Calculate vector square length +RMAPI float Vector2LengthSqr(Vector2 v) +{ + float result = (v.x*v.x) + (v.y*v.y); + + return result; +} + +// Calculate two vectors dot product +RMAPI float Vector2DotProduct(Vector2 v1, Vector2 v2) +{ + float result = (v1.x*v2.x + v1.y*v2.y); + + return result; +} + +// Calculate distance between two vectors +RMAPI float Vector2Distance(Vector2 v1, Vector2 v2) +{ + float result = sqrtf((v1.x - v2.x)*(v1.x - v2.x) + (v1.y - v2.y)*(v1.y - v2.y)); + + return result; +} + +// Calculate square distance between two vectors +RMAPI float Vector2DistanceSqr(Vector2 v1, Vector2 v2) +{ + float result = ((v1.x - v2.x)*(v1.x - v2.x) + (v1.y - v2.y)*(v1.y - v2.y)); + + return result; +} + +// Calculate angle between two vectors +// NOTE: Angle is calculated from origin point (0, 0) +RMAPI float Vector2Angle(Vector2 v1, Vector2 v2) +{ + float result = 0.0f; + + float dot = v1.x*v2.x + v1.y*v2.y; + float det = v1.x*v2.y - v1.y*v2.x; + + result = atan2f(det, dot); + + return result; +} + +// Calculate angle defined by a two vectors line +// NOTE: Parameters need to be normalized +// Current implementation should be aligned with glm::angle +RMAPI float Vector2LineAngle(Vector2 start, Vector2 end) +{ + float result = 0.0f; + + // TODO(10/9/2023): Currently angles move clockwise, determine if this is wanted behavior + result = -atan2f(end.y - start.y, end.x - start.x); + + return result; +} + +// Scale vector (multiply by value) +RMAPI Vector2 Vector2Scale(Vector2 v, float scale) +{ + Vector2 result = { v.x*scale, v.y*scale }; + + return result; +} + +// Multiply vector by vector +RMAPI Vector2 Vector2Multiply(Vector2 v1, Vector2 v2) +{ + Vector2 result = { v1.x*v2.x, v1.y*v2.y }; + + return result; +} + +// Negate vector +RMAPI Vector2 Vector2Negate(Vector2 v) +{ + Vector2 result = { -v.x, -v.y }; + + return result; +} + +// Divide vector by vector +RMAPI Vector2 Vector2Divide(Vector2 v1, Vector2 v2) +{ + Vector2 result = { v1.x/v2.x, v1.y/v2.y }; + + return result; +} + +// Normalize provided vector +RMAPI Vector2 Vector2Normalize(Vector2 v) +{ + Vector2 result = { 0 }; + float length = sqrtf((v.x*v.x) + (v.y*v.y)); + + if (length > 0) + { + float ilength = 1.0f/length; + result.x = v.x*ilength; + result.y = v.y*ilength; + } + + return result; +} + +// Transforms a Vector2 by a given Matrix +RMAPI Vector2 Vector2Transform(Vector2 v, Matrix mat) +{ + Vector2 result = { 0 }; + + float x = v.x; + float y = v.y; + float z = 0; + + result.x = mat.m0*x + mat.m4*y + mat.m8*z + mat.m12; + result.y = mat.m1*x + mat.m5*y + mat.m9*z + mat.m13; + + return result; +} + +// Calculate linear interpolation between two vectors +RMAPI Vector2 Vector2Lerp(Vector2 v1, Vector2 v2, float amount) +{ + Vector2 result = { 0 }; + + result.x = v1.x + amount*(v2.x - v1.x); + result.y = v1.y + amount*(v2.y - v1.y); + + return result; +} + +// Calculate reflected vector to normal +RMAPI Vector2 Vector2Reflect(Vector2 v, Vector2 normal) +{ + Vector2 result = { 0 }; + + float dotProduct = (v.x*normal.x + v.y*normal.y); // Dot product + + result.x = v.x - (2.0f*normal.x)*dotProduct; + result.y = v.y - (2.0f*normal.y)*dotProduct; + + return result; +} + +// Get min value for each pair of components +RMAPI Vector2 Vector2Min(Vector2 v1, Vector2 v2) +{ + Vector2 result = { 0 }; + + result.x = fminf(v1.x, v2.x); + result.y = fminf(v1.y, v2.y); + + return result; +} + +// Get max value for each pair of components +RMAPI Vector2 Vector2Max(Vector2 v1, Vector2 v2) +{ + Vector2 result = { 0 }; + + result.x = fmaxf(v1.x, v2.x); + result.y = fmaxf(v1.y, v2.y); + + return result; +} + +// Rotate vector by angle +RMAPI Vector2 Vector2Rotate(Vector2 v, float angle) +{ + Vector2 result = { 0 }; + + float cosres = cosf(angle); + float sinres = sinf(angle); + + result.x = v.x*cosres - v.y*sinres; + result.y = v.x*sinres + v.y*cosres; + + return result; +} + +// Move Vector towards target +RMAPI Vector2 Vector2MoveTowards(Vector2 v, Vector2 target, float maxDistance) +{ + Vector2 result = { 0 }; + + float dx = target.x - v.x; + float dy = target.y - v.y; + float value = (dx*dx) + (dy*dy); + + if ((value == 0) || ((maxDistance >= 0) && (value <= maxDistance*maxDistance))) return target; + + float dist = sqrtf(value); + + result.x = v.x + dx/dist*maxDistance; + result.y = v.y + dy/dist*maxDistance; + + return result; +} + +// Invert the given vector +RMAPI Vector2 Vector2Invert(Vector2 v) +{ + Vector2 result = { 1.0f/v.x, 1.0f/v.y }; + + return result; +} + +// Clamp the components of the vector between +// min and max values specified by the given vectors +RMAPI Vector2 Vector2Clamp(Vector2 v, Vector2 min, Vector2 max) +{ + Vector2 result = { 0 }; + + result.x = fminf(max.x, fmaxf(min.x, v.x)); + result.y = fminf(max.y, fmaxf(min.y, v.y)); + + return result; +} + +// Clamp the magnitude of the vector between two min and max values +RMAPI Vector2 Vector2ClampValue(Vector2 v, float min, float max) +{ + Vector2 result = v; + + float length = (v.x*v.x) + (v.y*v.y); + if (length > 0.0f) + { + length = sqrtf(length); + + float scale = 1; // By default, 1 as the neutral element. + if (length < min) + { + scale = min/length; + } + else if (length > max) + { + scale = max/length; + } + + result.x = v.x*scale; + result.y = v.y*scale; + } + + return result; +} + +// Check whether two given vectors are almost equal +RMAPI int Vector2Equals(Vector2 p, Vector2 q) +{ +#if !defined(EPSILON) + #define EPSILON 0.000001f +#endif + + int result = ((fabsf(p.x - q.x)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.x), fabsf(q.x))))) && + ((fabsf(p.y - q.y)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.y), fabsf(q.y))))); + + return result; +} + +// Compute the direction of a refracted ray +// v: normalized direction of the incoming ray +// n: normalized normal vector of the interface of two optical media +// r: ratio of the refractive index of the medium from where the ray comes +// to the refractive index of the medium on the other side of the surface +RMAPI Vector2 Vector2Refract(Vector2 v, Vector2 n, float r) +{ + Vector2 result = { 0 }; + + float dot = v.x*n.x + v.y*n.y; + float d = 1.0f - r*r*(1.0f - dot*dot); + + if (d >= 0.0f) + { + d = sqrtf(d); + v.x = r*v.x - (r*dot + d)*n.x; + v.y = r*v.y - (r*dot + d)*n.y; + + result = v; + } + + return result; +} + + +//---------------------------------------------------------------------------------- +// Module Functions Definition - Vector3 math +//---------------------------------------------------------------------------------- + +// Vector with components value 0.0f +RMAPI Vector3 Vector3Zero(void) +{ + Vector3 result = { 0.0f, 0.0f, 0.0f }; + + return result; +} + +// Vector with components value 1.0f +RMAPI Vector3 Vector3One(void) +{ + Vector3 result = { 1.0f, 1.0f, 1.0f }; + + return result; +} + +// Add two vectors +RMAPI Vector3 Vector3Add(Vector3 v1, Vector3 v2) +{ + Vector3 result = { v1.x + v2.x, v1.y + v2.y, v1.z + v2.z }; + + return result; +} + +// Add vector and float value +RMAPI Vector3 Vector3AddValue(Vector3 v, float add) +{ + Vector3 result = { v.x + add, v.y + add, v.z + add }; + + return result; +} + +// Subtract two vectors +RMAPI Vector3 Vector3Subtract(Vector3 v1, Vector3 v2) +{ + Vector3 result = { v1.x - v2.x, v1.y - v2.y, v1.z - v2.z }; + + return result; +} + +// Subtract vector by float value +RMAPI Vector3 Vector3SubtractValue(Vector3 v, float sub) +{ + Vector3 result = { v.x - sub, v.y - sub, v.z - sub }; + + return result; +} + +// Multiply vector by scalar +RMAPI Vector3 Vector3Scale(Vector3 v, float scalar) +{ + Vector3 result = { v.x*scalar, v.y*scalar, v.z*scalar }; + + return result; +} + +// Multiply vector by vector +RMAPI Vector3 Vector3Multiply(Vector3 v1, Vector3 v2) +{ + Vector3 result = { v1.x*v2.x, v1.y*v2.y, v1.z*v2.z }; + + return result; +} + +// Calculate two vectors cross product +RMAPI Vector3 Vector3CrossProduct(Vector3 v1, Vector3 v2) +{ + Vector3 result = { v1.y*v2.z - v1.z*v2.y, v1.z*v2.x - v1.x*v2.z, v1.x*v2.y - v1.y*v2.x }; + + return result; +} + +// Calculate one vector perpendicular vector +RMAPI Vector3 Vector3Perpendicular(Vector3 v) +{ + Vector3 result = { 0 }; + + float min = fabsf(v.x); + Vector3 cardinalAxis = {1.0f, 0.0f, 0.0f}; + + if (fabsf(v.y) < min) + { + min = fabsf(v.y); + Vector3 tmp = {0.0f, 1.0f, 0.0f}; + cardinalAxis = tmp; + } + + if (fabsf(v.z) < min) + { + Vector3 tmp = {0.0f, 0.0f, 1.0f}; + cardinalAxis = tmp; + } + + // Cross product between vectors + result.x = v.y*cardinalAxis.z - v.z*cardinalAxis.y; + result.y = v.z*cardinalAxis.x - v.x*cardinalAxis.z; + result.z = v.x*cardinalAxis.y - v.y*cardinalAxis.x; + + return result; +} + +// Calculate vector length +RMAPI float Vector3Length(const Vector3 v) +{ + float result = sqrtf(v.x*v.x + v.y*v.y + v.z*v.z); + + return result; +} + +// Calculate vector square length +RMAPI float Vector3LengthSqr(const Vector3 v) +{ + float result = v.x*v.x + v.y*v.y + v.z*v.z; + + return result; +} + +// Calculate two vectors dot product +RMAPI float Vector3DotProduct(Vector3 v1, Vector3 v2) +{ + float result = (v1.x*v2.x + v1.y*v2.y + v1.z*v2.z); + + return result; +} + +// Calculate distance between two vectors +RMAPI float Vector3Distance(Vector3 v1, Vector3 v2) +{ + float result = 0.0f; + + float dx = v2.x - v1.x; + float dy = v2.y - v1.y; + float dz = v2.z - v1.z; + result = sqrtf(dx*dx + dy*dy + dz*dz); + + return result; +} + +// Calculate square distance between two vectors +RMAPI float Vector3DistanceSqr(Vector3 v1, Vector3 v2) +{ + float result = 0.0f; + + float dx = v2.x - v1.x; + float dy = v2.y - v1.y; + float dz = v2.z - v1.z; + result = dx*dx + dy*dy + dz*dz; + + return result; +} + +// Calculate angle between two vectors +RMAPI float Vector3Angle(Vector3 v1, Vector3 v2) +{ + float result = 0.0f; + + Vector3 cross = { v1.y*v2.z - v1.z*v2.y, v1.z*v2.x - v1.x*v2.z, v1.x*v2.y - v1.y*v2.x }; + float len = sqrtf(cross.x*cross.x + cross.y*cross.y + cross.z*cross.z); + float dot = (v1.x*v2.x + v1.y*v2.y + v1.z*v2.z); + result = atan2f(len, dot); + + return result; +} + +// Negate provided vector (invert direction) +RMAPI Vector3 Vector3Negate(Vector3 v) +{ + Vector3 result = { -v.x, -v.y, -v.z }; + + return result; +} + +// Divide vector by vector +RMAPI Vector3 Vector3Divide(Vector3 v1, Vector3 v2) +{ + Vector3 result = { v1.x/v2.x, v1.y/v2.y, v1.z/v2.z }; + + return result; +} + +// Normalize provided vector +RMAPI Vector3 Vector3Normalize(Vector3 v) +{ + Vector3 result = v; + + float length = sqrtf(v.x*v.x + v.y*v.y + v.z*v.z); + if (length != 0.0f) + { + float ilength = 1.0f/length; + + result.x *= ilength; + result.y *= ilength; + result.z *= ilength; + } + + return result; +} + +//Calculate the projection of the vector v1 on to v2 +RMAPI Vector3 Vector3Project(Vector3 v1, Vector3 v2) +{ + Vector3 result = { 0 }; + + float v1dv2 = (v1.x*v2.x + v1.y*v2.y + v1.z*v2.z); + float v2dv2 = (v2.x*v2.x + v2.y*v2.y + v2.z*v2.z); + + float mag = v1dv2/v2dv2; + + result.x = v2.x*mag; + result.y = v2.y*mag; + result.z = v2.z*mag; + + return result; +} + +//Calculate the rejection of the vector v1 on to v2 +RMAPI Vector3 Vector3Reject(Vector3 v1, Vector3 v2) +{ + Vector3 result = { 0 }; + + float v1dv2 = (v1.x*v2.x + v1.y*v2.y + v1.z*v2.z); + float v2dv2 = (v2.x*v2.x + v2.y*v2.y + v2.z*v2.z); + + float mag = v1dv2/v2dv2; + + result.x = v1.x - (v2.x*mag); + result.y = v1.y - (v2.y*mag); + result.z = v1.z - (v2.z*mag); + + return result; +} + +// Orthonormalize provided vectors +// Makes vectors normalized and orthogonal to each other +// Gram-Schmidt function implementation +RMAPI void Vector3OrthoNormalize(Vector3 *v1, Vector3 *v2) +{ + float length = 0.0f; + float ilength = 0.0f; + + // Vector3Normalize(*v1); + Vector3 v = *v1; + length = sqrtf(v.x*v.x + v.y*v.y + v.z*v.z); + if (length == 0.0f) length = 1.0f; + ilength = 1.0f/length; + v1->x *= ilength; + v1->y *= ilength; + v1->z *= ilength; + + // Vector3CrossProduct(*v1, *v2) + Vector3 vn1 = { v1->y*v2->z - v1->z*v2->y, v1->z*v2->x - v1->x*v2->z, v1->x*v2->y - v1->y*v2->x }; + + // Vector3Normalize(vn1); + v = vn1; + length = sqrtf(v.x*v.x + v.y*v.y + v.z*v.z); + if (length == 0.0f) length = 1.0f; + ilength = 1.0f/length; + vn1.x *= ilength; + vn1.y *= ilength; + vn1.z *= ilength; + + // Vector3CrossProduct(vn1, *v1) + Vector3 vn2 = { vn1.y*v1->z - vn1.z*v1->y, vn1.z*v1->x - vn1.x*v1->z, vn1.x*v1->y - vn1.y*v1->x }; + + *v2 = vn2; +} + +// Transforms a Vector3 by a given Matrix +RMAPI Vector3 Vector3Transform(Vector3 v, Matrix mat) +{ + Vector3 result = { 0 }; + + float x = v.x; + float y = v.y; + float z = v.z; + + result.x = mat.m0*x + mat.m4*y + mat.m8*z + mat.m12; + result.y = mat.m1*x + mat.m5*y + mat.m9*z + mat.m13; + result.z = mat.m2*x + mat.m6*y + mat.m10*z + mat.m14; + + return result; +} + +// Transform a vector by quaternion rotation +RMAPI Vector3 Vector3RotateByQuaternion(Vector3 v, Quaternion q) +{ + Vector3 result = { 0 }; + + result.x = v.x*(q.x*q.x + q.w*q.w - q.y*q.y - q.z*q.z) + v.y*(2*q.x*q.y - 2*q.w*q.z) + v.z*(2*q.x*q.z + 2*q.w*q.y); + result.y = v.x*(2*q.w*q.z + 2*q.x*q.y) + v.y*(q.w*q.w - q.x*q.x + q.y*q.y - q.z*q.z) + v.z*(-2*q.w*q.x + 2*q.y*q.z); + result.z = v.x*(-2*q.w*q.y + 2*q.x*q.z) + v.y*(2*q.w*q.x + 2*q.y*q.z)+ v.z*(q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z); + + return result; +} + +// Rotates a vector around an axis +RMAPI Vector3 Vector3RotateByAxisAngle(Vector3 v, Vector3 axis, float angle) +{ + // Using Euler-Rodrigues Formula + // Ref.: https://en.wikipedia.org/w/index.php?title=Euler%E2%80%93Rodrigues_formula + + Vector3 result = v; + + // Vector3Normalize(axis); + float length = sqrtf(axis.x*axis.x + axis.y*axis.y + axis.z*axis.z); + if (length == 0.0f) length = 1.0f; + float ilength = 1.0f/length; + axis.x *= ilength; + axis.y *= ilength; + axis.z *= ilength; + + angle /= 2.0f; + float a = sinf(angle); + float b = axis.x*a; + float c = axis.y*a; + float d = axis.z*a; + a = cosf(angle); + Vector3 w = { b, c, d }; + + // Vector3CrossProduct(w, v) + Vector3 wv = { w.y*v.z - w.z*v.y, w.z*v.x - w.x*v.z, w.x*v.y - w.y*v.x }; + + // Vector3CrossProduct(w, wv) + Vector3 wwv = { w.y*wv.z - w.z*wv.y, w.z*wv.x - w.x*wv.z, w.x*wv.y - w.y*wv.x }; + + // Vector3Scale(wv, 2*a) + a *= 2; + wv.x *= a; + wv.y *= a; + wv.z *= a; + + // Vector3Scale(wwv, 2) + wwv.x *= 2; + wwv.y *= 2; + wwv.z *= 2; + + result.x += wv.x; + result.y += wv.y; + result.z += wv.z; + + result.x += wwv.x; + result.y += wwv.y; + result.z += wwv.z; + + return result; +} + +// Move Vector towards target +RMAPI Vector3 Vector3MoveTowards(Vector3 v, Vector3 target, float maxDistance) +{ + Vector3 result = { 0 }; + + float dx = target.x - v.x; + float dy = target.y - v.y; + float dz = target.z - v.z; + float value = (dx*dx) + (dy*dy) + (dz*dz); + + if ((value == 0) || ((maxDistance >= 0) && (value <= maxDistance*maxDistance))) return target; + + float dist = sqrtf(value); + + result.x = v.x + dx/dist*maxDistance; + result.y = v.y + dy/dist*maxDistance; + result.z = v.z + dz/dist*maxDistance; + + return result; +} + +// Calculate linear interpolation between two vectors +RMAPI Vector3 Vector3Lerp(Vector3 v1, Vector3 v2, float amount) +{ + Vector3 result = { 0 }; + + result.x = v1.x + amount*(v2.x - v1.x); + result.y = v1.y + amount*(v2.y - v1.y); + result.z = v1.z + amount*(v2.z - v1.z); + + return result; +} + +// Calculate cubic hermite interpolation between two vectors and their tangents +// as described in the GLTF 2.0 specification: https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#interpolation-cubic +RMAPI Vector3 Vector3CubicHermite(Vector3 v1, Vector3 tangent1, Vector3 v2, Vector3 tangent2, float amount) +{ + Vector3 result = { 0 }; + + float amountPow2 = amount*amount; + float amountPow3 = amount*amount*amount; + + result.x = (2*amountPow3 - 3*amountPow2 + 1)*v1.x + (amountPow3 - 2*amountPow2 + amount)*tangent1.x + (-2*amountPow3 + 3*amountPow2)*v2.x + (amountPow3 - amountPow2)*tangent2.x; + result.y = (2*amountPow3 - 3*amountPow2 + 1)*v1.y + (amountPow3 - 2*amountPow2 + amount)*tangent1.y + (-2*amountPow3 + 3*amountPow2)*v2.y + (amountPow3 - amountPow2)*tangent2.y; + result.z = (2*amountPow3 - 3*amountPow2 + 1)*v1.z + (amountPow3 - 2*amountPow2 + amount)*tangent1.z + (-2*amountPow3 + 3*amountPow2)*v2.z + (amountPow3 - amountPow2)*tangent2.z; + + return result; +} + +// Calculate reflected vector to normal +RMAPI Vector3 Vector3Reflect(Vector3 v, Vector3 normal) +{ + Vector3 result = { 0 }; + + // I is the original vector + // N is the normal of the incident plane + // R = I - (2*N*(DotProduct[I, N])) + + float dotProduct = (v.x*normal.x + v.y*normal.y + v.z*normal.z); + + result.x = v.x - (2.0f*normal.x)*dotProduct; + result.y = v.y - (2.0f*normal.y)*dotProduct; + result.z = v.z - (2.0f*normal.z)*dotProduct; + + return result; +} + +// Get min value for each pair of components +RMAPI Vector3 Vector3Min(Vector3 v1, Vector3 v2) +{ + Vector3 result = { 0 }; + + result.x = fminf(v1.x, v2.x); + result.y = fminf(v1.y, v2.y); + result.z = fminf(v1.z, v2.z); + + return result; +} + +// Get max value for each pair of components +RMAPI Vector3 Vector3Max(Vector3 v1, Vector3 v2) +{ + Vector3 result = { 0 }; + + result.x = fmaxf(v1.x, v2.x); + result.y = fmaxf(v1.y, v2.y); + result.z = fmaxf(v1.z, v2.z); + + return result; +} + +// Compute barycenter coordinates (u, v, w) for point p with respect to triangle (a, b, c) +// NOTE: Assumes P is on the plane of the triangle +RMAPI Vector3 Vector3Barycenter(Vector3 p, Vector3 a, Vector3 b, Vector3 c) +{ + Vector3 result = { 0 }; + + Vector3 v0 = { b.x - a.x, b.y - a.y, b.z - a.z }; // Vector3Subtract(b, a) + Vector3 v1 = { c.x - a.x, c.y - a.y, c.z - a.z }; // Vector3Subtract(c, a) + Vector3 v2 = { p.x - a.x, p.y - a.y, p.z - a.z }; // Vector3Subtract(p, a) + float d00 = (v0.x*v0.x + v0.y*v0.y + v0.z*v0.z); // Vector3DotProduct(v0, v0) + float d01 = (v0.x*v1.x + v0.y*v1.y + v0.z*v1.z); // Vector3DotProduct(v0, v1) + float d11 = (v1.x*v1.x + v1.y*v1.y + v1.z*v1.z); // Vector3DotProduct(v1, v1) + float d20 = (v2.x*v0.x + v2.y*v0.y + v2.z*v0.z); // Vector3DotProduct(v2, v0) + float d21 = (v2.x*v1.x + v2.y*v1.y + v2.z*v1.z); // Vector3DotProduct(v2, v1) + + float denom = d00*d11 - d01*d01; + + result.y = (d11*d20 - d01*d21)/denom; + result.z = (d00*d21 - d01*d20)/denom; + result.x = 1.0f - (result.z + result.y); + + return result; +} + +// Projects a Vector3 from screen space into object space +// NOTE: We are avoiding calling other raymath functions despite available +RMAPI Vector3 Vector3Unproject(Vector3 source, Matrix projection, Matrix view) +{ + Vector3 result = { 0 }; + + // Calculate unprojected matrix (multiply view matrix by projection matrix) and invert it + Matrix matViewProj = { // MatrixMultiply(view, projection); + view.m0*projection.m0 + view.m1*projection.m4 + view.m2*projection.m8 + view.m3*projection.m12, + view.m0*projection.m1 + view.m1*projection.m5 + view.m2*projection.m9 + view.m3*projection.m13, + view.m0*projection.m2 + view.m1*projection.m6 + view.m2*projection.m10 + view.m3*projection.m14, + view.m0*projection.m3 + view.m1*projection.m7 + view.m2*projection.m11 + view.m3*projection.m15, + view.m4*projection.m0 + view.m5*projection.m4 + view.m6*projection.m8 + view.m7*projection.m12, + view.m4*projection.m1 + view.m5*projection.m5 + view.m6*projection.m9 + view.m7*projection.m13, + view.m4*projection.m2 + view.m5*projection.m6 + view.m6*projection.m10 + view.m7*projection.m14, + view.m4*projection.m3 + view.m5*projection.m7 + view.m6*projection.m11 + view.m7*projection.m15, + view.m8*projection.m0 + view.m9*projection.m4 + view.m10*projection.m8 + view.m11*projection.m12, + view.m8*projection.m1 + view.m9*projection.m5 + view.m10*projection.m9 + view.m11*projection.m13, + view.m8*projection.m2 + view.m9*projection.m6 + view.m10*projection.m10 + view.m11*projection.m14, + view.m8*projection.m3 + view.m9*projection.m7 + view.m10*projection.m11 + view.m11*projection.m15, + view.m12*projection.m0 + view.m13*projection.m4 + view.m14*projection.m8 + view.m15*projection.m12, + view.m12*projection.m1 + view.m13*projection.m5 + view.m14*projection.m9 + view.m15*projection.m13, + view.m12*projection.m2 + view.m13*projection.m6 + view.m14*projection.m10 + view.m15*projection.m14, + view.m12*projection.m3 + view.m13*projection.m7 + view.m14*projection.m11 + view.m15*projection.m15 }; + + // Calculate inverted matrix -> MatrixInvert(matViewProj); + // Cache the matrix values (speed optimization) + float a00 = matViewProj.m0, a01 = matViewProj.m1, a02 = matViewProj.m2, a03 = matViewProj.m3; + float a10 = matViewProj.m4, a11 = matViewProj.m5, a12 = matViewProj.m6, a13 = matViewProj.m7; + float a20 = matViewProj.m8, a21 = matViewProj.m9, a22 = matViewProj.m10, a23 = matViewProj.m11; + float a30 = matViewProj.m12, a31 = matViewProj.m13, a32 = matViewProj.m14, a33 = matViewProj.m15; + + float b00 = a00*a11 - a01*a10; + float b01 = a00*a12 - a02*a10; + float b02 = a00*a13 - a03*a10; + float b03 = a01*a12 - a02*a11; + float b04 = a01*a13 - a03*a11; + float b05 = a02*a13 - a03*a12; + float b06 = a20*a31 - a21*a30; + float b07 = a20*a32 - a22*a30; + float b08 = a20*a33 - a23*a30; + float b09 = a21*a32 - a22*a31; + float b10 = a21*a33 - a23*a31; + float b11 = a22*a33 - a23*a32; + + // Calculate the invert determinant (inlined to avoid double-caching) + float invDet = 1.0f/(b00*b11 - b01*b10 + b02*b09 + b03*b08 - b04*b07 + b05*b06); + + Matrix matViewProjInv = { + (a11*b11 - a12*b10 + a13*b09)*invDet, + (-a01*b11 + a02*b10 - a03*b09)*invDet, + (a31*b05 - a32*b04 + a33*b03)*invDet, + (-a21*b05 + a22*b04 - a23*b03)*invDet, + (-a10*b11 + a12*b08 - a13*b07)*invDet, + (a00*b11 - a02*b08 + a03*b07)*invDet, + (-a30*b05 + a32*b02 - a33*b01)*invDet, + (a20*b05 - a22*b02 + a23*b01)*invDet, + (a10*b10 - a11*b08 + a13*b06)*invDet, + (-a00*b10 + a01*b08 - a03*b06)*invDet, + (a30*b04 - a31*b02 + a33*b00)*invDet, + (-a20*b04 + a21*b02 - a23*b00)*invDet, + (-a10*b09 + a11*b07 - a12*b06)*invDet, + (a00*b09 - a01*b07 + a02*b06)*invDet, + (-a30*b03 + a31*b01 - a32*b00)*invDet, + (a20*b03 - a21*b01 + a22*b00)*invDet }; + + // Create quaternion from source point + Quaternion quat = { source.x, source.y, source.z, 1.0f }; + + // Multiply quat point by unprojecte matrix + Quaternion qtransformed = { // QuaternionTransform(quat, matViewProjInv) + matViewProjInv.m0*quat.x + matViewProjInv.m4*quat.y + matViewProjInv.m8*quat.z + matViewProjInv.m12*quat.w, + matViewProjInv.m1*quat.x + matViewProjInv.m5*quat.y + matViewProjInv.m9*quat.z + matViewProjInv.m13*quat.w, + matViewProjInv.m2*quat.x + matViewProjInv.m6*quat.y + matViewProjInv.m10*quat.z + matViewProjInv.m14*quat.w, + matViewProjInv.m3*quat.x + matViewProjInv.m7*quat.y + matViewProjInv.m11*quat.z + matViewProjInv.m15*quat.w }; + + // Normalized world points in vectors + result.x = qtransformed.x/qtransformed.w; + result.y = qtransformed.y/qtransformed.w; + result.z = qtransformed.z/qtransformed.w; + + return result; +} + +// Get Vector3 as float array +RMAPI float3 Vector3ToFloatV(Vector3 v) +{ + float3 buffer = { 0 }; + + buffer.v[0] = v.x; + buffer.v[1] = v.y; + buffer.v[2] = v.z; + + return buffer; +} + +// Invert the given vector +RMAPI Vector3 Vector3Invert(Vector3 v) +{ + Vector3 result = { 1.0f/v.x, 1.0f/v.y, 1.0f/v.z }; + + return result; +} + +// Clamp the components of the vector between +// min and max values specified by the given vectors +RMAPI Vector3 Vector3Clamp(Vector3 v, Vector3 min, Vector3 max) +{ + Vector3 result = { 0 }; + + result.x = fminf(max.x, fmaxf(min.x, v.x)); + result.y = fminf(max.y, fmaxf(min.y, v.y)); + result.z = fminf(max.z, fmaxf(min.z, v.z)); + + return result; +} + +// Clamp the magnitude of the vector between two values +RMAPI Vector3 Vector3ClampValue(Vector3 v, float min, float max) +{ + Vector3 result = v; + + float length = (v.x*v.x) + (v.y*v.y) + (v.z*v.z); + if (length > 0.0f) + { + length = sqrtf(length); + + float scale = 1; // By default, 1 as the neutral element. + if (length < min) + { + scale = min/length; + } + else if (length > max) + { + scale = max/length; + } + + result.x = v.x*scale; + result.y = v.y*scale; + result.z = v.z*scale; + } + + return result; +} + +// Check whether two given vectors are almost equal +RMAPI int Vector3Equals(Vector3 p, Vector3 q) +{ +#if !defined(EPSILON) + #define EPSILON 0.000001f +#endif + + int result = ((fabsf(p.x - q.x)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.x), fabsf(q.x))))) && + ((fabsf(p.y - q.y)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.y), fabsf(q.y))))) && + ((fabsf(p.z - q.z)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.z), fabsf(q.z))))); + + return result; +} + +// Compute the direction of a refracted ray +// v: normalized direction of the incoming ray +// n: normalized normal vector of the interface of two optical media +// r: ratio of the refractive index of the medium from where the ray comes +// to the refractive index of the medium on the other side of the surface +RMAPI Vector3 Vector3Refract(Vector3 v, Vector3 n, float r) +{ + Vector3 result = { 0 }; + + float dot = v.x*n.x + v.y*n.y + v.z*n.z; + float d = 1.0f - r*r*(1.0f - dot*dot); + + if (d >= 0.0f) + { + d = sqrtf(d); + v.x = r*v.x - (r*dot + d)*n.x; + v.y = r*v.y - (r*dot + d)*n.y; + v.z = r*v.z - (r*dot + d)*n.z; + + result = v; + } + + return result; +} + + +//---------------------------------------------------------------------------------- +// Module Functions Definition - Vector4 math +//---------------------------------------------------------------------------------- + +RMAPI Vector4 Vector4Zero(void) +{ + Vector4 result = { 0.0f, 0.0f, 0.0f, 0.0f }; + return result; +} + +RMAPI Vector4 Vector4One(void) +{ + Vector4 result = { 1.0f, 1.0f, 1.0f, 1.0f }; + return result; +} + +RMAPI Vector4 Vector4Add(Vector4 v1, Vector4 v2) +{ + Vector4 result = { + v1.x + v2.x, + v1.y + v2.y, + v1.z + v2.z, + v1.w + v2.w + }; + return result; +} + +RMAPI Vector4 Vector4AddValue(Vector4 v, float add) +{ + Vector4 result = { + v.x + add, + v.y + add, + v.z + add, + v.w + add + }; + return result; +} + +RMAPI Vector4 Vector4Subtract(Vector4 v1, Vector4 v2) +{ + Vector4 result = { + v1.x - v2.x, + v1.y - v2.y, + v1.z - v2.z, + v1.w - v2.w + }; + return result; +} + +RMAPI Vector4 Vector4SubtractValue(Vector4 v, float add) +{ + Vector4 result = { + v.x - add, + v.y - add, + v.z - add, + v.w - add + }; + return result; +} + +RMAPI float Vector4Length(Vector4 v) +{ + float result = sqrtf((v.x*v.x) + (v.y*v.y) + (v.z*v.z) + (v.w*v.w)); + return result; +} + +RMAPI float Vector4LengthSqr(Vector4 v) +{ + float result = (v.x*v.x) + (v.y*v.y) + (v.z*v.z) + (v.w*v.w); + return result; +} + +RMAPI float Vector4DotProduct(Vector4 v1, Vector4 v2) +{ + float result = (v1.x*v2.x + v1.y*v2.y + v1.z*v2.z + v1.w*v2.w); + return result; +} + +// Calculate distance between two vectors +RMAPI float Vector4Distance(Vector4 v1, Vector4 v2) +{ + float result = sqrtf( + (v1.x - v2.x)*(v1.x - v2.x) + (v1.y - v2.y)*(v1.y - v2.y) + + (v1.z - v2.z)*(v1.z - v2.z) + (v1.w - v2.w)*(v1.w - v2.w)); + return result; +} + +// Calculate square distance between two vectors +RMAPI float Vector4DistanceSqr(Vector4 v1, Vector4 v2) +{ + float result = + (v1.x - v2.x)*(v1.x - v2.x) + (v1.y - v2.y)*(v1.y - v2.y) + + (v1.z - v2.z)*(v1.z - v2.z) + (v1.w - v2.w)*(v1.w - v2.w); + + return result; +} + +RMAPI Vector4 Vector4Scale(Vector4 v, float scale) +{ + Vector4 result = { v.x*scale, v.y*scale, v.z*scale, v.w*scale }; + return result; +} + +// Multiply vector by vector +RMAPI Vector4 Vector4Multiply(Vector4 v1, Vector4 v2) +{ + Vector4 result = { v1.x*v2.x, v1.y*v2.y, v1.z*v2.z, v1.w*v2.w }; + return result; +} + +// Negate vector +RMAPI Vector4 Vector4Negate(Vector4 v) +{ + Vector4 result = { -v.x, -v.y, -v.z, -v.w }; + return result; +} + +// Divide vector by vector +RMAPI Vector4 Vector4Divide(Vector4 v1, Vector4 v2) +{ + Vector4 result = { v1.x/v2.x, v1.y/v2.y, v1.z/v2.z, v1.w/v2.w }; + return result; +} + +// Normalize provided vector +RMAPI Vector4 Vector4Normalize(Vector4 v) +{ + Vector4 result = { 0 }; + float length = sqrtf((v.x*v.x) + (v.y*v.y) + (v.z*v.z) + (v.w*v.w)); + + if (length > 0) + { + float ilength = 1.0f/length; + result.x = v.x*ilength; + result.y = v.y*ilength; + result.z = v.z*ilength; + result.w = v.w*ilength; + } + + return result; +} + +// Get min value for each pair of components +RMAPI Vector4 Vector4Min(Vector4 v1, Vector4 v2) +{ + Vector4 result = { 0 }; + + result.x = fminf(v1.x, v2.x); + result.y = fminf(v1.y, v2.y); + result.z = fminf(v1.z, v2.z); + result.w = fminf(v1.w, v2.w); + + return result; +} + +// Get max value for each pair of components +RMAPI Vector4 Vector4Max(Vector4 v1, Vector4 v2) +{ + Vector4 result = { 0 }; + + result.x = fmaxf(v1.x, v2.x); + result.y = fmaxf(v1.y, v2.y); + result.z = fmaxf(v1.z, v2.z); + result.w = fmaxf(v1.w, v2.w); + + return result; +} + +// Calculate linear interpolation between two vectors +RMAPI Vector4 Vector4Lerp(Vector4 v1, Vector4 v2, float amount) +{ + Vector4 result = { 0 }; + + result.x = v1.x + amount*(v2.x - v1.x); + result.y = v1.y + amount*(v2.y - v1.y); + result.z = v1.z + amount*(v2.z - v1.z); + result.w = v1.w + amount*(v2.w - v1.w); + + return result; +} + +// Move Vector towards target +RMAPI Vector4 Vector4MoveTowards(Vector4 v, Vector4 target, float maxDistance) +{ + Vector4 result = { 0 }; + + float dx = target.x - v.x; + float dy = target.y - v.y; + float dz = target.z - v.z; + float dw = target.w - v.w; + float value = (dx*dx) + (dy*dy) + (dz*dz) + (dw*dw); + + if ((value == 0) || ((maxDistance >= 0) && (value <= maxDistance*maxDistance))) return target; + + float dist = sqrtf(value); + + result.x = v.x + dx/dist*maxDistance; + result.y = v.y + dy/dist*maxDistance; + result.z = v.z + dz/dist*maxDistance; + result.w = v.w + dw/dist*maxDistance; + + return result; +} + +// Invert the given vector +RMAPI Vector4 Vector4Invert(Vector4 v) +{ + Vector4 result = { 1.0f/v.x, 1.0f/v.y, 1.0f/v.z, 1.0f/v.w }; + return result; +} + +// Check whether two given vectors are almost equal +RMAPI int Vector4Equals(Vector4 p, Vector4 q) +{ +#if !defined(EPSILON) + #define EPSILON 0.000001f +#endif + + int result = ((fabsf(p.x - q.x)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.x), fabsf(q.x))))) && + ((fabsf(p.y - q.y)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.y), fabsf(q.y))))) && + ((fabsf(p.z - q.z)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.z), fabsf(q.z))))) && + ((fabsf(p.w - q.w)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.w), fabsf(q.w))))); + return result; +} + + +//---------------------------------------------------------------------------------- +// Module Functions Definition - Matrix math +//---------------------------------------------------------------------------------- + +// Compute matrix determinant +RMAPI float MatrixDeterminant(Matrix mat) +{ + float result = 0.0f; + + // Cache the matrix values (speed optimization) + float a00 = mat.m0, a01 = mat.m1, a02 = mat.m2, a03 = mat.m3; + float a10 = mat.m4, a11 = mat.m5, a12 = mat.m6, a13 = mat.m7; + float a20 = mat.m8, a21 = mat.m9, a22 = mat.m10, a23 = mat.m11; + float a30 = mat.m12, a31 = mat.m13, a32 = mat.m14, a33 = mat.m15; + + result = a30*a21*a12*a03 - a20*a31*a12*a03 - a30*a11*a22*a03 + a10*a31*a22*a03 + + a20*a11*a32*a03 - a10*a21*a32*a03 - a30*a21*a02*a13 + a20*a31*a02*a13 + + a30*a01*a22*a13 - a00*a31*a22*a13 - a20*a01*a32*a13 + a00*a21*a32*a13 + + a30*a11*a02*a23 - a10*a31*a02*a23 - a30*a01*a12*a23 + a00*a31*a12*a23 + + a10*a01*a32*a23 - a00*a11*a32*a23 - a20*a11*a02*a33 + a10*a21*a02*a33 + + a20*a01*a12*a33 - a00*a21*a12*a33 - a10*a01*a22*a33 + a00*a11*a22*a33; + + return result; +} + +// Get the trace of the matrix (sum of the values along the diagonal) +RMAPI float MatrixTrace(Matrix mat) +{ + float result = (mat.m0 + mat.m5 + mat.m10 + mat.m15); + + return result; +} + +// Transposes provided matrix +RMAPI Matrix MatrixTranspose(Matrix mat) +{ + Matrix result = { 0 }; + + result.m0 = mat.m0; + result.m1 = mat.m4; + result.m2 = mat.m8; + result.m3 = mat.m12; + result.m4 = mat.m1; + result.m5 = mat.m5; + result.m6 = mat.m9; + result.m7 = mat.m13; + result.m8 = mat.m2; + result.m9 = mat.m6; + result.m10 = mat.m10; + result.m11 = mat.m14; + result.m12 = mat.m3; + result.m13 = mat.m7; + result.m14 = mat.m11; + result.m15 = mat.m15; + + return result; +} + +// Invert provided matrix +RMAPI Matrix MatrixInvert(Matrix mat) +{ + Matrix result = { 0 }; + + // Cache the matrix values (speed optimization) + float a00 = mat.m0, a01 = mat.m1, a02 = mat.m2, a03 = mat.m3; + float a10 = mat.m4, a11 = mat.m5, a12 = mat.m6, a13 = mat.m7; + float a20 = mat.m8, a21 = mat.m9, a22 = mat.m10, a23 = mat.m11; + float a30 = mat.m12, a31 = mat.m13, a32 = mat.m14, a33 = mat.m15; + + float b00 = a00*a11 - a01*a10; + float b01 = a00*a12 - a02*a10; + float b02 = a00*a13 - a03*a10; + float b03 = a01*a12 - a02*a11; + float b04 = a01*a13 - a03*a11; + float b05 = a02*a13 - a03*a12; + float b06 = a20*a31 - a21*a30; + float b07 = a20*a32 - a22*a30; + float b08 = a20*a33 - a23*a30; + float b09 = a21*a32 - a22*a31; + float b10 = a21*a33 - a23*a31; + float b11 = a22*a33 - a23*a32; + + // Calculate the invert determinant (inlined to avoid double-caching) + float invDet = 1.0f/(b00*b11 - b01*b10 + b02*b09 + b03*b08 - b04*b07 + b05*b06); + + result.m0 = (a11*b11 - a12*b10 + a13*b09)*invDet; + result.m1 = (-a01*b11 + a02*b10 - a03*b09)*invDet; + result.m2 = (a31*b05 - a32*b04 + a33*b03)*invDet; + result.m3 = (-a21*b05 + a22*b04 - a23*b03)*invDet; + result.m4 = (-a10*b11 + a12*b08 - a13*b07)*invDet; + result.m5 = (a00*b11 - a02*b08 + a03*b07)*invDet; + result.m6 = (-a30*b05 + a32*b02 - a33*b01)*invDet; + result.m7 = (a20*b05 - a22*b02 + a23*b01)*invDet; + result.m8 = (a10*b10 - a11*b08 + a13*b06)*invDet; + result.m9 = (-a00*b10 + a01*b08 - a03*b06)*invDet; + result.m10 = (a30*b04 - a31*b02 + a33*b00)*invDet; + result.m11 = (-a20*b04 + a21*b02 - a23*b00)*invDet; + result.m12 = (-a10*b09 + a11*b07 - a12*b06)*invDet; + result.m13 = (a00*b09 - a01*b07 + a02*b06)*invDet; + result.m14 = (-a30*b03 + a31*b01 - a32*b00)*invDet; + result.m15 = (a20*b03 - a21*b01 + a22*b00)*invDet; + + return result; +} + +// Get identity matrix +RMAPI Matrix MatrixIdentity(void) +{ + Matrix result = { 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f }; + + return result; +} + +// Add two matrices +RMAPI Matrix MatrixAdd(Matrix left, Matrix right) +{ + Matrix result = { 0 }; + + result.m0 = left.m0 + right.m0; + result.m1 = left.m1 + right.m1; + result.m2 = left.m2 + right.m2; + result.m3 = left.m3 + right.m3; + result.m4 = left.m4 + right.m4; + result.m5 = left.m5 + right.m5; + result.m6 = left.m6 + right.m6; + result.m7 = left.m7 + right.m7; + result.m8 = left.m8 + right.m8; + result.m9 = left.m9 + right.m9; + result.m10 = left.m10 + right.m10; + result.m11 = left.m11 + right.m11; + result.m12 = left.m12 + right.m12; + result.m13 = left.m13 + right.m13; + result.m14 = left.m14 + right.m14; + result.m15 = left.m15 + right.m15; + + return result; +} + +// Subtract two matrices (left - right) +RMAPI Matrix MatrixSubtract(Matrix left, Matrix right) +{ + Matrix result = { 0 }; + + result.m0 = left.m0 - right.m0; + result.m1 = left.m1 - right.m1; + result.m2 = left.m2 - right.m2; + result.m3 = left.m3 - right.m3; + result.m4 = left.m4 - right.m4; + result.m5 = left.m5 - right.m5; + result.m6 = left.m6 - right.m6; + result.m7 = left.m7 - right.m7; + result.m8 = left.m8 - right.m8; + result.m9 = left.m9 - right.m9; + result.m10 = left.m10 - right.m10; + result.m11 = left.m11 - right.m11; + result.m12 = left.m12 - right.m12; + result.m13 = left.m13 - right.m13; + result.m14 = left.m14 - right.m14; + result.m15 = left.m15 - right.m15; + + return result; +} + +// Get two matrix multiplication +// NOTE: When multiplying matrices... the order matters! +RMAPI Matrix MatrixMultiply(Matrix left, Matrix right) +{ + Matrix result = { 0 }; + + result.m0 = left.m0*right.m0 + left.m1*right.m4 + left.m2*right.m8 + left.m3*right.m12; + result.m1 = left.m0*right.m1 + left.m1*right.m5 + left.m2*right.m9 + left.m3*right.m13; + result.m2 = left.m0*right.m2 + left.m1*right.m6 + left.m2*right.m10 + left.m3*right.m14; + result.m3 = left.m0*right.m3 + left.m1*right.m7 + left.m2*right.m11 + left.m3*right.m15; + result.m4 = left.m4*right.m0 + left.m5*right.m4 + left.m6*right.m8 + left.m7*right.m12; + result.m5 = left.m4*right.m1 + left.m5*right.m5 + left.m6*right.m9 + left.m7*right.m13; + result.m6 = left.m4*right.m2 + left.m5*right.m6 + left.m6*right.m10 + left.m7*right.m14; + result.m7 = left.m4*right.m3 + left.m5*right.m7 + left.m6*right.m11 + left.m7*right.m15; + result.m8 = left.m8*right.m0 + left.m9*right.m4 + left.m10*right.m8 + left.m11*right.m12; + result.m9 = left.m8*right.m1 + left.m9*right.m5 + left.m10*right.m9 + left.m11*right.m13; + result.m10 = left.m8*right.m2 + left.m9*right.m6 + left.m10*right.m10 + left.m11*right.m14; + result.m11 = left.m8*right.m3 + left.m9*right.m7 + left.m10*right.m11 + left.m11*right.m15; + result.m12 = left.m12*right.m0 + left.m13*right.m4 + left.m14*right.m8 + left.m15*right.m12; + result.m13 = left.m12*right.m1 + left.m13*right.m5 + left.m14*right.m9 + left.m15*right.m13; + result.m14 = left.m12*right.m2 + left.m13*right.m6 + left.m14*right.m10 + left.m15*right.m14; + result.m15 = left.m12*right.m3 + left.m13*right.m7 + left.m14*right.m11 + left.m15*right.m15; + + return result; +} + +// Get translation matrix +RMAPI Matrix MatrixTranslate(float x, float y, float z) +{ + Matrix result = { 1.0f, 0.0f, 0.0f, x, + 0.0f, 1.0f, 0.0f, y, + 0.0f, 0.0f, 1.0f, z, + 0.0f, 0.0f, 0.0f, 1.0f }; + + return result; +} + +// Create rotation matrix from axis and angle +// NOTE: Angle should be provided in radians +RMAPI Matrix MatrixRotate(Vector3 axis, float angle) +{ + Matrix result = { 0 }; + + float x = axis.x, y = axis.y, z = axis.z; + + float lengthSquared = x*x + y*y + z*z; + + if ((lengthSquared != 1.0f) && (lengthSquared != 0.0f)) + { + float ilength = 1.0f/sqrtf(lengthSquared); + x *= ilength; + y *= ilength; + z *= ilength; + } + + float sinres = sinf(angle); + float cosres = cosf(angle); + float t = 1.0f - cosres; + + result.m0 = x*x*t + cosres; + result.m1 = y*x*t + z*sinres; + result.m2 = z*x*t - y*sinres; + result.m3 = 0.0f; + + result.m4 = x*y*t - z*sinres; + result.m5 = y*y*t + cosres; + result.m6 = z*y*t + x*sinres; + result.m7 = 0.0f; + + result.m8 = x*z*t + y*sinres; + result.m9 = y*z*t - x*sinres; + result.m10 = z*z*t + cosres; + result.m11 = 0.0f; + + result.m12 = 0.0f; + result.m13 = 0.0f; + result.m14 = 0.0f; + result.m15 = 1.0f; + + return result; +} + +// Get x-rotation matrix +// NOTE: Angle must be provided in radians +RMAPI Matrix MatrixRotateX(float angle) +{ + Matrix result = { 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f }; // MatrixIdentity() + + float cosres = cosf(angle); + float sinres = sinf(angle); + + result.m5 = cosres; + result.m6 = sinres; + result.m9 = -sinres; + result.m10 = cosres; + + return result; +} + +// Get y-rotation matrix +// NOTE: Angle must be provided in radians +RMAPI Matrix MatrixRotateY(float angle) +{ + Matrix result = { 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f }; // MatrixIdentity() + + float cosres = cosf(angle); + float sinres = sinf(angle); + + result.m0 = cosres; + result.m2 = -sinres; + result.m8 = sinres; + result.m10 = cosres; + + return result; +} + +// Get z-rotation matrix +// NOTE: Angle must be provided in radians +RMAPI Matrix MatrixRotateZ(float angle) +{ + Matrix result = { 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f }; // MatrixIdentity() + + float cosres = cosf(angle); + float sinres = sinf(angle); + + result.m0 = cosres; + result.m1 = sinres; + result.m4 = -sinres; + result.m5 = cosres; + + return result; +} + + +// Get xyz-rotation matrix +// NOTE: Angle must be provided in radians +RMAPI Matrix MatrixRotateXYZ(Vector3 angle) +{ + Matrix result = { 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f }; // MatrixIdentity() + + float cosz = cosf(-angle.z); + float sinz = sinf(-angle.z); + float cosy = cosf(-angle.y); + float siny = sinf(-angle.y); + float cosx = cosf(-angle.x); + float sinx = sinf(-angle.x); + + result.m0 = cosz*cosy; + result.m1 = (cosz*siny*sinx) - (sinz*cosx); + result.m2 = (cosz*siny*cosx) + (sinz*sinx); + + result.m4 = sinz*cosy; + result.m5 = (sinz*siny*sinx) + (cosz*cosx); + result.m6 = (sinz*siny*cosx) - (cosz*sinx); + + result.m8 = -siny; + result.m9 = cosy*sinx; + result.m10= cosy*cosx; + + return result; +} + +// Get zyx-rotation matrix +// NOTE: Angle must be provided in radians +RMAPI Matrix MatrixRotateZYX(Vector3 angle) +{ + Matrix result = { 0 }; + + float cz = cosf(angle.z); + float sz = sinf(angle.z); + float cy = cosf(angle.y); + float sy = sinf(angle.y); + float cx = cosf(angle.x); + float sx = sinf(angle.x); + + result.m0 = cz*cy; + result.m4 = cz*sy*sx - cx*sz; + result.m8 = sz*sx + cz*cx*sy; + result.m12 = 0; + + result.m1 = cy*sz; + result.m5 = cz*cx + sz*sy*sx; + result.m9 = cx*sz*sy - cz*sx; + result.m13 = 0; + + result.m2 = -sy; + result.m6 = cy*sx; + result.m10 = cy*cx; + result.m14 = 0; + + result.m3 = 0; + result.m7 = 0; + result.m11 = 0; + result.m15 = 1; + + return result; +} + +// Get scaling matrix +RMAPI Matrix MatrixScale(float x, float y, float z) +{ + Matrix result = { x, 0.0f, 0.0f, 0.0f, + 0.0f, y, 0.0f, 0.0f, + 0.0f, 0.0f, z, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f }; + + return result; +} + +// Get perspective projection matrix +RMAPI Matrix MatrixFrustum(double left, double right, double bottom, double top, double nearPlane, double farPlane) +{ + Matrix result = { 0 }; + + float rl = (float)(right - left); + float tb = (float)(top - bottom); + float fn = (float)(farPlane - nearPlane); + + result.m0 = ((float)nearPlane*2.0f)/rl; + result.m1 = 0.0f; + result.m2 = 0.0f; + result.m3 = 0.0f; + + result.m4 = 0.0f; + result.m5 = ((float)nearPlane*2.0f)/tb; + result.m6 = 0.0f; + result.m7 = 0.0f; + + result.m8 = ((float)right + (float)left)/rl; + result.m9 = ((float)top + (float)bottom)/tb; + result.m10 = -((float)farPlane + (float)nearPlane)/fn; + result.m11 = -1.0f; + + result.m12 = 0.0f; + result.m13 = 0.0f; + result.m14 = -((float)farPlane*(float)nearPlane*2.0f)/fn; + result.m15 = 0.0f; + + return result; +} + +// Get perspective projection matrix +// NOTE: Fovy angle must be provided in radians +RMAPI Matrix MatrixPerspective(double fovY, double aspect, double nearPlane, double farPlane) +{ + Matrix result = { 0 }; + + double top = nearPlane*tan(fovY*0.5); + double bottom = -top; + double right = top*aspect; + double left = -right; + + // MatrixFrustum(-right, right, -top, top, near, far); + float rl = (float)(right - left); + float tb = (float)(top - bottom); + float fn = (float)(farPlane - nearPlane); + + result.m0 = ((float)nearPlane*2.0f)/rl; + result.m5 = ((float)nearPlane*2.0f)/tb; + result.m8 = ((float)right + (float)left)/rl; + result.m9 = ((float)top + (float)bottom)/tb; + result.m10 = -((float)farPlane + (float)nearPlane)/fn; + result.m11 = -1.0f; + result.m14 = -((float)farPlane*(float)nearPlane*2.0f)/fn; + + return result; +} + +// Get orthographic projection matrix +RMAPI Matrix MatrixOrtho(double left, double right, double bottom, double top, double nearPlane, double farPlane) +{ + Matrix result = { 0 }; + + float rl = (float)(right - left); + float tb = (float)(top - bottom); + float fn = (float)(farPlane - nearPlane); + + result.m0 = 2.0f/rl; + result.m1 = 0.0f; + result.m2 = 0.0f; + result.m3 = 0.0f; + result.m4 = 0.0f; + result.m5 = 2.0f/tb; + result.m6 = 0.0f; + result.m7 = 0.0f; + result.m8 = 0.0f; + result.m9 = 0.0f; + result.m10 = -2.0f/fn; + result.m11 = 0.0f; + result.m12 = -((float)left + (float)right)/rl; + result.m13 = -((float)top + (float)bottom)/tb; + result.m14 = -((float)farPlane + (float)nearPlane)/fn; + result.m15 = 1.0f; + + return result; +} + +// Get camera look-at matrix (view matrix) +RMAPI Matrix MatrixLookAt(Vector3 eye, Vector3 target, Vector3 up) +{ + Matrix result = { 0 }; + + float length = 0.0f; + float ilength = 0.0f; + + // Vector3Subtract(eye, target) + Vector3 vz = { eye.x - target.x, eye.y - target.y, eye.z - target.z }; + + // Vector3Normalize(vz) + Vector3 v = vz; + length = sqrtf(v.x*v.x + v.y*v.y + v.z*v.z); + if (length == 0.0f) length = 1.0f; + ilength = 1.0f/length; + vz.x *= ilength; + vz.y *= ilength; + vz.z *= ilength; + + // Vector3CrossProduct(up, vz) + Vector3 vx = { up.y*vz.z - up.z*vz.y, up.z*vz.x - up.x*vz.z, up.x*vz.y - up.y*vz.x }; + + // Vector3Normalize(x) + v = vx; + length = sqrtf(v.x*v.x + v.y*v.y + v.z*v.z); + if (length == 0.0f) length = 1.0f; + ilength = 1.0f/length; + vx.x *= ilength; + vx.y *= ilength; + vx.z *= ilength; + + // Vector3CrossProduct(vz, vx) + Vector3 vy = { vz.y*vx.z - vz.z*vx.y, vz.z*vx.x - vz.x*vx.z, vz.x*vx.y - vz.y*vx.x }; + + result.m0 = vx.x; + result.m1 = vy.x; + result.m2 = vz.x; + result.m3 = 0.0f; + result.m4 = vx.y; + result.m5 = vy.y; + result.m6 = vz.y; + result.m7 = 0.0f; + result.m8 = vx.z; + result.m9 = vy.z; + result.m10 = vz.z; + result.m11 = 0.0f; + result.m12 = -(vx.x*eye.x + vx.y*eye.y + vx.z*eye.z); // Vector3DotProduct(vx, eye) + result.m13 = -(vy.x*eye.x + vy.y*eye.y + vy.z*eye.z); // Vector3DotProduct(vy, eye) + result.m14 = -(vz.x*eye.x + vz.y*eye.y + vz.z*eye.z); // Vector3DotProduct(vz, eye) + result.m15 = 1.0f; + + return result; +} + +// Get float array of matrix data +RMAPI float16 MatrixToFloatV(Matrix mat) +{ + float16 result = { 0 }; + + result.v[0] = mat.m0; + result.v[1] = mat.m1; + result.v[2] = mat.m2; + result.v[3] = mat.m3; + result.v[4] = mat.m4; + result.v[5] = mat.m5; + result.v[6] = mat.m6; + result.v[7] = mat.m7; + result.v[8] = mat.m8; + result.v[9] = mat.m9; + result.v[10] = mat.m10; + result.v[11] = mat.m11; + result.v[12] = mat.m12; + result.v[13] = mat.m13; + result.v[14] = mat.m14; + result.v[15] = mat.m15; + + return result; +} + +//---------------------------------------------------------------------------------- +// Module Functions Definition - Quaternion math +//---------------------------------------------------------------------------------- + +// Add two quaternions +RMAPI Quaternion QuaternionAdd(Quaternion q1, Quaternion q2) +{ + Quaternion result = {q1.x + q2.x, q1.y + q2.y, q1.z + q2.z, q1.w + q2.w}; + + return result; +} + +// Add quaternion and float value +RMAPI Quaternion QuaternionAddValue(Quaternion q, float add) +{ + Quaternion result = {q.x + add, q.y + add, q.z + add, q.w + add}; + + return result; +} + +// Subtract two quaternions +RMAPI Quaternion QuaternionSubtract(Quaternion q1, Quaternion q2) +{ + Quaternion result = {q1.x - q2.x, q1.y - q2.y, q1.z - q2.z, q1.w - q2.w}; + + return result; +} + +// Subtract quaternion and float value +RMAPI Quaternion QuaternionSubtractValue(Quaternion q, float sub) +{ + Quaternion result = {q.x - sub, q.y - sub, q.z - sub, q.w - sub}; + + return result; +} + +// Get identity quaternion +RMAPI Quaternion QuaternionIdentity(void) +{ + Quaternion result = { 0.0f, 0.0f, 0.0f, 1.0f }; + + return result; +} + +// Computes the length of a quaternion +RMAPI float QuaternionLength(Quaternion q) +{ + float result = sqrtf(q.x*q.x + q.y*q.y + q.z*q.z + q.w*q.w); + + return result; +} + +// Normalize provided quaternion +RMAPI Quaternion QuaternionNormalize(Quaternion q) +{ + Quaternion result = { 0 }; + + float length = sqrtf(q.x*q.x + q.y*q.y + q.z*q.z + q.w*q.w); + if (length == 0.0f) length = 1.0f; + float ilength = 1.0f/length; + + result.x = q.x*ilength; + result.y = q.y*ilength; + result.z = q.z*ilength; + result.w = q.w*ilength; + + return result; +} + +// Invert provided quaternion +RMAPI Quaternion QuaternionInvert(Quaternion q) +{ + Quaternion result = q; + + float lengthSq = q.x*q.x + q.y*q.y + q.z*q.z + q.w*q.w; + + if (lengthSq != 0.0f) + { + float invLength = 1.0f/lengthSq; + + result.x *= -invLength; + result.y *= -invLength; + result.z *= -invLength; + result.w *= invLength; + } + + return result; +} + +// Calculate two quaternion multiplication +RMAPI Quaternion QuaternionMultiply(Quaternion q1, Quaternion q2) +{ + Quaternion result = { 0 }; + + float qax = q1.x, qay = q1.y, qaz = q1.z, qaw = q1.w; + float qbx = q2.x, qby = q2.y, qbz = q2.z, qbw = q2.w; + + result.x = qax*qbw + qaw*qbx + qay*qbz - qaz*qby; + result.y = qay*qbw + qaw*qby + qaz*qbx - qax*qbz; + result.z = qaz*qbw + qaw*qbz + qax*qby - qay*qbx; + result.w = qaw*qbw - qax*qbx - qay*qby - qaz*qbz; + + return result; +} + +// Scale quaternion by float value +RMAPI Quaternion QuaternionScale(Quaternion q, float mul) +{ + Quaternion result = { 0 }; + + result.x = q.x*mul; + result.y = q.y*mul; + result.z = q.z*mul; + result.w = q.w*mul; + + return result; +} + +// Divide two quaternions +RMAPI Quaternion QuaternionDivide(Quaternion q1, Quaternion q2) +{ + Quaternion result = { q1.x/q2.x, q1.y/q2.y, q1.z/q2.z, q1.w/q2.w }; + + return result; +} + +// Calculate linear interpolation between two quaternions +RMAPI Quaternion QuaternionLerp(Quaternion q1, Quaternion q2, float amount) +{ + Quaternion result = { 0 }; + + result.x = q1.x + amount*(q2.x - q1.x); + result.y = q1.y + amount*(q2.y - q1.y); + result.z = q1.z + amount*(q2.z - q1.z); + result.w = q1.w + amount*(q2.w - q1.w); + + return result; +} + +// Calculate slerp-optimized interpolation between two quaternions +RMAPI Quaternion QuaternionNlerp(Quaternion q1, Quaternion q2, float amount) +{ + Quaternion result = { 0 }; + + // QuaternionLerp(q1, q2, amount) + result.x = q1.x + amount*(q2.x - q1.x); + result.y = q1.y + amount*(q2.y - q1.y); + result.z = q1.z + amount*(q2.z - q1.z); + result.w = q1.w + amount*(q2.w - q1.w); + + // QuaternionNormalize(q); + Quaternion q = result; + float length = sqrtf(q.x*q.x + q.y*q.y + q.z*q.z + q.w*q.w); + if (length == 0.0f) length = 1.0f; + float ilength = 1.0f/length; + + result.x = q.x*ilength; + result.y = q.y*ilength; + result.z = q.z*ilength; + result.w = q.w*ilength; + + return result; +} + +// Calculates spherical linear interpolation between two quaternions +RMAPI Quaternion QuaternionSlerp(Quaternion q1, Quaternion q2, float amount) +{ + Quaternion result = { 0 }; + +#if !defined(EPSILON) + #define EPSILON 0.000001f +#endif + + float cosHalfTheta = q1.x*q2.x + q1.y*q2.y + q1.z*q2.z + q1.w*q2.w; + + if (cosHalfTheta < 0) + { + q2.x = -q2.x; q2.y = -q2.y; q2.z = -q2.z; q2.w = -q2.w; + cosHalfTheta = -cosHalfTheta; + } + + if (fabsf(cosHalfTheta) >= 1.0f) result = q1; + else if (cosHalfTheta > 0.95f) result = QuaternionNlerp(q1, q2, amount); + else + { + float halfTheta = acosf(cosHalfTheta); + float sinHalfTheta = sqrtf(1.0f - cosHalfTheta*cosHalfTheta); + + if (fabsf(sinHalfTheta) < EPSILON) + { + result.x = (q1.x*0.5f + q2.x*0.5f); + result.y = (q1.y*0.5f + q2.y*0.5f); + result.z = (q1.z*0.5f + q2.z*0.5f); + result.w = (q1.w*0.5f + q2.w*0.5f); + } + else + { + float ratioA = sinf((1 - amount)*halfTheta)/sinHalfTheta; + float ratioB = sinf(amount*halfTheta)/sinHalfTheta; + + result.x = (q1.x*ratioA + q2.x*ratioB); + result.y = (q1.y*ratioA + q2.y*ratioB); + result.z = (q1.z*ratioA + q2.z*ratioB); + result.w = (q1.w*ratioA + q2.w*ratioB); + } + } + + return result; +} + +// Calculate quaternion cubic spline interpolation using Cubic Hermite Spline algorithm +// as described in the GLTF 2.0 specification: https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#interpolation-cubic +RMAPI Quaternion QuaternionCubicHermiteSpline(Quaternion q1, Quaternion outTangent1, Quaternion q2, Quaternion inTangent2, float t) +{ + float t2 = t*t; + float t3 = t2*t; + float h00 = 2*t3 - 3*t2 + 1; + float h10 = t3 - 2*t2 + t; + float h01 = -2*t3 + 3*t2; + float h11 = t3 - t2; + + Quaternion p0 = QuaternionScale(q1, h00); + Quaternion m0 = QuaternionScale(outTangent1, h10); + Quaternion p1 = QuaternionScale(q2, h01); + Quaternion m1 = QuaternionScale(inTangent2, h11); + + Quaternion result = { 0 }; + + result = QuaternionAdd(p0, m0); + result = QuaternionAdd(result, p1); + result = QuaternionAdd(result, m1); + result = QuaternionNormalize(result); + + return result; +} + +// Calculate quaternion based on the rotation from one vector to another +RMAPI Quaternion QuaternionFromVector3ToVector3(Vector3 from, Vector3 to) +{ + Quaternion result = { 0 }; + + float cos2Theta = (from.x*to.x + from.y*to.y + from.z*to.z); // Vector3DotProduct(from, to) + Vector3 cross = { from.y*to.z - from.z*to.y, from.z*to.x - from.x*to.z, from.x*to.y - from.y*to.x }; // Vector3CrossProduct(from, to) + + result.x = cross.x; + result.y = cross.y; + result.z = cross.z; + result.w = 1.0f + cos2Theta; + + // QuaternionNormalize(q); + // NOTE: Normalize to essentially nlerp the original and identity to 0.5 + Quaternion q = result; + float length = sqrtf(q.x*q.x + q.y*q.y + q.z*q.z + q.w*q.w); + if (length == 0.0f) length = 1.0f; + float ilength = 1.0f/length; + + result.x = q.x*ilength; + result.y = q.y*ilength; + result.z = q.z*ilength; + result.w = q.w*ilength; + + return result; +} + +// Get a quaternion for a given rotation matrix +RMAPI Quaternion QuaternionFromMatrix(Matrix mat) +{ + Quaternion result = { 0 }; + + float fourWSquaredMinus1 = mat.m0 + mat.m5 + mat.m10; + float fourXSquaredMinus1 = mat.m0 - mat.m5 - mat.m10; + float fourYSquaredMinus1 = mat.m5 - mat.m0 - mat.m10; + float fourZSquaredMinus1 = mat.m10 - mat.m0 - mat.m5; + + int biggestIndex = 0; + float fourBiggestSquaredMinus1 = fourWSquaredMinus1; + if (fourXSquaredMinus1 > fourBiggestSquaredMinus1) + { + fourBiggestSquaredMinus1 = fourXSquaredMinus1; + biggestIndex = 1; + } + + if (fourYSquaredMinus1 > fourBiggestSquaredMinus1) + { + fourBiggestSquaredMinus1 = fourYSquaredMinus1; + biggestIndex = 2; + } + + if (fourZSquaredMinus1 > fourBiggestSquaredMinus1) + { + fourBiggestSquaredMinus1 = fourZSquaredMinus1; + biggestIndex = 3; + } + + float biggestVal = sqrtf(fourBiggestSquaredMinus1 + 1.0f)*0.5f; + float mult = 0.25f/biggestVal; + + switch (biggestIndex) + { + case 0: + result.w = biggestVal; + result.x = (mat.m6 - mat.m9)*mult; + result.y = (mat.m8 - mat.m2)*mult; + result.z = (mat.m1 - mat.m4)*mult; + break; + case 1: + result.x = biggestVal; + result.w = (mat.m6 - mat.m9)*mult; + result.y = (mat.m1 + mat.m4)*mult; + result.z = (mat.m8 + mat.m2)*mult; + break; + case 2: + result.y = biggestVal; + result.w = (mat.m8 - mat.m2)*mult; + result.x = (mat.m1 + mat.m4)*mult; + result.z = (mat.m6 + mat.m9)*mult; + break; + case 3: + result.z = biggestVal; + result.w = (mat.m1 - mat.m4)*mult; + result.x = (mat.m8 + mat.m2)*mult; + result.y = (mat.m6 + mat.m9)*mult; + break; + } + + return result; +} + +// Get a matrix for a given quaternion +RMAPI Matrix QuaternionToMatrix(Quaternion q) +{ + Matrix result = { 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f }; // MatrixIdentity() + + float a2 = q.x*q.x; + float b2 = q.y*q.y; + float c2 = q.z*q.z; + float ac = q.x*q.z; + float ab = q.x*q.y; + float bc = q.y*q.z; + float ad = q.w*q.x; + float bd = q.w*q.y; + float cd = q.w*q.z; + + result.m0 = 1 - 2*(b2 + c2); + result.m1 = 2*(ab + cd); + result.m2 = 2*(ac - bd); + + result.m4 = 2*(ab - cd); + result.m5 = 1 - 2*(a2 + c2); + result.m6 = 2*(bc + ad); + + result.m8 = 2*(ac + bd); + result.m9 = 2*(bc - ad); + result.m10 = 1 - 2*(a2 + b2); + + return result; +} + +// Get rotation quaternion for an angle and axis +// NOTE: Angle must be provided in radians +RMAPI Quaternion QuaternionFromAxisAngle(Vector3 axis, float angle) +{ + Quaternion result = { 0.0f, 0.0f, 0.0f, 1.0f }; + + float axisLength = sqrtf(axis.x*axis.x + axis.y*axis.y + axis.z*axis.z); + + if (axisLength != 0.0f) + { + angle *= 0.5f; + + float length = 0.0f; + float ilength = 0.0f; + + // Vector3Normalize(axis) + length = axisLength; + if (length == 0.0f) length = 1.0f; + ilength = 1.0f/length; + axis.x *= ilength; + axis.y *= ilength; + axis.z *= ilength; + + float sinres = sinf(angle); + float cosres = cosf(angle); + + result.x = axis.x*sinres; + result.y = axis.y*sinres; + result.z = axis.z*sinres; + result.w = cosres; + + // QuaternionNormalize(q); + Quaternion q = result; + length = sqrtf(q.x*q.x + q.y*q.y + q.z*q.z + q.w*q.w); + if (length == 0.0f) length = 1.0f; + ilength = 1.0f/length; + result.x = q.x*ilength; + result.y = q.y*ilength; + result.z = q.z*ilength; + result.w = q.w*ilength; + } + + return result; +} + +// Get the rotation angle and axis for a given quaternion +RMAPI void QuaternionToAxisAngle(Quaternion q, Vector3 *outAxis, float *outAngle) +{ + if (fabsf(q.w) > 1.0f) + { + // QuaternionNormalize(q); + float length = sqrtf(q.x*q.x + q.y*q.y + q.z*q.z + q.w*q.w); + if (length == 0.0f) length = 1.0f; + float ilength = 1.0f/length; + + q.x = q.x*ilength; + q.y = q.y*ilength; + q.z = q.z*ilength; + q.w = q.w*ilength; + } + + Vector3 resAxis = { 0.0f, 0.0f, 0.0f }; + float resAngle = 2.0f*acosf(q.w); + float den = sqrtf(1.0f - q.w*q.w); + + if (den > EPSILON) + { + resAxis.x = q.x/den; + resAxis.y = q.y/den; + resAxis.z = q.z/den; + } + else + { + // This occurs when the angle is zero. + // Not a problem: just set an arbitrary normalized axis. + resAxis.x = 1.0f; + } + + *outAxis = resAxis; + *outAngle = resAngle; +} + +// Get the quaternion equivalent to Euler angles +// NOTE: Rotation order is ZYX +RMAPI Quaternion QuaternionFromEuler(float pitch, float yaw, float roll) +{ + Quaternion result = { 0 }; + + float x0 = cosf(pitch*0.5f); + float x1 = sinf(pitch*0.5f); + float y0 = cosf(yaw*0.5f); + float y1 = sinf(yaw*0.5f); + float z0 = cosf(roll*0.5f); + float z1 = sinf(roll*0.5f); + + result.x = x1*y0*z0 - x0*y1*z1; + result.y = x0*y1*z0 + x1*y0*z1; + result.z = x0*y0*z1 - x1*y1*z0; + result.w = x0*y0*z0 + x1*y1*z1; + + return result; +} + +// Get the Euler angles equivalent to quaternion (roll, pitch, yaw) +// NOTE: Angles are returned in a Vector3 struct in radians +RMAPI Vector3 QuaternionToEuler(Quaternion q) +{ + Vector3 result = { 0 }; + + // Roll (x-axis rotation) + float x0 = 2.0f*(q.w*q.x + q.y*q.z); + float x1 = 1.0f - 2.0f*(q.x*q.x + q.y*q.y); + result.x = atan2f(x0, x1); + + // Pitch (y-axis rotation) + float y0 = 2.0f*(q.w*q.y - q.z*q.x); + y0 = y0 > 1.0f ? 1.0f : y0; + y0 = y0 < -1.0f ? -1.0f : y0; + result.y = asinf(y0); + + // Yaw (z-axis rotation) + float z0 = 2.0f*(q.w*q.z + q.x*q.y); + float z1 = 1.0f - 2.0f*(q.y*q.y + q.z*q.z); + result.z = atan2f(z0, z1); + + return result; +} + +// Transform a quaternion given a transformation matrix +RMAPI Quaternion QuaternionTransform(Quaternion q, Matrix mat) +{ + Quaternion result = { 0 }; + + result.x = mat.m0*q.x + mat.m4*q.y + mat.m8*q.z + mat.m12*q.w; + result.y = mat.m1*q.x + mat.m5*q.y + mat.m9*q.z + mat.m13*q.w; + result.z = mat.m2*q.x + mat.m6*q.y + mat.m10*q.z + mat.m14*q.w; + result.w = mat.m3*q.x + mat.m7*q.y + mat.m11*q.z + mat.m15*q.w; + + return result; +} + +// Check whether two given quaternions are almost equal +RMAPI int QuaternionEquals(Quaternion p, Quaternion q) +{ +#if !defined(EPSILON) + #define EPSILON 0.000001f +#endif + + int result = (((fabsf(p.x - q.x)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.x), fabsf(q.x))))) && + ((fabsf(p.y - q.y)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.y), fabsf(q.y))))) && + ((fabsf(p.z - q.z)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.z), fabsf(q.z))))) && + ((fabsf(p.w - q.w)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.w), fabsf(q.w)))))) || + (((fabsf(p.x + q.x)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.x), fabsf(q.x))))) && + ((fabsf(p.y + q.y)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.y), fabsf(q.y))))) && + ((fabsf(p.z + q.z)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.z), fabsf(q.z))))) && + ((fabsf(p.w + q.w)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.w), fabsf(q.w)))))); + + return result; +} + +// Decompose a transformation matrix into its rotational, translational and scaling components +RMAPI void MatrixDecompose(Matrix mat, Vector3 *translation, Quaternion *rotation, Vector3 *scale) +{ + // Extract translation. + translation->x = mat.m12; + translation->y = mat.m13; + translation->z = mat.m14; + + // Extract upper-left for determinant computation + const float a = mat.m0; + const float b = mat.m4; + const float c = mat.m8; + const float d = mat.m1; + const float e = mat.m5; + const float f = mat.m9; + const float g = mat.m2; + const float h = mat.m6; + const float i = mat.m10; + const float A = e*i - f*h; + const float B = f*g - d*i; + const float C = d*h - e*g; + + // Extract scale + const float det = a*A + b*B + c*C; + Vector3 abc = { a, b, c }; + Vector3 def = { d, e, f }; + Vector3 ghi = { g, h, i }; + + float scalex = Vector3Length(abc); + float scaley = Vector3Length(def); + float scalez = Vector3Length(ghi); + Vector3 s = { scalex, scaley, scalez }; + + if (det < 0) s = Vector3Negate(s); + + *scale = s; + + // Remove scale from the matrix if it is not close to zero + Matrix clone = mat; + if (!FloatEquals(det, 0)) + { + clone.m0 /= s.x; + clone.m4 /= s.x; + clone.m8 /= s.x; + clone.m1 /= s.y; + clone.m5 /= s.y; + clone.m9 /= s.y; + clone.m2 /= s.z; + clone.m6 /= s.z; + clone.m10 /= s.z; + + // Extract rotation + *rotation = QuaternionFromMatrix(clone); + } + else + { + // Set to identity if close to zero + *rotation = QuaternionIdentity(); + } +} + +#if defined(__cplusplus) && !defined(RAYMATH_DISABLE_CPP_OPERATORS) + +// Optional C++ math operators +//------------------------------------------------------------------------------- + +// Vector2 operators +static constexpr Vector2 Vector2Zeros = { 0, 0 }; +static constexpr Vector2 Vector2Ones = { 1, 1 }; +static constexpr Vector2 Vector2UnitX = { 1, 0 }; +static constexpr Vector2 Vector2UnitY = { 0, 1 }; + +inline Vector2 operator + (const Vector2& lhs, const Vector2& rhs) +{ + return Vector2Add(lhs, rhs); +} + +inline const Vector2& operator += (Vector2& lhs, const Vector2& rhs) +{ + lhs = Vector2Add(lhs, rhs); + return lhs; +} + +inline Vector2 operator - (const Vector2& lhs, const Vector2& rhs) +{ + return Vector2Subtract(lhs, rhs); +} + +inline const Vector2& operator -= (Vector2& lhs, const Vector2& rhs) +{ + lhs = Vector2Subtract(lhs, rhs); + return lhs; +} + +inline Vector2 operator * (const Vector2& lhs, const float& rhs) +{ + return Vector2Scale(lhs, rhs); +} + +inline const Vector2& operator *= (Vector2& lhs, const float& rhs) +{ + lhs = Vector2Scale(lhs, rhs); + return lhs; +} + +inline Vector2 operator * (const Vector2& lhs, const Vector2& rhs) +{ + return Vector2Multiply(lhs, rhs); +} + +inline const Vector2& operator *= (Vector2& lhs, const Vector2& rhs) +{ + lhs = Vector2Multiply(lhs, rhs); + return lhs; +} + +inline Vector2 operator * (const Vector2& lhs, const Matrix& rhs) +{ + return Vector2Transform(lhs, rhs); +} + +inline const Vector2& operator -= (Vector2& lhs, const Matrix& rhs) +{ + lhs = Vector2Transform(lhs, rhs); + return lhs; +} + +inline Vector2 operator / (const Vector2& lhs, const float& rhs) +{ + return Vector2Scale(lhs, 1.0f / rhs); +} + +inline const Vector2& operator /= (Vector2& lhs, const float& rhs) +{ + lhs = Vector2Scale(lhs, rhs); + return lhs; +} + +inline Vector2 operator / (const Vector2& lhs, const Vector2& rhs) +{ + return Vector2Divide(lhs, rhs); +} + +inline const Vector2& operator /= (Vector2& lhs, const Vector2& rhs) +{ + lhs = Vector2Divide(lhs, rhs); + return lhs; +} + +inline bool operator == (const Vector2& lhs, const Vector2& rhs) +{ + return FloatEquals(lhs.x, rhs.x) && FloatEquals(lhs.y, rhs.y); +} + +inline bool operator != (const Vector2& lhs, const Vector2& rhs) +{ + return !FloatEquals(lhs.x, rhs.x) || !FloatEquals(lhs.y, rhs.y); +} + +// Vector3 operators +static constexpr Vector3 Vector3Zeros = { 0, 0, 0 }; +static constexpr Vector3 Vector3Ones = { 1, 1, 1 }; +static constexpr Vector3 Vector3UnitX = { 1, 0, 0 }; +static constexpr Vector3 Vector3UnitY = { 0, 1, 0 }; +static constexpr Vector3 Vector3UnitZ = { 0, 0, 1 }; + +inline Vector3 operator + (const Vector3& lhs, const Vector3& rhs) +{ + return Vector3Add(lhs, rhs); +} + +inline const Vector3& operator += (Vector3& lhs, const Vector3& rhs) +{ + lhs = Vector3Add(lhs, rhs); + return lhs; +} + +inline Vector3 operator - (const Vector3& lhs, const Vector3& rhs) +{ + return Vector3Subtract(lhs, rhs); +} + +inline const Vector3& operator -= (Vector3& lhs, const Vector3& rhs) +{ + lhs = Vector3Subtract(lhs, rhs); + return lhs; +} + +inline Vector3 operator * (const Vector3& lhs, const float& rhs) +{ + return Vector3Scale(lhs, rhs); +} + +inline const Vector3& operator *= (Vector3& lhs, const float& rhs) +{ + lhs = Vector3Scale(lhs, rhs); + return lhs; +} + +inline Vector3 operator * (const Vector3& lhs, const Vector3& rhs) +{ + return Vector3Multiply(lhs, rhs); +} + +inline const Vector3& operator *= (Vector3& lhs, const Vector3& rhs) +{ + lhs = Vector3Multiply(lhs, rhs); + return lhs; +} + +inline Vector3 operator * (const Vector3& lhs, const Matrix& rhs) +{ + return Vector3Transform(lhs, rhs); +} + +inline const Vector3& operator -= (Vector3& lhs, const Matrix& rhs) +{ + lhs = Vector3Transform(lhs, rhs); + return lhs; +} + +inline Vector3 operator / (const Vector3& lhs, const float& rhs) +{ + return Vector3Scale(lhs, 1.0f / rhs); +} + +inline const Vector3& operator /= (Vector3& lhs, const float& rhs) +{ + lhs = Vector3Scale(lhs, rhs); + return lhs; +} + +inline Vector3 operator / (const Vector3& lhs, const Vector3& rhs) +{ + return Vector3Divide(lhs, rhs); +} + +inline const Vector3& operator /= (Vector3& lhs, const Vector3& rhs) +{ + lhs = Vector3Divide(lhs, rhs); + return lhs; +} + +inline bool operator == (const Vector3& lhs, const Vector3& rhs) +{ + return FloatEquals(lhs.x, rhs.x) && FloatEquals(lhs.y, rhs.y) && FloatEquals(lhs.z, rhs.z); +} + +inline bool operator != (const Vector3& lhs, const Vector3& rhs) +{ + return !FloatEquals(lhs.x, rhs.x) || !FloatEquals(lhs.y, rhs.y) || !FloatEquals(lhs.z, rhs.z); +} + +// Vector4 operators +static constexpr Vector4 Vector4Zeros = { 0, 0, 0, 0 }; +static constexpr Vector4 Vector4Ones = { 1, 1, 1, 1 }; +static constexpr Vector4 Vector4UnitX = { 1, 0, 0, 0 }; +static constexpr Vector4 Vector4UnitY = { 0, 1, 0, 0 }; +static constexpr Vector4 Vector4UnitZ = { 0, 0, 1, 0 }; +static constexpr Vector4 Vector4UnitW = { 0, 0, 0, 1 }; + +inline Vector4 operator + (const Vector4& lhs, const Vector4& rhs) +{ + return Vector4Add(lhs, rhs); +} + +inline const Vector4& operator += (Vector4& lhs, const Vector4& rhs) +{ + lhs = Vector4Add(lhs, rhs); + return lhs; +} + +inline Vector4 operator - (const Vector4& lhs, const Vector4& rhs) +{ + return Vector4Subtract(lhs, rhs); +} + +inline const Vector4& operator -= (Vector4& lhs, const Vector4& rhs) +{ + lhs = Vector4Subtract(lhs, rhs); + return lhs; +} + +inline Vector4 operator * (const Vector4& lhs, const float& rhs) +{ + return Vector4Scale(lhs, rhs); +} + +inline const Vector4& operator *= (Vector4& lhs, const float& rhs) +{ + lhs = Vector4Scale(lhs, rhs); + return lhs; +} + +inline Vector4 operator * (const Vector4& lhs, const Vector4& rhs) +{ + return Vector4Multiply(lhs, rhs); +} + +inline const Vector4& operator *= (Vector4& lhs, const Vector4& rhs) +{ + lhs = Vector4Multiply(lhs, rhs); + return lhs; +} + +inline Vector4 operator / (const Vector4& lhs, const float& rhs) +{ + return Vector4Scale(lhs, 1.0f / rhs); +} + +inline const Vector4& operator /= (Vector4& lhs, const float& rhs) +{ + lhs = Vector4Scale(lhs, rhs); + return lhs; +} + +inline Vector4 operator / (const Vector4& lhs, const Vector4& rhs) +{ + return Vector4Divide(lhs, rhs); +} + +inline const Vector4& operator /= (Vector4& lhs, const Vector4& rhs) +{ + lhs = Vector4Divide(lhs, rhs); + return lhs; +} + +inline bool operator == (const Vector4& lhs, const Vector4& rhs) +{ + return FloatEquals(lhs.x, rhs.x) && FloatEquals(lhs.y, rhs.y) && FloatEquals(lhs.z, rhs.z) && FloatEquals(lhs.w, rhs.w); +} + +inline bool operator != (const Vector4& lhs, const Vector4& rhs) +{ + return !FloatEquals(lhs.x, rhs.x) || !FloatEquals(lhs.y, rhs.y) || !FloatEquals(lhs.z, rhs.z) || !FloatEquals(lhs.w, rhs.w); +} + +// Quaternion operators +static constexpr Quaternion QuaternionZeros = { 0, 0, 0, 0 }; +static constexpr Quaternion QuaternionOnes = { 1, 1, 1, 1 }; +static constexpr Quaternion QuaternionUnitX = { 0, 0, 0, 1 }; + +inline Quaternion operator + (const Quaternion& lhs, const float& rhs) +{ + return QuaternionAddValue(lhs, rhs); +} + +inline const Quaternion& operator += (Quaternion& lhs, const float& rhs) +{ + lhs = QuaternionAddValue(lhs, rhs); + return lhs; +} + +inline Quaternion operator - (const Quaternion& lhs, const float& rhs) +{ + return QuaternionSubtractValue(lhs, rhs); +} + +inline const Quaternion& operator -= (Quaternion& lhs, const float& rhs) +{ + lhs = QuaternionSubtractValue(lhs, rhs); + return lhs; +} + +inline Quaternion operator * (const Quaternion& lhs, const Matrix& rhs) +{ + return QuaternionTransform(lhs, rhs); +} + +inline const Quaternion& operator *= (Quaternion& lhs, const Matrix& rhs) +{ + lhs = QuaternionTransform(lhs, rhs); + return lhs; +} + +// Matrix operators +inline Matrix operator + (const Matrix& lhs, const Matrix& rhs) +{ + return MatrixAdd(lhs, rhs); +} + +inline const Matrix& operator += (Matrix& lhs, const Matrix& rhs) +{ + lhs = MatrixAdd(lhs, rhs); + return lhs; +} + +inline Matrix operator - (const Matrix& lhs, const Matrix& rhs) +{ + return MatrixSubtract(lhs, rhs); +} + +inline const Matrix& operator -= (Matrix& lhs, const Matrix& rhs) +{ + lhs = MatrixSubtract(lhs, rhs); + return lhs; +} + +inline Matrix operator * (const Matrix& lhs, const Matrix& rhs) +{ + return MatrixMultiply(lhs, rhs); +} + +inline const Matrix& operator *= (Matrix& lhs, const Matrix& rhs) +{ + lhs = MatrixMultiply(lhs, rhs); + return lhs; +} +//------------------------------------------------------------------------------- +#endif // C++ operators + +#endif // RAYMATH_H diff --git a/Start_Windows/raylib/rlgl.h b/Start_Windows/raylib/rlgl.h new file mode 100644 index 0000000..756656e --- /dev/null +++ b/Start_Windows/raylib/rlgl.h @@ -0,0 +1,5262 @@ +/********************************************************************************************** +* +* rlgl v5.0 - A multi-OpenGL abstraction layer with an immediate-mode style API +* +* DESCRIPTION: +* An abstraction layer for multiple OpenGL versions (1.1, 2.1, 3.3 Core, 4.3 Core, ES 2.0) +* that provides a pseudo-OpenGL 1.1 immediate-mode style API (rlVertex, rlTranslate, rlRotate...) +* +* ADDITIONAL NOTES: +* When choosing an OpenGL backend different than OpenGL 1.1, some internal buffer are +* initialized on rlglInit() to accumulate vertex data +* +* When an internal state change is required all the stored vertex data is renderer in batch, +* additionally, rlDrawRenderBatchActive() could be called to force flushing of the batch +* +* Some resources are also loaded for convenience, here the complete list: +* - Default batch (RLGL.defaultBatch): RenderBatch system to accumulate vertex data +* - Default texture (RLGL.defaultTextureId): 1x1 white pixel R8G8B8A8 +* - Default shader (RLGL.State.defaultShaderId, RLGL.State.defaultShaderLocs) +* +* Internal buffer (and resources) must be manually unloaded calling rlglClose() +* +* CONFIGURATION: +* #define GRAPHICS_API_OPENGL_11 +* #define GRAPHICS_API_OPENGL_21 +* #define GRAPHICS_API_OPENGL_33 +* #define GRAPHICS_API_OPENGL_43 +* #define GRAPHICS_API_OPENGL_ES2 +* #define GRAPHICS_API_OPENGL_ES3 +* Use selected OpenGL graphics backend, should be supported by platform +* Those preprocessor defines are only used on rlgl module, if OpenGL version is +* required by any other module, use rlGetVersion() to check it +* +* #define RLGL_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 RLGL_RENDER_TEXTURES_HINT +* Enable framebuffer objects (fbo) support (enabled by default) +* Some GPUs could not support them despite the OpenGL version +* +* #define RLGL_SHOW_GL_DETAILS_INFO +* Show OpenGL extensions and capabilities detailed logs on init +* +* #define RLGL_ENABLE_OPENGL_DEBUG_CONTEXT +* Enable debug context (only available on OpenGL 4.3) +* +* rlgl capabilities could be customized just defining some internal +* values before library inclusion (default values listed): +* +* #define RL_DEFAULT_BATCH_BUFFER_ELEMENTS 8192 // Default internal render batch elements limits +* #define RL_DEFAULT_BATCH_BUFFERS 1 // Default number of batch buffers (multi-buffering) +* #define RL_DEFAULT_BATCH_DRAWCALLS 256 // Default number of batch draw calls (by state changes: mode, texture) +* #define RL_DEFAULT_BATCH_MAX_TEXTURE_UNITS 4 // Maximum number of textures units that can be activated on batch drawing (SetShaderValueTexture()) +* +* #define RL_MAX_MATRIX_STACK_SIZE 32 // Maximum size of internal Matrix stack +* #define RL_MAX_SHADER_LOCATIONS 32 // Maximum number of shader locations supported +* #define RL_CULL_DISTANCE_NEAR 0.01 // Default projection matrix near cull distance +* #define RL_CULL_DISTANCE_FAR 1000.0 // Default projection matrix far cull distance +* +* When loading a shader, the following vertex attributes and uniform +* location names are tried to be set automatically: +* +* #define RL_DEFAULT_SHADER_ATTRIB_NAME_POSITION "vertexPosition" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION +* #define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD "vertexTexCoord" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD +* #define RL_DEFAULT_SHADER_ATTRIB_NAME_NORMAL "vertexNormal" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL +* #define RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR "vertexColor" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR +* #define RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT "vertexTangent" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT +* #define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2 "vertexTexCoord2" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2 +* #define RL_DEFAULT_SHADER_ATTRIB_NAME_BONEIDS "vertexBoneIds" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS +* #define RL_DEFAULT_SHADER_ATTRIB_NAME_BONEWEIGHTS "vertexBoneWeights" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS +* #define RL_DEFAULT_SHADER_UNIFORM_NAME_MVP "mvp" // model-view-projection matrix +* #define RL_DEFAULT_SHADER_UNIFORM_NAME_VIEW "matView" // view matrix +* #define RL_DEFAULT_SHADER_UNIFORM_NAME_PROJECTION "matProjection" // projection matrix +* #define RL_DEFAULT_SHADER_UNIFORM_NAME_MODEL "matModel" // model matrix +* #define RL_DEFAULT_SHADER_UNIFORM_NAME_NORMAL "matNormal" // normal matrix (transpose(inverse(matModelView))) +* #define RL_DEFAULT_SHADER_UNIFORM_NAME_COLOR "colDiffuse" // color diffuse (base tint color, multiplied by texture color) +* #define RL_DEFAULT_SHADER_UNIFORM_NAME_BONE_MATRICES "boneMatrices" // bone matrices +* #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE0 "texture0" // texture0 (texture slot active 0) +* #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE1 "texture1" // texture1 (texture slot active 1) +* #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE2 "texture2" // texture2 (texture slot active 2) +* +* DEPENDENCIES: +* - OpenGL libraries (depending on platform and OpenGL version selected) +* - GLAD OpenGL extensions loading library (only for OpenGL 3.3 Core, 4.3 Core) +* +* +* LICENSE: zlib/libpng +* +* Copyright (c) 2014-2024 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 RLGL_H +#define RLGL_H + +#define RLGL_VERSION "5.0" + +// Function specifiers in case library is build/used as a shared library +// NOTE: Microsoft specifiers to tell compiler that symbols are imported/exported from a .dll +// NOTE: visibility(default) attribute makes symbols "visible" when compiled with -fvisibility=hidden +#if defined(_WIN32) && defined(BUILD_LIBTYPE_SHARED) + #define RLAPI __declspec(dllexport) // We are building the library as a Win32 shared library (.dll) +#elif defined(BUILD_LIBTYPE_SHARED) + #define RLAPI __attribute__((visibility("default"))) // We are building the library as a Unix shared library (.so/.dylib) +#elif defined(_WIN32) && defined(USE_LIBTYPE_SHARED) + #define RLAPI __declspec(dllimport) // We are using the library as a Win32 shared library (.dll) +#endif + +// Function specifiers definition +#ifndef RLAPI + #define RLAPI // Functions defined as 'extern' by default (implicit specifiers) +#endif + +// Support TRACELOG macros +#ifndef TRACELOG + #define TRACELOG(level, ...) (void)0 + #define TRACELOGD(...) (void)0 +#endif + +// Allow custom memory allocators +#ifndef RL_MALLOC + #define RL_MALLOC(sz) malloc(sz) +#endif +#ifndef RL_CALLOC + #define RL_CALLOC(n,sz) calloc(n,sz) +#endif +#ifndef RL_REALLOC + #define RL_REALLOC(n,sz) realloc(n,sz) +#endif +#ifndef RL_FREE + #define RL_FREE(p) free(p) +#endif + +// Security check in case no GRAPHICS_API_OPENGL_* defined +#if !defined(GRAPHICS_API_OPENGL_11) && \ + !defined(GRAPHICS_API_OPENGL_21) && \ + !defined(GRAPHICS_API_OPENGL_33) && \ + !defined(GRAPHICS_API_OPENGL_43) && \ + !defined(GRAPHICS_API_OPENGL_ES2) && \ + !defined(GRAPHICS_API_OPENGL_ES3) + #define GRAPHICS_API_OPENGL_33 +#endif + +// Security check in case multiple GRAPHICS_API_OPENGL_* defined +#if defined(GRAPHICS_API_OPENGL_11) + #if defined(GRAPHICS_API_OPENGL_21) + #undef GRAPHICS_API_OPENGL_21 + #endif + #if defined(GRAPHICS_API_OPENGL_33) + #undef GRAPHICS_API_OPENGL_33 + #endif + #if defined(GRAPHICS_API_OPENGL_43) + #undef GRAPHICS_API_OPENGL_43 + #endif + #if defined(GRAPHICS_API_OPENGL_ES2) + #undef GRAPHICS_API_OPENGL_ES2 + #endif +#endif + +// OpenGL 2.1 uses most of OpenGL 3.3 Core functionality +// WARNING: Specific parts are checked with #if defines +#if defined(GRAPHICS_API_OPENGL_21) + #define GRAPHICS_API_OPENGL_33 +#endif + +// OpenGL 4.3 uses OpenGL 3.3 Core functionality +#if defined(GRAPHICS_API_OPENGL_43) + #define GRAPHICS_API_OPENGL_33 +#endif + +// OpenGL ES 3.0 uses OpenGL ES 2.0 functionality (and more) +#if defined(GRAPHICS_API_OPENGL_ES3) + #define GRAPHICS_API_OPENGL_ES2 +#endif + +// Support framebuffer objects by default +// NOTE: Some driver implementation do not support it, despite they should +#define RLGL_RENDER_TEXTURES_HINT + +//---------------------------------------------------------------------------------- +// Defines and Macros +//---------------------------------------------------------------------------------- + +// Default internal render batch elements limits +#ifndef RL_DEFAULT_BATCH_BUFFER_ELEMENTS + #if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33) + // This is the maximum amount of elements (quads) per batch + // NOTE: Be careful with text, every letter maps to a quad + #define RL_DEFAULT_BATCH_BUFFER_ELEMENTS 8192 + #endif + #if defined(GRAPHICS_API_OPENGL_ES2) + // We reduce memory sizes for embedded systems (RPI and HTML5) + // NOTE: On HTML5 (emscripten) this is allocated on heap, + // by default it's only 16MB!...just take care... + #define RL_DEFAULT_BATCH_BUFFER_ELEMENTS 2048 + #endif +#endif +#ifndef RL_DEFAULT_BATCH_BUFFERS + #define RL_DEFAULT_BATCH_BUFFERS 1 // Default number of batch buffers (multi-buffering) +#endif +#ifndef RL_DEFAULT_BATCH_DRAWCALLS + #define RL_DEFAULT_BATCH_DRAWCALLS 256 // Default number of batch draw calls (by state changes: mode, texture) +#endif +#ifndef RL_DEFAULT_BATCH_MAX_TEXTURE_UNITS + #define RL_DEFAULT_BATCH_MAX_TEXTURE_UNITS 4 // Maximum number of textures units that can be activated on batch drawing (SetShaderValueTexture()) +#endif + +// Internal Matrix stack +#ifndef RL_MAX_MATRIX_STACK_SIZE + #define RL_MAX_MATRIX_STACK_SIZE 32 // Maximum size of Matrix stack +#endif + +// Shader limits +#ifndef RL_MAX_SHADER_LOCATIONS + #define RL_MAX_SHADER_LOCATIONS 32 // Maximum number of shader locations supported +#endif + +// Projection matrix culling +#ifndef RL_CULL_DISTANCE_NEAR + #define RL_CULL_DISTANCE_NEAR 0.01 // Default near cull distance +#endif +#ifndef RL_CULL_DISTANCE_FAR + #define RL_CULL_DISTANCE_FAR 1000.0 // Default far cull distance +#endif + +// Texture parameters (equivalent to OpenGL defines) +#define RL_TEXTURE_WRAP_S 0x2802 // GL_TEXTURE_WRAP_S +#define RL_TEXTURE_WRAP_T 0x2803 // GL_TEXTURE_WRAP_T +#define RL_TEXTURE_MAG_FILTER 0x2800 // GL_TEXTURE_MAG_FILTER +#define RL_TEXTURE_MIN_FILTER 0x2801 // GL_TEXTURE_MIN_FILTER + +#define RL_TEXTURE_FILTER_NEAREST 0x2600 // GL_NEAREST +#define RL_TEXTURE_FILTER_LINEAR 0x2601 // GL_LINEAR +#define RL_TEXTURE_FILTER_MIP_NEAREST 0x2700 // GL_NEAREST_MIPMAP_NEAREST +#define RL_TEXTURE_FILTER_NEAREST_MIP_LINEAR 0x2702 // GL_NEAREST_MIPMAP_LINEAR +#define RL_TEXTURE_FILTER_LINEAR_MIP_NEAREST 0x2701 // GL_LINEAR_MIPMAP_NEAREST +#define RL_TEXTURE_FILTER_MIP_LINEAR 0x2703 // GL_LINEAR_MIPMAP_LINEAR +#define RL_TEXTURE_FILTER_ANISOTROPIC 0x3000 // Anisotropic filter (custom identifier) +#define RL_TEXTURE_MIPMAP_BIAS_RATIO 0x4000 // Texture mipmap bias, percentage ratio (custom identifier) + +#define RL_TEXTURE_WRAP_REPEAT 0x2901 // GL_REPEAT +#define RL_TEXTURE_WRAP_CLAMP 0x812F // GL_CLAMP_TO_EDGE +#define RL_TEXTURE_WRAP_MIRROR_REPEAT 0x8370 // GL_MIRRORED_REPEAT +#define RL_TEXTURE_WRAP_MIRROR_CLAMP 0x8742 // GL_MIRROR_CLAMP_EXT + +// Matrix modes (equivalent to OpenGL) +#define RL_MODELVIEW 0x1700 // GL_MODELVIEW +#define RL_PROJECTION 0x1701 // GL_PROJECTION +#define RL_TEXTURE 0x1702 // GL_TEXTURE + +// Primitive assembly draw modes +#define RL_LINES 0x0001 // GL_LINES +#define RL_TRIANGLES 0x0004 // GL_TRIANGLES +#define RL_QUADS 0x0007 // GL_QUADS + +// GL equivalent data types +#define RL_UNSIGNED_BYTE 0x1401 // GL_UNSIGNED_BYTE +#define RL_FLOAT 0x1406 // GL_FLOAT + +// GL buffer usage hint +#define RL_STREAM_DRAW 0x88E0 // GL_STREAM_DRAW +#define RL_STREAM_READ 0x88E1 // GL_STREAM_READ +#define RL_STREAM_COPY 0x88E2 // GL_STREAM_COPY +#define RL_STATIC_DRAW 0x88E4 // GL_STATIC_DRAW +#define RL_STATIC_READ 0x88E5 // GL_STATIC_READ +#define RL_STATIC_COPY 0x88E6 // GL_STATIC_COPY +#define RL_DYNAMIC_DRAW 0x88E8 // GL_DYNAMIC_DRAW +#define RL_DYNAMIC_READ 0x88E9 // GL_DYNAMIC_READ +#define RL_DYNAMIC_COPY 0x88EA // GL_DYNAMIC_COPY + +// GL Shader type +#define RL_FRAGMENT_SHADER 0x8B30 // GL_FRAGMENT_SHADER +#define RL_VERTEX_SHADER 0x8B31 // GL_VERTEX_SHADER +#define RL_COMPUTE_SHADER 0x91B9 // GL_COMPUTE_SHADER + +// GL blending factors +#define RL_ZERO 0 // GL_ZERO +#define RL_ONE 1 // GL_ONE +#define RL_SRC_COLOR 0x0300 // GL_SRC_COLOR +#define RL_ONE_MINUS_SRC_COLOR 0x0301 // GL_ONE_MINUS_SRC_COLOR +#define RL_SRC_ALPHA 0x0302 // GL_SRC_ALPHA +#define RL_ONE_MINUS_SRC_ALPHA 0x0303 // GL_ONE_MINUS_SRC_ALPHA +#define RL_DST_ALPHA 0x0304 // GL_DST_ALPHA +#define RL_ONE_MINUS_DST_ALPHA 0x0305 // GL_ONE_MINUS_DST_ALPHA +#define RL_DST_COLOR 0x0306 // GL_DST_COLOR +#define RL_ONE_MINUS_DST_COLOR 0x0307 // GL_ONE_MINUS_DST_COLOR +#define RL_SRC_ALPHA_SATURATE 0x0308 // GL_SRC_ALPHA_SATURATE +#define RL_CONSTANT_COLOR 0x8001 // GL_CONSTANT_COLOR +#define RL_ONE_MINUS_CONSTANT_COLOR 0x8002 // GL_ONE_MINUS_CONSTANT_COLOR +#define RL_CONSTANT_ALPHA 0x8003 // GL_CONSTANT_ALPHA +#define RL_ONE_MINUS_CONSTANT_ALPHA 0x8004 // GL_ONE_MINUS_CONSTANT_ALPHA + +// GL blending functions/equations +#define RL_FUNC_ADD 0x8006 // GL_FUNC_ADD +#define RL_MIN 0x8007 // GL_MIN +#define RL_MAX 0x8008 // GL_MAX +#define RL_FUNC_SUBTRACT 0x800A // GL_FUNC_SUBTRACT +#define RL_FUNC_REVERSE_SUBTRACT 0x800B // GL_FUNC_REVERSE_SUBTRACT +#define RL_BLEND_EQUATION 0x8009 // GL_BLEND_EQUATION +#define RL_BLEND_EQUATION_RGB 0x8009 // GL_BLEND_EQUATION_RGB // (Same as BLEND_EQUATION) +#define RL_BLEND_EQUATION_ALPHA 0x883D // GL_BLEND_EQUATION_ALPHA +#define RL_BLEND_DST_RGB 0x80C8 // GL_BLEND_DST_RGB +#define RL_BLEND_SRC_RGB 0x80C9 // GL_BLEND_SRC_RGB +#define RL_BLEND_DST_ALPHA 0x80CA // GL_BLEND_DST_ALPHA +#define RL_BLEND_SRC_ALPHA 0x80CB // GL_BLEND_SRC_ALPHA +#define RL_BLEND_COLOR 0x8005 // GL_BLEND_COLOR + +#define RL_READ_FRAMEBUFFER 0x8CA8 // GL_READ_FRAMEBUFFER +#define RL_DRAW_FRAMEBUFFER 0x8CA9 // GL_DRAW_FRAMEBUFFER + +// Default shader vertex attribute locations +#ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION + #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION 0 +#endif +#ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD + #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD 1 +#endif +#ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL + #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL 2 +#endif +#ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR + #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR 3 +#endif + #ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT +#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT 4 +#endif +#ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2 + #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2 5 +#endif +#ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES + #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES 6 +#endif +#ifdef RL_SUPPORT_MESH_GPU_SKINNING +#ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS + #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS 7 +#endif +#ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS + #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS 8 +#endif +#endif + +//---------------------------------------------------------------------------------- +// Types and Structures Definition +//---------------------------------------------------------------------------------- +#if (defined(__STDC__) && __STDC_VERSION__ >= 199901L) || (defined(_MSC_VER) && _MSC_VER >= 1800) + #include +#elif !defined(__cplusplus) && !defined(bool) && !defined(RL_BOOL_TYPE) + // Boolean type +typedef enum bool { false = 0, true = !false } bool; +#endif + +#if !defined(RL_MATRIX_TYPE) +// Matrix, 4x4 components, column major, OpenGL style, right handed +typedef struct Matrix { + float m0, m4, m8, m12; // Matrix first row (4 components) + float m1, m5, m9, m13; // Matrix second row (4 components) + float m2, m6, m10, m14; // Matrix third row (4 components) + float m3, m7, m11, m15; // Matrix fourth row (4 components) +} Matrix; +#define RL_MATRIX_TYPE +#endif + +// Dynamic vertex buffers (position + texcoords + colors + indices arrays) +typedef struct rlVertexBuffer { + int elementCount; // Number of elements in the buffer (QUADS) + + float *vertices; // Vertex position (XYZ - 3 components per vertex) (shader-location = 0) + float *texcoords; // Vertex texture coordinates (UV - 2 components per vertex) (shader-location = 1) + float *normals; // Vertex normal (XYZ - 3 components per vertex) (shader-location = 2) + unsigned char *colors; // Vertex colors (RGBA - 4 components per vertex) (shader-location = 3) +#if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33) + unsigned int *indices; // Vertex indices (in case vertex data comes indexed) (6 indices per quad) +#endif +#if defined(GRAPHICS_API_OPENGL_ES2) + unsigned short *indices; // Vertex indices (in case vertex data comes indexed) (6 indices per quad) +#endif + unsigned int vaoId; // OpenGL Vertex Array Object id + unsigned int vboId[5]; // OpenGL Vertex Buffer Objects id (5 types of vertex data) +} rlVertexBuffer; + +// Draw call type +// NOTE: Only texture changes register a new draw, other state-change-related elements are not +// used at this moment (vaoId, shaderId, matrices), raylib just forces a batch draw call if any +// of those state-change happens (this is done in core module) +typedef struct rlDrawCall { + int mode; // Drawing mode: LINES, TRIANGLES, QUADS + int vertexCount; // Number of vertex of the draw + int vertexAlignment; // Number of vertex required for index alignment (LINES, TRIANGLES) + //unsigned int vaoId; // Vertex array id to be used on the draw -> Using RLGL.currentBatch->vertexBuffer.vaoId + //unsigned int shaderId; // Shader id to be used on the draw -> Using RLGL.currentShaderId + unsigned int textureId; // Texture id to be used on the draw -> Use to create new draw call if changes + + //Matrix projection; // Projection matrix for this draw -> Using RLGL.projection by default + //Matrix modelview; // Modelview matrix for this draw -> Using RLGL.modelview by default +} rlDrawCall; + +// rlRenderBatch type +typedef struct rlRenderBatch { + int bufferCount; // Number of vertex buffers (multi-buffering support) + int currentBuffer; // Current buffer tracking in case of multi-buffering + rlVertexBuffer *vertexBuffer; // Dynamic buffer(s) for vertex data + + rlDrawCall *draws; // Draw calls array, depends on textureId + int drawCounter; // Draw calls counter + float currentDepth; // Current depth value for next draw +} rlRenderBatch; + +// OpenGL version +typedef enum { + RL_OPENGL_11 = 1, // OpenGL 1.1 + RL_OPENGL_21, // OpenGL 2.1 (GLSL 120) + RL_OPENGL_33, // OpenGL 3.3 (GLSL 330) + RL_OPENGL_43, // OpenGL 4.3 (using GLSL 330) + RL_OPENGL_ES_20, // OpenGL ES 2.0 (GLSL 100) + RL_OPENGL_ES_30 // OpenGL ES 3.0 (GLSL 300 es) +} rlGlVersion; + +// Trace log level +// NOTE: Organized by priority level +typedef enum { + RL_LOG_ALL = 0, // Display all logs + RL_LOG_TRACE, // Trace logging, intended for internal use only + RL_LOG_DEBUG, // Debug logging, used for internal debugging, it should be disabled on release builds + RL_LOG_INFO, // Info logging, used for program execution info + RL_LOG_WARNING, // Warning logging, used on recoverable failures + RL_LOG_ERROR, // Error logging, used on unrecoverable failures + RL_LOG_FATAL, // Fatal logging, used to abort program: exit(EXIT_FAILURE) + RL_LOG_NONE // Disable logging +} rlTraceLogLevel; + +// Texture pixel formats +// NOTE: Support depends on OpenGL version +typedef enum { + RL_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE = 1, // 8 bit per pixel (no alpha) + RL_PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA, // 8*2 bpp (2 channels) + RL_PIXELFORMAT_UNCOMPRESSED_R5G6B5, // 16 bpp + RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8, // 24 bpp + RL_PIXELFORMAT_UNCOMPRESSED_R5G5B5A1, // 16 bpp (1 bit alpha) + RL_PIXELFORMAT_UNCOMPRESSED_R4G4B4A4, // 16 bpp (4 bit alpha) + RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8, // 32 bpp + RL_PIXELFORMAT_UNCOMPRESSED_R32, // 32 bpp (1 channel - float) + RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32, // 32*3 bpp (3 channels - float) + RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32, // 32*4 bpp (4 channels - float) + RL_PIXELFORMAT_UNCOMPRESSED_R16, // 16 bpp (1 channel - half float) + RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16, // 16*3 bpp (3 channels - half float) + RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16, // 16*4 bpp (4 channels - half float) + RL_PIXELFORMAT_COMPRESSED_DXT1_RGB, // 4 bpp (no alpha) + RL_PIXELFORMAT_COMPRESSED_DXT1_RGBA, // 4 bpp (1 bit alpha) + RL_PIXELFORMAT_COMPRESSED_DXT3_RGBA, // 8 bpp + RL_PIXELFORMAT_COMPRESSED_DXT5_RGBA, // 8 bpp + RL_PIXELFORMAT_COMPRESSED_ETC1_RGB, // 4 bpp + RL_PIXELFORMAT_COMPRESSED_ETC2_RGB, // 4 bpp + RL_PIXELFORMAT_COMPRESSED_ETC2_EAC_RGBA, // 8 bpp + RL_PIXELFORMAT_COMPRESSED_PVRT_RGB, // 4 bpp + RL_PIXELFORMAT_COMPRESSED_PVRT_RGBA, // 4 bpp + RL_PIXELFORMAT_COMPRESSED_ASTC_4x4_RGBA, // 8 bpp + RL_PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA // 2 bpp +} rlPixelFormat; + +// Texture parameters: filter mode +// NOTE 1: Filtering considers mipmaps if available in the texture +// NOTE 2: Filter is accordingly set for minification and magnification +typedef enum { + RL_TEXTURE_FILTER_POINT = 0, // No filter, just pixel approximation + RL_TEXTURE_FILTER_BILINEAR, // Linear filtering + RL_TEXTURE_FILTER_TRILINEAR, // Trilinear filtering (linear with mipmaps) + RL_TEXTURE_FILTER_ANISOTROPIC_4X, // Anisotropic filtering 4x + RL_TEXTURE_FILTER_ANISOTROPIC_8X, // Anisotropic filtering 8x + RL_TEXTURE_FILTER_ANISOTROPIC_16X, // Anisotropic filtering 16x +} rlTextureFilter; + +// Color blending modes (pre-defined) +typedef enum { + RL_BLEND_ALPHA = 0, // Blend textures considering alpha (default) + RL_BLEND_ADDITIVE, // Blend textures adding colors + RL_BLEND_MULTIPLIED, // Blend textures multiplying colors + RL_BLEND_ADD_COLORS, // Blend textures adding colors (alternative) + RL_BLEND_SUBTRACT_COLORS, // Blend textures subtracting colors (alternative) + RL_BLEND_ALPHA_PREMULTIPLY, // Blend premultiplied textures considering alpha + RL_BLEND_CUSTOM, // Blend textures using custom src/dst factors (use rlSetBlendFactors()) + RL_BLEND_CUSTOM_SEPARATE // Blend textures using custom src/dst factors (use rlSetBlendFactorsSeparate()) +} rlBlendMode; + +// Shader location point type +typedef enum { + RL_SHADER_LOC_VERTEX_POSITION = 0, // Shader location: vertex attribute: position + RL_SHADER_LOC_VERTEX_TEXCOORD01, // Shader location: vertex attribute: texcoord01 + RL_SHADER_LOC_VERTEX_TEXCOORD02, // Shader location: vertex attribute: texcoord02 + RL_SHADER_LOC_VERTEX_NORMAL, // Shader location: vertex attribute: normal + RL_SHADER_LOC_VERTEX_TANGENT, // Shader location: vertex attribute: tangent + RL_SHADER_LOC_VERTEX_COLOR, // Shader location: vertex attribute: color + RL_SHADER_LOC_MATRIX_MVP, // Shader location: matrix uniform: model-view-projection + RL_SHADER_LOC_MATRIX_VIEW, // Shader location: matrix uniform: view (camera transform) + RL_SHADER_LOC_MATRIX_PROJECTION, // Shader location: matrix uniform: projection + RL_SHADER_LOC_MATRIX_MODEL, // Shader location: matrix uniform: model (transform) + RL_SHADER_LOC_MATRIX_NORMAL, // Shader location: matrix uniform: normal + RL_SHADER_LOC_VECTOR_VIEW, // Shader location: vector uniform: view + RL_SHADER_LOC_COLOR_DIFFUSE, // Shader location: vector uniform: diffuse color + RL_SHADER_LOC_COLOR_SPECULAR, // Shader location: vector uniform: specular color + RL_SHADER_LOC_COLOR_AMBIENT, // Shader location: vector uniform: ambient color + RL_SHADER_LOC_MAP_ALBEDO, // Shader location: sampler2d texture: albedo (same as: RL_SHADER_LOC_MAP_DIFFUSE) + RL_SHADER_LOC_MAP_METALNESS, // Shader location: sampler2d texture: metalness (same as: RL_SHADER_LOC_MAP_SPECULAR) + RL_SHADER_LOC_MAP_NORMAL, // Shader location: sampler2d texture: normal + RL_SHADER_LOC_MAP_ROUGHNESS, // Shader location: sampler2d texture: roughness + RL_SHADER_LOC_MAP_OCCLUSION, // Shader location: sampler2d texture: occlusion + RL_SHADER_LOC_MAP_EMISSION, // Shader location: sampler2d texture: emission + RL_SHADER_LOC_MAP_HEIGHT, // Shader location: sampler2d texture: height + RL_SHADER_LOC_MAP_CUBEMAP, // Shader location: samplerCube texture: cubemap + RL_SHADER_LOC_MAP_IRRADIANCE, // Shader location: samplerCube texture: irradiance + RL_SHADER_LOC_MAP_PREFILTER, // Shader location: samplerCube texture: prefilter + RL_SHADER_LOC_MAP_BRDF // Shader location: sampler2d texture: brdf +} rlShaderLocationIndex; + +#define RL_SHADER_LOC_MAP_DIFFUSE RL_SHADER_LOC_MAP_ALBEDO +#define RL_SHADER_LOC_MAP_SPECULAR RL_SHADER_LOC_MAP_METALNESS + +// Shader uniform data type +typedef enum { + RL_SHADER_UNIFORM_FLOAT = 0, // Shader uniform type: float + RL_SHADER_UNIFORM_VEC2, // Shader uniform type: vec2 (2 float) + RL_SHADER_UNIFORM_VEC3, // Shader uniform type: vec3 (3 float) + RL_SHADER_UNIFORM_VEC4, // Shader uniform type: vec4 (4 float) + RL_SHADER_UNIFORM_INT, // Shader uniform type: int + RL_SHADER_UNIFORM_IVEC2, // Shader uniform type: ivec2 (2 int) + RL_SHADER_UNIFORM_IVEC3, // Shader uniform type: ivec3 (3 int) + RL_SHADER_UNIFORM_IVEC4, // Shader uniform type: ivec4 (4 int) + RL_SHADER_UNIFORM_UINT, // Shader uniform type: unsigned int + RL_SHADER_UNIFORM_UIVEC2, // Shader uniform type: uivec2 (2 unsigned int) + RL_SHADER_UNIFORM_UIVEC3, // Shader uniform type: uivec3 (3 unsigned int) + RL_SHADER_UNIFORM_UIVEC4, // Shader uniform type: uivec4 (4 unsigned int) + RL_SHADER_UNIFORM_SAMPLER2D // Shader uniform type: sampler2d +} rlShaderUniformDataType; + +// Shader attribute data types +typedef enum { + RL_SHADER_ATTRIB_FLOAT = 0, // Shader attribute type: float + RL_SHADER_ATTRIB_VEC2, // Shader attribute type: vec2 (2 float) + RL_SHADER_ATTRIB_VEC3, // Shader attribute type: vec3 (3 float) + RL_SHADER_ATTRIB_VEC4 // Shader attribute type: vec4 (4 float) +} rlShaderAttributeDataType; + +// Framebuffer attachment type +// NOTE: By default up to 8 color channels defined, but it can be more +typedef enum { + RL_ATTACHMENT_COLOR_CHANNEL0 = 0, // Framebuffer attachment type: color 0 + RL_ATTACHMENT_COLOR_CHANNEL1 = 1, // Framebuffer attachment type: color 1 + RL_ATTACHMENT_COLOR_CHANNEL2 = 2, // Framebuffer attachment type: color 2 + RL_ATTACHMENT_COLOR_CHANNEL3 = 3, // Framebuffer attachment type: color 3 + RL_ATTACHMENT_COLOR_CHANNEL4 = 4, // Framebuffer attachment type: color 4 + RL_ATTACHMENT_COLOR_CHANNEL5 = 5, // Framebuffer attachment type: color 5 + RL_ATTACHMENT_COLOR_CHANNEL6 = 6, // Framebuffer attachment type: color 6 + RL_ATTACHMENT_COLOR_CHANNEL7 = 7, // Framebuffer attachment type: color 7 + RL_ATTACHMENT_DEPTH = 100, // Framebuffer attachment type: depth + RL_ATTACHMENT_STENCIL = 200, // Framebuffer attachment type: stencil +} rlFramebufferAttachType; + +// Framebuffer texture attachment type +typedef enum { + RL_ATTACHMENT_CUBEMAP_POSITIVE_X = 0, // Framebuffer texture attachment type: cubemap, +X side + RL_ATTACHMENT_CUBEMAP_NEGATIVE_X = 1, // Framebuffer texture attachment type: cubemap, -X side + RL_ATTACHMENT_CUBEMAP_POSITIVE_Y = 2, // Framebuffer texture attachment type: cubemap, +Y side + RL_ATTACHMENT_CUBEMAP_NEGATIVE_Y = 3, // Framebuffer texture attachment type: cubemap, -Y side + RL_ATTACHMENT_CUBEMAP_POSITIVE_Z = 4, // Framebuffer texture attachment type: cubemap, +Z side + RL_ATTACHMENT_CUBEMAP_NEGATIVE_Z = 5, // Framebuffer texture attachment type: cubemap, -Z side + RL_ATTACHMENT_TEXTURE2D = 100, // Framebuffer texture attachment type: texture2d + RL_ATTACHMENT_RENDERBUFFER = 200, // Framebuffer texture attachment type: renderbuffer +} rlFramebufferAttachTextureType; + +// Face culling mode +typedef enum { + RL_CULL_FACE_FRONT = 0, + RL_CULL_FACE_BACK +} rlCullMode; + +//------------------------------------------------------------------------------------ +// Functions Declaration - Matrix operations +//------------------------------------------------------------------------------------ + +#if defined(__cplusplus) +extern "C" { // Prevents name mangling of functions +#endif + +RLAPI void rlMatrixMode(int mode); // Choose the current matrix to be transformed +RLAPI void rlPushMatrix(void); // Push the current matrix to stack +RLAPI void rlPopMatrix(void); // Pop latest inserted matrix from stack +RLAPI void rlLoadIdentity(void); // Reset current matrix to identity matrix +RLAPI void rlTranslatef(float x, float y, float z); // Multiply the current matrix by a translation matrix +RLAPI void rlRotatef(float angle, float x, float y, float z); // Multiply the current matrix by a rotation matrix +RLAPI void rlScalef(float x, float y, float z); // Multiply the current matrix by a scaling matrix +RLAPI void rlMultMatrixf(const float *matf); // Multiply the current matrix by another matrix +RLAPI void rlFrustum(double left, double right, double bottom, double top, double znear, double zfar); +RLAPI void rlOrtho(double left, double right, double bottom, double top, double znear, double zfar); +RLAPI void rlViewport(int x, int y, int width, int height); // Set the viewport area +RLAPI void rlSetClipPlanes(double nearPlane, double farPlane); // Set clip planes distances +RLAPI double rlGetCullDistanceNear(void); // Get cull plane distance near +RLAPI double rlGetCullDistanceFar(void); // Get cull plane distance far + +//------------------------------------------------------------------------------------ +// Functions Declaration - Vertex level operations +//------------------------------------------------------------------------------------ +RLAPI void rlBegin(int mode); // Initialize drawing mode (how to organize vertex) +RLAPI void rlEnd(void); // Finish vertex providing +RLAPI void rlVertex2i(int x, int y); // Define one vertex (position) - 2 int +RLAPI void rlVertex2f(float x, float y); // Define one vertex (position) - 2 float +RLAPI void rlVertex3f(float x, float y, float z); // Define one vertex (position) - 3 float +RLAPI void rlTexCoord2f(float x, float y); // Define one vertex (texture coordinate) - 2 float +RLAPI void rlNormal3f(float x, float y, float z); // Define one vertex (normal) - 3 float +RLAPI void rlColor4ub(unsigned char r, unsigned char g, unsigned char b, unsigned char a); // Define one vertex (color) - 4 byte +RLAPI void rlColor3f(float x, float y, float z); // Define one vertex (color) - 3 float +RLAPI void rlColor4f(float x, float y, float z, float w); // Define one vertex (color) - 4 float + +//------------------------------------------------------------------------------------ +// Functions Declaration - OpenGL style functions (common to 1.1, 3.3+, ES2) +// NOTE: This functions are used to completely abstract raylib code from OpenGL layer, +// some of them are direct wrappers over OpenGL calls, some others are custom +//------------------------------------------------------------------------------------ + +// Vertex buffers state +RLAPI bool rlEnableVertexArray(unsigned int vaoId); // Enable vertex array (VAO, if supported) +RLAPI void rlDisableVertexArray(void); // Disable vertex array (VAO, if supported) +RLAPI void rlEnableVertexBuffer(unsigned int id); // Enable vertex buffer (VBO) +RLAPI void rlDisableVertexBuffer(void); // Disable vertex buffer (VBO) +RLAPI void rlEnableVertexBufferElement(unsigned int id); // Enable vertex buffer element (VBO element) +RLAPI void rlDisableVertexBufferElement(void); // Disable vertex buffer element (VBO element) +RLAPI void rlEnableVertexAttribute(unsigned int index); // Enable vertex attribute index +RLAPI void rlDisableVertexAttribute(unsigned int index); // Disable vertex attribute index +#if defined(GRAPHICS_API_OPENGL_11) +RLAPI void rlEnableStatePointer(int vertexAttribType, void *buffer); // Enable attribute state pointer +RLAPI void rlDisableStatePointer(int vertexAttribType); // Disable attribute state pointer +#endif + +// Textures state +RLAPI void rlActiveTextureSlot(int slot); // Select and active a texture slot +RLAPI void rlEnableTexture(unsigned int id); // Enable texture +RLAPI void rlDisableTexture(void); // Disable texture +RLAPI void rlEnableTextureCubemap(unsigned int id); // Enable texture cubemap +RLAPI void rlDisableTextureCubemap(void); // Disable texture cubemap +RLAPI void rlTextureParameters(unsigned int id, int param, int value); // Set texture parameters (filter, wrap) +RLAPI void rlCubemapParameters(unsigned int id, int param, int value); // Set cubemap parameters (filter, wrap) + +// Shader state +RLAPI void rlEnableShader(unsigned int id); // Enable shader program +RLAPI void rlDisableShader(void); // Disable shader program + +// Framebuffer state +RLAPI void rlEnableFramebuffer(unsigned int id); // Enable render texture (fbo) +RLAPI void rlDisableFramebuffer(void); // Disable render texture (fbo), return to default framebuffer +RLAPI unsigned int rlGetActiveFramebuffer(void); // Get the currently active render texture (fbo), 0 for default framebuffer +RLAPI void rlActiveDrawBuffers(int count); // Activate multiple draw color buffers +RLAPI void rlBlitFramebuffer(int srcX, int srcY, int srcWidth, int srcHeight, int dstX, int dstY, int dstWidth, int dstHeight, int bufferMask); // Blit active framebuffer to main framebuffer +RLAPI void rlBindFramebuffer(unsigned int target, unsigned int framebuffer); // Bind framebuffer (FBO) + +// General render state +RLAPI void rlEnableColorBlend(void); // Enable color blending +RLAPI void rlDisableColorBlend(void); // Disable color blending +RLAPI void rlEnableDepthTest(void); // Enable depth test +RLAPI void rlDisableDepthTest(void); // Disable depth test +RLAPI void rlEnableDepthMask(void); // Enable depth write +RLAPI void rlDisableDepthMask(void); // Disable depth write +RLAPI void rlEnableBackfaceCulling(void); // Enable backface culling +RLAPI void rlDisableBackfaceCulling(void); // Disable backface culling +RLAPI void rlColorMask(bool r, bool g, bool b, bool a); // Color mask control +RLAPI void rlSetCullFace(int mode); // Set face culling mode +RLAPI void rlEnableScissorTest(void); // Enable scissor test +RLAPI void rlDisableScissorTest(void); // Disable scissor test +RLAPI void rlScissor(int x, int y, int width, int height); // Scissor test +RLAPI void rlEnableWireMode(void); // Enable wire mode +RLAPI void rlEnablePointMode(void); // Enable point mode +RLAPI void rlDisableWireMode(void); // Disable wire (and point) mode +RLAPI void rlSetLineWidth(float width); // Set the line drawing width +RLAPI float rlGetLineWidth(void); // Get the line drawing width +RLAPI void rlEnableSmoothLines(void); // Enable line aliasing +RLAPI void rlDisableSmoothLines(void); // Disable line aliasing +RLAPI void rlEnableStereoRender(void); // Enable stereo rendering +RLAPI void rlDisableStereoRender(void); // Disable stereo rendering +RLAPI bool rlIsStereoRenderEnabled(void); // Check if stereo render is enabled + +RLAPI void rlClearColor(unsigned char r, unsigned char g, unsigned char b, unsigned char a); // Clear color buffer with color +RLAPI void rlClearScreenBuffers(void); // Clear used screen buffers (color and depth) +RLAPI void rlCheckErrors(void); // Check and log OpenGL error codes +RLAPI void rlSetBlendMode(int mode); // Set blending mode +RLAPI void rlSetBlendFactors(int glSrcFactor, int glDstFactor, int glEquation); // Set blending mode factor and equation (using OpenGL factors) +RLAPI void rlSetBlendFactorsSeparate(int glSrcRGB, int glDstRGB, int glSrcAlpha, int glDstAlpha, int glEqRGB, int glEqAlpha); // Set blending mode factors and equations separately (using OpenGL factors) + +//------------------------------------------------------------------------------------ +// Functions Declaration - rlgl functionality +//------------------------------------------------------------------------------------ +// rlgl initialization functions +RLAPI void rlglInit(int width, int height); // Initialize rlgl (buffers, shaders, textures, states) +RLAPI void rlglClose(void); // De-initialize rlgl (buffers, shaders, textures) +RLAPI void rlLoadExtensions(void *loader); // Load OpenGL extensions (loader function required) +RLAPI int rlGetVersion(void); // Get current OpenGL version +RLAPI void rlSetFramebufferWidth(int width); // Set current framebuffer width +RLAPI int rlGetFramebufferWidth(void); // Get default framebuffer width +RLAPI void rlSetFramebufferHeight(int height); // Set current framebuffer height +RLAPI int rlGetFramebufferHeight(void); // Get default framebuffer height + +RLAPI unsigned int rlGetTextureIdDefault(void); // Get default texture id +RLAPI unsigned int rlGetShaderIdDefault(void); // Get default shader id +RLAPI int *rlGetShaderLocsDefault(void); // Get default shader locations + +// Render batch management +// NOTE: rlgl provides a default render batch to behave like OpenGL 1.1 immediate mode +// but this render batch API is exposed in case of custom batches are required +RLAPI rlRenderBatch rlLoadRenderBatch(int numBuffers, int bufferElements); // Load a render batch system +RLAPI void rlUnloadRenderBatch(rlRenderBatch batch); // Unload render batch system +RLAPI void rlDrawRenderBatch(rlRenderBatch *batch); // Draw render batch data (Update->Draw->Reset) +RLAPI void rlSetRenderBatchActive(rlRenderBatch *batch); // Set the active render batch for rlgl (NULL for default internal) +RLAPI void rlDrawRenderBatchActive(void); // Update and draw internal render batch +RLAPI bool rlCheckRenderBatchLimit(int vCount); // Check internal buffer overflow for a given number of vertex + +RLAPI void rlSetTexture(unsigned int id); // Set current texture for render batch and check buffers limits + +//------------------------------------------------------------------------------------------------------------------------ + +// Vertex buffers management +RLAPI unsigned int rlLoadVertexArray(void); // Load vertex array (vao) if supported +RLAPI unsigned int rlLoadVertexBuffer(const void *buffer, int size, bool dynamic); // Load a vertex buffer object +RLAPI unsigned int rlLoadVertexBufferElement(const void *buffer, int size, bool dynamic); // Load vertex buffer elements object +RLAPI void rlUpdateVertexBuffer(unsigned int bufferId, const void *data, int dataSize, int offset); // Update vertex buffer object data on GPU buffer +RLAPI void rlUpdateVertexBufferElements(unsigned int id, const void *data, int dataSize, int offset); // Update vertex buffer elements data on GPU buffer +RLAPI void rlUnloadVertexArray(unsigned int vaoId); // Unload vertex array (vao) +RLAPI void rlUnloadVertexBuffer(unsigned int vboId); // Unload vertex buffer object +RLAPI void rlSetVertexAttribute(unsigned int index, int compSize, int type, bool normalized, int stride, int offset); // Set vertex attribute data configuration +RLAPI void rlSetVertexAttributeDivisor(unsigned int index, int divisor); // Set vertex attribute data divisor +RLAPI void rlSetVertexAttributeDefault(int locIndex, const void *value, int attribType, int count); // Set vertex attribute default value, when attribute to provided +RLAPI void rlDrawVertexArray(int offset, int count); // Draw vertex array (currently active vao) +RLAPI void rlDrawVertexArrayElements(int offset, int count, const void *buffer); // Draw vertex array elements +RLAPI void rlDrawVertexArrayInstanced(int offset, int count, int instances); // Draw vertex array (currently active vao) with instancing +RLAPI void rlDrawVertexArrayElementsInstanced(int offset, int count, const void *buffer, int instances); // Draw vertex array elements with instancing + +// Textures management +RLAPI unsigned int rlLoadTexture(const void *data, int width, int height, int format, int mipmapCount); // Load texture data +RLAPI unsigned int rlLoadTextureDepth(int width, int height, bool useRenderBuffer); // Load depth texture/renderbuffer (to be attached to fbo) +RLAPI unsigned int rlLoadTextureCubemap(const void *data, int size, int format, int mipmapCount); // Load texture cubemap data +RLAPI void rlUpdateTexture(unsigned int id, int offsetX, int offsetY, int width, int height, int format, const void *data); // Update texture with new data on GPU +RLAPI void rlGetGlTextureFormats(int format, unsigned int *glInternalFormat, unsigned int *glFormat, unsigned int *glType); // Get OpenGL internal formats +RLAPI const char *rlGetPixelFormatName(unsigned int format); // Get name string for pixel format +RLAPI void rlUnloadTexture(unsigned int id); // Unload texture from GPU memory +RLAPI void rlGenTextureMipmaps(unsigned int id, int width, int height, int format, int *mipmaps); // Generate mipmap data for selected texture +RLAPI void *rlReadTexturePixels(unsigned int id, int width, int height, int format); // Read texture pixel data +RLAPI unsigned char *rlReadScreenPixels(int width, int height); // Read screen pixel data (color buffer) + +// Framebuffer management (fbo) +RLAPI unsigned int rlLoadFramebuffer(void); // Load an empty framebuffer +RLAPI void rlFramebufferAttach(unsigned int fboId, unsigned int texId, int attachType, int texType, int mipLevel); // Attach texture/renderbuffer to a framebuffer +RLAPI bool rlFramebufferComplete(unsigned int id); // Verify framebuffer is complete +RLAPI void rlUnloadFramebuffer(unsigned int id); // Delete framebuffer from GPU + +// Shaders management +RLAPI unsigned int rlLoadShaderCode(const char *vsCode, const char *fsCode); // Load shader from code strings +RLAPI unsigned int rlCompileShader(const char *shaderCode, int type); // Compile custom shader and return shader id (type: RL_VERTEX_SHADER, RL_FRAGMENT_SHADER, RL_COMPUTE_SHADER) +RLAPI unsigned int rlLoadShaderProgram(unsigned int vShaderId, unsigned int fShaderId); // Load custom shader program +RLAPI void rlUnloadShaderProgram(unsigned int id); // Unload shader program +RLAPI int rlGetLocationUniform(unsigned int shaderId, const char *uniformName); // Get shader location uniform +RLAPI int rlGetLocationAttrib(unsigned int shaderId, const char *attribName); // Get shader location attribute +RLAPI void rlSetUniform(int locIndex, const void *value, int uniformType, int count); // Set shader value uniform +RLAPI void rlSetUniformMatrix(int locIndex, Matrix mat); // Set shader value matrix +RLAPI void rlSetUniformMatrices(int locIndex, const Matrix *mat, int count); // Set shader value matrices +RLAPI void rlSetUniformSampler(int locIndex, unsigned int textureId); // Set shader value sampler +RLAPI void rlSetShader(unsigned int id, int *locs); // Set shader currently active (id and locations) + +// Compute shader management +RLAPI unsigned int rlLoadComputeShaderProgram(unsigned int shaderId); // Load compute shader program +RLAPI void rlComputeShaderDispatch(unsigned int groupX, unsigned int groupY, unsigned int groupZ); // Dispatch compute shader (equivalent to *draw* for graphics pipeline) + +// Shader buffer storage object management (ssbo) +RLAPI unsigned int rlLoadShaderBuffer(unsigned int size, const void *data, int usageHint); // Load shader storage buffer object (SSBO) +RLAPI void rlUnloadShaderBuffer(unsigned int ssboId); // Unload shader storage buffer object (SSBO) +RLAPI void rlUpdateShaderBuffer(unsigned int id, const void *data, unsigned int dataSize, unsigned int offset); // Update SSBO buffer data +RLAPI void rlBindShaderBuffer(unsigned int id, unsigned int index); // Bind SSBO buffer +RLAPI void rlReadShaderBuffer(unsigned int id, void *dest, unsigned int count, unsigned int offset); // Read SSBO buffer data (GPU->CPU) +RLAPI void rlCopyShaderBuffer(unsigned int destId, unsigned int srcId, unsigned int destOffset, unsigned int srcOffset, unsigned int count); // Copy SSBO data between buffers +RLAPI unsigned int rlGetShaderBufferSize(unsigned int id); // Get SSBO buffer size + +// Buffer management +RLAPI void rlBindImageTexture(unsigned int id, unsigned int index, int format, bool readonly); // Bind image texture + +// Matrix state management +RLAPI Matrix rlGetMatrixModelview(void); // Get internal modelview matrix +RLAPI Matrix rlGetMatrixProjection(void); // Get internal projection matrix +RLAPI Matrix rlGetMatrixTransform(void); // Get internal accumulated transform matrix +RLAPI Matrix rlGetMatrixProjectionStereo(int eye); // Get internal projection matrix for stereo render (selected eye) +RLAPI Matrix rlGetMatrixViewOffsetStereo(int eye); // Get internal view offset matrix for stereo render (selected eye) +RLAPI void rlSetMatrixProjection(Matrix proj); // Set a custom projection matrix (replaces internal projection matrix) +RLAPI void rlSetMatrixModelview(Matrix view); // Set a custom modelview matrix (replaces internal modelview matrix) +RLAPI void rlSetMatrixProjectionStereo(Matrix right, Matrix left); // Set eyes projection matrices for stereo rendering +RLAPI void rlSetMatrixViewOffsetStereo(Matrix right, Matrix left); // Set eyes view offsets matrices for stereo rendering + +// Quick and dirty cube/quad buffers load->draw->unload +RLAPI void rlLoadDrawCube(void); // Load and draw a cube +RLAPI void rlLoadDrawQuad(void); // Load and draw a quad + +#if defined(__cplusplus) +} +#endif + +#endif // RLGL_H + +/*********************************************************************************** +* +* RLGL IMPLEMENTATION +* +************************************************************************************/ + +#if defined(RLGL_IMPLEMENTATION) + +// Expose OpenGL functions from glad in raylib +#if defined(BUILD_LIBTYPE_SHARED) + #define GLAD_API_CALL_EXPORT + #define GLAD_API_CALL_EXPORT_BUILD +#endif + +#if defined(GRAPHICS_API_OPENGL_11) + #if defined(__APPLE__) + #include // OpenGL 1.1 library for OSX + #include // OpenGL extensions library + #else + // APIENTRY for OpenGL function pointer declarations is required + #if !defined(APIENTRY) + #if defined(_WIN32) + #define APIENTRY __stdcall + #else + #define APIENTRY + #endif + #endif + // WINGDIAPI definition. Some Windows OpenGL headers need it + #if !defined(WINGDIAPI) && defined(_WIN32) + #define WINGDIAPI __declspec(dllimport) + #endif + + #include // OpenGL 1.1 library + #endif +#endif + +#if defined(GRAPHICS_API_OPENGL_33) + #define GLAD_MALLOC RL_MALLOC + #define GLAD_FREE RL_FREE + + #define GLAD_GL_IMPLEMENTATION + #include "external/glad.h" // GLAD extensions loading library, includes OpenGL headers +#endif + +#if defined(GRAPHICS_API_OPENGL_ES3) + #include // OpenGL ES 3.0 library + #define GL_GLEXT_PROTOTYPES + #include // OpenGL ES 2.0 extensions library +#elif defined(GRAPHICS_API_OPENGL_ES2) + // NOTE: OpenGL ES 2.0 can be enabled on Desktop platforms, + // in that case, functions are loaded from a custom glad for OpenGL ES 2.0 + #if defined(PLATFORM_DESKTOP_GLFW) || defined(PLATFORM_DESKTOP_SDL) + #define GLAD_GLES2_IMPLEMENTATION + #include "external/glad_gles2.h" + #else + #define GL_GLEXT_PROTOTYPES + //#include // EGL library -> not required, platform layer + #include // OpenGL ES 2.0 library + #include // OpenGL ES 2.0 extensions library + #endif + + // It seems OpenGL ES 2.0 instancing entry points are not defined on Raspberry Pi + // provided headers (despite being defined in official Khronos GLES2 headers) + #if defined(PLATFORM_DRM) + typedef void (GL_APIENTRYP PFNGLDRAWARRAYSINSTANCEDEXTPROC) (GLenum mode, GLint start, GLsizei count, GLsizei primcount); + typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDEXTPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount); + typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBDIVISOREXTPROC) (GLuint index, GLuint divisor); + #endif +#endif + +#include // Required for: malloc(), free() +#include // Required for: strcmp(), strlen() [Used in rlglInit(), on extensions loading] +#include // Required for: sqrtf(), sinf(), cosf(), floor(), log() + +//---------------------------------------------------------------------------------- +// Defines and Macros +//---------------------------------------------------------------------------------- +#ifndef PI + #define PI 3.14159265358979323846f +#endif +#ifndef DEG2RAD + #define DEG2RAD (PI/180.0f) +#endif +#ifndef RAD2DEG + #define RAD2DEG (180.0f/PI) +#endif + +#ifndef GL_SHADING_LANGUAGE_VERSION + #define GL_SHADING_LANGUAGE_VERSION 0x8B8C +#endif + +#ifndef GL_COMPRESSED_RGB_S3TC_DXT1_EXT + #define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0 +#endif +#ifndef GL_COMPRESSED_RGBA_S3TC_DXT1_EXT + #define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1 +#endif +#ifndef GL_COMPRESSED_RGBA_S3TC_DXT3_EXT + #define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2 +#endif +#ifndef GL_COMPRESSED_RGBA_S3TC_DXT5_EXT + #define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3 +#endif +#ifndef GL_ETC1_RGB8_OES + #define GL_ETC1_RGB8_OES 0x8D64 +#endif +#ifndef GL_COMPRESSED_RGB8_ETC2 + #define GL_COMPRESSED_RGB8_ETC2 0x9274 +#endif +#ifndef GL_COMPRESSED_RGBA8_ETC2_EAC + #define GL_COMPRESSED_RGBA8_ETC2_EAC 0x9278 +#endif +#ifndef GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG + #define GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG 0x8C00 +#endif +#ifndef GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG + #define GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG 0x8C02 +#endif +#ifndef GL_COMPRESSED_RGBA_ASTC_4x4_KHR + #define GL_COMPRESSED_RGBA_ASTC_4x4_KHR 0x93b0 +#endif +#ifndef GL_COMPRESSED_RGBA_ASTC_8x8_KHR + #define GL_COMPRESSED_RGBA_ASTC_8x8_KHR 0x93b7 +#endif + +#ifndef GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT + #define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF +#endif +#ifndef GL_TEXTURE_MAX_ANISOTROPY_EXT + #define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE +#endif + +#ifndef GL_PROGRAM_POINT_SIZE + #define GL_PROGRAM_POINT_SIZE 0x8642 +#endif + +#ifndef GL_LINE_WIDTH + #define GL_LINE_WIDTH 0x0B21 +#endif + +#if defined(GRAPHICS_API_OPENGL_11) + #define GL_UNSIGNED_SHORT_5_6_5 0x8363 + #define GL_UNSIGNED_SHORT_5_5_5_1 0x8034 + #define GL_UNSIGNED_SHORT_4_4_4_4 0x8033 +#endif + +#if defined(GRAPHICS_API_OPENGL_21) + #define GL_LUMINANCE 0x1909 + #define GL_LUMINANCE_ALPHA 0x190A +#endif + +#if defined(GRAPHICS_API_OPENGL_ES2) + #define glClearDepth glClearDepthf + #if !defined(GRAPHICS_API_OPENGL_ES3) + #define GL_READ_FRAMEBUFFER GL_FRAMEBUFFER + #define GL_DRAW_FRAMEBUFFER GL_FRAMEBUFFER + #endif +#endif + +// Default shader vertex attribute names to set location points +#ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_POSITION + #define RL_DEFAULT_SHADER_ATTRIB_NAME_POSITION "vertexPosition" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_NAME_POSITION +#endif +#ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD + #define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD "vertexTexCoord" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD +#endif +#ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_NORMAL + #define RL_DEFAULT_SHADER_ATTRIB_NAME_NORMAL "vertexNormal" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_NAME_NORMAL +#endif +#ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR + #define RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR "vertexColor" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR +#endif +#ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT + #define RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT "vertexTangent" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT +#endif +#ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2 + #define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2 "vertexTexCoord2" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2 +#endif +#ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_BONEIDS + #define RL_DEFAULT_SHADER_ATTRIB_NAME_BONEIDS "vertexBoneIds" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_NAME_BONEIDS +#endif +#ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_BONEWEIGHTS + #define RL_DEFAULT_SHADER_ATTRIB_NAME_BONEWEIGHTS "vertexBoneWeights" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_NAME_BONEWEIGHTS +#endif + +#ifndef RL_DEFAULT_SHADER_UNIFORM_NAME_MVP + #define RL_DEFAULT_SHADER_UNIFORM_NAME_MVP "mvp" // model-view-projection matrix +#endif +#ifndef RL_DEFAULT_SHADER_UNIFORM_NAME_VIEW + #define RL_DEFAULT_SHADER_UNIFORM_NAME_VIEW "matView" // view matrix +#endif +#ifndef RL_DEFAULT_SHADER_UNIFORM_NAME_PROJECTION + #define RL_DEFAULT_SHADER_UNIFORM_NAME_PROJECTION "matProjection" // projection matrix +#endif +#ifndef RL_DEFAULT_SHADER_UNIFORM_NAME_MODEL + #define RL_DEFAULT_SHADER_UNIFORM_NAME_MODEL "matModel" // model matrix +#endif +#ifndef RL_DEFAULT_SHADER_UNIFORM_NAME_NORMAL + #define RL_DEFAULT_SHADER_UNIFORM_NAME_NORMAL "matNormal" // normal matrix (transpose(inverse(matModelView)) +#endif +#ifndef RL_DEFAULT_SHADER_UNIFORM_NAME_COLOR + #define RL_DEFAULT_SHADER_UNIFORM_NAME_COLOR "colDiffuse" // color diffuse (base tint color, multiplied by texture color) +#endif +#ifndef RL_DEFAULT_SHADER_UNIFORM_NAME_BONE_MATRICES + #define RL_DEFAULT_SHADER_UNIFORM_NAME_BONE_MATRICES "boneMatrices" // bone matrices +#endif +#ifndef RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE0 + #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE0 "texture0" // texture0 (texture slot active 0) +#endif +#ifndef RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE1 + #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE1 "texture1" // texture1 (texture slot active 1) +#endif +#ifndef RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE2 + #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE2 "texture2" // texture2 (texture slot active 2) +#endif + +//---------------------------------------------------------------------------------- +// Types and Structures Definition +//---------------------------------------------------------------------------------- +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) +typedef struct rlglData { + rlRenderBatch *currentBatch; // Current render batch + rlRenderBatch defaultBatch; // Default internal render batch + + struct { + int vertexCounter; // Current active render batch vertex counter (generic, used for all batches) + float texcoordx, texcoordy; // Current active texture coordinate (added on glVertex*()) + float normalx, normaly, normalz; // Current active normal (added on glVertex*()) + unsigned char colorr, colorg, colorb, colora; // Current active color (added on glVertex*()) + + int currentMatrixMode; // Current matrix mode + Matrix *currentMatrix; // Current matrix pointer + Matrix modelview; // Default modelview matrix + Matrix projection; // Default projection matrix + Matrix transform; // Transform matrix to be used with rlTranslate, rlRotate, rlScale + bool transformRequired; // Require transform matrix application to current draw-call vertex (if required) + Matrix stack[RL_MAX_MATRIX_STACK_SIZE];// Matrix stack for push/pop + int stackCounter; // Matrix stack counter + + unsigned int defaultTextureId; // Default texture used on shapes/poly drawing (required by shader) + unsigned int activeTextureId[RL_DEFAULT_BATCH_MAX_TEXTURE_UNITS]; // Active texture ids to be enabled on batch drawing (0 active by default) + unsigned int defaultVShaderId; // Default vertex shader id (used by default shader program) + unsigned int defaultFShaderId; // Default fragment shader id (used by default shader program) + unsigned int defaultShaderId; // Default shader program id, supports vertex color and diffuse texture + int *defaultShaderLocs; // Default shader locations pointer to be used on rendering + unsigned int currentShaderId; // Current shader id to be used on rendering (by default, defaultShaderId) + int *currentShaderLocs; // Current shader locations pointer to be used on rendering (by default, defaultShaderLocs) + + bool stereoRender; // Stereo rendering flag + Matrix projectionStereo[2]; // VR stereo rendering eyes projection matrices + Matrix viewOffsetStereo[2]; // VR stereo rendering eyes view offset matrices + + // Blending variables + int currentBlendMode; // Blending mode active + int glBlendSrcFactor; // Blending source factor + int glBlendDstFactor; // Blending destination factor + int glBlendEquation; // Blending equation + int glBlendSrcFactorRGB; // Blending source RGB factor + int glBlendDestFactorRGB; // Blending destination RGB factor + int glBlendSrcFactorAlpha; // Blending source alpha factor + int glBlendDestFactorAlpha; // Blending destination alpha factor + int glBlendEquationRGB; // Blending equation for RGB + int glBlendEquationAlpha; // Blending equation for alpha + bool glCustomBlendModeModified; // Custom blending factor and equation modification status + + int framebufferWidth; // Current framebuffer width + int framebufferHeight; // Current framebuffer height + + } State; // Renderer state + struct { + bool vao; // VAO support (OpenGL ES2 could not support VAO extension) (GL_ARB_vertex_array_object) + bool instancing; // Instancing supported (GL_ANGLE_instanced_arrays, GL_EXT_draw_instanced + GL_EXT_instanced_arrays) + bool texNPOT; // NPOT textures full support (GL_ARB_texture_non_power_of_two, GL_OES_texture_npot) + bool texDepth; // Depth textures supported (GL_ARB_depth_texture, GL_OES_depth_texture) + bool texDepthWebGL; // Depth textures supported WebGL specific (GL_WEBGL_depth_texture) + bool texFloat32; // float textures support (32 bit per channel) (GL_OES_texture_float) + bool texFloat16; // half float textures support (16 bit per channel) (GL_OES_texture_half_float) + bool texCompDXT; // DDS texture compression support (GL_EXT_texture_compression_s3tc, GL_WEBGL_compressed_texture_s3tc, GL_WEBKIT_WEBGL_compressed_texture_s3tc) + bool texCompETC1; // ETC1 texture compression support (GL_OES_compressed_ETC1_RGB8_texture, GL_WEBGL_compressed_texture_etc1) + bool texCompETC2; // ETC2/EAC texture compression support (GL_ARB_ES3_compatibility) + bool texCompPVRT; // PVR texture compression support (GL_IMG_texture_compression_pvrtc) + bool texCompASTC; // ASTC texture compression support (GL_KHR_texture_compression_astc_hdr, GL_KHR_texture_compression_astc_ldr) + bool texMirrorClamp; // Clamp mirror wrap mode supported (GL_EXT_texture_mirror_clamp) + bool texAnisoFilter; // Anisotropic texture filtering support (GL_EXT_texture_filter_anisotropic) + bool computeShader; // Compute shaders support (GL_ARB_compute_shader) + bool ssbo; // Shader storage buffer object support (GL_ARB_shader_storage_buffer_object) + + float maxAnisotropyLevel; // Maximum anisotropy level supported (minimum is 2.0f) + int maxDepthBits; // Maximum bits for depth component + + } ExtSupported; // Extensions supported flags +} rlglData; + +typedef void *(*rlglLoadProc)(const char *name); // OpenGL extension functions loader signature (same as GLADloadproc) + +#endif // GRAPHICS_API_OPENGL_33 || GRAPHICS_API_OPENGL_ES2 + +//---------------------------------------------------------------------------------- +// Global Variables Definition +//---------------------------------------------------------------------------------- +static double rlCullDistanceNear = RL_CULL_DISTANCE_NEAR; +static double rlCullDistanceFar = RL_CULL_DISTANCE_FAR; + +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) +static rlglData RLGL = { 0 }; +#endif // GRAPHICS_API_OPENGL_33 || GRAPHICS_API_OPENGL_ES2 + +#if defined(GRAPHICS_API_OPENGL_ES2) && !defined(GRAPHICS_API_OPENGL_ES3) +// NOTE: VAO functionality is exposed through extensions (OES) +static PFNGLGENVERTEXARRAYSOESPROC glGenVertexArrays = NULL; +static PFNGLBINDVERTEXARRAYOESPROC glBindVertexArray = NULL; +static PFNGLDELETEVERTEXARRAYSOESPROC glDeleteVertexArrays = NULL; + +// NOTE: Instancing functionality could also be available through extension +static PFNGLDRAWARRAYSINSTANCEDEXTPROC glDrawArraysInstanced = NULL; +static PFNGLDRAWELEMENTSINSTANCEDEXTPROC glDrawElementsInstanced = NULL; +static PFNGLVERTEXATTRIBDIVISOREXTPROC glVertexAttribDivisor = NULL; +#endif + +//---------------------------------------------------------------------------------- +// Module specific Functions Declaration +//---------------------------------------------------------------------------------- +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) +static void rlLoadShaderDefault(void); // Load default shader +static void rlUnloadShaderDefault(void); // Unload default shader +#if defined(RLGL_SHOW_GL_DETAILS_INFO) +static const char *rlGetCompressedFormatName(int format); // Get compressed format official GL identifier name +#endif // RLGL_SHOW_GL_DETAILS_INFO +#endif // GRAPHICS_API_OPENGL_33 || GRAPHICS_API_OPENGL_ES2 + +static int rlGetPixelDataSize(int width, int height, int format); // Get pixel data size in bytes (image or texture) + +// Auxiliar matrix math functions +typedef struct rl_float16 { + float v[16]; +} rl_float16; +static rl_float16 rlMatrixToFloatV(Matrix mat); // Get float array of matrix data +#define rlMatrixToFloat(mat) (rlMatrixToFloatV(mat).v) // Get float vector for Matrix +static Matrix rlMatrixIdentity(void); // Get identity matrix +static Matrix rlMatrixMultiply(Matrix left, Matrix right); // Multiply two matrices +static Matrix rlMatrixTranspose(Matrix mat); // Transposes provided matrix +static Matrix rlMatrixInvert(Matrix mat); // Invert provided matrix + +//---------------------------------------------------------------------------------- +// Module Functions Definition - Matrix operations +//---------------------------------------------------------------------------------- + +#if defined(GRAPHICS_API_OPENGL_11) +// Fallback to OpenGL 1.1 function calls +//--------------------------------------- +void rlMatrixMode(int mode) +{ + switch (mode) + { + case RL_PROJECTION: glMatrixMode(GL_PROJECTION); break; + case RL_MODELVIEW: glMatrixMode(GL_MODELVIEW); break; + case RL_TEXTURE: glMatrixMode(GL_TEXTURE); break; + default: break; + } +} + +void rlFrustum(double left, double right, double bottom, double top, double znear, double zfar) +{ + glFrustum(left, right, bottom, top, znear, zfar); +} + +void rlOrtho(double left, double right, double bottom, double top, double znear, double zfar) +{ + glOrtho(left, right, bottom, top, znear, zfar); +} + +void rlPushMatrix(void) { glPushMatrix(); } +void rlPopMatrix(void) { glPopMatrix(); } +void rlLoadIdentity(void) { glLoadIdentity(); } +void rlTranslatef(float x, float y, float z) { glTranslatef(x, y, z); } +void rlRotatef(float angle, float x, float y, float z) { glRotatef(angle, x, y, z); } +void rlScalef(float x, float y, float z) { glScalef(x, y, z); } +void rlMultMatrixf(const float *matf) { glMultMatrixf(matf); } +#endif +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) +// Choose the current matrix to be transformed +void rlMatrixMode(int mode) +{ + if (mode == RL_PROJECTION) RLGL.State.currentMatrix = &RLGL.State.projection; + else if (mode == RL_MODELVIEW) RLGL.State.currentMatrix = &RLGL.State.modelview; + //else if (mode == RL_TEXTURE) // Not supported + + RLGL.State.currentMatrixMode = mode; +} + +// Push the current matrix into RLGL.State.stack +void rlPushMatrix(void) +{ + if (RLGL.State.stackCounter >= RL_MAX_MATRIX_STACK_SIZE) TRACELOG(RL_LOG_ERROR, "RLGL: Matrix stack overflow (RL_MAX_MATRIX_STACK_SIZE)"); + + if (RLGL.State.currentMatrixMode == RL_MODELVIEW) + { + RLGL.State.transformRequired = true; + RLGL.State.currentMatrix = &RLGL.State.transform; + } + + RLGL.State.stack[RLGL.State.stackCounter] = *RLGL.State.currentMatrix; + RLGL.State.stackCounter++; +} + +// Pop lattest inserted matrix from RLGL.State.stack +void rlPopMatrix(void) +{ + if (RLGL.State.stackCounter > 0) + { + Matrix mat = RLGL.State.stack[RLGL.State.stackCounter - 1]; + *RLGL.State.currentMatrix = mat; + RLGL.State.stackCounter--; + } + + if ((RLGL.State.stackCounter == 0) && (RLGL.State.currentMatrixMode == RL_MODELVIEW)) + { + RLGL.State.currentMatrix = &RLGL.State.modelview; + RLGL.State.transformRequired = false; + } +} + +// Reset current matrix to identity matrix +void rlLoadIdentity(void) +{ + *RLGL.State.currentMatrix = rlMatrixIdentity(); +} + +// Multiply the current matrix by a translation matrix +void rlTranslatef(float x, float y, float z) +{ + Matrix matTranslation = { + 1.0f, 0.0f, 0.0f, x, + 0.0f, 1.0f, 0.0f, y, + 0.0f, 0.0f, 1.0f, z, + 0.0f, 0.0f, 0.0f, 1.0f + }; + + // NOTE: We transpose matrix with multiplication order + *RLGL.State.currentMatrix = rlMatrixMultiply(matTranslation, *RLGL.State.currentMatrix); +} + +// Multiply the current matrix by a rotation matrix +// NOTE: The provided angle must be in degrees +void rlRotatef(float angle, float x, float y, float z) +{ + Matrix matRotation = rlMatrixIdentity(); + + // Axis vector (x, y, z) normalization + float lengthSquared = x*x + y*y + z*z; + if ((lengthSquared != 1.0f) && (lengthSquared != 0.0f)) + { + float inverseLength = 1.0f/sqrtf(lengthSquared); + x *= inverseLength; + y *= inverseLength; + z *= inverseLength; + } + + // Rotation matrix generation + float sinres = sinf(DEG2RAD*angle); + float cosres = cosf(DEG2RAD*angle); + float t = 1.0f - cosres; + + matRotation.m0 = x*x*t + cosres; + matRotation.m1 = y*x*t + z*sinres; + matRotation.m2 = z*x*t - y*sinres; + matRotation.m3 = 0.0f; + + matRotation.m4 = x*y*t - z*sinres; + matRotation.m5 = y*y*t + cosres; + matRotation.m6 = z*y*t + x*sinres; + matRotation.m7 = 0.0f; + + matRotation.m8 = x*z*t + y*sinres; + matRotation.m9 = y*z*t - x*sinres; + matRotation.m10 = z*z*t + cosres; + matRotation.m11 = 0.0f; + + matRotation.m12 = 0.0f; + matRotation.m13 = 0.0f; + matRotation.m14 = 0.0f; + matRotation.m15 = 1.0f; + + // NOTE: We transpose matrix with multiplication order + *RLGL.State.currentMatrix = rlMatrixMultiply(matRotation, *RLGL.State.currentMatrix); +} + +// Multiply the current matrix by a scaling matrix +void rlScalef(float x, float y, float z) +{ + Matrix matScale = { + x, 0.0f, 0.0f, 0.0f, + 0.0f, y, 0.0f, 0.0f, + 0.0f, 0.0f, z, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + }; + + // NOTE: We transpose matrix with multiplication order + *RLGL.State.currentMatrix = rlMatrixMultiply(matScale, *RLGL.State.currentMatrix); +} + +// Multiply the current matrix by another matrix +void rlMultMatrixf(const float *matf) +{ + // Matrix creation from array + Matrix mat = { matf[0], matf[4], matf[8], matf[12], + matf[1], matf[5], matf[9], matf[13], + matf[2], matf[6], matf[10], matf[14], + matf[3], matf[7], matf[11], matf[15] }; + + *RLGL.State.currentMatrix = rlMatrixMultiply(mat, *RLGL.State.currentMatrix); +} + +// Multiply the current matrix by a perspective matrix generated by parameters +void rlFrustum(double left, double right, double bottom, double top, double znear, double zfar) +{ + Matrix matFrustum = { 0 }; + + float rl = (float)(right - left); + float tb = (float)(top - bottom); + float fn = (float)(zfar - znear); + + matFrustum.m0 = ((float) znear*2.0f)/rl; + matFrustum.m1 = 0.0f; + matFrustum.m2 = 0.0f; + matFrustum.m3 = 0.0f; + + matFrustum.m4 = 0.0f; + matFrustum.m5 = ((float) znear*2.0f)/tb; + matFrustum.m6 = 0.0f; + matFrustum.m7 = 0.0f; + + matFrustum.m8 = ((float)right + (float)left)/rl; + matFrustum.m9 = ((float)top + (float)bottom)/tb; + matFrustum.m10 = -((float)zfar + (float)znear)/fn; + matFrustum.m11 = -1.0f; + + matFrustum.m12 = 0.0f; + matFrustum.m13 = 0.0f; + matFrustum.m14 = -((float)zfar*(float)znear*2.0f)/fn; + matFrustum.m15 = 0.0f; + + *RLGL.State.currentMatrix = rlMatrixMultiply(*RLGL.State.currentMatrix, matFrustum); +} + +// Multiply the current matrix by an orthographic matrix generated by parameters +void rlOrtho(double left, double right, double bottom, double top, double znear, double zfar) +{ + // NOTE: If left-right and top-botton values are equal it could create a division by zero, + // response to it is platform/compiler dependant + Matrix matOrtho = { 0 }; + + float rl = (float)(right - left); + float tb = (float)(top - bottom); + float fn = (float)(zfar - znear); + + matOrtho.m0 = 2.0f/rl; + matOrtho.m1 = 0.0f; + matOrtho.m2 = 0.0f; + matOrtho.m3 = 0.0f; + matOrtho.m4 = 0.0f; + matOrtho.m5 = 2.0f/tb; + matOrtho.m6 = 0.0f; + matOrtho.m7 = 0.0f; + matOrtho.m8 = 0.0f; + matOrtho.m9 = 0.0f; + matOrtho.m10 = -2.0f/fn; + matOrtho.m11 = 0.0f; + matOrtho.m12 = -((float)left + (float)right)/rl; + matOrtho.m13 = -((float)top + (float)bottom)/tb; + matOrtho.m14 = -((float)zfar + (float)znear)/fn; + matOrtho.m15 = 1.0f; + + *RLGL.State.currentMatrix = rlMatrixMultiply(*RLGL.State.currentMatrix, matOrtho); +} +#endif + +// Set the viewport area (transformation from normalized device coordinates to window coordinates) +// NOTE: We store current viewport dimensions +void rlViewport(int x, int y, int width, int height) +{ + glViewport(x, y, width, height); +} + +// Set clip planes distances +void rlSetClipPlanes(double nearPlane, double farPlane) +{ + rlCullDistanceNear = nearPlane; + rlCullDistanceFar = farPlane; +} + +// Get cull plane distance near +double rlGetCullDistanceNear(void) +{ + return rlCullDistanceNear; +} + +// Get cull plane distance far +double rlGetCullDistanceFar(void) +{ + return rlCullDistanceFar; +} + +//---------------------------------------------------------------------------------- +// Module Functions Definition - Vertex level operations +//---------------------------------------------------------------------------------- +#if defined(GRAPHICS_API_OPENGL_11) +// Fallback to OpenGL 1.1 function calls +//--------------------------------------- +void rlBegin(int mode) +{ + switch (mode) + { + case RL_LINES: glBegin(GL_LINES); break; + case RL_TRIANGLES: glBegin(GL_TRIANGLES); break; + case RL_QUADS: glBegin(GL_QUADS); break; + default: break; + } +} + +void rlEnd(void) { glEnd(); } +void rlVertex2i(int x, int y) { glVertex2i(x, y); } +void rlVertex2f(float x, float y) { glVertex2f(x, y); } +void rlVertex3f(float x, float y, float z) { glVertex3f(x, y, z); } +void rlTexCoord2f(float x, float y) { glTexCoord2f(x, y); } +void rlNormal3f(float x, float y, float z) { glNormal3f(x, y, z); } +void rlColor4ub(unsigned char r, unsigned char g, unsigned char b, unsigned char a) { glColor4ub(r, g, b, a); } +void rlColor3f(float x, float y, float z) { glColor3f(x, y, z); } +void rlColor4f(float x, float y, float z, float w) { glColor4f(x, y, z, w); } +#endif +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) +// Initialize drawing mode (how to organize vertex) +void rlBegin(int mode) +{ + // Draw mode can be RL_LINES, RL_TRIANGLES and RL_QUADS + // NOTE: In all three cases, vertex are accumulated over default internal vertex buffer + if (RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].mode != mode) + { + if (RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount > 0) + { + // Make sure current RLGL.currentBatch->draws[i].vertexCount is aligned a multiple of 4, + // that way, following QUADS drawing will keep aligned with index processing + // It implies adding some extra alignment vertex at the end of the draw, + // those vertex are not processed but they are considered as an additional offset + // for the next set of vertex to be drawn + if (RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].mode == RL_LINES) RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexAlignment = ((RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount < 4)? RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount : RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount%4); + else if (RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].mode == RL_TRIANGLES) RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexAlignment = ((RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount < 4)? 1 : (4 - (RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount%4))); + else RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexAlignment = 0; + + if (!rlCheckRenderBatchLimit(RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexAlignment)) + { + RLGL.State.vertexCounter += RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexAlignment; + RLGL.currentBatch->drawCounter++; + } + } + + if (RLGL.currentBatch->drawCounter >= RL_DEFAULT_BATCH_DRAWCALLS) rlDrawRenderBatch(RLGL.currentBatch); + + RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].mode = mode; + RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount = 0; + RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].textureId = RLGL.State.defaultTextureId; + } +} + +// Finish vertex providing +void rlEnd(void) +{ + // NOTE: Depth increment is dependant on rlOrtho(): z-near and z-far values, + // as well as depth buffer bit-depth (16bit or 24bit or 32bit) + // Correct increment formula would be: depthInc = (zfar - znear)/pow(2, bits) + RLGL.currentBatch->currentDepth += (1.0f/20000.0f); +} + +// Define one vertex (position) +// NOTE: Vertex position data is the basic information required for drawing +void rlVertex3f(float x, float y, float z) +{ + float tx = x; + float ty = y; + float tz = z; + + // Transform provided vector if required + if (RLGL.State.transformRequired) + { + tx = RLGL.State.transform.m0*x + RLGL.State.transform.m4*y + RLGL.State.transform.m8*z + RLGL.State.transform.m12; + ty = RLGL.State.transform.m1*x + RLGL.State.transform.m5*y + RLGL.State.transform.m9*z + RLGL.State.transform.m13; + tz = RLGL.State.transform.m2*x + RLGL.State.transform.m6*y + RLGL.State.transform.m10*z + RLGL.State.transform.m14; + } + + // WARNING: We can't break primitives when launching a new batch + // RL_LINES comes in pairs, RL_TRIANGLES come in groups of 3 vertices and RL_QUADS come in groups of 4 vertices + // We must check current draw.mode when a new vertex is required and finish the batch only if the draw.mode draw.vertexCount is %2, %3 or %4 + if (RLGL.State.vertexCounter > (RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].elementCount*4 - 4)) + { + if ((RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].mode == RL_LINES) && + (RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount%2 == 0)) + { + // Reached the maximum number of vertices for RL_LINES drawing + // Launch a draw call but keep current state for next vertices comming + // NOTE: We add +1 vertex to the check for security + rlCheckRenderBatchLimit(2 + 1); + } + else if ((RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].mode == RL_TRIANGLES) && + (RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount%3 == 0)) + { + rlCheckRenderBatchLimit(3 + 1); + } + else if ((RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].mode == RL_QUADS) && + (RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount%4 == 0)) + { + rlCheckRenderBatchLimit(4 + 1); + } + } + + // Add vertices + RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vertices[3*RLGL.State.vertexCounter] = tx; + RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vertices[3*RLGL.State.vertexCounter + 1] = ty; + RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vertices[3*RLGL.State.vertexCounter + 2] = tz; + + // Add current texcoord + RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].texcoords[2*RLGL.State.vertexCounter] = RLGL.State.texcoordx; + RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].texcoords[2*RLGL.State.vertexCounter + 1] = RLGL.State.texcoordy; + + // Add current normal + RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].normals[3*RLGL.State.vertexCounter] = RLGL.State.normalx; + RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].normals[3*RLGL.State.vertexCounter + 1] = RLGL.State.normaly; + RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].normals[3*RLGL.State.vertexCounter + 2] = RLGL.State.normalz; + + // Add current color + RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].colors[4*RLGL.State.vertexCounter] = RLGL.State.colorr; + RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].colors[4*RLGL.State.vertexCounter + 1] = RLGL.State.colorg; + RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].colors[4*RLGL.State.vertexCounter + 2] = RLGL.State.colorb; + RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].colors[4*RLGL.State.vertexCounter + 3] = RLGL.State.colora; + + RLGL.State.vertexCounter++; + RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount++; +} + +// Define one vertex (position) +void rlVertex2f(float x, float y) +{ + rlVertex3f(x, y, RLGL.currentBatch->currentDepth); +} + +// Define one vertex (position) +void rlVertex2i(int x, int y) +{ + rlVertex3f((float)x, (float)y, RLGL.currentBatch->currentDepth); +} + +// Define one vertex (texture coordinate) +// NOTE: Texture coordinates are limited to QUADS only +void rlTexCoord2f(float x, float y) +{ + RLGL.State.texcoordx = x; + RLGL.State.texcoordy = y; +} + +// Define one vertex (normal) +// NOTE: Normals limited to TRIANGLES only? +void rlNormal3f(float x, float y, float z) +{ + float normalx = x; + float normaly = y; + float normalz = z; + if (RLGL.State.transformRequired) + { + normalx = RLGL.State.transform.m0*x + RLGL.State.transform.m4*y + RLGL.State.transform.m8*z; + normaly = RLGL.State.transform.m1*x + RLGL.State.transform.m5*y + RLGL.State.transform.m9*z; + normalz = RLGL.State.transform.m2*x + RLGL.State.transform.m6*y + RLGL.State.transform.m10*z; + } + float length = sqrtf(normalx*normalx + normaly*normaly + normalz*normalz); + if (length != 0.0f) + { + float ilength = 1.0f/length; + normalx *= ilength; + normaly *= ilength; + normalz *= ilength; + } + RLGL.State.normalx = normalx; + RLGL.State.normaly = normaly; + RLGL.State.normalz = normalz; +} + +// Define one vertex (color) +void rlColor4ub(unsigned char x, unsigned char y, unsigned char z, unsigned char w) +{ + RLGL.State.colorr = x; + RLGL.State.colorg = y; + RLGL.State.colorb = z; + RLGL.State.colora = w; +} + +// Define one vertex (color) +void rlColor4f(float r, float g, float b, float a) +{ + rlColor4ub((unsigned char)(r*255), (unsigned char)(g*255), (unsigned char)(b*255), (unsigned char)(a*255)); +} + +// Define one vertex (color) +void rlColor3f(float x, float y, float z) +{ + rlColor4ub((unsigned char)(x*255), (unsigned char)(y*255), (unsigned char)(z*255), 255); +} + +#endif + +//-------------------------------------------------------------------------------------- +// Module Functions Definition - OpenGL style functions (common to 1.1, 3.3+, ES2) +//-------------------------------------------------------------------------------------- + +// Set current texture to use +void rlSetTexture(unsigned int id) +{ + if (id == 0) + { +#if defined(GRAPHICS_API_OPENGL_11) + rlDisableTexture(); +#else + // NOTE: If quads batch limit is reached, we force a draw call and next batch starts + if (RLGL.State.vertexCounter >= + RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].elementCount*4) + { + rlDrawRenderBatch(RLGL.currentBatch); + } +#endif + } + else + { +#if defined(GRAPHICS_API_OPENGL_11) + rlEnableTexture(id); +#else + if (RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].textureId != id) + { + if (RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount > 0) + { + // Make sure current RLGL.currentBatch->draws[i].vertexCount is aligned a multiple of 4, + // that way, following QUADS drawing will keep aligned with index processing + // It implies adding some extra alignment vertex at the end of the draw, + // those vertex are not processed but they are considered as an additional offset + // for the next set of vertex to be drawn + if (RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].mode == RL_LINES) RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexAlignment = ((RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount < 4)? RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount : RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount%4); + else if (RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].mode == RL_TRIANGLES) RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexAlignment = ((RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount < 4)? 1 : (4 - (RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount%4))); + else RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexAlignment = 0; + + if (!rlCheckRenderBatchLimit(RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexAlignment)) + { + RLGL.State.vertexCounter += RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexAlignment; + + RLGL.currentBatch->drawCounter++; + } + } + + if (RLGL.currentBatch->drawCounter >= RL_DEFAULT_BATCH_DRAWCALLS) rlDrawRenderBatch(RLGL.currentBatch); + + RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].textureId = id; + RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount = 0; + } +#endif + } +} + +// Select and active a texture slot +void rlActiveTextureSlot(int slot) +{ +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + glActiveTexture(GL_TEXTURE0 + slot); +#endif +} + +// Enable texture +void rlEnableTexture(unsigned int id) +{ +#if defined(GRAPHICS_API_OPENGL_11) + glEnable(GL_TEXTURE_2D); +#endif + glBindTexture(GL_TEXTURE_2D, id); +} + +// Disable texture +void rlDisableTexture(void) +{ +#if defined(GRAPHICS_API_OPENGL_11) + glDisable(GL_TEXTURE_2D); +#endif + glBindTexture(GL_TEXTURE_2D, 0); +} + +// Enable texture cubemap +void rlEnableTextureCubemap(unsigned int id) +{ +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + glBindTexture(GL_TEXTURE_CUBE_MAP, id); +#endif +} + +// Disable texture cubemap +void rlDisableTextureCubemap(void) +{ +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + glBindTexture(GL_TEXTURE_CUBE_MAP, 0); +#endif +} + +// Set texture parameters (wrap mode/filter mode) +void rlTextureParameters(unsigned int id, int param, int value) +{ + glBindTexture(GL_TEXTURE_2D, id); + +#if !defined(GRAPHICS_API_OPENGL_11) + // Reset anisotropy filter, in case it was set + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0f); +#endif + + switch (param) + { + case RL_TEXTURE_WRAP_S: + case RL_TEXTURE_WRAP_T: + { + if (value == RL_TEXTURE_WRAP_MIRROR_CLAMP) + { +#if !defined(GRAPHICS_API_OPENGL_11) + if (RLGL.ExtSupported.texMirrorClamp) glTexParameteri(GL_TEXTURE_2D, param, value); + else TRACELOG(RL_LOG_WARNING, "GL: Clamp mirror wrap mode not supported (GL_MIRROR_CLAMP_EXT)"); +#endif + } + else glTexParameteri(GL_TEXTURE_2D, param, value); + + } break; + case RL_TEXTURE_MAG_FILTER: + case RL_TEXTURE_MIN_FILTER: glTexParameteri(GL_TEXTURE_2D, param, value); break; + case RL_TEXTURE_FILTER_ANISOTROPIC: + { +#if !defined(GRAPHICS_API_OPENGL_11) + if (value <= RLGL.ExtSupported.maxAnisotropyLevel) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)value); + else if (RLGL.ExtSupported.maxAnisotropyLevel > 0.0f) + { + TRACELOG(RL_LOG_WARNING, "GL: Maximum anisotropic filter level supported is %iX", id, (int)RLGL.ExtSupported.maxAnisotropyLevel); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)value); + } + else TRACELOG(RL_LOG_WARNING, "GL: Anisotropic filtering not supported"); +#endif + } break; +#if defined(GRAPHICS_API_OPENGL_33) + case RL_TEXTURE_MIPMAP_BIAS_RATIO: glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, value/100.0f); +#endif + default: break; + } + + glBindTexture(GL_TEXTURE_2D, 0); +} + +// Set cubemap parameters (wrap mode/filter mode) +void rlCubemapParameters(unsigned int id, int param, int value) +{ +#if !defined(GRAPHICS_API_OPENGL_11) + glBindTexture(GL_TEXTURE_CUBE_MAP, id); + + // Reset anisotropy filter, in case it was set + glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0f); + + switch (param) + { + case RL_TEXTURE_WRAP_S: + case RL_TEXTURE_WRAP_T: + { + if (value == RL_TEXTURE_WRAP_MIRROR_CLAMP) + { + if (RLGL.ExtSupported.texMirrorClamp) glTexParameteri(GL_TEXTURE_CUBE_MAP, param, value); + else TRACELOG(RL_LOG_WARNING, "GL: Clamp mirror wrap mode not supported (GL_MIRROR_CLAMP_EXT)"); + } + else glTexParameteri(GL_TEXTURE_CUBE_MAP, param, value); + + } break; + case RL_TEXTURE_MAG_FILTER: + case RL_TEXTURE_MIN_FILTER: glTexParameteri(GL_TEXTURE_CUBE_MAP, param, value); break; + case RL_TEXTURE_FILTER_ANISOTROPIC: + { + if (value <= RLGL.ExtSupported.maxAnisotropyLevel) glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)value); + else if (RLGL.ExtSupported.maxAnisotropyLevel > 0.0f) + { + TRACELOG(RL_LOG_WARNING, "GL: Maximum anisotropic filter level supported is %iX", id, (int)RLGL.ExtSupported.maxAnisotropyLevel); + glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)value); + } + else TRACELOG(RL_LOG_WARNING, "GL: Anisotropic filtering not supported"); + } break; +#if defined(GRAPHICS_API_OPENGL_33) + case RL_TEXTURE_MIPMAP_BIAS_RATIO: glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_LOD_BIAS, value/100.0f); +#endif + default: break; + } + + glBindTexture(GL_TEXTURE_CUBE_MAP, 0); +#endif +} + +// Enable shader program +void rlEnableShader(unsigned int id) +{ +#if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)) + glUseProgram(id); +#endif +} + +// Disable shader program +void rlDisableShader(void) +{ +#if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)) + glUseProgram(0); +#endif +} + +// Enable rendering to texture (fbo) +void rlEnableFramebuffer(unsigned int id) +{ +#if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)) && defined(RLGL_RENDER_TEXTURES_HINT) + glBindFramebuffer(GL_FRAMEBUFFER, id); +#endif +} + +// return the active render texture (fbo) +unsigned int rlGetActiveFramebuffer(void) +{ + GLint fboId = 0; +#if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES3)) && defined(RLGL_RENDER_TEXTURES_HINT) + glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &fboId); +#endif + return fboId; +} + +// Disable rendering to texture +void rlDisableFramebuffer(void) +{ +#if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)) && defined(RLGL_RENDER_TEXTURES_HINT) + glBindFramebuffer(GL_FRAMEBUFFER, 0); +#endif +} + +// Blit active framebuffer to main framebuffer +void rlBlitFramebuffer(int srcX, int srcY, int srcWidth, int srcHeight, int dstX, int dstY, int dstWidth, int dstHeight, int bufferMask) +{ +#if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES3)) && defined(RLGL_RENDER_TEXTURES_HINT) + glBlitFramebuffer(srcX, srcY, srcWidth, srcHeight, dstX, dstY, dstWidth, dstHeight, bufferMask, GL_NEAREST); +#endif +} + +// Bind framebuffer object (fbo) +void rlBindFramebuffer(unsigned int target, unsigned int framebuffer) +{ +#if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)) && defined(RLGL_RENDER_TEXTURES_HINT) + glBindFramebuffer(target, framebuffer); +#endif +} + +// Activate multiple draw color buffers +// NOTE: One color buffer is always active by default +void rlActiveDrawBuffers(int count) +{ +#if ((defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES3)) && defined(RLGL_RENDER_TEXTURES_HINT)) + // NOTE: Maximum number of draw buffers supported is implementation dependant, + // it can be queried with glGet*() but it must be at least 8 + //GLint maxDrawBuffers = 0; + //glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers); + + if (count > 0) + { + if (count > 8) TRACELOG(LOG_WARNING, "GL: Max color buffers limited to 8"); + else + { + unsigned int buffers[8] = { +#if defined(GRAPHICS_API_OPENGL_ES3) + GL_COLOR_ATTACHMENT0_EXT, + GL_COLOR_ATTACHMENT1_EXT, + GL_COLOR_ATTACHMENT2_EXT, + GL_COLOR_ATTACHMENT3_EXT, + GL_COLOR_ATTACHMENT4_EXT, + GL_COLOR_ATTACHMENT5_EXT, + GL_COLOR_ATTACHMENT6_EXT, + GL_COLOR_ATTACHMENT7_EXT, +#else + GL_COLOR_ATTACHMENT0, + GL_COLOR_ATTACHMENT1, + GL_COLOR_ATTACHMENT2, + GL_COLOR_ATTACHMENT3, + GL_COLOR_ATTACHMENT4, + GL_COLOR_ATTACHMENT5, + GL_COLOR_ATTACHMENT6, + GL_COLOR_ATTACHMENT7, +#endif + }; + +#if defined(GRAPHICS_API_OPENGL_ES3) + glDrawBuffersEXT(count, buffers); +#else + glDrawBuffers(count, buffers); +#endif + } + } + else TRACELOG(LOG_WARNING, "GL: One color buffer active by default"); +#endif +} + +//---------------------------------------------------------------------------------- +// General render state configuration +//---------------------------------------------------------------------------------- + +// Enable color blending +void rlEnableColorBlend(void) { glEnable(GL_BLEND); } + +// Disable color blending +void rlDisableColorBlend(void) { glDisable(GL_BLEND); } + +// Enable depth test +void rlEnableDepthTest(void) { glEnable(GL_DEPTH_TEST); } + +// Disable depth test +void rlDisableDepthTest(void) { glDisable(GL_DEPTH_TEST); } + +// Enable depth write +void rlEnableDepthMask(void) { glDepthMask(GL_TRUE); } + +// Disable depth write +void rlDisableDepthMask(void) { glDepthMask(GL_FALSE); } + +// Enable backface culling +void rlEnableBackfaceCulling(void) { glEnable(GL_CULL_FACE); } + +// Disable backface culling +void rlDisableBackfaceCulling(void) { glDisable(GL_CULL_FACE); } + +// Set color mask active for screen read/draw +void rlColorMask(bool r, bool g, bool b, bool a) { glColorMask(r, g, b, a); } + +// Set face culling mode +void rlSetCullFace(int mode) +{ + switch (mode) + { + case RL_CULL_FACE_BACK: glCullFace(GL_BACK); break; + case RL_CULL_FACE_FRONT: glCullFace(GL_FRONT); break; + default: break; + } +} + +// Enable scissor test +void rlEnableScissorTest(void) { glEnable(GL_SCISSOR_TEST); } + +// Disable scissor test +void rlDisableScissorTest(void) { glDisable(GL_SCISSOR_TEST); } + +// Scissor test +void rlScissor(int x, int y, int width, int height) { glScissor(x, y, width, height); } + +// Enable wire mode +void rlEnableWireMode(void) +{ +#if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33) + // NOTE: glPolygonMode() not available on OpenGL ES + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); +#endif +} + +// Enable point mode +void rlEnablePointMode(void) +{ +#if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33) + // NOTE: glPolygonMode() not available on OpenGL ES + glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); + glEnable(GL_PROGRAM_POINT_SIZE); +#endif +} + +// Disable wire mode +void rlDisableWireMode(void) +{ +#if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33) + // NOTE: glPolygonMode() not available on OpenGL ES + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); +#endif +} + +// Set the line drawing width +void rlSetLineWidth(float width) { glLineWidth(width); } + +// Get the line drawing width +float rlGetLineWidth(void) +{ + float width = 0; + glGetFloatv(GL_LINE_WIDTH, &width); + return width; +} + +// Enable line aliasing +void rlEnableSmoothLines(void) +{ +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_11) + glEnable(GL_LINE_SMOOTH); +#endif +} + +// Disable line aliasing +void rlDisableSmoothLines(void) +{ +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_11) + glDisable(GL_LINE_SMOOTH); +#endif +} + +// Enable stereo rendering +void rlEnableStereoRender(void) +{ +#if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)) + RLGL.State.stereoRender = true; +#endif +} + +// Disable stereo rendering +void rlDisableStereoRender(void) +{ +#if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)) + RLGL.State.stereoRender = false; +#endif +} + +// Check if stereo render is enabled +bool rlIsStereoRenderEnabled(void) +{ +#if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)) + return RLGL.State.stereoRender; +#else + return false; +#endif +} + +// Clear color buffer with color +void rlClearColor(unsigned char r, unsigned char g, unsigned char b, unsigned char a) +{ + // Color values clamp to 0.0f(0) and 1.0f(255) + float cr = (float)r/255; + float cg = (float)g/255; + float cb = (float)b/255; + float ca = (float)a/255; + + glClearColor(cr, cg, cb, ca); +} + +// Clear used screen buffers (color and depth) +void rlClearScreenBuffers(void) +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear used buffers: Color and Depth (Depth is used for 3D) + //glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); // Stencil buffer not used... +} + +// Check and log OpenGL error codes +void rlCheckErrors(void) +{ +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + int check = 1; + while (check) + { + const GLenum err = glGetError(); + switch (err) + { + case GL_NO_ERROR: check = 0; break; + case 0x0500: TRACELOG(RL_LOG_WARNING, "GL: Error detected: GL_INVALID_ENUM"); break; + case 0x0501: TRACELOG(RL_LOG_WARNING, "GL: Error detected: GL_INVALID_VALUE"); break; + case 0x0502: TRACELOG(RL_LOG_WARNING, "GL: Error detected: GL_INVALID_OPERATION"); break; + case 0x0503: TRACELOG(RL_LOG_WARNING, "GL: Error detected: GL_STACK_OVERFLOW"); break; + case 0x0504: TRACELOG(RL_LOG_WARNING, "GL: Error detected: GL_STACK_UNDERFLOW"); break; + case 0x0505: TRACELOG(RL_LOG_WARNING, "GL: Error detected: GL_OUT_OF_MEMORY"); break; + case 0x0506: TRACELOG(RL_LOG_WARNING, "GL: Error detected: GL_INVALID_FRAMEBUFFER_OPERATION"); break; + default: TRACELOG(RL_LOG_WARNING, "GL: Error detected: Unknown error code: %x", err); break; + } + } +#endif +} + +// Set blend mode +void rlSetBlendMode(int mode) +{ +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + if ((RLGL.State.currentBlendMode != mode) || ((mode == RL_BLEND_CUSTOM || mode == RL_BLEND_CUSTOM_SEPARATE) && RLGL.State.glCustomBlendModeModified)) + { + rlDrawRenderBatch(RLGL.currentBatch); + + switch (mode) + { + case RL_BLEND_ALPHA: glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendEquation(GL_FUNC_ADD); break; + case RL_BLEND_ADDITIVE: glBlendFunc(GL_SRC_ALPHA, GL_ONE); glBlendEquation(GL_FUNC_ADD); break; + case RL_BLEND_MULTIPLIED: glBlendFunc(GL_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA); glBlendEquation(GL_FUNC_ADD); break; + case RL_BLEND_ADD_COLORS: glBlendFunc(GL_ONE, GL_ONE); glBlendEquation(GL_FUNC_ADD); break; + case RL_BLEND_SUBTRACT_COLORS: glBlendFunc(GL_ONE, GL_ONE); glBlendEquation(GL_FUNC_SUBTRACT); break; + case RL_BLEND_ALPHA_PREMULTIPLY: glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); glBlendEquation(GL_FUNC_ADD); break; + case RL_BLEND_CUSTOM: + { + // NOTE: Using GL blend src/dst factors and GL equation configured with rlSetBlendFactors() + glBlendFunc(RLGL.State.glBlendSrcFactor, RLGL.State.glBlendDstFactor); glBlendEquation(RLGL.State.glBlendEquation); + + } break; + case RL_BLEND_CUSTOM_SEPARATE: + { + // NOTE: Using GL blend src/dst factors and GL equation configured with rlSetBlendFactorsSeparate() + glBlendFuncSeparate(RLGL.State.glBlendSrcFactorRGB, RLGL.State.glBlendDestFactorRGB, RLGL.State.glBlendSrcFactorAlpha, RLGL.State.glBlendDestFactorAlpha); + glBlendEquationSeparate(RLGL.State.glBlendEquationRGB, RLGL.State.glBlendEquationAlpha); + + } break; + default: break; + } + + RLGL.State.currentBlendMode = mode; + RLGL.State.glCustomBlendModeModified = false; + } +#endif +} + +// Set blending mode factor and equation +void rlSetBlendFactors(int glSrcFactor, int glDstFactor, int glEquation) +{ +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + if ((RLGL.State.glBlendSrcFactor != glSrcFactor) || + (RLGL.State.glBlendDstFactor != glDstFactor) || + (RLGL.State.glBlendEquation != glEquation)) + { + RLGL.State.glBlendSrcFactor = glSrcFactor; + RLGL.State.glBlendDstFactor = glDstFactor; + RLGL.State.glBlendEquation = glEquation; + + RLGL.State.glCustomBlendModeModified = true; + } +#endif +} + +// Set blending mode factor and equation separately for RGB and alpha +void rlSetBlendFactorsSeparate(int glSrcRGB, int glDstRGB, int glSrcAlpha, int glDstAlpha, int glEqRGB, int glEqAlpha) +{ +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + if ((RLGL.State.glBlendSrcFactorRGB != glSrcRGB) || + (RLGL.State.glBlendDestFactorRGB != glDstRGB) || + (RLGL.State.glBlendSrcFactorAlpha != glSrcAlpha) || + (RLGL.State.glBlendDestFactorAlpha != glDstAlpha) || + (RLGL.State.glBlendEquationRGB != glEqRGB) || + (RLGL.State.glBlendEquationAlpha != glEqAlpha)) + { + RLGL.State.glBlendSrcFactorRGB = glSrcRGB; + RLGL.State.glBlendDestFactorRGB = glDstRGB; + RLGL.State.glBlendSrcFactorAlpha = glSrcAlpha; + RLGL.State.glBlendDestFactorAlpha = glDstAlpha; + RLGL.State.glBlendEquationRGB = glEqRGB; + RLGL.State.glBlendEquationAlpha = glEqAlpha; + + RLGL.State.glCustomBlendModeModified = true; + } +#endif +} + +//---------------------------------------------------------------------------------- +// Module Functions Definition - OpenGL Debug +//---------------------------------------------------------------------------------- +#if defined(RLGL_ENABLE_OPENGL_DEBUG_CONTEXT) && defined(GRAPHICS_API_OPENGL_43) +static void GLAPIENTRY rlDebugMessageCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, const void *userParam) +{ + // Ignore non-significant error/warning codes (NVidia drivers) + // NOTE: Here there are the details with a sample output: + // - #131169 - Framebuffer detailed info: The driver allocated storage for renderbuffer 2. (severity: low) + // - #131185 - Buffer detailed info: Buffer object 1 (bound to GL_ELEMENT_ARRAY_BUFFER_ARB, usage hint is GL_ENUM_88e4) + // will use VIDEO memory as the source for buffer object operations. (severity: low) + // - #131218 - Program/shader state performance warning: Vertex shader in program 7 is being recompiled based on GL state. (severity: medium) + // - #131204 - Texture state usage warning: The texture object (0) bound to texture image unit 0 does not have + // a defined base level and cannot be used for texture mapping. (severity: low) + if ((id == 131169) || (id == 131185) || (id == 131218) || (id == 131204)) return; + + const char *msgSource = NULL; + switch (source) + { + case GL_DEBUG_SOURCE_API: msgSource = "API"; break; + case GL_DEBUG_SOURCE_WINDOW_SYSTEM: msgSource = "WINDOW_SYSTEM"; break; + case GL_DEBUG_SOURCE_SHADER_COMPILER: msgSource = "SHADER_COMPILER"; break; + case GL_DEBUG_SOURCE_THIRD_PARTY: msgSource = "THIRD_PARTY"; break; + case GL_DEBUG_SOURCE_APPLICATION: msgSource = "APPLICATION"; break; + case GL_DEBUG_SOURCE_OTHER: msgSource = "OTHER"; break; + default: break; + } + + const char *msgType = NULL; + switch (type) + { + case GL_DEBUG_TYPE_ERROR: msgType = "ERROR"; break; + case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: msgType = "DEPRECATED_BEHAVIOR"; break; + case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: msgType = "UNDEFINED_BEHAVIOR"; break; + case GL_DEBUG_TYPE_PORTABILITY: msgType = "PORTABILITY"; break; + case GL_DEBUG_TYPE_PERFORMANCE: msgType = "PERFORMANCE"; break; + case GL_DEBUG_TYPE_MARKER: msgType = "MARKER"; break; + case GL_DEBUG_TYPE_PUSH_GROUP: msgType = "PUSH_GROUP"; break; + case GL_DEBUG_TYPE_POP_GROUP: msgType = "POP_GROUP"; break; + case GL_DEBUG_TYPE_OTHER: msgType = "OTHER"; break; + default: break; + } + + const char *msgSeverity = "DEFAULT"; + switch (severity) + { + case GL_DEBUG_SEVERITY_LOW: msgSeverity = "LOW"; break; + case GL_DEBUG_SEVERITY_MEDIUM: msgSeverity = "MEDIUM"; break; + case GL_DEBUG_SEVERITY_HIGH: msgSeverity = "HIGH"; break; + case GL_DEBUG_SEVERITY_NOTIFICATION: msgSeverity = "NOTIFICATION"; break; + default: break; + } + + TRACELOG(LOG_WARNING, "GL: OpenGL debug message: %s", message); + TRACELOG(LOG_WARNING, " > Type: %s", msgType); + TRACELOG(LOG_WARNING, " > Source = %s", msgSource); + TRACELOG(LOG_WARNING, " > Severity = %s", msgSeverity); +} +#endif + +//---------------------------------------------------------------------------------- +// Module Functions Definition - rlgl functionality +//---------------------------------------------------------------------------------- + +// Initialize rlgl: OpenGL extensions, default buffers/shaders/textures, OpenGL states +void rlglInit(int width, int height) +{ + // Enable OpenGL debug context if required +#if defined(RLGL_ENABLE_OPENGL_DEBUG_CONTEXT) && defined(GRAPHICS_API_OPENGL_43) + if ((glDebugMessageCallback != NULL) && (glDebugMessageControl != NULL)) + { + glDebugMessageCallback(rlDebugMessageCallback, 0); + // glDebugMessageControl(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_ERROR, GL_DEBUG_SEVERITY_HIGH, 0, 0, GL_TRUE); + + // Debug context options: + // - GL_DEBUG_OUTPUT - Faster version but not useful for breakpoints + // - GL_DEBUG_OUTPUT_SYNCHRONUS - Callback is in sync with errors, so a breakpoint can be placed on the callback in order to get a stacktrace for the GL error + glEnable(GL_DEBUG_OUTPUT); + glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS); + } +#endif + +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + // Init default white texture + unsigned char pixels[4] = { 255, 255, 255, 255 }; // 1 pixel RGBA (4 bytes) + RLGL.State.defaultTextureId = rlLoadTexture(pixels, 1, 1, RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8, 1); + + if (RLGL.State.defaultTextureId != 0) TRACELOG(RL_LOG_INFO, "TEXTURE: [ID %i] Default texture loaded successfully", RLGL.State.defaultTextureId); + else TRACELOG(RL_LOG_WARNING, "TEXTURE: Failed to load default texture"); + + // Init default Shader (customized for GL 3.3 and ES2) + // Loaded: RLGL.State.defaultShaderId + RLGL.State.defaultShaderLocs + rlLoadShaderDefault(); + RLGL.State.currentShaderId = RLGL.State.defaultShaderId; + RLGL.State.currentShaderLocs = RLGL.State.defaultShaderLocs; + + // Init default vertex arrays buffers + // Simulate that the default shader has the location RL_SHADER_LOC_VERTEX_NORMAL to bind the normal buffer for the default render batch + RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_NORMAL] = RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL; + RLGL.defaultBatch = rlLoadRenderBatch(RL_DEFAULT_BATCH_BUFFERS, RL_DEFAULT_BATCH_BUFFER_ELEMENTS); + RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_NORMAL] = -1; + RLGL.currentBatch = &RLGL.defaultBatch; + + // Init stack matrices (emulating OpenGL 1.1) + for (int i = 0; i < RL_MAX_MATRIX_STACK_SIZE; i++) RLGL.State.stack[i] = rlMatrixIdentity(); + + // Init internal matrices + RLGL.State.transform = rlMatrixIdentity(); + RLGL.State.projection = rlMatrixIdentity(); + RLGL.State.modelview = rlMatrixIdentity(); + RLGL.State.currentMatrix = &RLGL.State.modelview; +#endif // GRAPHICS_API_OPENGL_33 || GRAPHICS_API_OPENGL_ES2 + + // Initialize OpenGL default states + //---------------------------------------------------------- + // Init state: Depth test + glDepthFunc(GL_LEQUAL); // Type of depth testing to apply + glDisable(GL_DEPTH_TEST); // Disable depth testing for 2D (only used for 3D) + + // Init state: Blending mode + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // Color blending function (how colors are mixed) + glEnable(GL_BLEND); // Enable color blending (required to work with transparencies) + + // Init state: Culling + // NOTE: All shapes/models triangles are drawn CCW + glCullFace(GL_BACK); // Cull the back face (default) + glFrontFace(GL_CCW); // Front face are defined counter clockwise (default) + glEnable(GL_CULL_FACE); // Enable backface culling + + // Init state: Cubemap seamless +#if defined(GRAPHICS_API_OPENGL_33) + glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); // Seamless cubemaps (not supported on OpenGL ES 2.0) +#endif + +#if defined(GRAPHICS_API_OPENGL_11) + // Init state: Color hints (deprecated in OpenGL 3.0+) + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Improve quality of color and texture coordinate interpolation + glShadeModel(GL_SMOOTH); // Smooth shading between vertex (vertex colors interpolation) +#endif + +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + // Store screen size into global variables + RLGL.State.framebufferWidth = width; + RLGL.State.framebufferHeight = height; + + TRACELOG(RL_LOG_INFO, "RLGL: Default OpenGL state initialized successfully"); + //---------------------------------------------------------- +#endif + + // Init state: Color/Depth buffers clear + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Set clear color (black) + glClearDepth(1.0f); // Set clear depth value (default) + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear color and depth buffers (depth buffer required for 3D) +} + +// Vertex Buffer Object deinitialization (memory free) +void rlglClose(void) +{ +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + rlUnloadRenderBatch(RLGL.defaultBatch); + + rlUnloadShaderDefault(); // Unload default shader + + glDeleteTextures(1, &RLGL.State.defaultTextureId); // Unload default texture + TRACELOG(RL_LOG_INFO, "TEXTURE: [ID %i] Default texture unloaded successfully", RLGL.State.defaultTextureId); +#endif +} + +// Load OpenGL extensions +// NOTE: External loader function must be provided +void rlLoadExtensions(void *loader) +{ +#if defined(GRAPHICS_API_OPENGL_33) // Also defined for GRAPHICS_API_OPENGL_21 + // NOTE: glad is generated and contains only required OpenGL 3.3 Core extensions (and lower versions) + if (gladLoadGL((GLADloadfunc)loader) == 0) TRACELOG(RL_LOG_WARNING, "GLAD: Cannot load OpenGL extensions"); + else TRACELOG(RL_LOG_INFO, "GLAD: OpenGL extensions loaded successfully"); + + // Get number of supported extensions + GLint numExt = 0; + glGetIntegerv(GL_NUM_EXTENSIONS, &numExt); + TRACELOG(RL_LOG_INFO, "GL: Supported extensions count: %i", numExt); + +#if defined(RLGL_SHOW_GL_DETAILS_INFO) + // Get supported extensions list + // WARNING: glGetStringi() not available on OpenGL 2.1 + TRACELOG(RL_LOG_INFO, "GL: OpenGL extensions:"); + for (int i = 0; i < numExt; i++) TRACELOG(RL_LOG_INFO, " %s", glGetStringi(GL_EXTENSIONS, i)); +#endif + +#if defined(GRAPHICS_API_OPENGL_21) + // Register supported extensions flags + // Optional OpenGL 2.1 extensions + RLGL.ExtSupported.vao = GLAD_GL_ARB_vertex_array_object; + RLGL.ExtSupported.instancing = (GLAD_GL_EXT_draw_instanced && GLAD_GL_ARB_instanced_arrays); + RLGL.ExtSupported.texNPOT = GLAD_GL_ARB_texture_non_power_of_two; + RLGL.ExtSupported.texFloat32 = GLAD_GL_ARB_texture_float; + RLGL.ExtSupported.texFloat16 = GLAD_GL_ARB_texture_float; + RLGL.ExtSupported.texDepth = GLAD_GL_ARB_depth_texture; + RLGL.ExtSupported.maxDepthBits = 32; + RLGL.ExtSupported.texAnisoFilter = GLAD_GL_EXT_texture_filter_anisotropic; + RLGL.ExtSupported.texMirrorClamp = GLAD_GL_EXT_texture_mirror_clamp; +#else + // Register supported extensions flags + // OpenGL 3.3 extensions supported by default (core) + RLGL.ExtSupported.vao = true; + RLGL.ExtSupported.instancing = true; + RLGL.ExtSupported.texNPOT = true; + RLGL.ExtSupported.texFloat32 = true; + RLGL.ExtSupported.texFloat16 = true; + RLGL.ExtSupported.texDepth = true; + RLGL.ExtSupported.maxDepthBits = 32; + RLGL.ExtSupported.texAnisoFilter = true; + RLGL.ExtSupported.texMirrorClamp = true; +#endif + + // Optional OpenGL 3.3 extensions + RLGL.ExtSupported.texCompASTC = GLAD_GL_KHR_texture_compression_astc_hdr && GLAD_GL_KHR_texture_compression_astc_ldr; + RLGL.ExtSupported.texCompDXT = GLAD_GL_EXT_texture_compression_s3tc; // Texture compression: DXT + RLGL.ExtSupported.texCompETC2 = GLAD_GL_ARB_ES3_compatibility; // Texture compression: ETC2/EAC + #if defined(GRAPHICS_API_OPENGL_43) + RLGL.ExtSupported.computeShader = GLAD_GL_ARB_compute_shader; + RLGL.ExtSupported.ssbo = GLAD_GL_ARB_shader_storage_buffer_object; + #endif + +#endif // GRAPHICS_API_OPENGL_33 + +#if defined(GRAPHICS_API_OPENGL_ES3) + // Register supported extensions flags + // OpenGL ES 3.0 extensions supported by default (or it should be) + RLGL.ExtSupported.vao = true; + RLGL.ExtSupported.instancing = true; + RLGL.ExtSupported.texNPOT = true; + RLGL.ExtSupported.texFloat32 = true; + RLGL.ExtSupported.texFloat16 = true; + RLGL.ExtSupported.texDepth = true; + RLGL.ExtSupported.texDepthWebGL = true; + RLGL.ExtSupported.maxDepthBits = 24; + RLGL.ExtSupported.texAnisoFilter = true; + RLGL.ExtSupported.texMirrorClamp = true; + // TODO: Check for additional OpenGL ES 3.0 supported extensions: + //RLGL.ExtSupported.texCompDXT = true; + //RLGL.ExtSupported.texCompETC1 = true; + //RLGL.ExtSupported.texCompETC2 = true; + //RLGL.ExtSupported.texCompPVRT = true; + //RLGL.ExtSupported.texCompASTC = true; + //RLGL.ExtSupported.maxAnisotropyLevel = true; + //RLGL.ExtSupported.computeShader = true; + //RLGL.ExtSupported.ssbo = true; + +#elif defined(GRAPHICS_API_OPENGL_ES2) + + #if defined(PLATFORM_DESKTOP_GLFW) || defined(PLATFORM_DESKTOP_SDL) + // TODO: Support GLAD loader for OpenGL ES 3.0 + if (gladLoadGLES2((GLADloadfunc)loader) == 0) TRACELOG(RL_LOG_WARNING, "GLAD: Cannot load OpenGL ES2.0 functions"); + else TRACELOG(RL_LOG_INFO, "GLAD: OpenGL ES 2.0 loaded successfully"); + #endif + + // Get supported extensions list + GLint numExt = 0; + const char **extList = RL_MALLOC(512*sizeof(const char *)); // Allocate 512 strings pointers (2 KB) + const char *extensions = (const char *)glGetString(GL_EXTENSIONS); // One big const string + + // NOTE: We have to duplicate string because glGetString() returns a const string + int size = strlen(extensions) + 1; // Get extensions string size in bytes + char *extensionsDup = (char *)RL_CALLOC(size, sizeof(char)); + strcpy(extensionsDup, extensions); + extList[numExt] = extensionsDup; + + for (int i = 0; i < size; i++) + { + if (extensionsDup[i] == ' ') + { + extensionsDup[i] = '\0'; + numExt++; + extList[numExt] = &extensionsDup[i + 1]; + } + } + + TRACELOG(RL_LOG_INFO, "GL: Supported extensions count: %i", numExt); + +#if defined(RLGL_SHOW_GL_DETAILS_INFO) + TRACELOG(RL_LOG_INFO, "GL: OpenGL extensions:"); + for (int i = 0; i < numExt; i++) TRACELOG(RL_LOG_INFO, " %s", extList[i]); +#endif + + // Check required extensions + for (int i = 0; i < numExt; i++) + { + // Check VAO support + // NOTE: Only check on OpenGL ES, OpenGL 3.3 has VAO support as core feature + if (strcmp(extList[i], (const char *)"GL_OES_vertex_array_object") == 0) + { + // The extension is supported by our hardware and driver, try to get related functions pointers + // NOTE: emscripten does not support VAOs natively, it uses emulation and it reduces overall performance... + glGenVertexArrays = (PFNGLGENVERTEXARRAYSOESPROC)((rlglLoadProc)loader)("glGenVertexArraysOES"); + glBindVertexArray = (PFNGLBINDVERTEXARRAYOESPROC)((rlglLoadProc)loader)("glBindVertexArrayOES"); + glDeleteVertexArrays = (PFNGLDELETEVERTEXARRAYSOESPROC)((rlglLoadProc)loader)("glDeleteVertexArraysOES"); + //glIsVertexArray = (PFNGLISVERTEXARRAYOESPROC)loader("glIsVertexArrayOES"); // NOTE: Fails in WebGL, omitted + + if ((glGenVertexArrays != NULL) && (glBindVertexArray != NULL) && (glDeleteVertexArrays != NULL)) RLGL.ExtSupported.vao = true; + } + + // Check instanced rendering support + if (strstr(extList[i], (const char*)"instanced_arrays") != NULL) // Broad check for instanced_arrays + { + // Specific check + if (strcmp(extList[i], (const char *)"GL_ANGLE_instanced_arrays") == 0) // ANGLE + { + glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawArraysInstancedANGLE"); + glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawElementsInstancedANGLE"); + glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISOREXTPROC)((rlglLoadProc)loader)("glVertexAttribDivisorANGLE"); + } + else if (strcmp(extList[i], (const char *)"GL_EXT_instanced_arrays") == 0) // EXT + { + glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawArraysInstancedEXT"); + glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawElementsInstancedEXT"); + glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISOREXTPROC)((rlglLoadProc)loader)("glVertexAttribDivisorEXT"); + } + else if (strcmp(extList[i], (const char *)"GL_NV_instanced_arrays") == 0) // NVIDIA GLES + { + glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawArraysInstancedNV"); + glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawElementsInstancedNV"); + glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISOREXTPROC)((rlglLoadProc)loader)("glVertexAttribDivisorNV"); + } + + // The feature will only be marked as supported if the elements from GL_XXX_instanced_arrays are present + if ((glDrawArraysInstanced != NULL) && (glDrawElementsInstanced != NULL) && (glVertexAttribDivisor != NULL)) RLGL.ExtSupported.instancing = true; + } + else if (strstr(extList[i], (const char *)"draw_instanced") != NULL) + { + // GL_ANGLE_draw_instanced doesn't exist + if (strcmp(extList[i], (const char *)"GL_EXT_draw_instanced") == 0) + { + glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawArraysInstancedEXT"); + glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawElementsInstancedEXT"); + } + else if (strcmp(extList[i], (const char*)"GL_NV_draw_instanced") == 0) + { + glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawArraysInstancedNV"); + glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawElementsInstancedNV"); + } + + // But the functions will at least be loaded if only GL_XX_EXT_draw_instanced exist + if ((glDrawArraysInstanced != NULL) && (glDrawElementsInstanced != NULL) && (glVertexAttribDivisor != NULL)) RLGL.ExtSupported.instancing = true; + } + + // Check NPOT textures support + // NOTE: Only check on OpenGL ES, OpenGL 3.3 has NPOT textures full support as core feature + if (strcmp(extList[i], (const char *)"GL_OES_texture_npot") == 0) RLGL.ExtSupported.texNPOT = true; + + // Check texture float support + if (strcmp(extList[i], (const char *)"GL_OES_texture_float") == 0) RLGL.ExtSupported.texFloat32 = true; + if (strcmp(extList[i], (const char *)"GL_OES_texture_half_float") == 0) RLGL.ExtSupported.texFloat16 = true; + + // Check depth texture support + if (strcmp(extList[i], (const char *)"GL_OES_depth_texture") == 0) RLGL.ExtSupported.texDepth = true; + if (strcmp(extList[i], (const char *)"GL_WEBGL_depth_texture") == 0) RLGL.ExtSupported.texDepthWebGL = true; // WebGL requires unsized internal format + if (RLGL.ExtSupported.texDepthWebGL) RLGL.ExtSupported.texDepth = true; + + if (strcmp(extList[i], (const char *)"GL_OES_depth24") == 0) RLGL.ExtSupported.maxDepthBits = 24; // Not available on WebGL + if (strcmp(extList[i], (const char *)"GL_OES_depth32") == 0) RLGL.ExtSupported.maxDepthBits = 32; // Not available on WebGL + + // Check texture compression support: DXT + if ((strcmp(extList[i], (const char *)"GL_EXT_texture_compression_s3tc") == 0) || + (strcmp(extList[i], (const char *)"GL_WEBGL_compressed_texture_s3tc") == 0) || + (strcmp(extList[i], (const char *)"GL_WEBKIT_WEBGL_compressed_texture_s3tc") == 0)) RLGL.ExtSupported.texCompDXT = true; + + // Check texture compression support: ETC1 + if ((strcmp(extList[i], (const char *)"GL_OES_compressed_ETC1_RGB8_texture") == 0) || + (strcmp(extList[i], (const char *)"GL_WEBGL_compressed_texture_etc1") == 0)) RLGL.ExtSupported.texCompETC1 = true; + + // Check texture compression support: ETC2/EAC + if (strcmp(extList[i], (const char *)"GL_ARB_ES3_compatibility") == 0) RLGL.ExtSupported.texCompETC2 = true; + + // Check texture compression support: PVR + if (strcmp(extList[i], (const char *)"GL_IMG_texture_compression_pvrtc") == 0) RLGL.ExtSupported.texCompPVRT = true; + + // Check texture compression support: ASTC + if (strcmp(extList[i], (const char *)"GL_KHR_texture_compression_astc_hdr") == 0) RLGL.ExtSupported.texCompASTC = true; + + // Check anisotropic texture filter support + if (strcmp(extList[i], (const char *)"GL_EXT_texture_filter_anisotropic") == 0) RLGL.ExtSupported.texAnisoFilter = true; + + // Check clamp mirror wrap mode support + if (strcmp(extList[i], (const char *)"GL_EXT_texture_mirror_clamp") == 0) RLGL.ExtSupported.texMirrorClamp = true; + } + + // Free extensions pointers + RL_FREE(extList); + RL_FREE(extensionsDup); // Duplicated string must be deallocated +#endif // GRAPHICS_API_OPENGL_ES2 + + // Check OpenGL information and capabilities + //------------------------------------------------------------------------------ + // Show current OpenGL and GLSL version + TRACELOG(RL_LOG_INFO, "GL: OpenGL device information:"); + TRACELOG(RL_LOG_INFO, " > Vendor: %s", glGetString(GL_VENDOR)); + TRACELOG(RL_LOG_INFO, " > Renderer: %s", glGetString(GL_RENDERER)); + TRACELOG(RL_LOG_INFO, " > Version: %s", glGetString(GL_VERSION)); + TRACELOG(RL_LOG_INFO, " > GLSL: %s", glGetString(GL_SHADING_LANGUAGE_VERSION)); + +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + // NOTE: Anisotropy levels capability is an extension + #ifndef GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT + #define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF + #endif + glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &RLGL.ExtSupported.maxAnisotropyLevel); + +#if defined(RLGL_SHOW_GL_DETAILS_INFO) + // Show some OpenGL GPU capabilities + TRACELOG(RL_LOG_INFO, "GL: OpenGL capabilities:"); + GLint capability = 0; + glGetIntegerv(GL_MAX_TEXTURE_SIZE, &capability); + TRACELOG(RL_LOG_INFO, " GL_MAX_TEXTURE_SIZE: %i", capability); + glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &capability); + TRACELOG(RL_LOG_INFO, " GL_MAX_CUBE_MAP_TEXTURE_SIZE: %i", capability); + glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &capability); + TRACELOG(RL_LOG_INFO, " GL_MAX_TEXTURE_IMAGE_UNITS: %i", capability); + glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &capability); + TRACELOG(RL_LOG_INFO, " GL_MAX_VERTEX_ATTRIBS: %i", capability); + #if !defined(GRAPHICS_API_OPENGL_ES2) + glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &capability); + TRACELOG(RL_LOG_INFO, " GL_MAX_UNIFORM_BLOCK_SIZE: %i", capability); + glGetIntegerv(GL_MAX_DRAW_BUFFERS, &capability); + TRACELOG(RL_LOG_INFO, " GL_MAX_DRAW_BUFFERS: %i", capability); + if (RLGL.ExtSupported.texAnisoFilter) TRACELOG(RL_LOG_INFO, " GL_MAX_TEXTURE_MAX_ANISOTROPY: %.0f", RLGL.ExtSupported.maxAnisotropyLevel); + #endif + glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &capability); + TRACELOG(RL_LOG_INFO, " GL_NUM_COMPRESSED_TEXTURE_FORMATS: %i", capability); + GLint *compFormats = (GLint *)RL_CALLOC(capability, sizeof(GLint)); + glGetIntegerv(GL_COMPRESSED_TEXTURE_FORMATS, compFormats); + for (int i = 0; i < capability; i++) TRACELOG(RL_LOG_INFO, " %s", rlGetCompressedFormatName(compFormats[i])); + RL_FREE(compFormats); + +#if defined(GRAPHICS_API_OPENGL_43) + glGetIntegerv(GL_MAX_VERTEX_ATTRIB_BINDINGS, &capability); + TRACELOG(RL_LOG_INFO, " GL_MAX_VERTEX_ATTRIB_BINDINGS: %i", capability); + glGetIntegerv(GL_MAX_UNIFORM_LOCATIONS, &capability); + TRACELOG(RL_LOG_INFO, " GL_MAX_UNIFORM_LOCATIONS: %i", capability); +#endif // GRAPHICS_API_OPENGL_43 +#else // RLGL_SHOW_GL_DETAILS_INFO + + // Show some basic info about GL supported features + if (RLGL.ExtSupported.vao) TRACELOG(RL_LOG_INFO, "GL: VAO extension detected, VAO functions loaded successfully"); + else TRACELOG(RL_LOG_WARNING, "GL: VAO extension not found, VAO not supported"); + if (RLGL.ExtSupported.texNPOT) TRACELOG(RL_LOG_INFO, "GL: NPOT textures extension detected, full NPOT textures supported"); + else TRACELOG(RL_LOG_WARNING, "GL: NPOT textures extension not found, limited NPOT support (no-mipmaps, no-repeat)"); + if (RLGL.ExtSupported.texCompDXT) TRACELOG(RL_LOG_INFO, "GL: DXT compressed textures supported"); + if (RLGL.ExtSupported.texCompETC1) TRACELOG(RL_LOG_INFO, "GL: ETC1 compressed textures supported"); + if (RLGL.ExtSupported.texCompETC2) TRACELOG(RL_LOG_INFO, "GL: ETC2/EAC compressed textures supported"); + if (RLGL.ExtSupported.texCompPVRT) TRACELOG(RL_LOG_INFO, "GL: PVRT compressed textures supported"); + if (RLGL.ExtSupported.texCompASTC) TRACELOG(RL_LOG_INFO, "GL: ASTC compressed textures supported"); + if (RLGL.ExtSupported.computeShader) TRACELOG(RL_LOG_INFO, "GL: Compute shaders supported"); + if (RLGL.ExtSupported.ssbo) TRACELOG(RL_LOG_INFO, "GL: Shader storage buffer objects supported"); +#endif // RLGL_SHOW_GL_DETAILS_INFO + +#endif // GRAPHICS_API_OPENGL_33 || GRAPHICS_API_OPENGL_ES2 +} + +// Get current OpenGL version +int rlGetVersion(void) +{ + int glVersion = 0; +#if defined(GRAPHICS_API_OPENGL_11) + glVersion = RL_OPENGL_11; +#endif +#if defined(GRAPHICS_API_OPENGL_21) + glVersion = RL_OPENGL_21; +#elif defined(GRAPHICS_API_OPENGL_43) + glVersion = RL_OPENGL_43; +#elif defined(GRAPHICS_API_OPENGL_33) + glVersion = RL_OPENGL_33; +#endif +#if defined(GRAPHICS_API_OPENGL_ES3) + glVersion = RL_OPENGL_ES_30; +#elif defined(GRAPHICS_API_OPENGL_ES2) + glVersion = RL_OPENGL_ES_20; +#endif + + return glVersion; +} + +// Set current framebuffer width +void rlSetFramebufferWidth(int width) +{ +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + RLGL.State.framebufferWidth = width; +#endif +} + +// Set current framebuffer height +void rlSetFramebufferHeight(int height) +{ +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + RLGL.State.framebufferHeight = height; +#endif +} + +// Get default framebuffer width +int rlGetFramebufferWidth(void) +{ + int width = 0; +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + width = RLGL.State.framebufferWidth; +#endif + return width; +} + +// Get default framebuffer height +int rlGetFramebufferHeight(void) +{ + int height = 0; +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + height = RLGL.State.framebufferHeight; +#endif + return height; +} + +// Get default internal texture (white texture) +// NOTE: Default texture is a 1x1 pixel UNCOMPRESSED_R8G8B8A8 +unsigned int rlGetTextureIdDefault(void) +{ + unsigned int id = 0; +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + id = RLGL.State.defaultTextureId; +#endif + return id; +} + +// Get default shader id +unsigned int rlGetShaderIdDefault(void) +{ + unsigned int id = 0; +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + id = RLGL.State.defaultShaderId; +#endif + return id; +} + +// Get default shader locs +int *rlGetShaderLocsDefault(void) +{ + int *locs = NULL; +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + locs = RLGL.State.defaultShaderLocs; +#endif + return locs; +} + +// Render batch management +//------------------------------------------------------------------------------------------------ +// Load render batch +rlRenderBatch rlLoadRenderBatch(int numBuffers, int bufferElements) +{ + rlRenderBatch batch = { 0 }; + +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + // Initialize CPU (RAM) vertex buffers (position, texcoord, color data and indexes) + //-------------------------------------------------------------------------------------------- + batch.vertexBuffer = (rlVertexBuffer *)RL_MALLOC(numBuffers*sizeof(rlVertexBuffer)); + + for (int i = 0; i < numBuffers; i++) + { + batch.vertexBuffer[i].elementCount = bufferElements; + + batch.vertexBuffer[i].vertices = (float *)RL_MALLOC(bufferElements*3*4*sizeof(float)); // 3 float by vertex, 4 vertex by quad + batch.vertexBuffer[i].texcoords = (float *)RL_MALLOC(bufferElements*2*4*sizeof(float)); // 2 float by texcoord, 4 texcoord by quad + batch.vertexBuffer[i].normals = (float *)RL_MALLOC(bufferElements*3*4*sizeof(float)); // 3 float by vertex, 4 vertex by quad + batch.vertexBuffer[i].colors = (unsigned char *)RL_MALLOC(bufferElements*4*4*sizeof(unsigned char)); // 4 float by color, 4 colors by quad +#if defined(GRAPHICS_API_OPENGL_33) + batch.vertexBuffer[i].indices = (unsigned int *)RL_MALLOC(bufferElements*6*sizeof(unsigned int)); // 6 int by quad (indices) +#endif +#if defined(GRAPHICS_API_OPENGL_ES2) + batch.vertexBuffer[i].indices = (unsigned short *)RL_MALLOC(bufferElements*6*sizeof(unsigned short)); // 6 int by quad (indices) +#endif + + for (int j = 0; j < (3*4*bufferElements); j++) batch.vertexBuffer[i].vertices[j] = 0.0f; + for (int j = 0; j < (2*4*bufferElements); j++) batch.vertexBuffer[i].texcoords[j] = 0.0f; + for (int j = 0; j < (3*4*bufferElements); j++) batch.vertexBuffer[i].normals[j] = 0.0f; + for (int j = 0; j < (4*4*bufferElements); j++) batch.vertexBuffer[i].colors[j] = 0; + + int k = 0; + + // Indices can be initialized right now + for (int j = 0; j < (6*bufferElements); j += 6) + { + batch.vertexBuffer[i].indices[j] = 4*k; + batch.vertexBuffer[i].indices[j + 1] = 4*k + 1; + batch.vertexBuffer[i].indices[j + 2] = 4*k + 2; + batch.vertexBuffer[i].indices[j + 3] = 4*k; + batch.vertexBuffer[i].indices[j + 4] = 4*k + 2; + batch.vertexBuffer[i].indices[j + 5] = 4*k + 3; + + k++; + } + + RLGL.State.vertexCounter = 0; + } + + TRACELOG(RL_LOG_INFO, "RLGL: Render batch vertex buffers loaded successfully in RAM (CPU)"); + //-------------------------------------------------------------------------------------------- + + // Upload to GPU (VRAM) vertex data and initialize VAOs/VBOs + //-------------------------------------------------------------------------------------------- + for (int i = 0; i < numBuffers; i++) + { + if (RLGL.ExtSupported.vao) + { + // Initialize Quads VAO + glGenVertexArrays(1, &batch.vertexBuffer[i].vaoId); + glBindVertexArray(batch.vertexBuffer[i].vaoId); + } + + // Quads - Vertex buffers binding and attributes enable + // Vertex position buffer (shader-location = 0) + glGenBuffers(1, &batch.vertexBuffer[i].vboId[0]); + glBindBuffer(GL_ARRAY_BUFFER, batch.vertexBuffer[i].vboId[0]); + glBufferData(GL_ARRAY_BUFFER, bufferElements*3*4*sizeof(float), batch.vertexBuffer[i].vertices, GL_DYNAMIC_DRAW); + glEnableVertexAttribArray(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_POSITION]); + glVertexAttribPointer(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_POSITION], 3, GL_FLOAT, 0, 0, 0); + + // Vertex texcoord buffer (shader-location = 1) + glGenBuffers(1, &batch.vertexBuffer[i].vboId[1]); + glBindBuffer(GL_ARRAY_BUFFER, batch.vertexBuffer[i].vboId[1]); + glBufferData(GL_ARRAY_BUFFER, bufferElements*2*4*sizeof(float), batch.vertexBuffer[i].texcoords, GL_DYNAMIC_DRAW); + glEnableVertexAttribArray(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_TEXCOORD01]); + glVertexAttribPointer(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_TEXCOORD01], 2, GL_FLOAT, 0, 0, 0); + + // Vertex normal buffer (shader-location = 2) + glGenBuffers(1, &batch.vertexBuffer[i].vboId[2]); + glBindBuffer(GL_ARRAY_BUFFER, batch.vertexBuffer[i].vboId[2]); + glBufferData(GL_ARRAY_BUFFER, bufferElements*3*4*sizeof(float), batch.vertexBuffer[i].normals, GL_DYNAMIC_DRAW); + glEnableVertexAttribArray(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_NORMAL]); + glVertexAttribPointer(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_NORMAL], 3, GL_FLOAT, 0, 0, 0); + + // Vertex color buffer (shader-location = 3) + glGenBuffers(1, &batch.vertexBuffer[i].vboId[3]); + glBindBuffer(GL_ARRAY_BUFFER, batch.vertexBuffer[i].vboId[3]); + glBufferData(GL_ARRAY_BUFFER, bufferElements*4*4*sizeof(unsigned char), batch.vertexBuffer[i].colors, GL_DYNAMIC_DRAW); + glEnableVertexAttribArray(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_COLOR]); + glVertexAttribPointer(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_COLOR], 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); + + // Fill index buffer + glGenBuffers(1, &batch.vertexBuffer[i].vboId[4]); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, batch.vertexBuffer[i].vboId[4]); +#if defined(GRAPHICS_API_OPENGL_33) + glBufferData(GL_ELEMENT_ARRAY_BUFFER, bufferElements*6*sizeof(int), batch.vertexBuffer[i].indices, GL_STATIC_DRAW); +#endif +#if defined(GRAPHICS_API_OPENGL_ES2) + glBufferData(GL_ELEMENT_ARRAY_BUFFER, bufferElements*6*sizeof(short), batch.vertexBuffer[i].indices, GL_STATIC_DRAW); +#endif + } + + TRACELOG(RL_LOG_INFO, "RLGL: Render batch vertex buffers loaded successfully in VRAM (GPU)"); + + // Unbind the current VAO + if (RLGL.ExtSupported.vao) glBindVertexArray(0); + //-------------------------------------------------------------------------------------------- + + // Init draw calls tracking system + //-------------------------------------------------------------------------------------------- + batch.draws = (rlDrawCall *)RL_MALLOC(RL_DEFAULT_BATCH_DRAWCALLS*sizeof(rlDrawCall)); + + for (int i = 0; i < RL_DEFAULT_BATCH_DRAWCALLS; i++) + { + batch.draws[i].mode = RL_QUADS; + batch.draws[i].vertexCount = 0; + batch.draws[i].vertexAlignment = 0; + //batch.draws[i].vaoId = 0; + //batch.draws[i].shaderId = 0; + batch.draws[i].textureId = RLGL.State.defaultTextureId; + //batch.draws[i].RLGL.State.projection = rlMatrixIdentity(); + //batch.draws[i].RLGL.State.modelview = rlMatrixIdentity(); + } + + batch.bufferCount = numBuffers; // Record buffer count + batch.drawCounter = 1; // Reset draws counter + batch.currentDepth = -1.0f; // Reset depth value + //-------------------------------------------------------------------------------------------- +#endif + + return batch; +} + +// Unload default internal buffers vertex data from CPU and GPU +void rlUnloadRenderBatch(rlRenderBatch batch) +{ +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + // Unbind everything + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + + // Unload all vertex buffers data + for (int i = 0; i < batch.bufferCount; i++) + { + // Unbind VAO attribs data + if (RLGL.ExtSupported.vao) + { + glBindVertexArray(batch.vertexBuffer[i].vaoId); + glDisableVertexAttribArray(RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION); + glDisableVertexAttribArray(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD); + glDisableVertexAttribArray(RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL); + glDisableVertexAttribArray(RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR); + glBindVertexArray(0); + } + + // Delete VBOs from GPU (VRAM) + glDeleteBuffers(1, &batch.vertexBuffer[i].vboId[0]); + glDeleteBuffers(1, &batch.vertexBuffer[i].vboId[1]); + glDeleteBuffers(1, &batch.vertexBuffer[i].vboId[2]); + glDeleteBuffers(1, &batch.vertexBuffer[i].vboId[3]); + glDeleteBuffers(1, &batch.vertexBuffer[i].vboId[4]); + + // Delete VAOs from GPU (VRAM) + if (RLGL.ExtSupported.vao) glDeleteVertexArrays(1, &batch.vertexBuffer[i].vaoId); + + // Free vertex arrays memory from CPU (RAM) + RL_FREE(batch.vertexBuffer[i].vertices); + RL_FREE(batch.vertexBuffer[i].texcoords); + RL_FREE(batch.vertexBuffer[i].normals); + RL_FREE(batch.vertexBuffer[i].colors); + RL_FREE(batch.vertexBuffer[i].indices); + } + + // Unload arrays + RL_FREE(batch.vertexBuffer); + RL_FREE(batch.draws); +#endif +} + +// Draw render batch +// NOTE: We require a pointer to reset batch and increase current buffer (multi-buffer) +void rlDrawRenderBatch(rlRenderBatch *batch) +{ +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + // Update batch vertex buffers + //------------------------------------------------------------------------------------------------------------ + // NOTE: If there is not vertex data, buffers doesn't need to be updated (vertexCount > 0) + // TODO: If no data changed on the CPU arrays --> No need to re-update GPU arrays (use a change detector flag?) + if (RLGL.State.vertexCounter > 0) + { + // Activate elements VAO + if (RLGL.ExtSupported.vao) glBindVertexArray(batch->vertexBuffer[batch->currentBuffer].vaoId); + + // Vertex positions buffer + glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[0]); + glBufferSubData(GL_ARRAY_BUFFER, 0, RLGL.State.vertexCounter*3*sizeof(float), batch->vertexBuffer[batch->currentBuffer].vertices); + //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*4*batch->vertexBuffer[batch->currentBuffer].elementCount, batch->vertexBuffer[batch->currentBuffer].vertices, GL_DYNAMIC_DRAW); // Update all buffer + + // Texture coordinates buffer + glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[1]); + glBufferSubData(GL_ARRAY_BUFFER, 0, RLGL.State.vertexCounter*2*sizeof(float), batch->vertexBuffer[batch->currentBuffer].texcoords); + //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*4*batch->vertexBuffer[batch->currentBuffer].elementCount, batch->vertexBuffer[batch->currentBuffer].texcoords, GL_DYNAMIC_DRAW); // Update all buffer + + // Normals buffer + glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[2]); + glBufferSubData(GL_ARRAY_BUFFER, 0, RLGL.State.vertexCounter*3*sizeof(float), batch->vertexBuffer[batch->currentBuffer].normals); + //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*4*batch->vertexBuffer[batch->currentBuffer].elementCount, batch->vertexBuffer[batch->currentBuffer].normals, GL_DYNAMIC_DRAW); // Update all buffer + + // Colors buffer + glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[3]); + glBufferSubData(GL_ARRAY_BUFFER, 0, RLGL.State.vertexCounter*4*sizeof(unsigned char), batch->vertexBuffer[batch->currentBuffer].colors); + //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*4*4*batch->vertexBuffer[batch->currentBuffer].elementCount, batch->vertexBuffer[batch->currentBuffer].colors, GL_DYNAMIC_DRAW); // Update all buffer + + // NOTE: glMapBuffer() causes sync issue + // If GPU is working with this buffer, glMapBuffer() will wait(stall) until GPU to finish its job + // To avoid waiting (idle), you can call first glBufferData() with NULL pointer before glMapBuffer() + // If you do that, the previous data in PBO will be discarded and glMapBuffer() returns a new + // allocated pointer immediately even if GPU is still working with the previous data + + // Another option: map the buffer object into client's memory + // Probably this code could be moved somewhere else... + // batch->vertexBuffer[batch->currentBuffer].vertices = (float *)glMapBuffer(GL_ARRAY_BUFFER, GL_READ_WRITE); + // if (batch->vertexBuffer[batch->currentBuffer].vertices) + // { + // Update vertex data + // } + // glUnmapBuffer(GL_ARRAY_BUFFER); + + // Unbind the current VAO + if (RLGL.ExtSupported.vao) glBindVertexArray(0); + } + //------------------------------------------------------------------------------------------------------------ + + // Draw batch vertex buffers (considering VR stereo if required) + //------------------------------------------------------------------------------------------------------------ + Matrix matProjection = RLGL.State.projection; + Matrix matModelView = RLGL.State.modelview; + + int eyeCount = 1; + if (RLGL.State.stereoRender) eyeCount = 2; + + for (int eye = 0; eye < eyeCount; eye++) + { + if (eyeCount == 2) + { + // Setup current eye viewport (half screen width) + rlViewport(eye*RLGL.State.framebufferWidth/2, 0, RLGL.State.framebufferWidth/2, RLGL.State.framebufferHeight); + + // Set current eye view offset to modelview matrix + rlSetMatrixModelview(rlMatrixMultiply(matModelView, RLGL.State.viewOffsetStereo[eye])); + // Set current eye projection matrix + rlSetMatrixProjection(RLGL.State.projectionStereo[eye]); + } + + // Draw buffers + if (RLGL.State.vertexCounter > 0) + { + // Set current shader and upload current MVP matrix + glUseProgram(RLGL.State.currentShaderId); + + // Create modelview-projection matrix and upload to shader + Matrix matMVP = rlMatrixMultiply(RLGL.State.modelview, RLGL.State.projection); + glUniformMatrix4fv(RLGL.State.currentShaderLocs[RL_SHADER_LOC_MATRIX_MVP], 1, false, rlMatrixToFloat(matMVP)); + + if (RLGL.State.currentShaderLocs[RL_SHADER_LOC_MATRIX_PROJECTION] != -1) + { + glUniformMatrix4fv(RLGL.State.currentShaderLocs[RL_SHADER_LOC_MATRIX_PROJECTION], 1, false, rlMatrixToFloat(RLGL.State.projection)); + } + + // WARNING: For the following setup of the view, model, and normal matrices, it is expected that + // transformations and rendering occur between rlPushMatrix() and rlPopMatrix() + + if (RLGL.State.currentShaderLocs[RL_SHADER_LOC_MATRIX_VIEW] != -1) + { + glUniformMatrix4fv(RLGL.State.currentShaderLocs[RL_SHADER_LOC_MATRIX_VIEW], 1, false, rlMatrixToFloat(RLGL.State.modelview)); + } + + if (RLGL.State.currentShaderLocs[RL_SHADER_LOC_MATRIX_MODEL] != -1) + { + glUniformMatrix4fv(RLGL.State.currentShaderLocs[RL_SHADER_LOC_MATRIX_MODEL], 1, false, rlMatrixToFloat(RLGL.State.transform)); + } + + if (RLGL.State.currentShaderLocs[RL_SHADER_LOC_MATRIX_NORMAL] != -1) + { + glUniformMatrix4fv(RLGL.State.currentShaderLocs[RL_SHADER_LOC_MATRIX_NORMAL], 1, false, rlMatrixToFloat(rlMatrixTranspose(rlMatrixInvert(RLGL.State.transform)))); + } + + if (RLGL.ExtSupported.vao) glBindVertexArray(batch->vertexBuffer[batch->currentBuffer].vaoId); + else + { + // Bind vertex attrib: position (shader-location = 0) + glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[0]); + glVertexAttribPointer(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_POSITION], 3, GL_FLOAT, 0, 0, 0); + glEnableVertexAttribArray(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_POSITION]); + + // Bind vertex attrib: texcoord (shader-location = 1) + glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[1]); + glVertexAttribPointer(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_TEXCOORD01], 2, GL_FLOAT, 0, 0, 0); + glEnableVertexAttribArray(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_TEXCOORD01]); + + // Bind vertex attrib: normal (shader-location = 2) + glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[2]); + glVertexAttribPointer(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_NORMAL], 3, GL_FLOAT, 0, 0, 0); + glEnableVertexAttribArray(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_NORMAL]); + + // Bind vertex attrib: color (shader-location = 3) + glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[3]); + glVertexAttribPointer(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_COLOR], 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); + glEnableVertexAttribArray(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_COLOR]); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[4]); + } + + // Setup some default shader values + glUniform4f(RLGL.State.currentShaderLocs[RL_SHADER_LOC_COLOR_DIFFUSE], 1.0f, 1.0f, 1.0f, 1.0f); + glUniform1i(RLGL.State.currentShaderLocs[RL_SHADER_LOC_MAP_DIFFUSE], 0); // Active default sampler2D: texture0 + + // Activate additional sampler textures + // Those additional textures will be common for all draw calls of the batch + for (int i = 0; i < RL_DEFAULT_BATCH_MAX_TEXTURE_UNITS; i++) + { + if (RLGL.State.activeTextureId[i] > 0) + { + glActiveTexture(GL_TEXTURE0 + 1 + i); + glBindTexture(GL_TEXTURE_2D, RLGL.State.activeTextureId[i]); + } + } + + // Activate default sampler2D texture0 (one texture is always active for default batch shader) + // NOTE: Batch system accumulates calls by texture0 changes, additional textures are enabled for all the draw calls + glActiveTexture(GL_TEXTURE0); + + for (int i = 0, vertexOffset = 0; i < batch->drawCounter; i++) + { + // Bind current draw call texture, activated as GL_TEXTURE0 and Bound to sampler2D texture0 by default + glBindTexture(GL_TEXTURE_2D, batch->draws[i].textureId); + + if ((batch->draws[i].mode == RL_LINES) || (batch->draws[i].mode == RL_TRIANGLES)) glDrawArrays(batch->draws[i].mode, vertexOffset, batch->draws[i].vertexCount); + else + { + #if defined(GRAPHICS_API_OPENGL_33) + // We need to define the number of indices to be processed: elementCount*6 + // NOTE: The final parameter tells the GPU the offset in bytes from the + // start of the index buffer to the location of the first index to process + glDrawElements(GL_TRIANGLES, batch->draws[i].vertexCount/4*6, GL_UNSIGNED_INT, (GLvoid *)(vertexOffset/4*6*sizeof(GLuint))); + #endif + #if defined(GRAPHICS_API_OPENGL_ES2) + glDrawElements(GL_TRIANGLES, batch->draws[i].vertexCount/4*6, GL_UNSIGNED_SHORT, (GLvoid *)(vertexOffset/4*6*sizeof(GLushort))); + #endif + } + + vertexOffset += (batch->draws[i].vertexCount + batch->draws[i].vertexAlignment); + } + + if (!RLGL.ExtSupported.vao) + { + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + } + + glBindTexture(GL_TEXTURE_2D, 0); // Unbind textures + } + + if (RLGL.ExtSupported.vao) glBindVertexArray(0); // Unbind VAO + + glUseProgram(0); // Unbind shader program + } + + // Restore viewport to default measures + if (eyeCount == 2) rlViewport(0, 0, RLGL.State.framebufferWidth, RLGL.State.framebufferHeight); + //------------------------------------------------------------------------------------------------------------ + + // Reset batch buffers + //------------------------------------------------------------------------------------------------------------ + // Reset vertex counter for next frame + RLGL.State.vertexCounter = 0; + + // Reset depth for next draw + batch->currentDepth = -1.0f; + + // Restore projection/modelview matrices + RLGL.State.projection = matProjection; + RLGL.State.modelview = matModelView; + + // Reset RLGL.currentBatch->draws array + for (int i = 0; i < RL_DEFAULT_BATCH_DRAWCALLS; i++) + { + batch->draws[i].mode = RL_QUADS; + batch->draws[i].vertexCount = 0; + batch->draws[i].textureId = RLGL.State.defaultTextureId; + } + + // Reset active texture units for next batch + for (int i = 0; i < RL_DEFAULT_BATCH_MAX_TEXTURE_UNITS; i++) RLGL.State.activeTextureId[i] = 0; + + // Reset draws counter to one draw for the batch + batch->drawCounter = 1; + //------------------------------------------------------------------------------------------------------------ + + // Change to next buffer in the list (in case of multi-buffering) + batch->currentBuffer++; + if (batch->currentBuffer >= batch->bufferCount) batch->currentBuffer = 0; +#endif +} + +// Set the active render batch for rlgl +void rlSetRenderBatchActive(rlRenderBatch *batch) +{ +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + rlDrawRenderBatch(RLGL.currentBatch); + + if (batch != NULL) RLGL.currentBatch = batch; + else RLGL.currentBatch = &RLGL.defaultBatch; +#endif +} + +// Update and draw internal render batch +void rlDrawRenderBatchActive(void) +{ +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + rlDrawRenderBatch(RLGL.currentBatch); // NOTE: Stereo rendering is checked inside +#endif +} + +// Check internal buffer overflow for a given number of vertex +// and force a rlRenderBatch draw call if required +bool rlCheckRenderBatchLimit(int vCount) +{ + bool overflow = false; + +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + if ((RLGL.State.vertexCounter + vCount) >= + (RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].elementCount*4)) + { + overflow = true; + + // Store current primitive drawing mode and texture id + int currentMode = RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].mode; + int currentTexture = RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].textureId; + + rlDrawRenderBatch(RLGL.currentBatch); // NOTE: Stereo rendering is checked inside + + // Restore state of last batch so we can continue adding vertices + RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].mode = currentMode; + RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].textureId = currentTexture; + } +#endif + + return overflow; +} + +// Textures data management +//----------------------------------------------------------------------------------------- +// Convert image data to OpenGL texture (returns OpenGL valid Id) +unsigned int rlLoadTexture(const void *data, int width, int height, int format, int mipmapCount) +{ + unsigned int id = 0; + + glBindTexture(GL_TEXTURE_2D, 0); // Free any old binding + + // Check texture format support by OpenGL 1.1 (compressed textures not supported) +#if defined(GRAPHICS_API_OPENGL_11) + if (format >= RL_PIXELFORMAT_COMPRESSED_DXT1_RGB) + { + TRACELOG(RL_LOG_WARNING, "GL: OpenGL 1.1 does not support GPU compressed texture formats"); + return id; + } +#else + if ((!RLGL.ExtSupported.texCompDXT) && ((format == RL_PIXELFORMAT_COMPRESSED_DXT1_RGB) || (format == RL_PIXELFORMAT_COMPRESSED_DXT1_RGBA) || + (format == RL_PIXELFORMAT_COMPRESSED_DXT3_RGBA) || (format == RL_PIXELFORMAT_COMPRESSED_DXT5_RGBA))) + { + TRACELOG(RL_LOG_WARNING, "GL: DXT compressed texture format not supported"); + return id; + } +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + if ((!RLGL.ExtSupported.texCompETC1) && (format == RL_PIXELFORMAT_COMPRESSED_ETC1_RGB)) + { + TRACELOG(RL_LOG_WARNING, "GL: ETC1 compressed texture format not supported"); + return id; + } + + if ((!RLGL.ExtSupported.texCompETC2) && ((format == RL_PIXELFORMAT_COMPRESSED_ETC2_RGB) || (format == RL_PIXELFORMAT_COMPRESSED_ETC2_EAC_RGBA))) + { + TRACELOG(RL_LOG_WARNING, "GL: ETC2 compressed texture format not supported"); + return id; + } + + if ((!RLGL.ExtSupported.texCompPVRT) && ((format == RL_PIXELFORMAT_COMPRESSED_PVRT_RGB) || (format == RL_PIXELFORMAT_COMPRESSED_PVRT_RGBA))) + { + TRACELOG(RL_LOG_WARNING, "GL: PVRT compressed texture format not supported"); + return id; + } + + if ((!RLGL.ExtSupported.texCompASTC) && ((format == RL_PIXELFORMAT_COMPRESSED_ASTC_4x4_RGBA) || (format == RL_PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA))) + { + TRACELOG(RL_LOG_WARNING, "GL: ASTC compressed texture format not supported"); + return id; + } +#endif +#endif // GRAPHICS_API_OPENGL_11 + + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + + glGenTextures(1, &id); // Generate texture id + + glBindTexture(GL_TEXTURE_2D, id); + + int mipWidth = width; + int mipHeight = height; + int mipOffset = 0; // Mipmap data offset, only used for tracelog + + // NOTE: Added pointer math separately from function to avoid UBSAN complaining + unsigned char *dataPtr = NULL; + if (data != NULL) dataPtr = (unsigned char *)data; + + // Load the different mipmap levels + for (int i = 0; i < mipmapCount; i++) + { + unsigned int mipSize = rlGetPixelDataSize(mipWidth, mipHeight, format); + + unsigned int glInternalFormat, glFormat, glType; + rlGetGlTextureFormats(format, &glInternalFormat, &glFormat, &glType); + + TRACELOGD("TEXTURE: Load mipmap level %i (%i x %i), size: %i, offset: %i", i, mipWidth, mipHeight, mipSize, mipOffset); + + if (glInternalFormat != 0) + { + if (format < RL_PIXELFORMAT_COMPRESSED_DXT1_RGB) glTexImage2D(GL_TEXTURE_2D, i, glInternalFormat, mipWidth, mipHeight, 0, glFormat, glType, dataPtr); +#if !defined(GRAPHICS_API_OPENGL_11) + else glCompressedTexImage2D(GL_TEXTURE_2D, i, glInternalFormat, mipWidth, mipHeight, 0, mipSize, dataPtr); +#endif + +#if defined(GRAPHICS_API_OPENGL_33) + if (format == RL_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE) + { + GLint swizzleMask[] = { GL_RED, GL_RED, GL_RED, GL_ONE }; + glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); + } + else if (format == RL_PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA) + { +#if defined(GRAPHICS_API_OPENGL_21) + GLint swizzleMask[] = { GL_RED, GL_RED, GL_RED, GL_ALPHA }; +#elif defined(GRAPHICS_API_OPENGL_33) + GLint swizzleMask[] = { GL_RED, GL_RED, GL_RED, GL_GREEN }; +#endif + glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); + } +#endif + } + + mipWidth /= 2; + mipHeight /= 2; + mipOffset += mipSize; // Increment offset position to next mipmap + if (data != NULL) dataPtr += mipSize; // Increment data pointer to next mipmap + + // Security check for NPOT textures + if (mipWidth < 1) mipWidth = 1; + if (mipHeight < 1) mipHeight = 1; + } + + // Texture parameters configuration + // NOTE: glTexParameteri does NOT affect texture uploading, just the way it's used +#if defined(GRAPHICS_API_OPENGL_ES2) + // NOTE: OpenGL ES 2.0 with no GL_OES_texture_npot support (i.e. WebGL) has limited NPOT support, so CLAMP_TO_EDGE must be used + if (RLGL.ExtSupported.texNPOT) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // Set texture to repeat on x-axis + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); // Set texture to repeat on y-axis + } + else + { + // NOTE: If using negative texture coordinates (LoadOBJ()), it does not work! + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); // Set texture to clamp on x-axis + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); // Set texture to clamp on y-axis + } +#else + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // Set texture to repeat on x-axis + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); // Set texture to repeat on y-axis +#endif + + // Magnification and minification filters + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // Alternative: GL_LINEAR + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); // Alternative: GL_LINEAR + +#if defined(GRAPHICS_API_OPENGL_33) + if (mipmapCount > 1) + { + // Activate Trilinear filtering if mipmaps are available + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + } +#endif + + // At this point we have the texture loaded in GPU and texture parameters configured + + // NOTE: If mipmaps were not in data, they are not generated automatically + + // Unbind current texture + glBindTexture(GL_TEXTURE_2D, 0); + + if (id > 0) TRACELOG(RL_LOG_INFO, "TEXTURE: [ID %i] Texture loaded successfully (%ix%i | %s | %i mipmaps)", id, width, height, rlGetPixelFormatName(format), mipmapCount); + else TRACELOG(RL_LOG_WARNING, "TEXTURE: Failed to load texture"); + + return id; +} + +// Load depth texture/renderbuffer (to be attached to fbo) +// WARNING: OpenGL ES 2.0 requires GL_OES_depth_texture and WebGL requires WEBGL_depth_texture extensions +unsigned int rlLoadTextureDepth(int width, int height, bool useRenderBuffer) +{ + unsigned int id = 0; + +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + // In case depth textures not supported, we force renderbuffer usage + if (!RLGL.ExtSupported.texDepth) useRenderBuffer = true; + + // NOTE: We let the implementation to choose the best bit-depth + // Possible formats: GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT32 and GL_DEPTH_COMPONENT32F + unsigned int glInternalFormat = GL_DEPTH_COMPONENT; + +#if (defined(GRAPHICS_API_OPENGL_ES2) || defined(GRAPHICS_API_OPENGL_ES3)) + // WARNING: WebGL platform requires unsized internal format definition (GL_DEPTH_COMPONENT) + // while other platforms using OpenGL ES 2.0 require/support sized internal formats depending on the GPU capabilities + if (!RLGL.ExtSupported.texDepthWebGL || useRenderBuffer) + { + if (RLGL.ExtSupported.maxDepthBits == 32) glInternalFormat = GL_DEPTH_COMPONENT32_OES; + else if (RLGL.ExtSupported.maxDepthBits == 24) glInternalFormat = GL_DEPTH_COMPONENT24_OES; + else glInternalFormat = GL_DEPTH_COMPONENT16; + } +#endif + + if (!useRenderBuffer && RLGL.ExtSupported.texDepth) + { + glGenTextures(1, &id); + glBindTexture(GL_TEXTURE_2D, id); + glTexImage2D(GL_TEXTURE_2D, 0, glInternalFormat, width, height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + glBindTexture(GL_TEXTURE_2D, 0); + + TRACELOG(RL_LOG_INFO, "TEXTURE: Depth texture loaded successfully"); + } + else + { + // Create the renderbuffer that will serve as the depth attachment for the framebuffer + // NOTE: A renderbuffer is simpler than a texture and could offer better performance on embedded devices + glGenRenderbuffers(1, &id); + glBindRenderbuffer(GL_RENDERBUFFER, id); + glRenderbufferStorage(GL_RENDERBUFFER, glInternalFormat, width, height); + + glBindRenderbuffer(GL_RENDERBUFFER, 0); + + TRACELOG(RL_LOG_INFO, "TEXTURE: [ID %i] Depth renderbuffer loaded successfully (%i bits)", id, (RLGL.ExtSupported.maxDepthBits >= 24)? RLGL.ExtSupported.maxDepthBits : 16); + } +#endif + + return id; +} + +// Load texture cubemap +// NOTE: Cubemap data is expected to be 6 images in a single data array (one after the other), +// expected the following convention: +X, -X, +Y, -Y, +Z, -Z +unsigned int rlLoadTextureCubemap(const void *data, int size, int format, int mipmapCount) +{ + unsigned int id = 0; + +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + int mipSize = size; + + // NOTE: Added pointer math separately from function to avoid UBSAN complaining + unsigned char *dataPtr = NULL; + if (data != NULL) dataPtr = (unsigned char *)data; + + unsigned int dataSize = rlGetPixelDataSize(size, size, format); + + glGenTextures(1, &id); + glBindTexture(GL_TEXTURE_CUBE_MAP, id); + + unsigned int glInternalFormat, glFormat, glType; + rlGetGlTextureFormats(format, &glInternalFormat, &glFormat, &glType); + + if (glInternalFormat != 0) + { + // Load cubemap faces/mipmaps + for (int i = 0; i < 6*mipmapCount; i++) + { + int mipmapLevel = i/6; + int face = i%6; + + if (data == NULL) + { + if (format < RL_PIXELFORMAT_COMPRESSED_DXT1_RGB) + { + if ((format == RL_PIXELFORMAT_UNCOMPRESSED_R32) || + (format == RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32) || + (format == RL_PIXELFORMAT_UNCOMPRESSED_R16) || + (format == RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16)) TRACELOG(RL_LOG_WARNING, "TEXTURES: Cubemap requested format not supported"); + else glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, mipmapLevel, glInternalFormat, mipSize, mipSize, 0, glFormat, glType, NULL); + } + else TRACELOG(RL_LOG_WARNING, "TEXTURES: Empty cubemap creation does not support compressed format"); + } + else + { + if (format < RL_PIXELFORMAT_COMPRESSED_DXT1_RGB) glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, mipmapLevel, glInternalFormat, mipSize, mipSize, 0, glFormat, glType, (unsigned char *)dataPtr + face*dataSize); + else glCompressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, mipmapLevel, glInternalFormat, mipSize, mipSize, 0, dataSize, (unsigned char *)dataPtr + face*dataSize); + } + +#if defined(GRAPHICS_API_OPENGL_33) + if (format == RL_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE) + { + GLint swizzleMask[] = { GL_RED, GL_RED, GL_RED, GL_ONE }; + glTexParameteriv(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); + } + else if (format == RL_PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA) + { +#if defined(GRAPHICS_API_OPENGL_21) + GLint swizzleMask[] = { GL_RED, GL_RED, GL_RED, GL_ALPHA }; +#elif defined(GRAPHICS_API_OPENGL_33) + GLint swizzleMask[] = { GL_RED, GL_RED, GL_RED, GL_GREEN }; +#endif + glTexParameteriv(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); + } +#endif + if (face == 5) + { + mipSize /= 2; + if (data != NULL) dataPtr += dataSize*6; // Increment data pointer to next mipmap + + // Security check for NPOT textures + if (mipSize < 1) mipSize = 1; + + dataSize = rlGetPixelDataSize(mipSize, mipSize, format); + } + } + } + + // Set cubemap texture sampling parameters + if (mipmapCount > 1) glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + else glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); +#if defined(GRAPHICS_API_OPENGL_33) + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); // Flag not supported on OpenGL ES 2.0 +#endif + + glBindTexture(GL_TEXTURE_CUBE_MAP, 0); +#endif + + if (id > 0) TRACELOG(RL_LOG_INFO, "TEXTURE: [ID %i] Cubemap texture loaded successfully (%ix%i)", id, size, size); + else TRACELOG(RL_LOG_WARNING, "TEXTURE: Failed to load cubemap texture"); + + return id; +} + +// Update already loaded texture in GPU with new data +// NOTE: We don't know safely if internal texture format is the expected one... +void rlUpdateTexture(unsigned int id, int offsetX, int offsetY, int width, int height, int format, const void *data) +{ + glBindTexture(GL_TEXTURE_2D, id); + + unsigned int glInternalFormat, glFormat, glType; + rlGetGlTextureFormats(format, &glInternalFormat, &glFormat, &glType); + + if ((glInternalFormat != 0) && (format < RL_PIXELFORMAT_COMPRESSED_DXT1_RGB)) + { + glTexSubImage2D(GL_TEXTURE_2D, 0, offsetX, offsetY, width, height, glFormat, glType, data); + } + else TRACELOG(RL_LOG_WARNING, "TEXTURE: [ID %i] Failed to update for current texture format (%i)", id, format); +} + +// Get OpenGL internal formats and data type from raylib PixelFormat +void rlGetGlTextureFormats(int format, unsigned int *glInternalFormat, unsigned int *glFormat, unsigned int *glType) +{ + *glInternalFormat = 0; + *glFormat = 0; + *glType = 0; + + switch (format) + { + #if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_21) || defined(GRAPHICS_API_OPENGL_ES2) + // NOTE: on OpenGL ES 2.0 (WebGL), internalFormat must match format and options allowed are: GL_LUMINANCE, GL_RGB, GL_RGBA + case RL_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE: *glInternalFormat = GL_LUMINANCE; *glFormat = GL_LUMINANCE; *glType = GL_UNSIGNED_BYTE; break; + case RL_PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA: *glInternalFormat = GL_LUMINANCE_ALPHA; *glFormat = GL_LUMINANCE_ALPHA; *glType = GL_UNSIGNED_BYTE; break; + case RL_PIXELFORMAT_UNCOMPRESSED_R5G6B5: *glInternalFormat = GL_RGB; *glFormat = GL_RGB; *glType = GL_UNSIGNED_SHORT_5_6_5; break; + case RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8: *glInternalFormat = GL_RGB; *glFormat = GL_RGB; *glType = GL_UNSIGNED_BYTE; break; + case RL_PIXELFORMAT_UNCOMPRESSED_R5G5B5A1: *glInternalFormat = GL_RGBA; *glFormat = GL_RGBA; *glType = GL_UNSIGNED_SHORT_5_5_5_1; break; + case RL_PIXELFORMAT_UNCOMPRESSED_R4G4B4A4: *glInternalFormat = GL_RGBA; *glFormat = GL_RGBA; *glType = GL_UNSIGNED_SHORT_4_4_4_4; break; + case RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8: *glInternalFormat = GL_RGBA; *glFormat = GL_RGBA; *glType = GL_UNSIGNED_BYTE; break; + #if !defined(GRAPHICS_API_OPENGL_11) + #if defined(GRAPHICS_API_OPENGL_ES3) + case RL_PIXELFORMAT_UNCOMPRESSED_R32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_R32F_EXT; *glFormat = GL_RED_EXT; *glType = GL_FLOAT; break; + case RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_RGB32F_EXT; *glFormat = GL_RGB; *glType = GL_FLOAT; break; + case RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_RGBA32F_EXT; *glFormat = GL_RGBA; *glType = GL_FLOAT; break; + case RL_PIXELFORMAT_UNCOMPRESSED_R16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_R16F_EXT; *glFormat = GL_RED_EXT; *glType = GL_HALF_FLOAT; break; + case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_RGB16F_EXT; *glFormat = GL_RGB; *glType = GL_HALF_FLOAT; break; + case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_RGBA16F_EXT; *glFormat = GL_RGBA; *glType = GL_HALF_FLOAT; break; + #else + case RL_PIXELFORMAT_UNCOMPRESSED_R32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_LUMINANCE; *glFormat = GL_LUMINANCE; *glType = GL_FLOAT; break; // NOTE: Requires extension OES_texture_float + case RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_RGB; *glFormat = GL_RGB; *glType = GL_FLOAT; break; // NOTE: Requires extension OES_texture_float + case RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_RGBA; *glFormat = GL_RGBA; *glType = GL_FLOAT; break; // NOTE: Requires extension OES_texture_float + #if defined(GRAPHICS_API_OPENGL_21) + case RL_PIXELFORMAT_UNCOMPRESSED_R16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_LUMINANCE; *glFormat = GL_LUMINANCE; *glType = GL_HALF_FLOAT_ARB; break; + case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_RGB; *glFormat = GL_RGB; *glType = GL_HALF_FLOAT_ARB; break; + case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_RGBA; *glFormat = GL_RGBA; *glType = GL_HALF_FLOAT_ARB; break; + #else // defined(GRAPHICS_API_OPENGL_ES2) + case RL_PIXELFORMAT_UNCOMPRESSED_R16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_LUMINANCE; *glFormat = GL_LUMINANCE; *glType = GL_HALF_FLOAT_OES; break; // NOTE: Requires extension OES_texture_half_float + case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_RGB; *glFormat = GL_RGB; *glType = GL_HALF_FLOAT_OES; break; // NOTE: Requires extension OES_texture_half_float + case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_RGBA; *glFormat = GL_RGBA; *glType = GL_HALF_FLOAT_OES; break; // NOTE: Requires extension OES_texture_half_float + #endif + #endif + #endif + #elif defined(GRAPHICS_API_OPENGL_33) + case RL_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE: *glInternalFormat = GL_R8; *glFormat = GL_RED; *glType = GL_UNSIGNED_BYTE; break; + case RL_PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA: *glInternalFormat = GL_RG8; *glFormat = GL_RG; *glType = GL_UNSIGNED_BYTE; break; + case RL_PIXELFORMAT_UNCOMPRESSED_R5G6B5: *glInternalFormat = GL_RGB565; *glFormat = GL_RGB; *glType = GL_UNSIGNED_SHORT_5_6_5; break; + case RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8: *glInternalFormat = GL_RGB8; *glFormat = GL_RGB; *glType = GL_UNSIGNED_BYTE; break; + case RL_PIXELFORMAT_UNCOMPRESSED_R5G5B5A1: *glInternalFormat = GL_RGB5_A1; *glFormat = GL_RGBA; *glType = GL_UNSIGNED_SHORT_5_5_5_1; break; + case RL_PIXELFORMAT_UNCOMPRESSED_R4G4B4A4: *glInternalFormat = GL_RGBA4; *glFormat = GL_RGBA; *glType = GL_UNSIGNED_SHORT_4_4_4_4; break; + case RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8: *glInternalFormat = GL_RGBA8; *glFormat = GL_RGBA; *glType = GL_UNSIGNED_BYTE; break; + case RL_PIXELFORMAT_UNCOMPRESSED_R32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_R32F; *glFormat = GL_RED; *glType = GL_FLOAT; break; + case RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_RGB32F; *glFormat = GL_RGB; *glType = GL_FLOAT; break; + case RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_RGBA32F; *glFormat = GL_RGBA; *glType = GL_FLOAT; break; + case RL_PIXELFORMAT_UNCOMPRESSED_R16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_R16F; *glFormat = GL_RED; *glType = GL_HALF_FLOAT; break; + case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_RGB16F; *glFormat = GL_RGB; *glType = GL_HALF_FLOAT; break; + case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_RGBA16F; *glFormat = GL_RGBA; *glType = GL_HALF_FLOAT; break; + #endif + #if !defined(GRAPHICS_API_OPENGL_11) + case RL_PIXELFORMAT_COMPRESSED_DXT1_RGB: if (RLGL.ExtSupported.texCompDXT) *glInternalFormat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT; break; + case RL_PIXELFORMAT_COMPRESSED_DXT1_RGBA: if (RLGL.ExtSupported.texCompDXT) *glInternalFormat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; break; + case RL_PIXELFORMAT_COMPRESSED_DXT3_RGBA: if (RLGL.ExtSupported.texCompDXT) *glInternalFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; break; + case RL_PIXELFORMAT_COMPRESSED_DXT5_RGBA: if (RLGL.ExtSupported.texCompDXT) *glInternalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; break; + case RL_PIXELFORMAT_COMPRESSED_ETC1_RGB: if (RLGL.ExtSupported.texCompETC1) *glInternalFormat = GL_ETC1_RGB8_OES; break; // NOTE: Requires OpenGL ES 2.0 or OpenGL 4.3 + case RL_PIXELFORMAT_COMPRESSED_ETC2_RGB: if (RLGL.ExtSupported.texCompETC2) *glInternalFormat = GL_COMPRESSED_RGB8_ETC2; break; // NOTE: Requires OpenGL ES 3.0 or OpenGL 4.3 + case RL_PIXELFORMAT_COMPRESSED_ETC2_EAC_RGBA: if (RLGL.ExtSupported.texCompETC2) *glInternalFormat = GL_COMPRESSED_RGBA8_ETC2_EAC; break; // NOTE: Requires OpenGL ES 3.0 or OpenGL 4.3 + case RL_PIXELFORMAT_COMPRESSED_PVRT_RGB: if (RLGL.ExtSupported.texCompPVRT) *glInternalFormat = GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG; break; // NOTE: Requires PowerVR GPU + case RL_PIXELFORMAT_COMPRESSED_PVRT_RGBA: if (RLGL.ExtSupported.texCompPVRT) *glInternalFormat = GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG; break; // NOTE: Requires PowerVR GPU + case RL_PIXELFORMAT_COMPRESSED_ASTC_4x4_RGBA: if (RLGL.ExtSupported.texCompASTC) *glInternalFormat = GL_COMPRESSED_RGBA_ASTC_4x4_KHR; break; // NOTE: Requires OpenGL ES 3.1 or OpenGL 4.3 + case RL_PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA: if (RLGL.ExtSupported.texCompASTC) *glInternalFormat = GL_COMPRESSED_RGBA_ASTC_8x8_KHR; break; // NOTE: Requires OpenGL ES 3.1 or OpenGL 4.3 + #endif + default: TRACELOG(RL_LOG_WARNING, "TEXTURE: Current format not supported (%i)", format); break; + } +} + +// Unload texture from GPU memory +void rlUnloadTexture(unsigned int id) +{ + glDeleteTextures(1, &id); +} + +// Generate mipmap data for selected texture +// NOTE: Only supports GPU mipmap generation +void rlGenTextureMipmaps(unsigned int id, int width, int height, int format, int *mipmaps) +{ +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + glBindTexture(GL_TEXTURE_2D, id); + + // Check if texture is power-of-two (POT) + bool texIsPOT = false; + + if (((width > 0) && ((width & (width - 1)) == 0)) && + ((height > 0) && ((height & (height - 1)) == 0))) texIsPOT = true; + + if ((texIsPOT) || (RLGL.ExtSupported.texNPOT)) + { + //glHint(GL_GENERATE_MIPMAP_HINT, GL_DONT_CARE); // Hint for mipmaps generation algorithm: GL_FASTEST, GL_NICEST, GL_DONT_CARE + glGenerateMipmap(GL_TEXTURE_2D); // Generate mipmaps automatically + + #define MIN(a,b) (((a)<(b))? (a):(b)) + #define MAX(a,b) (((a)>(b))? (a):(b)) + + *mipmaps = 1 + (int)floor(log(MAX(width, height))/log(2)); + TRACELOG(RL_LOG_INFO, "TEXTURE: [ID %i] Mipmaps generated automatically, total: %i", id, *mipmaps); + } + else TRACELOG(RL_LOG_WARNING, "TEXTURE: [ID %i] Failed to generate mipmaps", id); + + glBindTexture(GL_TEXTURE_2D, 0); +#else + TRACELOG(RL_LOG_WARNING, "TEXTURE: [ID %i] GPU mipmap generation not supported", id); +#endif +} + +// Read texture pixel data +void *rlReadTexturePixels(unsigned int id, int width, int height, int format) +{ + void *pixels = NULL; + +#if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33) + glBindTexture(GL_TEXTURE_2D, id); + + // NOTE: Using texture id, we can retrieve some texture info (but not on OpenGL ES 2.0) + // Possible texture info: GL_TEXTURE_RED_SIZE, GL_TEXTURE_GREEN_SIZE, GL_TEXTURE_BLUE_SIZE, GL_TEXTURE_ALPHA_SIZE + //int width, height, format; + //glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width); + //glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height); + //glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &format); + + // NOTE: Each row written to or read from by OpenGL pixel operations like glGetTexImage are aligned to a 4 byte boundary by default, which may add some padding + // Use glPixelStorei to modify padding with the GL_[UN]PACK_ALIGNMENT setting + // GL_PACK_ALIGNMENT affects operations that read from OpenGL memory (glReadPixels, glGetTexImage, etc.) + // GL_UNPACK_ALIGNMENT affects operations that write to OpenGL memory (glTexImage, etc.) + glPixelStorei(GL_PACK_ALIGNMENT, 1); + + unsigned int glInternalFormat, glFormat, glType; + rlGetGlTextureFormats(format, &glInternalFormat, &glFormat, &glType); + unsigned int size = rlGetPixelDataSize(width, height, format); + + if ((glInternalFormat != 0) && (format < RL_PIXELFORMAT_COMPRESSED_DXT1_RGB)) + { + pixels = RL_MALLOC(size); + glGetTexImage(GL_TEXTURE_2D, 0, glFormat, glType, pixels); + } + else TRACELOG(RL_LOG_WARNING, "TEXTURE: [ID %i] Data retrieval not suported for pixel format (%i)", id, format); + + glBindTexture(GL_TEXTURE_2D, 0); +#endif + +#if defined(GRAPHICS_API_OPENGL_ES2) + // glGetTexImage() is not available on OpenGL ES 2.0 + // Texture width and height are required on OpenGL ES 2.0, there is no way to get it from texture id + // Two possible Options: + // 1 - Bind texture to color fbo attachment and glReadPixels() + // 2 - Create an fbo, activate it, render quad with texture, glReadPixels() + // We are using Option 1, just need to care for texture format on retrieval + // NOTE: This behaviour could be conditioned by graphic driver... + unsigned int fboId = rlLoadFramebuffer(); + + glBindFramebuffer(GL_FRAMEBUFFER, fboId); + glBindTexture(GL_TEXTURE_2D, 0); + + // Attach our texture to FBO + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, id, 0); + + // We read data as RGBA because FBO texture is configured as RGBA, despite binding another texture format + pixels = (unsigned char *)RL_MALLOC(rlGetPixelDataSize(width, height, RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8)); + glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + // Clean up temporal fbo + rlUnloadFramebuffer(fboId); +#endif + + return pixels; +} + +// Read screen pixel data (color buffer) +unsigned char *rlReadScreenPixels(int width, int height) +{ + unsigned char *screenData = (unsigned char *)RL_CALLOC(width*height*4, sizeof(unsigned char)); + + // NOTE 1: glReadPixels returns image flipped vertically -> (0,0) is the bottom left corner of the framebuffer + // NOTE 2: We are getting alpha channel! Be careful, it can be transparent if not cleared properly! + glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, screenData); + + // Flip image vertically! + unsigned char *imgData = (unsigned char *)RL_MALLOC(width*height*4*sizeof(unsigned char)); + + for (int y = height - 1; y >= 0; y--) + { + for (int x = 0; x < (width*4); x++) + { + imgData[((height - 1) - y)*width*4 + x] = screenData[(y*width*4) + x]; // Flip line + + // Set alpha component value to 255 (no trasparent image retrieval) + // NOTE: Alpha value has already been applied to RGB in framebuffer, we don't need it! + if (((x + 1)%4) == 0) imgData[((height - 1) - y)*width*4 + x] = 255; + } + } + + RL_FREE(screenData); + + return imgData; // NOTE: image data should be freed +} + +// Framebuffer management (fbo) +//----------------------------------------------------------------------------------------- +// Load a framebuffer to be used for rendering +// NOTE: No textures attached +unsigned int rlLoadFramebuffer(void) +{ + unsigned int fboId = 0; + +#if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)) && defined(RLGL_RENDER_TEXTURES_HINT) + glGenFramebuffers(1, &fboId); // Create the framebuffer object + glBindFramebuffer(GL_FRAMEBUFFER, 0); // Unbind any framebuffer +#endif + + return fboId; +} + +// Attach color buffer texture to an fbo (unloads previous attachment) +// NOTE: Attach type: 0-Color, 1-Depth renderbuffer, 2-Depth texture +void rlFramebufferAttach(unsigned int fboId, unsigned int texId, int attachType, int texType, int mipLevel) +{ +#if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)) && defined(RLGL_RENDER_TEXTURES_HINT) + glBindFramebuffer(GL_FRAMEBUFFER, fboId); + + switch (attachType) + { + case RL_ATTACHMENT_COLOR_CHANNEL0: + case RL_ATTACHMENT_COLOR_CHANNEL1: + case RL_ATTACHMENT_COLOR_CHANNEL2: + case RL_ATTACHMENT_COLOR_CHANNEL3: + case RL_ATTACHMENT_COLOR_CHANNEL4: + case RL_ATTACHMENT_COLOR_CHANNEL5: + case RL_ATTACHMENT_COLOR_CHANNEL6: + case RL_ATTACHMENT_COLOR_CHANNEL7: + { + if (texType == RL_ATTACHMENT_TEXTURE2D) glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + attachType, GL_TEXTURE_2D, texId, mipLevel); + else if (texType == RL_ATTACHMENT_RENDERBUFFER) glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + attachType, GL_RENDERBUFFER, texId); + else if (texType >= RL_ATTACHMENT_CUBEMAP_POSITIVE_X) glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + attachType, GL_TEXTURE_CUBE_MAP_POSITIVE_X + texType, texId, mipLevel); + + } break; + case RL_ATTACHMENT_DEPTH: + { + if (texType == RL_ATTACHMENT_TEXTURE2D) glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, texId, mipLevel); + else if (texType == RL_ATTACHMENT_RENDERBUFFER) glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, texId); + + } break; + case RL_ATTACHMENT_STENCIL: + { + if (texType == RL_ATTACHMENT_TEXTURE2D) glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, texId, mipLevel); + else if (texType == RL_ATTACHMENT_RENDERBUFFER) glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, texId); + + } break; + default: break; + } + + glBindFramebuffer(GL_FRAMEBUFFER, 0); +#endif +} + +// Verify render texture is complete +bool rlFramebufferComplete(unsigned int id) +{ + bool result = false; + +#if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)) && defined(RLGL_RENDER_TEXTURES_HINT) + glBindFramebuffer(GL_FRAMEBUFFER, id); + + GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + + if (status != GL_FRAMEBUFFER_COMPLETE) + { + switch (status) + { + case GL_FRAMEBUFFER_UNSUPPORTED: TRACELOG(RL_LOG_WARNING, "FBO: [ID %i] Framebuffer is unsupported", id); break; + case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: TRACELOG(RL_LOG_WARNING, "FBO: [ID %i] Framebuffer has incomplete attachment", id); break; +#if defined(GRAPHICS_API_OPENGL_ES2) + case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS: TRACELOG(RL_LOG_WARNING, "FBO: [ID %i] Framebuffer has incomplete dimensions", id); break; +#endif + case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: TRACELOG(RL_LOG_WARNING, "FBO: [ID %i] Framebuffer has a missing attachment", id); break; + default: break; + } + } + + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + result = (status == GL_FRAMEBUFFER_COMPLETE); +#endif + + return result; +} + +// Unload framebuffer from GPU memory +// NOTE: All attached textures/cubemaps/renderbuffers are also deleted +void rlUnloadFramebuffer(unsigned int id) +{ +#if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)) && defined(RLGL_RENDER_TEXTURES_HINT) + // Query depth attachment to automatically delete texture/renderbuffer + int depthType = 0, depthId = 0; + glBindFramebuffer(GL_FRAMEBUFFER, id); // Bind framebuffer to query depth texture type + glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &depthType); + + // TODO: Review warning retrieving object name in WebGL + // WARNING: WebGL: INVALID_ENUM: getFramebufferAttachmentParameter: invalid parameter name + // https://registry.khronos.org/webgl/specs/latest/1.0/ + glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &depthId); + + unsigned int depthIdU = (unsigned int)depthId; + if (depthType == GL_RENDERBUFFER) glDeleteRenderbuffers(1, &depthIdU); + else if (depthType == GL_TEXTURE) glDeleteTextures(1, &depthIdU); + + // NOTE: If a texture object is deleted while its image is attached to the *currently bound* framebuffer, + // the texture image is automatically detached from the currently bound framebuffer + + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glDeleteFramebuffers(1, &id); + + TRACELOG(RL_LOG_INFO, "FBO: [ID %i] Unloaded framebuffer from VRAM (GPU)", id); +#endif +} + +// Vertex data management +//----------------------------------------------------------------------------------------- +// Load a new attributes buffer +unsigned int rlLoadVertexBuffer(const void *buffer, int size, bool dynamic) +{ + unsigned int id = 0; + +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + glGenBuffers(1, &id); + glBindBuffer(GL_ARRAY_BUFFER, id); + glBufferData(GL_ARRAY_BUFFER, size, buffer, dynamic? GL_DYNAMIC_DRAW : GL_STATIC_DRAW); +#endif + + return id; +} + +// Load a new attributes element buffer +unsigned int rlLoadVertexBufferElement(const void *buffer, int size, bool dynamic) +{ + unsigned int id = 0; + +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + glGenBuffers(1, &id); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, id); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, size, buffer, dynamic? GL_DYNAMIC_DRAW : GL_STATIC_DRAW); +#endif + + return id; +} + +// Enable vertex buffer (VBO) +void rlEnableVertexBuffer(unsigned int id) +{ +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + glBindBuffer(GL_ARRAY_BUFFER, id); +#endif +} + +// Disable vertex buffer (VBO) +void rlDisableVertexBuffer(void) +{ +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + glBindBuffer(GL_ARRAY_BUFFER, 0); +#endif +} + +// Enable vertex buffer element (VBO element) +void rlEnableVertexBufferElement(unsigned int id) +{ +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, id); +#endif +} + +// Disable vertex buffer element (VBO element) +void rlDisableVertexBufferElement(void) +{ +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); +#endif +} + +// Update vertex buffer with new data +// NOTE: dataSize and offset must be provided in bytes +void rlUpdateVertexBuffer(unsigned int id, const void *data, int dataSize, int offset) +{ +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + glBindBuffer(GL_ARRAY_BUFFER, id); + glBufferSubData(GL_ARRAY_BUFFER, offset, dataSize, data); +#endif +} + +// Update vertex buffer elements with new data +// NOTE: dataSize and offset must be provided in bytes +void rlUpdateVertexBufferElements(unsigned int id, const void *data, int dataSize, int offset) +{ +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, id); + glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, offset, dataSize, data); +#endif +} + +// Enable vertex array object (VAO) +bool rlEnableVertexArray(unsigned int vaoId) +{ + bool result = false; +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + if (RLGL.ExtSupported.vao) + { + glBindVertexArray(vaoId); + result = true; + } +#endif + return result; +} + +// Disable vertex array object (VAO) +void rlDisableVertexArray(void) +{ +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + if (RLGL.ExtSupported.vao) glBindVertexArray(0); +#endif +} + +// Enable vertex attribute index +void rlEnableVertexAttribute(unsigned int index) +{ +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + glEnableVertexAttribArray(index); +#endif +} + +// Disable vertex attribute index +void rlDisableVertexAttribute(unsigned int index) +{ +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + glDisableVertexAttribArray(index); +#endif +} + +// Draw vertex array +void rlDrawVertexArray(int offset, int count) +{ + glDrawArrays(GL_TRIANGLES, offset, count); +} + +// Draw vertex array elements +void rlDrawVertexArrayElements(int offset, int count, const void *buffer) +{ + // NOTE: Added pointer math separately from function to avoid UBSAN complaining + unsigned short *bufferPtr = (unsigned short *)buffer; + if (offset > 0) bufferPtr += offset; + + glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_SHORT, (const unsigned short *)bufferPtr); +} + +// Draw vertex array instanced +void rlDrawVertexArrayInstanced(int offset, int count, int instances) +{ +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + glDrawArraysInstanced(GL_TRIANGLES, 0, count, instances); +#endif +} + +// Draw vertex array elements instanced +void rlDrawVertexArrayElementsInstanced(int offset, int count, const void *buffer, int instances) +{ +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + // NOTE: Added pointer math separately from function to avoid UBSAN complaining + unsigned short *bufferPtr = (unsigned short *)buffer; + if (offset > 0) bufferPtr += offset; + + glDrawElementsInstanced(GL_TRIANGLES, count, GL_UNSIGNED_SHORT, (const unsigned short *)bufferPtr, instances); +#endif +} + +#if defined(GRAPHICS_API_OPENGL_11) +// Enable vertex state pointer +void rlEnableStatePointer(int vertexAttribType, void *buffer) +{ + if (buffer != NULL) glEnableClientState(vertexAttribType); + switch (vertexAttribType) + { + case GL_VERTEX_ARRAY: glVertexPointer(3, GL_FLOAT, 0, buffer); break; + case GL_TEXTURE_COORD_ARRAY: glTexCoordPointer(2, GL_FLOAT, 0, buffer); break; + case GL_NORMAL_ARRAY: if (buffer != NULL) glNormalPointer(GL_FLOAT, 0, buffer); break; + case GL_COLOR_ARRAY: if (buffer != NULL) glColorPointer(4, GL_UNSIGNED_BYTE, 0, buffer); break; + //case GL_INDEX_ARRAY: if (buffer != NULL) glIndexPointer(GL_SHORT, 0, buffer); break; // Indexed colors + default: break; + } +} + +// Disable vertex state pointer +void rlDisableStatePointer(int vertexAttribType) +{ + glDisableClientState(vertexAttribType); +} +#endif + +// Load vertex array object (VAO) +unsigned int rlLoadVertexArray(void) +{ + unsigned int vaoId = 0; +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + if (RLGL.ExtSupported.vao) + { + glGenVertexArrays(1, &vaoId); + } +#endif + return vaoId; +} + +// Set vertex attribute +void rlSetVertexAttribute(unsigned int index, int compSize, int type, bool normalized, int stride, int offset) +{ +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + // NOTE: Data type could be: GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_INT, GL_UNSIGNED_INT + // Additional types (depends on OpenGL version or extensions): + // - GL_HALF_FLOAT, GL_FLOAT, GL_DOUBLE, GL_FIXED, + // - GL_INT_2_10_10_10_REV, GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_INT_10F_11F_11F_REV + + size_t offsetNative = offset; + glVertexAttribPointer(index, compSize, type, normalized, stride, (void *)offsetNative); +#endif +} + +// Set vertex attribute divisor +void rlSetVertexAttributeDivisor(unsigned int index, int divisor) +{ +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + glVertexAttribDivisor(index, divisor); +#endif +} + +// Unload vertex array object (VAO) +void rlUnloadVertexArray(unsigned int vaoId) +{ +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + if (RLGL.ExtSupported.vao) + { + glBindVertexArray(0); + glDeleteVertexArrays(1, &vaoId); + TRACELOG(RL_LOG_INFO, "VAO: [ID %i] Unloaded vertex array data from VRAM (GPU)", vaoId); + } +#endif +} + +// Unload vertex buffer (VBO) +void rlUnloadVertexBuffer(unsigned int vboId) +{ +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + glDeleteBuffers(1, &vboId); + //TRACELOG(RL_LOG_INFO, "VBO: Unloaded vertex data from VRAM (GPU)"); +#endif +} + +// Shaders management +//----------------------------------------------------------------------------------------------- +// Load shader from code strings +// NOTE: If shader string is NULL, using default vertex/fragment shaders +unsigned int rlLoadShaderCode(const char *vsCode, const char *fsCode) +{ + unsigned int id = 0; + +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + unsigned int vertexShaderId = 0; + unsigned int fragmentShaderId = 0; + + // Compile vertex shader (if provided) + // NOTE: If not vertex shader is provided, use default one + if (vsCode != NULL) vertexShaderId = rlCompileShader(vsCode, GL_VERTEX_SHADER); + else vertexShaderId = RLGL.State.defaultVShaderId; + + // Compile fragment shader (if provided) + // NOTE: If not vertex shader is provided, use default one + if (fsCode != NULL) fragmentShaderId = rlCompileShader(fsCode, GL_FRAGMENT_SHADER); + else fragmentShaderId = RLGL.State.defaultFShaderId; + + // In case vertex and fragment shader are the default ones, no need to recompile, we can just assign the default shader program id + if ((vertexShaderId == RLGL.State.defaultVShaderId) && (fragmentShaderId == RLGL.State.defaultFShaderId)) id = RLGL.State.defaultShaderId; + else if ((vertexShaderId > 0) && (fragmentShaderId > 0)) + { + // One of or both shader are new, we need to compile a new shader program + id = rlLoadShaderProgram(vertexShaderId, fragmentShaderId); + + // We can detach and delete vertex/fragment shaders (if not default ones) + // NOTE: We detach shader before deletion to make sure memory is freed + if (vertexShaderId != RLGL.State.defaultVShaderId) + { + // WARNING: Shader program linkage could fail and returned id is 0 + if (id > 0) glDetachShader(id, vertexShaderId); + glDeleteShader(vertexShaderId); + } + if (fragmentShaderId != RLGL.State.defaultFShaderId) + { + // WARNING: Shader program linkage could fail and returned id is 0 + if (id > 0) glDetachShader(id, fragmentShaderId); + glDeleteShader(fragmentShaderId); + } + + // In case shader program loading failed, we assign default shader + if (id == 0) + { + // In case shader loading fails, we return the default shader + TRACELOG(RL_LOG_WARNING, "SHADER: Failed to load custom shader code, using default shader"); + id = RLGL.State.defaultShaderId; + } + /* + else + { + // Get available shader uniforms + // NOTE: This information is useful for debug... + int uniformCount = -1; + glGetProgramiv(id, GL_ACTIVE_UNIFORMS, &uniformCount); + + for (int i = 0; i < uniformCount; i++) + { + int namelen = -1; + int num = -1; + char name[256] = { 0 }; // Assume no variable names longer than 256 + GLenum type = GL_ZERO; + + // Get the name of the uniforms + glGetActiveUniform(id, i, sizeof(name) - 1, &namelen, &num, &type, name); + + name[namelen] = 0; + TRACELOGD("SHADER: [ID %i] Active uniform (%s) set at location: %i", id, name, glGetUniformLocation(id, name)); + } + } + */ + } +#endif + + return id; +} + +// Compile custom shader and return shader id +unsigned int rlCompileShader(const char *shaderCode, int type) +{ + unsigned int shader = 0; + +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + shader = glCreateShader(type); + glShaderSource(shader, 1, &shaderCode, NULL); + + GLint success = 0; + glCompileShader(shader); + glGetShaderiv(shader, GL_COMPILE_STATUS, &success); + + if (success == GL_FALSE) + { + switch (type) + { + case GL_VERTEX_SHADER: TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Failed to compile vertex shader code", shader); break; + case GL_FRAGMENT_SHADER: TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Failed to compile fragment shader code", shader); break; + //case GL_GEOMETRY_SHADER: + #if defined(GRAPHICS_API_OPENGL_43) + case GL_COMPUTE_SHADER: TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Failed to compile compute shader code", shader); break; + #elif defined(GRAPHICS_API_OPENGL_33) + case GL_COMPUTE_SHADER: TRACELOG(RL_LOG_WARNING, "SHADER: Compute shaders not enabled. Define GRAPHICS_API_OPENGL_43", shader); break; + #endif + default: break; + } + + int maxLength = 0; + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &maxLength); + + if (maxLength > 0) + { + int length = 0; + char *log = (char *)RL_CALLOC(maxLength, sizeof(char)); + glGetShaderInfoLog(shader, maxLength, &length, log); + TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Compile error: %s", shader, log); + RL_FREE(log); + } + + shader = 0; + } + else + { + switch (type) + { + case GL_VERTEX_SHADER: TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Vertex shader compiled successfully", shader); break; + case GL_FRAGMENT_SHADER: TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Fragment shader compiled successfully", shader); break; + //case GL_GEOMETRY_SHADER: + #if defined(GRAPHICS_API_OPENGL_43) + case GL_COMPUTE_SHADER: TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Compute shader compiled successfully", shader); break; + #elif defined(GRAPHICS_API_OPENGL_33) + case GL_COMPUTE_SHADER: TRACELOG(RL_LOG_WARNING, "SHADER: Compute shaders not enabled. Define GRAPHICS_API_OPENGL_43", shader); break; + #endif + default: break; + } + } +#endif + + return shader; +} + +// Load custom shader strings and return program id +unsigned int rlLoadShaderProgram(unsigned int vShaderId, unsigned int fShaderId) +{ + unsigned int program = 0; + +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + GLint success = 0; + program = glCreateProgram(); + + glAttachShader(program, vShaderId); + glAttachShader(program, fShaderId); + + // NOTE: Default attribute shader locations must be Bound before linking + glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION, RL_DEFAULT_SHADER_ATTRIB_NAME_POSITION); + glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD, RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD); + glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL, RL_DEFAULT_SHADER_ATTRIB_NAME_NORMAL); + glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR, RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR); + glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT, RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT); + glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2, RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2); + +#ifdef RL_SUPPORT_MESH_GPU_SKINNING + glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS, RL_DEFAULT_SHADER_ATTRIB_NAME_BONEIDS); + glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS, RL_DEFAULT_SHADER_ATTRIB_NAME_BONEWEIGHTS); +#endif + + // NOTE: If some attrib name is no found on the shader, it locations becomes -1 + + glLinkProgram(program); + + // NOTE: All uniform variables are intitialised to 0 when a program links + + glGetProgramiv(program, GL_LINK_STATUS, &success); + + if (success == GL_FALSE) + { + TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Failed to link shader program", program); + + int maxLength = 0; + glGetProgramiv(program, GL_INFO_LOG_LENGTH, &maxLength); + + if (maxLength > 0) + { + int length = 0; + char *log = (char *)RL_CALLOC(maxLength, sizeof(char)); + glGetProgramInfoLog(program, maxLength, &length, log); + TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Link error: %s", program, log); + RL_FREE(log); + } + + glDeleteProgram(program); + + program = 0; + } + else + { + // Get the size of compiled shader program (not available on OpenGL ES 2.0) + // NOTE: If GL_LINK_STATUS is GL_FALSE, program binary length is zero + //GLint binarySize = 0; + //glGetProgramiv(id, GL_PROGRAM_BINARY_LENGTH, &binarySize); + + TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Program shader loaded successfully", program); + } +#endif + return program; +} + +// Unload shader program +void rlUnloadShaderProgram(unsigned int id) +{ +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + glDeleteProgram(id); + + TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Unloaded shader program data from VRAM (GPU)", id); +#endif +} + +// Get shader location uniform +int rlGetLocationUniform(unsigned int shaderId, const char *uniformName) +{ + int location = -1; +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + location = glGetUniformLocation(shaderId, uniformName); + + //if (location == -1) TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Failed to find shader uniform: %s", shaderId, uniformName); + //else TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Shader uniform (%s) set at location: %i", shaderId, uniformName, location); +#endif + return location; +} + +// Get shader location attribute +int rlGetLocationAttrib(unsigned int shaderId, const char *attribName) +{ + int location = -1; +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + location = glGetAttribLocation(shaderId, attribName); + + //if (location == -1) TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Failed to find shader attribute: %s", shaderId, attribName); + //else TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Shader attribute (%s) set at location: %i", shaderId, attribName, location); +#endif + return location; +} + +// Set shader value uniform +void rlSetUniform(int locIndex, const void *value, int uniformType, int count) +{ +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + switch (uniformType) + { + case RL_SHADER_UNIFORM_FLOAT: glUniform1fv(locIndex, count, (float *)value); break; + case RL_SHADER_UNIFORM_VEC2: glUniform2fv(locIndex, count, (float *)value); break; + case RL_SHADER_UNIFORM_VEC3: glUniform3fv(locIndex, count, (float *)value); break; + case RL_SHADER_UNIFORM_VEC4: glUniform4fv(locIndex, count, (float *)value); break; + case RL_SHADER_UNIFORM_INT: glUniform1iv(locIndex, count, (int *)value); break; + case RL_SHADER_UNIFORM_IVEC2: glUniform2iv(locIndex, count, (int *)value); break; + case RL_SHADER_UNIFORM_IVEC3: glUniform3iv(locIndex, count, (int *)value); break; + case RL_SHADER_UNIFORM_IVEC4: glUniform4iv(locIndex, count, (int *)value); break; + #if !defined(GRAPHICS_API_OPENGL_ES2) + case RL_SHADER_UNIFORM_UINT: glUniform1uiv(locIndex, count, (unsigned int *)value); break; + case RL_SHADER_UNIFORM_UIVEC2: glUniform2uiv(locIndex, count, (unsigned int *)value); break; + case RL_SHADER_UNIFORM_UIVEC3: glUniform3uiv(locIndex, count, (unsigned int *)value); break; + case RL_SHADER_UNIFORM_UIVEC4: glUniform4uiv(locIndex, count, (unsigned int *)value); break; + #endif + case RL_SHADER_UNIFORM_SAMPLER2D: glUniform1iv(locIndex, count, (int *)value); break; + default: TRACELOG(RL_LOG_WARNING, "SHADER: Failed to set uniform value, data type not recognized"); + + // TODO: Support glUniform1uiv(), glUniform2uiv(), glUniform3uiv(), glUniform4uiv() + } +#endif +} + +// Set shader value attribute +void rlSetVertexAttributeDefault(int locIndex, const void *value, int attribType, int count) +{ +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + switch (attribType) + { + case RL_SHADER_ATTRIB_FLOAT: if (count == 1) glVertexAttrib1fv(locIndex, (float *)value); break; + case RL_SHADER_ATTRIB_VEC2: if (count == 2) glVertexAttrib2fv(locIndex, (float *)value); break; + case RL_SHADER_ATTRIB_VEC3: if (count == 3) glVertexAttrib3fv(locIndex, (float *)value); break; + case RL_SHADER_ATTRIB_VEC4: if (count == 4) glVertexAttrib4fv(locIndex, (float *)value); break; + default: TRACELOG(RL_LOG_WARNING, "SHADER: Failed to set attrib default value, data type not recognized"); + } +#endif +} + +// Set shader value uniform matrix +void rlSetUniformMatrix(int locIndex, Matrix mat) +{ +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + float matfloat[16] = { + mat.m0, mat.m1, mat.m2, mat.m3, + mat.m4, mat.m5, mat.m6, mat.m7, + mat.m8, mat.m9, mat.m10, mat.m11, + mat.m12, mat.m13, mat.m14, mat.m15 + }; + glUniformMatrix4fv(locIndex, 1, false, matfloat); +#endif +} + +// Set shader value uniform matrix +void rlSetUniformMatrices(int locIndex, const Matrix *matrices, int count) +{ +#if defined(GRAPHICS_API_OPENGL_33) + glUniformMatrix4fv(locIndex, count, true, (const float *)matrices); +#elif defined(GRAPHICS_API_OPENGL_ES2) + // WARNING: WebGL does not support Matrix transpose ("true" parameter) + // REF: https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/uniformMatrix + glUniformMatrix4fv(locIndex, count, false, (const float *)matrices); +#endif +} + +// Set shader value uniform sampler +void rlSetUniformSampler(int locIndex, unsigned int textureId) +{ +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + // Check if texture is already active + for (int i = 0; i < RL_DEFAULT_BATCH_MAX_TEXTURE_UNITS; i++) + { + if (RLGL.State.activeTextureId[i] == textureId) + { + glUniform1i(locIndex, 1 + i); + return; + } + } + + // Register a new active texture for the internal batch system + // NOTE: Default texture is always activated as GL_TEXTURE0 + for (int i = 0; i < RL_DEFAULT_BATCH_MAX_TEXTURE_UNITS; i++) + { + if (RLGL.State.activeTextureId[i] == 0) + { + glUniform1i(locIndex, 1 + i); // Activate new texture unit + RLGL.State.activeTextureId[i] = textureId; // Save texture id for binding on drawing + break; + } + } +#endif +} + +// Set shader currently active (id and locations) +void rlSetShader(unsigned int id, int *locs) +{ +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + if (RLGL.State.currentShaderId != id) + { + rlDrawRenderBatch(RLGL.currentBatch); + RLGL.State.currentShaderId = id; + RLGL.State.currentShaderLocs = locs; + } +#endif +} + +// Load compute shader program +unsigned int rlLoadComputeShaderProgram(unsigned int shaderId) +{ + unsigned int program = 0; + +#if defined(GRAPHICS_API_OPENGL_43) + GLint success = 0; + program = glCreateProgram(); + glAttachShader(program, shaderId); + glLinkProgram(program); + + // NOTE: All uniform variables are intitialised to 0 when a program links + + glGetProgramiv(program, GL_LINK_STATUS, &success); + + if (success == GL_FALSE) + { + TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Failed to link compute shader program", program); + + int maxLength = 0; + glGetProgramiv(program, GL_INFO_LOG_LENGTH, &maxLength); + + if (maxLength > 0) + { + int length = 0; + char *log = (char *)RL_CALLOC(maxLength, sizeof(char)); + glGetProgramInfoLog(program, maxLength, &length, log); + TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Link error: %s", program, log); + RL_FREE(log); + } + + glDeleteProgram(program); + + program = 0; + } + else + { + // Get the size of compiled shader program (not available on OpenGL ES 2.0) + // NOTE: If GL_LINK_STATUS is GL_FALSE, program binary length is zero + //GLint binarySize = 0; + //glGetProgramiv(id, GL_PROGRAM_BINARY_LENGTH, &binarySize); + + TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Compute shader program loaded successfully", program); + } +#else + TRACELOG(RL_LOG_WARNING, "SHADER: Compute shaders not enabled. Define GRAPHICS_API_OPENGL_43"); +#endif + + return program; +} + +// Dispatch compute shader (equivalent to *draw* for graphics pilepine) +void rlComputeShaderDispatch(unsigned int groupX, unsigned int groupY, unsigned int groupZ) +{ +#if defined(GRAPHICS_API_OPENGL_43) + glDispatchCompute(groupX, groupY, groupZ); +#endif +} + +// Load shader storage buffer object (SSBO) +unsigned int rlLoadShaderBuffer(unsigned int size, const void *data, int usageHint) +{ + unsigned int ssbo = 0; + +#if defined(GRAPHICS_API_OPENGL_43) + glGenBuffers(1, &ssbo); + glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo); + glBufferData(GL_SHADER_STORAGE_BUFFER, size, data, usageHint? usageHint : RL_STREAM_COPY); + if (data == NULL) glClearBufferData(GL_SHADER_STORAGE_BUFFER, GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE, NULL); // Clear buffer data to 0 + glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); +#else + TRACELOG(RL_LOG_WARNING, "SSBO: SSBO not enabled. Define GRAPHICS_API_OPENGL_43"); +#endif + + return ssbo; +} + +// Unload shader storage buffer object (SSBO) +void rlUnloadShaderBuffer(unsigned int ssboId) +{ +#if defined(GRAPHICS_API_OPENGL_43) + glDeleteBuffers(1, &ssboId); +#else + TRACELOG(RL_LOG_WARNING, "SSBO: SSBO not enabled. Define GRAPHICS_API_OPENGL_43"); +#endif + +} + +// Update SSBO buffer data +void rlUpdateShaderBuffer(unsigned int id, const void *data, unsigned int dataSize, unsigned int offset) +{ +#if defined(GRAPHICS_API_OPENGL_43) + glBindBuffer(GL_SHADER_STORAGE_BUFFER, id); + glBufferSubData(GL_SHADER_STORAGE_BUFFER, offset, dataSize, data); +#endif +} + +// Get SSBO buffer size +unsigned int rlGetShaderBufferSize(unsigned int id) +{ +#if defined(GRAPHICS_API_OPENGL_43) + GLint64 size = 0; + glBindBuffer(GL_SHADER_STORAGE_BUFFER, id); + glGetBufferParameteri64v(GL_SHADER_STORAGE_BUFFER, GL_BUFFER_SIZE, &size); + return (size > 0)? (unsigned int)size : 0; +#else + return 0; +#endif +} + +// Read SSBO buffer data (GPU->CPU) +void rlReadShaderBuffer(unsigned int id, void *dest, unsigned int count, unsigned int offset) +{ +#if defined(GRAPHICS_API_OPENGL_43) + glBindBuffer(GL_SHADER_STORAGE_BUFFER, id); + glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, offset, count, dest); +#endif +} + +// Bind SSBO buffer +void rlBindShaderBuffer(unsigned int id, unsigned int index) +{ +#if defined(GRAPHICS_API_OPENGL_43) + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, index, id); +#endif +} + +// Copy SSBO buffer data +void rlCopyShaderBuffer(unsigned int destId, unsigned int srcId, unsigned int destOffset, unsigned int srcOffset, unsigned int count) +{ +#if defined(GRAPHICS_API_OPENGL_43) + glBindBuffer(GL_COPY_READ_BUFFER, srcId); + glBindBuffer(GL_COPY_WRITE_BUFFER, destId); + glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, srcOffset, destOffset, count); +#endif +} + +// Bind image texture +void rlBindImageTexture(unsigned int id, unsigned int index, int format, bool readonly) +{ +#if defined(GRAPHICS_API_OPENGL_43) + unsigned int glInternalFormat = 0, glFormat = 0, glType = 0; + + rlGetGlTextureFormats(format, &glInternalFormat, &glFormat, &glType); + glBindImageTexture(index, id, 0, 0, 0, readonly? GL_READ_ONLY : GL_READ_WRITE, glInternalFormat); +#else + TRACELOG(RL_LOG_WARNING, "TEXTURE: Image texture binding not enabled. Define GRAPHICS_API_OPENGL_43"); +#endif +} + +// Matrix state management +//----------------------------------------------------------------------------------------- +// Get internal modelview matrix +Matrix rlGetMatrixModelview(void) +{ + Matrix matrix = rlMatrixIdentity(); +#if defined(GRAPHICS_API_OPENGL_11) + float mat[16]; + glGetFloatv(GL_MODELVIEW_MATRIX, mat); + matrix.m0 = mat[0]; + matrix.m1 = mat[1]; + matrix.m2 = mat[2]; + matrix.m3 = mat[3]; + matrix.m4 = mat[4]; + matrix.m5 = mat[5]; + matrix.m6 = mat[6]; + matrix.m7 = mat[7]; + matrix.m8 = mat[8]; + matrix.m9 = mat[9]; + matrix.m10 = mat[10]; + matrix.m11 = mat[11]; + matrix.m12 = mat[12]; + matrix.m13 = mat[13]; + matrix.m14 = mat[14]; + matrix.m15 = mat[15]; +#else + matrix = RLGL.State.modelview; +#endif + return matrix; +} + +// Get internal projection matrix +Matrix rlGetMatrixProjection(void) +{ +#if defined(GRAPHICS_API_OPENGL_11) + float mat[16]; + glGetFloatv(GL_PROJECTION_MATRIX,mat); + Matrix m; + m.m0 = mat[0]; + m.m1 = mat[1]; + m.m2 = mat[2]; + m.m3 = mat[3]; + m.m4 = mat[4]; + m.m5 = mat[5]; + m.m6 = mat[6]; + m.m7 = mat[7]; + m.m8 = mat[8]; + m.m9 = mat[9]; + m.m10 = mat[10]; + m.m11 = mat[11]; + m.m12 = mat[12]; + m.m13 = mat[13]; + m.m14 = mat[14]; + m.m15 = mat[15]; + return m; +#else + return RLGL.State.projection; +#endif +} + +// Get internal accumulated transform matrix +Matrix rlGetMatrixTransform(void) +{ + Matrix mat = rlMatrixIdentity(); +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + // TODO: Consider possible transform matrices in the RLGL.State.stack + // Is this the right order? or should we start with the first stored matrix instead of the last one? + //Matrix matStackTransform = rlMatrixIdentity(); + //for (int i = RLGL.State.stackCounter; i > 0; i--) matStackTransform = rlMatrixMultiply(RLGL.State.stack[i], matStackTransform); + mat = RLGL.State.transform; +#endif + return mat; +} + +// Get internal projection matrix for stereo render (selected eye) +Matrix rlGetMatrixProjectionStereo(int eye) +{ + Matrix mat = rlMatrixIdentity(); +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + mat = RLGL.State.projectionStereo[eye]; +#endif + return mat; +} + +// Get internal view offset matrix for stereo render (selected eye) +Matrix rlGetMatrixViewOffsetStereo(int eye) +{ + Matrix mat = rlMatrixIdentity(); +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + mat = RLGL.State.viewOffsetStereo[eye]; +#endif + return mat; +} + +// Set a custom modelview matrix (replaces internal modelview matrix) +void rlSetMatrixModelview(Matrix view) +{ +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + RLGL.State.modelview = view; +#endif +} + +// Set a custom projection matrix (replaces internal projection matrix) +void rlSetMatrixProjection(Matrix projection) +{ +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + RLGL.State.projection = projection; +#endif +} + +// Set eyes projection matrices for stereo rendering +void rlSetMatrixProjectionStereo(Matrix right, Matrix left) +{ +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + RLGL.State.projectionStereo[0] = right; + RLGL.State.projectionStereo[1] = left; +#endif +} + +// Set eyes view offsets matrices for stereo rendering +void rlSetMatrixViewOffsetStereo(Matrix right, Matrix left) +{ +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + RLGL.State.viewOffsetStereo[0] = right; + RLGL.State.viewOffsetStereo[1] = left; +#endif +} + +// Load and draw a quad in NDC +void rlLoadDrawQuad(void) +{ +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + unsigned int quadVAO = 0; + unsigned int quadVBO = 0; + + float vertices[] = { + // Positions Texcoords + -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, + -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, + 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, + 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, + }; + + // Gen VAO to contain VBO + glGenVertexArrays(1, &quadVAO); + glBindVertexArray(quadVAO); + + // Gen and fill vertex buffer (VBO) + glGenBuffers(1, &quadVBO); + glBindBuffer(GL_ARRAY_BUFFER, quadVBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), &vertices, GL_STATIC_DRAW); + + // Bind vertex attributes (position, texcoords) + glEnableVertexAttribArray(RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION); + glVertexAttribPointer(RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION, 3, GL_FLOAT, GL_FALSE, 5*sizeof(float), (void *)0); // Positions + glEnableVertexAttribArray(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD); + glVertexAttribPointer(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD, 2, GL_FLOAT, GL_FALSE, 5*sizeof(float), (void *)(3*sizeof(float))); // Texcoords + + // Draw quad + glBindVertexArray(quadVAO); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + glBindVertexArray(0); + + // Delete buffers (VBO and VAO) + glDeleteBuffers(1, &quadVBO); + glDeleteVertexArrays(1, &quadVAO); +#endif +} + +// Load and draw a cube in NDC +void rlLoadDrawCube(void) +{ +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + unsigned int cubeVAO = 0; + unsigned int cubeVBO = 0; + + float vertices[] = { + // Positions Normals Texcoords + -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, + 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, + 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, + 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, + -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, + -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, + -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, + 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, + 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, + -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, + -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, + -1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, + -1.0f, 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, + -1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, + -1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, + -1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, + -1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, + 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, + 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, + 1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, + 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, + 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, + 1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, + -1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, + 1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 1.0f, + 1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, + 1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, + -1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, + -1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, + -1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, + 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, + 1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, + -1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, + -1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f + }; + + // Gen VAO to contain VBO + glGenVertexArrays(1, &cubeVAO); + glBindVertexArray(cubeVAO); + + // Gen and fill vertex buffer (VBO) + glGenBuffers(1, &cubeVBO); + glBindBuffer(GL_ARRAY_BUFFER, cubeVBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); + + // Bind vertex attributes (position, normals, texcoords) + glBindVertexArray(cubeVAO); + glEnableVertexAttribArray(RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION); + glVertexAttribPointer(RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION, 3, GL_FLOAT, GL_FALSE, 8*sizeof(float), (void *)0); // Positions + glEnableVertexAttribArray(RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL); + glVertexAttribPointer(RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL, 3, GL_FLOAT, GL_FALSE, 8*sizeof(float), (void *)(3*sizeof(float))); // Normals + glEnableVertexAttribArray(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD); + glVertexAttribPointer(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD, 2, GL_FLOAT, GL_FALSE, 8*sizeof(float), (void *)(6*sizeof(float))); // Texcoords + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindVertexArray(0); + + // Draw cube + glBindVertexArray(cubeVAO); + glDrawArrays(GL_TRIANGLES, 0, 36); + glBindVertexArray(0); + + // Delete VBO and VAO + glDeleteBuffers(1, &cubeVBO); + glDeleteVertexArrays(1, &cubeVAO); +#endif +} + +// Get name string for pixel format +const char *rlGetPixelFormatName(unsigned int format) +{ + switch (format) + { + case RL_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE: return "GRAYSCALE"; break; // 8 bit per pixel (no alpha) + case RL_PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA: return "GRAY_ALPHA"; break; // 8*2 bpp (2 channels) + case RL_PIXELFORMAT_UNCOMPRESSED_R5G6B5: return "R5G6B5"; break; // 16 bpp + case RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8: return "R8G8B8"; break; // 24 bpp + case RL_PIXELFORMAT_UNCOMPRESSED_R5G5B5A1: return "R5G5B5A1"; break; // 16 bpp (1 bit alpha) + case RL_PIXELFORMAT_UNCOMPRESSED_R4G4B4A4: return "R4G4B4A4"; break; // 16 bpp (4 bit alpha) + case RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8: return "R8G8B8A8"; break; // 32 bpp + case RL_PIXELFORMAT_UNCOMPRESSED_R32: return "R32"; break; // 32 bpp (1 channel - float) + case RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32: return "R32G32B32"; break; // 32*3 bpp (3 channels - float) + case RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: return "R32G32B32A32"; break; // 32*4 bpp (4 channels - float) + case RL_PIXELFORMAT_UNCOMPRESSED_R16: return "R16"; break; // 16 bpp (1 channel - half float) + case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16: return "R16G16B16"; break; // 16*3 bpp (3 channels - half float) + case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: return "R16G16B16A16"; break; // 16*4 bpp (4 channels - half float) + case RL_PIXELFORMAT_COMPRESSED_DXT1_RGB: return "DXT1_RGB"; break; // 4 bpp (no alpha) + case RL_PIXELFORMAT_COMPRESSED_DXT1_RGBA: return "DXT1_RGBA"; break; // 4 bpp (1 bit alpha) + case RL_PIXELFORMAT_COMPRESSED_DXT3_RGBA: return "DXT3_RGBA"; break; // 8 bpp + case RL_PIXELFORMAT_COMPRESSED_DXT5_RGBA: return "DXT5_RGBA"; break; // 8 bpp + case RL_PIXELFORMAT_COMPRESSED_ETC1_RGB: return "ETC1_RGB"; break; // 4 bpp + case RL_PIXELFORMAT_COMPRESSED_ETC2_RGB: return "ETC2_RGB"; break; // 4 bpp + case RL_PIXELFORMAT_COMPRESSED_ETC2_EAC_RGBA: return "ETC2_RGBA"; break; // 8 bpp + case RL_PIXELFORMAT_COMPRESSED_PVRT_RGB: return "PVRT_RGB"; break; // 4 bpp + case RL_PIXELFORMAT_COMPRESSED_PVRT_RGBA: return "PVRT_RGBA"; break; // 4 bpp + case RL_PIXELFORMAT_COMPRESSED_ASTC_4x4_RGBA: return "ASTC_4x4_RGBA"; break; // 8 bpp + case RL_PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA: return "ASTC_8x8_RGBA"; break; // 2 bpp + default: return "UNKNOWN"; break; + } +} + +//---------------------------------------------------------------------------------- +// Module specific Functions Definition +//---------------------------------------------------------------------------------- +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) +// Load default shader (just vertex positioning and texture coloring) +// NOTE: This shader program is used for internal buffers +// NOTE: Loaded: RLGL.State.defaultShaderId, RLGL.State.defaultShaderLocs +static void rlLoadShaderDefault(void) +{ + RLGL.State.defaultShaderLocs = (int *)RL_CALLOC(RL_MAX_SHADER_LOCATIONS, sizeof(int)); + + // NOTE: All locations must be reseted to -1 (no location) + for (int i = 0; i < RL_MAX_SHADER_LOCATIONS; i++) RLGL.State.defaultShaderLocs[i] = -1; + + // Vertex shader directly defined, no external file required + const char *defaultVShaderCode = +#if defined(GRAPHICS_API_OPENGL_21) + "#version 120 \n" + "attribute vec3 vertexPosition; \n" + "attribute vec2 vertexTexCoord; \n" + "attribute vec4 vertexColor; \n" + "varying vec2 fragTexCoord; \n" + "varying vec4 fragColor; \n" +#elif defined(GRAPHICS_API_OPENGL_33) + "#version 330 \n" + "in vec3 vertexPosition; \n" + "in vec2 vertexTexCoord; \n" + "in vec4 vertexColor; \n" + "out vec2 fragTexCoord; \n" + "out vec4 fragColor; \n" +#endif + +#if defined(GRAPHICS_API_OPENGL_ES3) + "#version 300 es \n" + "precision mediump float; \n" // Precision required for OpenGL ES3 (WebGL 2) (on some browsers) + "in vec3 vertexPosition; \n" + "in vec2 vertexTexCoord; \n" + "in vec4 vertexColor; \n" + "out vec2 fragTexCoord; \n" + "out vec4 fragColor; \n" +#elif defined(GRAPHICS_API_OPENGL_ES2) + "#version 100 \n" + "precision mediump float; \n" // Precision required for OpenGL ES2 (WebGL) (on some browsers) + "attribute vec3 vertexPosition; \n" + "attribute vec2 vertexTexCoord; \n" + "attribute vec4 vertexColor; \n" + "varying vec2 fragTexCoord; \n" + "varying vec4 fragColor; \n" +#endif + + "uniform mat4 mvp; \n" + "void main() \n" + "{ \n" + " fragTexCoord = vertexTexCoord; \n" + " fragColor = vertexColor; \n" + " gl_Position = mvp*vec4(vertexPosition, 1.0); \n" + "} \n"; + + // Fragment shader directly defined, no external file required + const char *defaultFShaderCode = +#if defined(GRAPHICS_API_OPENGL_21) + "#version 120 \n" + "varying vec2 fragTexCoord; \n" + "varying vec4 fragColor; \n" + "uniform sampler2D texture0; \n" + "uniform vec4 colDiffuse; \n" + "void main() \n" + "{ \n" + " vec4 texelColor = texture2D(texture0, fragTexCoord); \n" + " gl_FragColor = texelColor*colDiffuse*fragColor; \n" + "} \n"; +#elif defined(GRAPHICS_API_OPENGL_33) + "#version 330 \n" + "in vec2 fragTexCoord; \n" + "in vec4 fragColor; \n" + "out vec4 finalColor; \n" + "uniform sampler2D texture0; \n" + "uniform vec4 colDiffuse; \n" + "void main() \n" + "{ \n" + " vec4 texelColor = texture(texture0, fragTexCoord); \n" + " finalColor = texelColor*colDiffuse*fragColor; \n" + "} \n"; +#endif + +#if defined(GRAPHICS_API_OPENGL_ES3) + "#version 300 es \n" + "precision mediump float; \n" // Precision required for OpenGL ES3 (WebGL 2) + "in vec2 fragTexCoord; \n" + "in vec4 fragColor; \n" + "out vec4 finalColor; \n" + "uniform sampler2D texture0; \n" + "uniform vec4 colDiffuse; \n" + "void main() \n" + "{ \n" + " vec4 texelColor = texture(texture0, fragTexCoord); \n" + " finalColor = texelColor*colDiffuse*fragColor; \n" + "} \n"; +#elif defined(GRAPHICS_API_OPENGL_ES2) + "#version 100 \n" + "precision mediump float; \n" // Precision required for OpenGL ES2 (WebGL) + "varying vec2 fragTexCoord; \n" + "varying vec4 fragColor; \n" + "uniform sampler2D texture0; \n" + "uniform vec4 colDiffuse; \n" + "void main() \n" + "{ \n" + " vec4 texelColor = texture2D(texture0, fragTexCoord); \n" + " gl_FragColor = texelColor*colDiffuse*fragColor; \n" + "} \n"; +#endif + + // NOTE: Compiled vertex/fragment shaders are not deleted, + // they are kept for re-use as default shaders in case some shader loading fails + RLGL.State.defaultVShaderId = rlCompileShader(defaultVShaderCode, GL_VERTEX_SHADER); // Compile default vertex shader + RLGL.State.defaultFShaderId = rlCompileShader(defaultFShaderCode, GL_FRAGMENT_SHADER); // Compile default fragment shader + + RLGL.State.defaultShaderId = rlLoadShaderProgram(RLGL.State.defaultVShaderId, RLGL.State.defaultFShaderId); + + if (RLGL.State.defaultShaderId > 0) + { + TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Default shader loaded successfully", RLGL.State.defaultShaderId); + + // Set default shader locations: attributes locations + RLGL.State.defaultShaderLocs[RL_SHADER_LOC_VERTEX_POSITION] = glGetAttribLocation(RLGL.State.defaultShaderId, RL_DEFAULT_SHADER_ATTRIB_NAME_POSITION); + RLGL.State.defaultShaderLocs[RL_SHADER_LOC_VERTEX_TEXCOORD01] = glGetAttribLocation(RLGL.State.defaultShaderId, RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD); + RLGL.State.defaultShaderLocs[RL_SHADER_LOC_VERTEX_COLOR] = glGetAttribLocation(RLGL.State.defaultShaderId, RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR); + + // Set default shader locations: uniform locations + RLGL.State.defaultShaderLocs[RL_SHADER_LOC_MATRIX_MVP] = glGetUniformLocation(RLGL.State.defaultShaderId, RL_DEFAULT_SHADER_UNIFORM_NAME_MVP); + RLGL.State.defaultShaderLocs[RL_SHADER_LOC_COLOR_DIFFUSE] = glGetUniformLocation(RLGL.State.defaultShaderId, RL_DEFAULT_SHADER_UNIFORM_NAME_COLOR); + RLGL.State.defaultShaderLocs[RL_SHADER_LOC_MAP_DIFFUSE] = glGetUniformLocation(RLGL.State.defaultShaderId, RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE0); + } + else TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Failed to load default shader", RLGL.State.defaultShaderId); +} + +// Unload default shader +// NOTE: Unloads: RLGL.State.defaultShaderId, RLGL.State.defaultShaderLocs +static void rlUnloadShaderDefault(void) +{ + glUseProgram(0); + + glDetachShader(RLGL.State.defaultShaderId, RLGL.State.defaultVShaderId); + glDetachShader(RLGL.State.defaultShaderId, RLGL.State.defaultFShaderId); + glDeleteShader(RLGL.State.defaultVShaderId); + glDeleteShader(RLGL.State.defaultFShaderId); + + glDeleteProgram(RLGL.State.defaultShaderId); + + RL_FREE(RLGL.State.defaultShaderLocs); + + TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Default shader unloaded successfully", RLGL.State.defaultShaderId); +} + +#if defined(RLGL_SHOW_GL_DETAILS_INFO) +// Get compressed format official GL identifier name +static const char *rlGetCompressedFormatName(int format) +{ + switch (format) + { + // GL_EXT_texture_compression_s3tc + case 0x83F0: return "GL_COMPRESSED_RGB_S3TC_DXT1_EXT"; break; + case 0x83F1: return "GL_COMPRESSED_RGBA_S3TC_DXT1_EXT"; break; + case 0x83F2: return "GL_COMPRESSED_RGBA_S3TC_DXT3_EXT"; break; + case 0x83F3: return "GL_COMPRESSED_RGBA_S3TC_DXT5_EXT"; break; + // GL_3DFX_texture_compression_FXT1 + case 0x86B0: return "GL_COMPRESSED_RGB_FXT1_3DFX"; break; + case 0x86B1: return "GL_COMPRESSED_RGBA_FXT1_3DFX"; break; + // GL_IMG_texture_compression_pvrtc + case 0x8C00: return "GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG"; break; + case 0x8C01: return "GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG"; break; + case 0x8C02: return "GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG"; break; + case 0x8C03: return "GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG"; break; + // GL_OES_compressed_ETC1_RGB8_texture + case 0x8D64: return "GL_ETC1_RGB8_OES"; break; + // GL_ARB_texture_compression_rgtc + case 0x8DBB: return "GL_COMPRESSED_RED_RGTC1"; break; + case 0x8DBC: return "GL_COMPRESSED_SIGNED_RED_RGTC1"; break; + case 0x8DBD: return "GL_COMPRESSED_RG_RGTC2"; break; + case 0x8DBE: return "GL_COMPRESSED_SIGNED_RG_RGTC2"; break; + // GL_ARB_texture_compression_bptc + case 0x8E8C: return "GL_COMPRESSED_RGBA_BPTC_UNORM_ARB"; break; + case 0x8E8D: return "GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB"; break; + case 0x8E8E: return "GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB"; break; + case 0x8E8F: return "GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB"; break; + // GL_ARB_ES3_compatibility + case 0x9274: return "GL_COMPRESSED_RGB8_ETC2"; break; + case 0x9275: return "GL_COMPRESSED_SRGB8_ETC2"; break; + case 0x9276: return "GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2"; break; + case 0x9277: return "GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2"; break; + case 0x9278: return "GL_COMPRESSED_RGBA8_ETC2_EAC"; break; + case 0x9279: return "GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC"; break; + case 0x9270: return "GL_COMPRESSED_R11_EAC"; break; + case 0x9271: return "GL_COMPRESSED_SIGNED_R11_EAC"; break; + case 0x9272: return "GL_COMPRESSED_RG11_EAC"; break; + case 0x9273: return "GL_COMPRESSED_SIGNED_RG11_EAC"; break; + // GL_KHR_texture_compression_astc_hdr + case 0x93B0: return "GL_COMPRESSED_RGBA_ASTC_4x4_KHR"; break; + case 0x93B1: return "GL_COMPRESSED_RGBA_ASTC_5x4_KHR"; break; + case 0x93B2: return "GL_COMPRESSED_RGBA_ASTC_5x5_KHR"; break; + case 0x93B3: return "GL_COMPRESSED_RGBA_ASTC_6x5_KHR"; break; + case 0x93B4: return "GL_COMPRESSED_RGBA_ASTC_6x6_KHR"; break; + case 0x93B5: return "GL_COMPRESSED_RGBA_ASTC_8x5_KHR"; break; + case 0x93B6: return "GL_COMPRESSED_RGBA_ASTC_8x6_KHR"; break; + case 0x93B7: return "GL_COMPRESSED_RGBA_ASTC_8x8_KHR"; break; + case 0x93B8: return "GL_COMPRESSED_RGBA_ASTC_10x5_KHR"; break; + case 0x93B9: return "GL_COMPRESSED_RGBA_ASTC_10x6_KHR"; break; + case 0x93BA: return "GL_COMPRESSED_RGBA_ASTC_10x8_KHR"; break; + case 0x93BB: return "GL_COMPRESSED_RGBA_ASTC_10x10_KHR"; break; + case 0x93BC: return "GL_COMPRESSED_RGBA_ASTC_12x10_KHR"; break; + case 0x93BD: return "GL_COMPRESSED_RGBA_ASTC_12x12_KHR"; break; + case 0x93D0: return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR"; break; + case 0x93D1: return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR"; break; + case 0x93D2: return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR"; break; + case 0x93D3: return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR"; break; + case 0x93D4: return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR"; break; + case 0x93D5: return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR"; break; + case 0x93D6: return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR"; break; + case 0x93D7: return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR"; break; + case 0x93D8: return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR"; break; + case 0x93D9: return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR"; break; + case 0x93DA: return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR"; break; + case 0x93DB: return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR"; break; + case 0x93DC: return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR"; break; + case 0x93DD: return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR"; break; + default: return "GL_COMPRESSED_UNKNOWN"; break; + } +} +#endif // RLGL_SHOW_GL_DETAILS_INFO + +#endif // GRAPHICS_API_OPENGL_33 || GRAPHICS_API_OPENGL_ES2 + +// Get pixel data size in bytes (image or texture) +// NOTE: Size depends on pixel format +static int rlGetPixelDataSize(int width, int height, int format) +{ + int dataSize = 0; // Size in bytes + int bpp = 0; // Bits per pixel + + switch (format) + { + case RL_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE: bpp = 8; break; + case RL_PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA: + case RL_PIXELFORMAT_UNCOMPRESSED_R5G6B5: + case RL_PIXELFORMAT_UNCOMPRESSED_R5G5B5A1: + case RL_PIXELFORMAT_UNCOMPRESSED_R4G4B4A4: bpp = 16; break; + case RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8: bpp = 32; break; + case RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8: bpp = 24; break; + case RL_PIXELFORMAT_UNCOMPRESSED_R32: bpp = 32; break; + case RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32: bpp = 32*3; break; + case RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: bpp = 32*4; break; + case RL_PIXELFORMAT_UNCOMPRESSED_R16: bpp = 16; break; + case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16: bpp = 16*3; break; + case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: bpp = 16*4; break; + case RL_PIXELFORMAT_COMPRESSED_DXT1_RGB: + case RL_PIXELFORMAT_COMPRESSED_DXT1_RGBA: + case RL_PIXELFORMAT_COMPRESSED_ETC1_RGB: + case RL_PIXELFORMAT_COMPRESSED_ETC2_RGB: + case RL_PIXELFORMAT_COMPRESSED_PVRT_RGB: + case RL_PIXELFORMAT_COMPRESSED_PVRT_RGBA: bpp = 4; break; + case RL_PIXELFORMAT_COMPRESSED_DXT3_RGBA: + case RL_PIXELFORMAT_COMPRESSED_DXT5_RGBA: + case RL_PIXELFORMAT_COMPRESSED_ETC2_EAC_RGBA: + case RL_PIXELFORMAT_COMPRESSED_ASTC_4x4_RGBA: bpp = 8; break; + case RL_PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA: bpp = 2; break; + default: break; + } + + double bytesPerPixel = (double)bpp/8.0; + dataSize = (int)(bytesPerPixel*width*height); // Total data size in bytes + + // Most compressed formats works on 4x4 blocks, + // if texture is smaller, minimum dataSize is 8 or 16 + if ((width < 4) && (height < 4)) + { + if ((format >= RL_PIXELFORMAT_COMPRESSED_DXT1_RGB) && (format < RL_PIXELFORMAT_COMPRESSED_DXT3_RGBA)) dataSize = 8; + else if ((format >= RL_PIXELFORMAT_COMPRESSED_DXT3_RGBA) && (format < RL_PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA)) dataSize = 16; + } + + return dataSize; +} + +// Auxiliar math functions + +// Get float array of matrix data +static rl_float16 rlMatrixToFloatV(Matrix mat) +{ + rl_float16 result = { 0 }; + + result.v[0] = mat.m0; + result.v[1] = mat.m1; + result.v[2] = mat.m2; + result.v[3] = mat.m3; + result.v[4] = mat.m4; + result.v[5] = mat.m5; + result.v[6] = mat.m6; + result.v[7] = mat.m7; + result.v[8] = mat.m8; + result.v[9] = mat.m9; + result.v[10] = mat.m10; + result.v[11] = mat.m11; + result.v[12] = mat.m12; + result.v[13] = mat.m13; + result.v[14] = mat.m14; + result.v[15] = mat.m15; + + return result; +} + +// Get identity matrix +static Matrix rlMatrixIdentity(void) +{ + Matrix result = { + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + }; + + return result; +} + +// Get two matrix multiplication +// NOTE: When multiplying matrices... the order matters! +static Matrix rlMatrixMultiply(Matrix left, Matrix right) +{ + Matrix result = { 0 }; + + result.m0 = left.m0*right.m0 + left.m1*right.m4 + left.m2*right.m8 + left.m3*right.m12; + result.m1 = left.m0*right.m1 + left.m1*right.m5 + left.m2*right.m9 + left.m3*right.m13; + result.m2 = left.m0*right.m2 + left.m1*right.m6 + left.m2*right.m10 + left.m3*right.m14; + result.m3 = left.m0*right.m3 + left.m1*right.m7 + left.m2*right.m11 + left.m3*right.m15; + result.m4 = left.m4*right.m0 + left.m5*right.m4 + left.m6*right.m8 + left.m7*right.m12; + result.m5 = left.m4*right.m1 + left.m5*right.m5 + left.m6*right.m9 + left.m7*right.m13; + result.m6 = left.m4*right.m2 + left.m5*right.m6 + left.m6*right.m10 + left.m7*right.m14; + result.m7 = left.m4*right.m3 + left.m5*right.m7 + left.m6*right.m11 + left.m7*right.m15; + result.m8 = left.m8*right.m0 + left.m9*right.m4 + left.m10*right.m8 + left.m11*right.m12; + result.m9 = left.m8*right.m1 + left.m9*right.m5 + left.m10*right.m9 + left.m11*right.m13; + result.m10 = left.m8*right.m2 + left.m9*right.m6 + left.m10*right.m10 + left.m11*right.m14; + result.m11 = left.m8*right.m3 + left.m9*right.m7 + left.m10*right.m11 + left.m11*right.m15; + result.m12 = left.m12*right.m0 + left.m13*right.m4 + left.m14*right.m8 + left.m15*right.m12; + result.m13 = left.m12*right.m1 + left.m13*right.m5 + left.m14*right.m9 + left.m15*right.m13; + result.m14 = left.m12*right.m2 + left.m13*right.m6 + left.m14*right.m10 + left.m15*right.m14; + result.m15 = left.m12*right.m3 + left.m13*right.m7 + left.m14*right.m11 + left.m15*right.m15; + + return result; +} + +// Transposes provided matrix +static Matrix rlMatrixTranspose(Matrix mat) +{ + Matrix result = { 0 }; + + result.m0 = mat.m0; + result.m1 = mat.m4; + result.m2 = mat.m8; + result.m3 = mat.m12; + result.m4 = mat.m1; + result.m5 = mat.m5; + result.m6 = mat.m9; + result.m7 = mat.m13; + result.m8 = mat.m2; + result.m9 = mat.m6; + result.m10 = mat.m10; + result.m11 = mat.m14; + result.m12 = mat.m3; + result.m13 = mat.m7; + result.m14 = mat.m11; + result.m15 = mat.m15; + + return result; +} + +// Invert provided matrix +static Matrix rlMatrixInvert(Matrix mat) +{ + Matrix result = { 0 }; + + // Cache the matrix values (speed optimization) + float a00 = mat.m0, a01 = mat.m1, a02 = mat.m2, a03 = mat.m3; + float a10 = mat.m4, a11 = mat.m5, a12 = mat.m6, a13 = mat.m7; + float a20 = mat.m8, a21 = mat.m9, a22 = mat.m10, a23 = mat.m11; + float a30 = mat.m12, a31 = mat.m13, a32 = mat.m14, a33 = mat.m15; + + float b00 = a00*a11 - a01*a10; + float b01 = a00*a12 - a02*a10; + float b02 = a00*a13 - a03*a10; + float b03 = a01*a12 - a02*a11; + float b04 = a01*a13 - a03*a11; + float b05 = a02*a13 - a03*a12; + float b06 = a20*a31 - a21*a30; + float b07 = a20*a32 - a22*a30; + float b08 = a20*a33 - a23*a30; + float b09 = a21*a32 - a22*a31; + float b10 = a21*a33 - a23*a31; + float b11 = a22*a33 - a23*a32; + + // Calculate the invert determinant (inlined to avoid double-caching) + float invDet = 1.0f/(b00*b11 - b01*b10 + b02*b09 + b03*b08 - b04*b07 + b05*b06); + + result.m0 = (a11*b11 - a12*b10 + a13*b09)*invDet; + result.m1 = (-a01*b11 + a02*b10 - a03*b09)*invDet; + result.m2 = (a31*b05 - a32*b04 + a33*b03)*invDet; + result.m3 = (-a21*b05 + a22*b04 - a23*b03)*invDet; + result.m4 = (-a10*b11 + a12*b08 - a13*b07)*invDet; + result.m5 = (a00*b11 - a02*b08 + a03*b07)*invDet; + result.m6 = (-a30*b05 + a32*b02 - a33*b01)*invDet; + result.m7 = (a20*b05 - a22*b02 + a23*b01)*invDet; + result.m8 = (a10*b10 - a11*b08 + a13*b06)*invDet; + result.m9 = (-a00*b10 + a01*b08 - a03*b06)*invDet; + result.m10 = (a30*b04 - a31*b02 + a33*b00)*invDet; + result.m11 = (-a20*b04 + a21*b02 - a23*b00)*invDet; + result.m12 = (-a10*b09 + a11*b07 - a12*b06)*invDet; + result.m13 = (a00*b09 - a01*b07 + a02*b06)*invDet; + result.m14 = (-a30*b03 + a31*b01 - a32*b00)*invDet; + result.m15 = (a20*b03 - a21*b01 + a22*b00)*invDet; + + return result; +} + +#endif // RLGL_IMPLEMENTATION diff --git a/Start_Windows/unit_tests.c b/Start_Windows/unit_tests.c new file mode 100644 index 0000000..50a62cf --- /dev/null +++ b/Start_Windows/unit_tests.c @@ -0,0 +1,143 @@ +#include +#include +#include +#include "unity.h" + +#include "input.h" +#include "game.h" + +// ANSI Escape Codes für Farben +// Hinweis: damit das in CLion mit der integrierten Konsole/Output funktioniert, muss man auf die Run-Config gehen und +// das Häkchen bei 'emulate terminal in the output console' setzen +// (s. auch: https://stackoverflow.com/questions/32742850/how-to-show-colored-console-output-in-clion) +#define RESET "\033[0m" +#define GREEN "\033[32m" +#define RED "\033[31m" +#define YELLOW "\033[33m" +#define CYAN "\033[36m" +#define BOLD "\033[1m" + +// Eine Funktion, um die Test-Ergebnisse zu färben +void print_test_result(int result) { + if (result == 0) { + // Test war erfolgreich + printf(GREEN "OK\n" RESET); + } else { + // Test ist fehlgeschlagen + printf(RED "FAILED\n" RESET); + } +} + +// ---------- Tests für input.c ---------- +void test_readWords_simple(void) { + FILE *f = fopen("testwords_simple.txt", "r"); + + char words[10][MAX_WORD_LEN]; + int count = readWords(f, words, 10); + fclose(f); + + TEST_ASSERT_EQUAL_INT(3, count); + TEST_ASSERT_EQUAL_STRING("APFEL", words[0]); + TEST_ASSERT_EQUAL_STRING("BANANE", words[1]); + TEST_ASSERT_EQUAL_STRING("KIWI", words[2]); +} + +void test_readWords_with_delimiters(void) { + FILE *f = fopen("testwords_delims.txt", "r"); + + char words[10][MAX_WORD_LEN]; + int count = readWords(f, words, 10); + fclose(f); + + TEST_ASSERT_EQUAL_INT(3, count); + TEST_ASSERT_EQUAL_STRING("HUND", words[0]); + TEST_ASSERT_EQUAL_STRING("KATZE", words[1]); + TEST_ASSERT_EQUAL_STRING("MAUS", words[2]); +} + +void test_readWords_empty_file(void) { + FILE *f = fopen("testwords_empty.txt", "r"); + + char words[10][MAX_WORD_LEN]; + int count = readWords(f, words, 10); + fclose(f); + + TEST_ASSERT_EQUAL_INT(0, count); +} + +// ---------- Tests für game.c ---------- +void test_createWordSalad_all_fit(void) { + char words[3][MAX_WORD_LEN] = {"CAT", "DOG", "MOUSE"}; + char salad[MAX_SEARCH_FIELD_LEN][MAX_SEARCH_FIELD_LEN]; + + int placed = createWordSalad(salad, 20, words, 3); + + TEST_ASSERT_EQUAL_INT(3, placed); + + // Sicherstellen, dass alle Felder gefüllt sind + for (int i = 0; i < 20; i++) { + for (int j = 0; j < 20; j++) { + TEST_ASSERT_GREATER_OR_EQUAL('A', salad[i][j]); + TEST_ASSERT_LESS_OR_EQUAL('Z', salad[i][j]); + } + } +} + +void test_createWordSalad_too_small(void) { + char words[2][MAX_WORD_LEN] = {"ELEPHANT", "GIRAFFE"}; + char salad[MAX_SEARCH_FIELD_LEN][MAX_SEARCH_FIELD_LEN]; + + int placed = createWordSalad(salad, 5, words, 2); + + TEST_ASSERT_GREATER_OR_EQUAL(0, placed); + TEST_ASSERT_LESS_OR_EQUAL(2, placed); + + // Feld muss vollständig gefüllt sein + for (int i = 0; i < 5; i++) { + for (int j = 0; j < 5; j++) { + TEST_ASSERT_GREATER_OR_EQUAL('A', salad[i][j]); + TEST_ASSERT_LESS_OR_EQUAL('Z', salad[i][j]); + } + } +} + +// ---------- Test Setup und TearDown Funktionen ---------- + +// Hier Setup- und TearDown-Funktionen definieren, +// falls Vor- und Nachbereitungen für die Tests benötigt. + +void setUp(void) { + FILE *f = fopen("testwords_delims.txt", "w"); + fprintf(f, "Hund,Katze; Maus\n"); + fclose(f); + + f = fopen("testwords_simple.txt", "w"); + fprintf(f, "Apfel\nBanane\nKiwi"); + fclose(f); + + f = fopen("testwords_empty.txt", "w"); + fclose(f); +} + +void tearDown(void) { + remove("testwords_delims.txt"); + remove("testwords_simple.txt"); + remove("testwords_empty.txt"); +} + +// ---------- Test Runner ---------- + +int main(void) { + UNITY_BEGIN(); + + RUN_TEST(test_readWords_simple); + RUN_TEST(test_readWords_with_delimiters); + RUN_TEST(test_readWords_empty_file); + RUN_TEST(test_createWordSalad_all_fit); + RUN_TEST(test_createWordSalad_too_small); + + int result = UNITY_END(); // Test-Ergebnisse + print_test_result(result); + + return result; +} diff --git a/Start_Windows/unity/makefile b/Start_Windows/unity/makefile new file mode 100644 index 0000000..9cfd64f --- /dev/null +++ b/Start_Windows/unity/makefile @@ -0,0 +1,3 @@ +unity: unity.c unity.h + gcc -c -Wall -o unity.o unity.c + ar rcs libunity.a unity.o \ No newline at end of file diff --git a/Start_Windows/unity/unity.c b/Start_Windows/unity/unity.c new file mode 100644 index 0000000..3ea455d --- /dev/null +++ b/Start_Windows/unity/unity.c @@ -0,0 +1,2622 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#include "unity.h" + +#ifndef UNITY_PROGMEM +#define UNITY_PROGMEM +#endif + +/* If omitted from header, declare overrideable prototypes here so they're ready for use */ +#ifdef UNITY_OMIT_OUTPUT_CHAR_HEADER_DECLARATION +void UNITY_OUTPUT_CHAR(int); +#endif + +/* Helpful macros for us to use here in Assert functions */ +#define UNITY_FAIL_AND_BAIL do { Unity.CurrentTestFailed = 1; UNITY_OUTPUT_FLUSH(); TEST_ABORT(); } while (0) +#define UNITY_IGNORE_AND_BAIL do { Unity.CurrentTestIgnored = 1; UNITY_OUTPUT_FLUSH(); TEST_ABORT(); } while (0) +#define RETURN_IF_FAIL_OR_IGNORE do { if (Unity.CurrentTestFailed || Unity.CurrentTestIgnored) { TEST_ABORT(); } } while (0) + +struct UNITY_STORAGE_T Unity; + +#ifdef UNITY_OUTPUT_COLOR +const char UNITY_PROGMEM UnityStrOk[] = "\033[42mOK\033[0m"; +const char UNITY_PROGMEM UnityStrPass[] = "\033[42mPASS\033[0m"; +const char UNITY_PROGMEM UnityStrFail[] = "\033[41mFAIL\033[0m"; +const char UNITY_PROGMEM UnityStrIgnore[] = "\033[43mIGNORE\033[0m"; +#else +const char UNITY_PROGMEM UnityStrOk[] = "OK"; +const char UNITY_PROGMEM UnityStrPass[] = "PASS"; +const char UNITY_PROGMEM UnityStrFail[] = "FAIL"; +const char UNITY_PROGMEM UnityStrIgnore[] = "IGNORE"; +#endif +static const char UNITY_PROGMEM UnityStrNull[] = "NULL"; +static const char UNITY_PROGMEM UnityStrSpacer[] = ". "; +static const char UNITY_PROGMEM UnityStrExpected[] = " Expected "; +static const char UNITY_PROGMEM UnityStrWas[] = " Was "; +static const char UNITY_PROGMEM UnityStrGt[] = " to be greater than "; +static const char UNITY_PROGMEM UnityStrLt[] = " to be less than "; +static const char UNITY_PROGMEM UnityStrOrEqual[] = "or equal to "; +static const char UNITY_PROGMEM UnityStrNotEqual[] = " to be not equal to "; +static const char UNITY_PROGMEM UnityStrElement[] = " Element "; +static const char UNITY_PROGMEM UnityStrByte[] = " Byte "; +static const char UNITY_PROGMEM UnityStrMemory[] = " Memory Mismatch."; +static const char UNITY_PROGMEM UnityStrDelta[] = " Values Not Within Delta "; +static const char UNITY_PROGMEM UnityStrPointless[] = " You Asked Me To Compare Nothing, Which Was Pointless."; +static const char UNITY_PROGMEM UnityStrNullPointerForExpected[] = " Expected pointer to be NULL"; +static const char UNITY_PROGMEM UnityStrNullPointerForActual[] = " Actual pointer was NULL"; +#ifndef UNITY_EXCLUDE_FLOAT +static const char UNITY_PROGMEM UnityStrNot[] = "Not "; +static const char UNITY_PROGMEM UnityStrInf[] = "Infinity"; +static const char UNITY_PROGMEM UnityStrNegInf[] = "Negative Infinity"; +static const char UNITY_PROGMEM UnityStrNaN[] = "NaN"; +static const char UNITY_PROGMEM UnityStrDet[] = "Determinate"; +static const char UNITY_PROGMEM UnityStrInvalidFloatTrait[] = "Invalid Float Trait"; +#endif +const char UNITY_PROGMEM UnityStrErrShorthand[] = "Unity Shorthand Support Disabled"; +const char UNITY_PROGMEM UnityStrErrFloat[] = "Unity Floating Point Disabled"; +const char UNITY_PROGMEM UnityStrErrDouble[] = "Unity Double Precision Disabled"; +const char UNITY_PROGMEM UnityStrErr64[] = "Unity 64-bit Support Disabled"; +const char UNITY_PROGMEM UnityStrErrDetailStack[] = "Unity Detail Stack Support Disabled"; +static const char UNITY_PROGMEM UnityStrBreaker[] = "-----------------------"; +static const char UNITY_PROGMEM UnityStrResultsTests[] = " Tests "; +static const char UNITY_PROGMEM UnityStrResultsFailures[] = " Failures "; +static const char UNITY_PROGMEM UnityStrResultsIgnored[] = " Ignored "; +#ifndef UNITY_EXCLUDE_DETAILS +#ifdef UNITY_DETAIL_STACK_SIZE +static const char* UNITY_PROGMEM UnityStrDetailLabels[] = UNITY_DETAIL_LABEL_NAMES; +static const UNITY_COUNTER_TYPE UNITY_PROGMEM UnityStrDetailLabelsCount = sizeof(UnityStrDetailLabels) / sizeof(const char*); +static const char UNITY_PROGMEM UnityStrErrDetailStackEmpty[] = " Detail Stack Empty"; +static const char UNITY_PROGMEM UnityStrErrDetailStackFull[] = " Detail Stack Full"; +static const char UNITY_PROGMEM UnityStrErrDetailStackLabel[] = " Detail Label Outside Of UNITY_DETAIL_LABEL_NAMES: "; +static const char UNITY_PROGMEM UnityStrErrDetailStackPop[] = " Detail Pop With Unexpected Arguments"; +#else +static const char UNITY_PROGMEM UnityStrDetail1Name[] = UNITY_DETAIL1_NAME " "; +static const char UNITY_PROGMEM UnityStrDetail2Name[] = " " UNITY_DETAIL2_NAME " "; +#endif +#endif +/*----------------------------------------------- + * Pretty Printers & Test Result Output Handlers + *-----------------------------------------------*/ + +/*-----------------------------------------------*/ +/* Local helper function to print characters. */ +static void UnityPrintChar(const char* pch) +{ + /* printable characters plus CR & LF are printed */ + if ((*pch <= 126) && (*pch >= 32)) + { + UNITY_OUTPUT_CHAR(*pch); + } + /* write escaped carriage returns */ + else if (*pch == 13) + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('r'); + } + /* write escaped line feeds */ + else if (*pch == 10) + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('n'); + } + /* unprintable characters are shown as codes */ + else + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('x'); + UnityPrintNumberHex((UNITY_UINT)*pch, 2); + } +} + +/*-----------------------------------------------*/ +/* Local helper function to print ANSI escape strings e.g. "\033[42m". */ +#ifdef UNITY_OUTPUT_COLOR +static UNITY_UINT UnityPrintAnsiEscapeString(const char* string) +{ + const char* pch = string; + UNITY_UINT count = 0; + + while (*pch && (*pch != 'm')) + { + UNITY_OUTPUT_CHAR(*pch); + pch++; + count++; + } + UNITY_OUTPUT_CHAR('m'); + count++; + + return count; +} +#endif + +/*-----------------------------------------------*/ +void UnityPrint(const char* string) +{ + const char* pch = string; + + if (pch != NULL) + { + while (*pch) + { +#ifdef UNITY_OUTPUT_COLOR + /* print ANSI escape code */ + if ((*pch == 27) && (*(pch + 1) == '[')) + { + pch += UnityPrintAnsiEscapeString(pch); + continue; + } +#endif + UnityPrintChar(pch); + pch++; + } + } +} +/*-----------------------------------------------*/ +void UnityPrintLen(const char* string, const UNITY_UINT32 length) +{ + const char* pch = string; + + if (pch != NULL) + { + while (*pch && ((UNITY_UINT32)(pch - string) < length)) + { + /* printable characters plus CR & LF are printed */ + if ((*pch <= 126) && (*pch >= 32)) + { + UNITY_OUTPUT_CHAR(*pch); + } + /* write escaped carriage returns */ + else if (*pch == 13) + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('r'); + } + /* write escaped line feeds */ + else if (*pch == 10) + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('n'); + } + /* unprintable characters are shown as codes */ + else + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('x'); + UnityPrintNumberHex((UNITY_UINT)*pch, 2); + } + pch++; + } + } +} + +/*-----------------------------------------------*/ +void UnityPrintIntNumberByStyle(const UNITY_INT number, const UNITY_DISPLAY_STYLE_T style) +{ + if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) + { + if (style == UNITY_DISPLAY_STYLE_CHAR) + { + /* printable characters plus CR & LF are printed */ + UNITY_OUTPUT_CHAR('\''); + if ((number <= 126) && (number >= 32)) + { + UNITY_OUTPUT_CHAR((int)number); + } + /* write escaped carriage returns */ + else if (number == 13) + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('r'); + } + /* write escaped line feeds */ + else if (number == 10) + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('n'); + } + /* unprintable characters are shown as codes */ + else + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('x'); + UnityPrintNumberHex((UNITY_UINT)number, 2); + } + UNITY_OUTPUT_CHAR('\''); + } + else + { + UnityPrintNumber(number); + } + } +} + +void UnityPrintUintNumberByStyle(const UNITY_UINT number, const UNITY_DISPLAY_STYLE_T style) +{ + if ((style & UNITY_DISPLAY_RANGE_UINT) == UNITY_DISPLAY_RANGE_UINT) + { + UnityPrintNumberUnsigned(number); + } + else + { + UNITY_OUTPUT_CHAR('0'); + UNITY_OUTPUT_CHAR('x'); + UnityPrintNumberHex((UNITY_UINT)number, (char)((style & 0xF) * 2)); + } +} + +/*-----------------------------------------------*/ +void UnityPrintNumber(const UNITY_INT number_to_print) +{ + UNITY_UINT number = (UNITY_UINT)number_to_print; + + if (number_to_print < 0) + { + /* A negative number, including MIN negative */ + UNITY_OUTPUT_CHAR('-'); + number = (~number) + 1; + } + UnityPrintNumberUnsigned(number); +} + +/*----------------------------------------------- + * basically do an itoa using as little ram as possible */ +void UnityPrintNumberUnsigned(const UNITY_UINT number) +{ + UNITY_UINT divisor = 1; + + /* figure out initial divisor */ + while (number / divisor > 9) + { + divisor *= 10; + } + + /* now mod and print, then divide divisor */ + do + { + UNITY_OUTPUT_CHAR((char)('0' + (number / divisor % 10))); + divisor /= 10; + } while (divisor > 0); +} + +/*-----------------------------------------------*/ +void UnityPrintNumberHex(const UNITY_UINT number, const char nibbles_to_print) +{ + int nibble; + char nibbles = nibbles_to_print; + + if ((unsigned)nibbles > UNITY_MAX_NIBBLES) + { + nibbles = UNITY_MAX_NIBBLES; + } + + while (nibbles > 0) + { + nibbles--; + nibble = (int)(number >> (nibbles * 4)) & 0x0F; + if (nibble <= 9) + { + UNITY_OUTPUT_CHAR((char)('0' + nibble)); + } + else + { + UNITY_OUTPUT_CHAR((char)('A' - 10 + nibble)); + } + } +} + +/*-----------------------------------------------*/ +void UnityPrintMask(const UNITY_UINT mask, const UNITY_UINT number) +{ + UNITY_UINT current_bit = (UNITY_UINT)1 << (UNITY_INT_WIDTH - 1); + UNITY_INT32 i; + + for (i = 0; i < UNITY_INT_WIDTH; i++) + { + if (current_bit & mask) + { + if (current_bit & number) + { + UNITY_OUTPUT_CHAR('1'); + } + else + { + UNITY_OUTPUT_CHAR('0'); + } + } + else + { + UNITY_OUTPUT_CHAR('X'); + } + current_bit = current_bit >> 1; + } +} + +/*-----------------------------------------------*/ +#ifndef UNITY_EXCLUDE_FLOAT_PRINT +/* + * This function prints a floating-point value in a format similar to + * printf("%.7g") on a single-precision machine or printf("%.9g") on a + * double-precision machine. The 7th digit won't always be totally correct + * in single-precision operation (for that level of accuracy, a more + * complicated algorithm would be needed). + */ +void UnityPrintFloat(const UNITY_DOUBLE input_number) +{ +#ifdef UNITY_INCLUDE_DOUBLE + static const int sig_digits = 9; + static const UNITY_INT32 min_scaled = 100000000; + static const UNITY_INT32 max_scaled = 1000000000; +#else + static const int sig_digits = 7; + static const UNITY_INT32 min_scaled = 1000000; + static const UNITY_INT32 max_scaled = 10000000; +#endif + + UNITY_DOUBLE number = input_number; + + /* print minus sign (does not handle negative zero) */ + if (number < 0.0f) + { + UNITY_OUTPUT_CHAR('-'); + number = -number; + } + + /* handle zero, NaN, and +/- infinity */ + if (number == 0.0f) + { + UnityPrint("0"); + } + else if (UNITY_IS_NAN(number)) + { + UnityPrint("nan"); + } + else if (UNITY_IS_INF(number)) + { + UnityPrint("inf"); + } + else + { + UNITY_INT32 n_int = 0; + UNITY_INT32 n; + int exponent = 0; + int decimals; + int digits; + char buf[16] = {0}; + + /* + * Scale up or down by powers of 10. To minimize rounding error, + * start with a factor/divisor of 10^10, which is the largest + * power of 10 that can be represented exactly. Finally, compute + * (exactly) the remaining power of 10 and perform one more + * multiplication or division. + */ + if (number < 1.0f) + { + UNITY_DOUBLE factor = 1.0f; + + while (number < (UNITY_DOUBLE)max_scaled / 1e10f) { number *= 1e10f; exponent -= 10; } + while (number * factor < (UNITY_DOUBLE)min_scaled) { factor *= 10.0f; exponent--; } + + number *= factor; + } + else if (number > (UNITY_DOUBLE)max_scaled) + { + UNITY_DOUBLE divisor = 1.0f; + + while (number > (UNITY_DOUBLE)min_scaled * 1e10f) { number /= 1e10f; exponent += 10; } + while (number / divisor > (UNITY_DOUBLE)max_scaled) { divisor *= 10.0f; exponent++; } + + number /= divisor; + } + else + { + /* + * In this range, we can split off the integer part before + * doing any multiplications. This reduces rounding error by + * freeing up significant bits in the fractional part. + */ + UNITY_DOUBLE factor = 1.0f; + n_int = (UNITY_INT32)number; + number -= (UNITY_DOUBLE)n_int; + + while (n_int < min_scaled) { n_int *= 10; factor *= 10.0f; exponent--; } + + number *= factor; + } + + /* round to nearest integer */ + n = ((UNITY_INT32)(number + number) + 1) / 2; + +#ifndef UNITY_ROUND_TIES_AWAY_FROM_ZERO + /* round to even if exactly between two integers */ + if ((n & 1) && (((UNITY_DOUBLE)n - number) == 0.5f)) + n--; +#endif + + n += n_int; + + if (n >= max_scaled) + { + n = min_scaled; + exponent++; + } + + /* determine where to place decimal point */ + decimals = ((exponent <= 0) && (exponent >= -(sig_digits + 3))) ? (-exponent) : (sig_digits - 1); + exponent += decimals; + + /* truncate trailing zeroes after decimal point */ + while ((decimals > 0) && ((n % 10) == 0)) + { + n /= 10; + decimals--; + } + + /* build up buffer in reverse order */ + digits = 0; + while ((n != 0) || (digits <= decimals)) + { + buf[digits++] = (char)('0' + n % 10); + n /= 10; + } + + /* print out buffer (backwards) */ + while (digits > 0) + { + if (digits == decimals) + { + UNITY_OUTPUT_CHAR('.'); + } + UNITY_OUTPUT_CHAR(buf[--digits]); + } + + /* print exponent if needed */ + if (exponent != 0) + { + UNITY_OUTPUT_CHAR('e'); + + if (exponent < 0) + { + UNITY_OUTPUT_CHAR('-'); + exponent = -exponent; + } + else + { + UNITY_OUTPUT_CHAR('+'); + } + + digits = 0; + while ((exponent != 0) || (digits < 2)) + { + buf[digits++] = (char)('0' + exponent % 10); + exponent /= 10; + } + while (digits > 0) + { + UNITY_OUTPUT_CHAR(buf[--digits]); + } + } + } +} +#endif /* ! UNITY_EXCLUDE_FLOAT_PRINT */ + +/*-----------------------------------------------*/ +static void UnityTestResultsBegin(const char* file, const UNITY_LINE_TYPE line) +{ +#ifdef UNITY_OUTPUT_FOR_ECLIPSE + UNITY_OUTPUT_CHAR('('); + UnityPrint(file); + UNITY_OUTPUT_CHAR(':'); + UnityPrintNumber((UNITY_INT)line); + UNITY_OUTPUT_CHAR(')'); + UNITY_OUTPUT_CHAR(' '); + UnityPrint(Unity.CurrentTestName); + UNITY_OUTPUT_CHAR(':'); +#else +#ifdef UNITY_OUTPUT_FOR_IAR_WORKBENCH + UnityPrint("'); + UnityPrint(Unity.CurrentTestName); + UnityPrint(" "); +#else +#ifdef UNITY_OUTPUT_FOR_QT_CREATOR + UnityPrint("file://"); + UnityPrint(file); + UNITY_OUTPUT_CHAR(':'); + UnityPrintNumber((UNITY_INT)line); + UNITY_OUTPUT_CHAR(' '); + UnityPrint(Unity.CurrentTestName); + UNITY_OUTPUT_CHAR(':'); +#else + UnityPrint(file); + UNITY_OUTPUT_CHAR(':'); + UnityPrintNumber((UNITY_INT)line); + UNITY_OUTPUT_CHAR(':'); + UnityPrint(Unity.CurrentTestName); + UNITY_OUTPUT_CHAR(':'); +#endif +#endif +#endif +} + +/*-----------------------------------------------*/ +static void UnityTestResultsFailBegin(const UNITY_LINE_TYPE line) +{ + UnityTestResultsBegin(Unity.TestFile, line); + UnityPrint(UnityStrFail); + UNITY_OUTPUT_CHAR(':'); +} + +/*-----------------------------------------------*/ +void UnityConcludeTest(void) +{ + if (Unity.CurrentTestIgnored) + { + Unity.TestIgnores++; + } + else if (!Unity.CurrentTestFailed) + { + UnityTestResultsBegin(Unity.TestFile, Unity.CurrentTestLineNumber); + UnityPrint(UnityStrPass); + } + else + { + Unity.TestFailures++; + } + + Unity.CurrentTestFailed = 0; + Unity.CurrentTestIgnored = 0; + UNITY_PRINT_EXEC_TIME(); + UNITY_PRINT_EOL(); + UNITY_FLUSH_CALL(); +} + +/*-----------------------------------------------*/ +static void UnityAddMsgIfSpecified(const char* msg) +{ +#ifdef UNITY_PRINT_TEST_CONTEXT + UnityPrint(UnityStrSpacer); + UNITY_PRINT_TEST_CONTEXT(); +#endif +#ifndef UNITY_EXCLUDE_DETAILS +#ifdef UNITY_DETAIL_STACK_SIZE + { + UNITY_COUNTER_TYPE c; + for (c = 0; (c < Unity.CurrentDetailStackSize) && (c < UNITY_DETAIL_STACK_SIZE); c++) { + const char* label; + if ((Unity.CurrentDetailStackLabels[c] == UNITY_DETAIL_NONE) || (Unity.CurrentDetailStackLabels[c] > UnityStrDetailLabelsCount)) { + break; + } + label = UnityStrDetailLabels[Unity.CurrentDetailStackLabels[c]]; + UnityPrint(UnityStrSpacer); + if ((label[0] == '#') && (label[1] != 0)) { + UnityPrint(label + 2); + UNITY_OUTPUT_CHAR(' '); + if ((label[1] & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) { + UnityPrintIntNumberByStyle((UNITY_INT)Unity.CurrentDetailStackValues[c], label[1]); + } else { + UnityPrintUintNumberByStyle((UNITY_UINT)Unity.CurrentDetailStackValues[c], label[1]); + } + } else if (Unity.CurrentDetailStackValues[c] != 0){ + UnityPrint(label); + UNITY_OUTPUT_CHAR(' '); + UnityPrint((const char*)Unity.CurrentDetailStackValues[c]); + } + } + } +#else + if (Unity.CurrentDetail1) + { + UnityPrint(UnityStrSpacer); + UnityPrint(UnityStrDetail1Name); + UnityPrint(Unity.CurrentDetail1); + if (Unity.CurrentDetail2) + { + UnityPrint(UnityStrDetail2Name); + UnityPrint(Unity.CurrentDetail2); + } + } +#endif +#endif + if (msg) + { + UnityPrint(UnityStrSpacer); + UnityPrint(msg); + } +} + +/*-----------------------------------------------*/ +static void UnityPrintExpectedAndActualStrings(const char* expected, const char* actual) +{ + UnityPrint(UnityStrExpected); + if (expected != NULL) + { + UNITY_OUTPUT_CHAR('\''); + UnityPrint(expected); + UNITY_OUTPUT_CHAR('\''); + } + else + { + UnityPrint(UnityStrNull); + } + UnityPrint(UnityStrWas); + if (actual != NULL) + { + UNITY_OUTPUT_CHAR('\''); + UnityPrint(actual); + UNITY_OUTPUT_CHAR('\''); + } + else + { + UnityPrint(UnityStrNull); + } +} + +/*-----------------------------------------------*/ +static void UnityPrintExpectedAndActualStringsLen(const char* expected, + const char* actual, + const UNITY_UINT32 length) +{ + UnityPrint(UnityStrExpected); + if (expected != NULL) + { + UNITY_OUTPUT_CHAR('\''); + UnityPrintLen(expected, length); + UNITY_OUTPUT_CHAR('\''); + } + else + { + UnityPrint(UnityStrNull); + } + UnityPrint(UnityStrWas); + if (actual != NULL) + { + UNITY_OUTPUT_CHAR('\''); + UnityPrintLen(actual, length); + UNITY_OUTPUT_CHAR('\''); + } + else + { + UnityPrint(UnityStrNull); + } +} + +/*----------------------------------------------- + * Assertion & Control Helpers + *-----------------------------------------------*/ + +/*-----------------------------------------------*/ +static int UnityIsOneArrayNull(UNITY_INTERNAL_PTR expected, + UNITY_INTERNAL_PTR actual, + const UNITY_LINE_TYPE lineNumber, + const char* msg) +{ + /* Both are NULL or same pointer */ + if (expected == actual) { return 0; } + + /* print and return true if just expected is NULL */ + if (expected == NULL) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrNullPointerForExpected); + UnityAddMsgIfSpecified(msg); + return 1; + } + + /* print and return true if just actual is NULL */ + if (actual == NULL) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrNullPointerForActual); + UnityAddMsgIfSpecified(msg); + return 1; + } + + return 0; /* return false if neither is NULL */ +} + +/*----------------------------------------------- + * Assertion Functions + *-----------------------------------------------*/ + +/*-----------------------------------------------*/ +void UnityAssertBits(const UNITY_INT mask, + const UNITY_INT expected, + const UNITY_INT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + RETURN_IF_FAIL_OR_IGNORE; + + if ((mask & expected) != (mask & actual)) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + UnityPrintMask((UNITY_UINT)mask, (UNITY_UINT)expected); + UnityPrint(UnityStrWas); + UnityPrintMask((UNITY_UINT)mask, (UNITY_UINT)actual); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertEqualIntNumber(const UNITY_INT expected, + const UNITY_INT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style) +{ + RETURN_IF_FAIL_OR_IGNORE; + + if (expected != actual) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + UnityPrintIntNumberByStyle(expected, style); + UnityPrint(UnityStrWas); + UnityPrintIntNumberByStyle(actual, style); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +void UnityAssertEqualUintNumber(const UNITY_UINT expected, + const UNITY_UINT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style) +{ + RETURN_IF_FAIL_OR_IGNORE; + + if (expected != actual) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + UnityPrintUintNumberByStyle(expected, style); + UnityPrint(UnityStrWas); + UnityPrintUintNumberByStyle(actual, style); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} +/*-----------------------------------------------*/ +void UnityAssertIntGreaterOrLessOrEqualNumber(const UNITY_INT threshold, + const UNITY_INT actual, + const UNITY_COMPARISON_T compare, + const char *msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style) +{ + int failed = 0; + RETURN_IF_FAIL_OR_IGNORE; + + if ((threshold == actual) && !(compare & UNITY_EQUAL_TO)) { failed = 1; } + + if ((actual > threshold) && (compare & UNITY_SMALLER_THAN)) { failed = 1; } + if ((actual < threshold) && (compare & UNITY_GREATER_THAN)) { failed = 1; } + + if (failed) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + UnityPrintIntNumberByStyle(actual, style); + if (compare & UNITY_GREATER_THAN) { UnityPrint(UnityStrGt); } + if (compare & UNITY_SMALLER_THAN) { UnityPrint(UnityStrLt); } + if (compare & UNITY_EQUAL_TO) { UnityPrint(UnityStrOrEqual); } + if (compare == UNITY_NOT_EQUAL) { UnityPrint(UnityStrNotEqual); } + UnityPrintIntNumberByStyle(threshold, style); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +void UnityAssertUintGreaterOrLessOrEqualNumber(const UNITY_UINT threshold, + const UNITY_UINT actual, + const UNITY_COMPARISON_T compare, + const char *msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style) +{ + int failed = 0; + RETURN_IF_FAIL_OR_IGNORE; + + if ((threshold == actual) && !(compare & UNITY_EQUAL_TO)) { failed = 1; } + + /* UINT or HEX */ + if ((actual > threshold) && (compare & UNITY_SMALLER_THAN)) { failed = 1; } + if ((actual < threshold) && (compare & UNITY_GREATER_THAN)) { failed = 1; } + + if (failed) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + UnityPrintUintNumberByStyle(actual, style); + if (compare & UNITY_GREATER_THAN) { UnityPrint(UnityStrGt); } + if (compare & UNITY_SMALLER_THAN) { UnityPrint(UnityStrLt); } + if (compare & UNITY_EQUAL_TO) { UnityPrint(UnityStrOrEqual); } + if (compare == UNITY_NOT_EQUAL) { UnityPrint(UnityStrNotEqual); } + UnityPrintUintNumberByStyle(threshold, style); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +#define UnityPrintPointlessAndBail() \ +do { \ + UnityTestResultsFailBegin(lineNumber); \ + UnityPrint(UnityStrPointless); \ + UnityAddMsgIfSpecified(msg); \ + UNITY_FAIL_AND_BAIL; \ +} while (0) + +/*-----------------------------------------------*/ +void UnityAssertEqualIntArray(UNITY_INTERNAL_PTR expected, + UNITY_INTERNAL_PTR actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style, + const UNITY_FLAGS_T flags) +{ + UNITY_UINT32 elements = num_elements; + unsigned int length = style & 0xF; + unsigned int increment = 0; + + RETURN_IF_FAIL_OR_IGNORE; + + if (num_elements == 0) + { +#ifdef UNITY_COMPARE_PTRS_ON_ZERO_ARRAY + UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, lineNumber, msg); +#else + UnityPrintPointlessAndBail(); +#endif + } + + if (expected == actual) + { + return; /* Both are NULL or same pointer */ + } + + if (UnityIsOneArrayNull(expected, actual, lineNumber, msg)) + { + UNITY_FAIL_AND_BAIL; + } + + while ((elements > 0) && (elements--)) + { + UNITY_INT expect_val; + UNITY_INT actual_val; + + switch (length) + { + case 1: + expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT8*)expected; + actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT8*)actual; + if (style & (UNITY_DISPLAY_RANGE_UINT | UNITY_DISPLAY_RANGE_HEX)) + { + expect_val &= 0x000000FF; + actual_val &= 0x000000FF; + } + increment = sizeof(UNITY_INT8); + break; + + case 2: + expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT16*)expected; + actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT16*)actual; + if (style & (UNITY_DISPLAY_RANGE_UINT | UNITY_DISPLAY_RANGE_HEX)) + { + expect_val &= 0x0000FFFF; + actual_val &= 0x0000FFFF; + } + increment = sizeof(UNITY_INT16); + break; + +#ifdef UNITY_SUPPORT_64 + case 8: + expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT64*)expected; + actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT64*)actual; + increment = sizeof(UNITY_INT64); + break; +#endif + + default: /* default is length 4 bytes */ + case 4: + expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT32*)expected; + actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT32*)actual; +#ifdef UNITY_SUPPORT_64 + if (style & (UNITY_DISPLAY_RANGE_UINT | UNITY_DISPLAY_RANGE_HEX)) + { + expect_val &= 0x00000000FFFFFFFF; + actual_val &= 0x00000000FFFFFFFF; + } +#endif + increment = sizeof(UNITY_INT32); + length = 4; + break; + } + + if (expect_val != actual_val) + { + if ((style & UNITY_DISPLAY_RANGE_UINT) && (length < (UNITY_INT_WIDTH / 8))) + { /* For UINT, remove sign extension (padding 1's) from signed type casts above */ + UNITY_INT mask = 1; + mask = (mask << 8 * length) - 1; + expect_val &= mask; + actual_val &= mask; + } + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrElement); + UnityPrintNumberUnsigned(num_elements - elements - 1); + UnityPrint(UnityStrExpected); + UnityPrintIntNumberByStyle(expect_val, style); + UnityPrint(UnityStrWas); + UnityPrintIntNumberByStyle(actual_val, style); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } + /* Walk through array by incrementing the pointers */ + if (flags == UNITY_ARRAY_TO_ARRAY) + { + expected = (UNITY_INTERNAL_PTR)((const char*)expected + increment); + } + actual = (UNITY_INTERNAL_PTR)((const char*)actual + increment); + } +} + +/*-----------------------------------------------*/ +#ifndef UNITY_EXCLUDE_FLOAT +/* Wrap this define in a function with variable types as float or double */ +#define UNITY_FLOAT_OR_DOUBLE_WITHIN(delta, expected, actual, diff) \ + if (UNITY_IS_INF(expected) && UNITY_IS_INF(actual) && (((expected) < 0) == ((actual) < 0))) return 1; \ + if (UNITY_NAN_CHECK) return 1; \ + (diff) = (actual) - (expected); \ + if ((diff) < 0) (diff) = -(diff); \ + if ((delta) < 0) (delta) = -(delta); \ + return !(UNITY_IS_NAN(diff) || UNITY_IS_INF(diff) || ((diff) > (delta))) + /* This first part of this condition will catch any NaN or Infinite values */ +#ifndef UNITY_NAN_NOT_EQUAL_NAN + #define UNITY_NAN_CHECK UNITY_IS_NAN(expected) && UNITY_IS_NAN(actual) +#else + #define UNITY_NAN_CHECK 0 +#endif + +#ifndef UNITY_EXCLUDE_FLOAT_PRINT + #define UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(expected, actual) \ + do { \ + UnityPrint(UnityStrExpected); \ + UnityPrintFloat(expected); \ + UnityPrint(UnityStrWas); \ + UnityPrintFloat(actual); \ + } while (0) +#else + #define UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(expected, actual) \ + UnityPrint(UnityStrDelta) +#endif /* UNITY_EXCLUDE_FLOAT_PRINT */ + +/*-----------------------------------------------*/ +static int UnityFloatsWithin(UNITY_FLOAT delta, UNITY_FLOAT expected, UNITY_FLOAT actual) +{ + UNITY_FLOAT diff; + UNITY_FLOAT_OR_DOUBLE_WITHIN(delta, expected, actual, diff); +} + +/*-----------------------------------------------*/ +void UnityAssertWithinFloatArray(const UNITY_FLOAT delta, + UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* expected, + UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags) +{ + UNITY_UINT32 elements = num_elements; + UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* ptr_expected = expected; + UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* ptr_actual = actual; + UNITY_FLOAT in_delta = delta; + UNITY_FLOAT current_element_delta = delta; + + RETURN_IF_FAIL_OR_IGNORE; + + if (elements == 0) + { +#ifdef UNITY_COMPARE_PTRS_ON_ZERO_ARRAY + UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, lineNumber, msg); +#else + UnityPrintPointlessAndBail(); +#endif + } + + if (UNITY_IS_INF(in_delta)) + { + return; /* Arrays will be force equal with infinite delta */ + } + + if (UNITY_IS_NAN(in_delta)) + { + /* Delta must be correct number */ + UnityPrintPointlessAndBail(); + } + + if (expected == actual) + { + return; /* Both are NULL or same pointer */ + } + + if (UnityIsOneArrayNull((UNITY_INTERNAL_PTR)expected, (UNITY_INTERNAL_PTR)actual, lineNumber, msg)) + { + UNITY_FAIL_AND_BAIL; + } + + /* fix delta sign if need */ + if (in_delta < 0) + { + in_delta = -in_delta; + } + + while (elements--) + { + current_element_delta = *ptr_expected * UNITY_FLOAT_PRECISION; + + if (current_element_delta < 0) + { + /* fix delta sign for correct calculations */ + current_element_delta = -current_element_delta; + } + + if (!UnityFloatsWithin(in_delta + current_element_delta, *ptr_expected, *ptr_actual)) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrElement); + UnityPrintNumberUnsigned(num_elements - elements - 1); + UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT((UNITY_DOUBLE)*ptr_expected, (UNITY_DOUBLE)*ptr_actual); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } + if (flags == UNITY_ARRAY_TO_ARRAY) + { + ptr_expected++; + } + ptr_actual++; + } +} + +/*-----------------------------------------------*/ +void UnityAssertFloatsWithin(const UNITY_FLOAT delta, + const UNITY_FLOAT expected, + const UNITY_FLOAT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + RETURN_IF_FAIL_OR_IGNORE; + + + if (!UnityFloatsWithin(delta, expected, actual)) + { + UnityTestResultsFailBegin(lineNumber); + UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT((UNITY_DOUBLE)expected, (UNITY_DOUBLE)actual); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertFloatsNotWithin(const UNITY_FLOAT delta, + const UNITY_FLOAT expected, + const UNITY_FLOAT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + RETURN_IF_FAIL_OR_IGNORE; + + if (UnityFloatsWithin(delta, expected, actual)) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + UnityPrintFloat((UNITY_DOUBLE)expected); + UnityPrint(UnityStrNotEqual); + UnityPrintFloat((UNITY_DOUBLE)actual); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertGreaterOrLessFloat(const UNITY_FLOAT threshold, + const UNITY_FLOAT actual, + const UNITY_COMPARISON_T compare, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + int failed; + + RETURN_IF_FAIL_OR_IGNORE; + + failed = 0; + + /* Checking for "not success" rather than failure to get the right result for NaN */ + if (!(actual < threshold) && (compare & UNITY_SMALLER_THAN)) { failed = 1; } + if (!(actual > threshold) && (compare & UNITY_GREATER_THAN)) { failed = 1; } + + if ((compare & UNITY_EQUAL_TO) && UnityFloatsWithin(threshold * UNITY_FLOAT_PRECISION, threshold, actual)) { failed = 0; } + + if (failed) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + UnityPrintFloat(actual); + if (compare & UNITY_GREATER_THAN) { UnityPrint(UnityStrGt); } + if (compare & UNITY_SMALLER_THAN) { UnityPrint(UnityStrLt); } + if (compare & UNITY_EQUAL_TO) { UnityPrint(UnityStrOrEqual); } + UnityPrintFloat(threshold); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertFloatSpecial(const UNITY_FLOAT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLOAT_TRAIT_T style) +{ + const char* trait_names[] = {UnityStrInf, UnityStrNegInf, UnityStrNaN, UnityStrDet}; + UNITY_INT should_be_trait = ((UNITY_INT)style & 1); + UNITY_INT is_trait = !should_be_trait; + UNITY_INT trait_index = (UNITY_INT)(style >> 1); + + RETURN_IF_FAIL_OR_IGNORE; + + switch (style) + { + case UNITY_FLOAT_IS_INF: + case UNITY_FLOAT_IS_NOT_INF: + is_trait = UNITY_IS_INF(actual) && (actual > 0); + break; + case UNITY_FLOAT_IS_NEG_INF: + case UNITY_FLOAT_IS_NOT_NEG_INF: + is_trait = UNITY_IS_INF(actual) && (actual < 0); + break; + + case UNITY_FLOAT_IS_NAN: + case UNITY_FLOAT_IS_NOT_NAN: + is_trait = UNITY_IS_NAN(actual) ? 1 : 0; + break; + + case UNITY_FLOAT_IS_DET: /* A determinate number is non infinite and not NaN. */ + case UNITY_FLOAT_IS_NOT_DET: + is_trait = !UNITY_IS_INF(actual) && !UNITY_IS_NAN(actual); + break; + + case UNITY_FLOAT_INVALID_TRAIT: /* Supress warning */ + default: /* including UNITY_FLOAT_INVALID_TRAIT */ + trait_index = 0; + trait_names[0] = UnityStrInvalidFloatTrait; + break; + } + + if (is_trait != should_be_trait) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + if (!should_be_trait) + { + UnityPrint(UnityStrNot); + } + UnityPrint(trait_names[trait_index]); + UnityPrint(UnityStrWas); +#ifndef UNITY_EXCLUDE_FLOAT_PRINT + UnityPrintFloat((UNITY_DOUBLE)actual); +#else + if (should_be_trait) + { + UnityPrint(UnityStrNot); + } + UnityPrint(trait_names[trait_index]); +#endif + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +#endif /* not UNITY_EXCLUDE_FLOAT */ + +/*-----------------------------------------------*/ +#ifndef UNITY_EXCLUDE_DOUBLE +static int UnityDoublesWithin(UNITY_DOUBLE delta, UNITY_DOUBLE expected, UNITY_DOUBLE actual) +{ + UNITY_DOUBLE diff; + UNITY_FLOAT_OR_DOUBLE_WITHIN(delta, expected, actual, diff); +} + +/*-----------------------------------------------*/ +void UnityAssertWithinDoubleArray(const UNITY_DOUBLE delta, + UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* expected, + UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags) +{ + UNITY_UINT32 elements = num_elements; + UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* ptr_expected = expected; + UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* ptr_actual = actual; + UNITY_DOUBLE in_delta = delta; + UNITY_DOUBLE current_element_delta = delta; + + RETURN_IF_FAIL_OR_IGNORE; + + if (elements == 0) + { +#ifdef UNITY_COMPARE_PTRS_ON_ZERO_ARRAY + UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, lineNumber, msg); +#else + UnityPrintPointlessAndBail(); +#endif + } + + if (UNITY_IS_INF(in_delta)) + { + return; /* Arrays will be force equal with infinite delta */ + } + + if (UNITY_IS_NAN(in_delta)) + { + /* Delta must be correct number */ + UnityPrintPointlessAndBail(); + } + + if (expected == actual) + { + return; /* Both are NULL or same pointer */ + } + + if (UnityIsOneArrayNull((UNITY_INTERNAL_PTR)expected, (UNITY_INTERNAL_PTR)actual, lineNumber, msg)) + { + UNITY_FAIL_AND_BAIL; + } + + /* fix delta sign if need */ + if (in_delta < 0) + { + in_delta = -in_delta; + } + + while (elements--) + { + current_element_delta = *ptr_expected * UNITY_DOUBLE_PRECISION; + + if (current_element_delta < 0) + { + /* fix delta sign for correct calculations */ + current_element_delta = -current_element_delta; + } + + if (!UnityDoublesWithin(in_delta + current_element_delta, *ptr_expected, *ptr_actual)) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrElement); + UnityPrintNumberUnsigned(num_elements - elements - 1); + UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(*ptr_expected, *ptr_actual); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } + if (flags == UNITY_ARRAY_TO_ARRAY) + { + ptr_expected++; + } + ptr_actual++; + } +} + +/*-----------------------------------------------*/ +void UnityAssertDoublesWithin(const UNITY_DOUBLE delta, + const UNITY_DOUBLE expected, + const UNITY_DOUBLE actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + RETURN_IF_FAIL_OR_IGNORE; + + if (!UnityDoublesWithin(delta, expected, actual)) + { + UnityTestResultsFailBegin(lineNumber); + UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(expected, actual); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertDoublesNotWithin(const UNITY_DOUBLE delta, + const UNITY_DOUBLE expected, + const UNITY_DOUBLE actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + RETURN_IF_FAIL_OR_IGNORE; + + if (UnityDoublesWithin(delta, expected, actual)) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + UnityPrintFloat((UNITY_DOUBLE)expected); + UnityPrint(UnityStrNotEqual); + UnityPrintFloat((UNITY_DOUBLE)actual); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertGreaterOrLessDouble(const UNITY_DOUBLE threshold, + const UNITY_DOUBLE actual, + const UNITY_COMPARISON_T compare, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + int failed; + + RETURN_IF_FAIL_OR_IGNORE; + + failed = 0; + + /* Checking for "not success" rather than failure to get the right result for NaN */ + if (!(actual < threshold) && (compare & UNITY_SMALLER_THAN)) { failed = 1; } + if (!(actual > threshold) && (compare & UNITY_GREATER_THAN)) { failed = 1; } + + if ((compare & UNITY_EQUAL_TO) && UnityDoublesWithin(threshold * UNITY_DOUBLE_PRECISION, threshold, actual)) { failed = 0; } + + if (failed) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + UnityPrintFloat(actual); + if (compare & UNITY_GREATER_THAN) { UnityPrint(UnityStrGt); } + if (compare & UNITY_SMALLER_THAN) { UnityPrint(UnityStrLt); } + if (compare & UNITY_EQUAL_TO) { UnityPrint(UnityStrOrEqual); } + UnityPrintFloat(threshold); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertDoubleSpecial(const UNITY_DOUBLE actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLOAT_TRAIT_T style) +{ + const char* trait_names[] = {UnityStrInf, UnityStrNegInf, UnityStrNaN, UnityStrDet}; + UNITY_INT should_be_trait = ((UNITY_INT)style & 1); + UNITY_INT is_trait = !should_be_trait; + UNITY_INT trait_index = (UNITY_INT)(style >> 1); + + RETURN_IF_FAIL_OR_IGNORE; + + switch (style) + { + case UNITY_FLOAT_IS_INF: + case UNITY_FLOAT_IS_NOT_INF: + is_trait = UNITY_IS_INF(actual) && (actual > 0); + break; + case UNITY_FLOAT_IS_NEG_INF: + case UNITY_FLOAT_IS_NOT_NEG_INF: + is_trait = UNITY_IS_INF(actual) && (actual < 0); + break; + + case UNITY_FLOAT_IS_NAN: + case UNITY_FLOAT_IS_NOT_NAN: + is_trait = UNITY_IS_NAN(actual) ? 1 : 0; + break; + + case UNITY_FLOAT_IS_DET: /* A determinate number is non infinite and not NaN. */ + case UNITY_FLOAT_IS_NOT_DET: + is_trait = !UNITY_IS_INF(actual) && !UNITY_IS_NAN(actual); + break; + + case UNITY_FLOAT_INVALID_TRAIT: /* Supress warning */ + default: /* including UNITY_FLOAT_INVALID_TRAIT */ + trait_index = 0; + trait_names[0] = UnityStrInvalidFloatTrait; + break; + } + + if (is_trait != should_be_trait) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + if (!should_be_trait) + { + UnityPrint(UnityStrNot); + } + UnityPrint(trait_names[trait_index]); + UnityPrint(UnityStrWas); +#ifndef UNITY_EXCLUDE_FLOAT_PRINT + UnityPrintFloat(actual); +#else + if (should_be_trait) + { + UnityPrint(UnityStrNot); + } + UnityPrint(trait_names[trait_index]); +#endif + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +#endif /* not UNITY_EXCLUDE_DOUBLE */ + +/*-----------------------------------------------*/ +void UnityAssertIntNumbersWithin(const UNITY_UINT delta, + const UNITY_INT expected, + const UNITY_INT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style) +{ + RETURN_IF_FAIL_OR_IGNORE; + + if (actual > expected) + { + Unity.CurrentTestFailed = (((UNITY_UINT)actual - (UNITY_UINT)expected) > delta); + } + else + { + Unity.CurrentTestFailed = (((UNITY_UINT)expected - (UNITY_UINT)actual) > delta); + } + + if (Unity.CurrentTestFailed) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrDelta); + UnityPrintIntNumberByStyle((UNITY_INT)delta, style); + UnityPrint(UnityStrExpected); + UnityPrintIntNumberByStyle(expected, style); + UnityPrint(UnityStrWas); + UnityPrintIntNumberByStyle(actual, style); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +void UnityAssertUintNumbersWithin(const UNITY_UINT delta, + const UNITY_UINT expected, + const UNITY_UINT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style) +{ + RETURN_IF_FAIL_OR_IGNORE; + + if (actual > expected) + { + Unity.CurrentTestFailed = ((actual - expected) > delta); + } + else + { + Unity.CurrentTestFailed = ((expected - actual) > delta); + } + + if (Unity.CurrentTestFailed) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrDelta); + UnityPrintUintNumberByStyle(delta, style); + UnityPrint(UnityStrExpected); + UnityPrintUintNumberByStyle(expected, style); + UnityPrint(UnityStrWas); + UnityPrintUintNumberByStyle(actual, style); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertNumbersArrayWithin(const UNITY_UINT delta, + UNITY_INTERNAL_PTR expected, + UNITY_INTERNAL_PTR actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style, + const UNITY_FLAGS_T flags) +{ + UNITY_UINT32 elements = num_elements; + unsigned int length = style & 0xF; + unsigned int increment = 0; + + RETURN_IF_FAIL_OR_IGNORE; + + if (num_elements == 0) + { +#ifdef UNITY_COMPARE_PTRS_ON_ZERO_ARRAY + UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, lineNumber, msg); +#else + UnityPrintPointlessAndBail(); +#endif + } + + if (expected == actual) + { + return; /* Both are NULL or same pointer */ + } + + if (UnityIsOneArrayNull(expected, actual, lineNumber, msg)) + { + UNITY_FAIL_AND_BAIL; + } + + while ((elements > 0) && (elements--)) + { + UNITY_INT expect_val; + UNITY_INT actual_val; + + switch (length) + { + case 1: + /* fixing problems with signed overflow on unsigned numbers */ + if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) + { + expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT8*)expected; + actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT8*)actual; + increment = sizeof(UNITY_INT8); + } + else + { + expect_val = (UNITY_INT)*(UNITY_PTR_ATTRIBUTE const UNITY_UINT8*)expected; + actual_val = (UNITY_INT)*(UNITY_PTR_ATTRIBUTE const UNITY_UINT8*)actual; + increment = sizeof(UNITY_UINT8); + } + break; + + case 2: + /* fixing problems with signed overflow on unsigned numbers */ + if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) + { + expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT16*)expected; + actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT16*)actual; + increment = sizeof(UNITY_INT16); + } + else + { + expect_val = (UNITY_INT)*(UNITY_PTR_ATTRIBUTE const UNITY_UINT16*)expected; + actual_val = (UNITY_INT)*(UNITY_PTR_ATTRIBUTE const UNITY_UINT16*)actual; + increment = sizeof(UNITY_UINT16); + } + break; + +#ifdef UNITY_SUPPORT_64 + case 8: + /* fixing problems with signed overflow on unsigned numbers */ + if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) + { + expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT64*)expected; + actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT64*)actual; + increment = sizeof(UNITY_INT64); + } + else + { + expect_val = (UNITY_INT)*(UNITY_PTR_ATTRIBUTE const UNITY_UINT64*)expected; + actual_val = (UNITY_INT)*(UNITY_PTR_ATTRIBUTE const UNITY_UINT64*)actual; + increment = sizeof(UNITY_UINT64); + } + break; +#endif + + default: /* default is length 4 bytes */ + case 4: + /* fixing problems with signed overflow on unsigned numbers */ + if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) + { + expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT32*)expected; + actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT32*)actual; + increment = sizeof(UNITY_INT32); + } + else + { + expect_val = (UNITY_INT)*(UNITY_PTR_ATTRIBUTE const UNITY_UINT32*)expected; + actual_val = (UNITY_INT)*(UNITY_PTR_ATTRIBUTE const UNITY_UINT32*)actual; + increment = sizeof(UNITY_UINT32); + } + length = 4; + break; + } + + if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) + { + if (actual_val > expect_val) + { + Unity.CurrentTestFailed = (((UNITY_UINT)actual_val - (UNITY_UINT)expect_val) > delta); + } + else + { + Unity.CurrentTestFailed = (((UNITY_UINT)expect_val - (UNITY_UINT)actual_val) > delta); + } + } + else + { + if ((UNITY_UINT)actual_val > (UNITY_UINT)expect_val) + { + Unity.CurrentTestFailed = (((UNITY_UINT)actual_val - (UNITY_UINT)expect_val) > delta); + } + else + { + Unity.CurrentTestFailed = (((UNITY_UINT)expect_val - (UNITY_UINT)actual_val) > delta); + } + } + + if (Unity.CurrentTestFailed) + { + if ((style & UNITY_DISPLAY_RANGE_UINT) && (length < (UNITY_INT_WIDTH / 8))) + { /* For UINT, remove sign extension (padding 1's) from signed type casts above */ + UNITY_INT mask = 1; + mask = (mask << 8 * length) - 1; + expect_val &= mask; + actual_val &= mask; + } + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrDelta); + UnityPrintIntNumberByStyle((UNITY_INT)delta, style); + UnityPrint(UnityStrElement); + UnityPrintNumberUnsigned(num_elements - elements - 1); + UnityPrint(UnityStrExpected); + UnityPrintIntNumberByStyle(expect_val, style); + UnityPrint(UnityStrWas); + UnityPrintIntNumberByStyle(actual_val, style); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } + /* Walk through array by incrementing the pointers */ + if (flags == UNITY_ARRAY_TO_ARRAY) + { + expected = (UNITY_INTERNAL_PTR)((const char*)expected + increment); + } + actual = (UNITY_INTERNAL_PTR)((const char*)actual + increment); + } +} + +/*-----------------------------------------------*/ +void UnityAssertEqualString(const char* expected, + const char* actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + UNITY_UINT32 i; + + RETURN_IF_FAIL_OR_IGNORE; + + /* if both pointers not null compare the strings */ + if (expected && actual) + { + for (i = 0; expected[i] || actual[i]; i++) + { + if (expected[i] != actual[i]) + { + Unity.CurrentTestFailed = 1; + break; + } + } + } + else + { /* fail if either null but not if both */ + if (expected || actual) + { + Unity.CurrentTestFailed = 1; + } + } + + if (Unity.CurrentTestFailed) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrintExpectedAndActualStrings(expected, actual); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertEqualStringLen(const char* expected, + const char* actual, + const UNITY_UINT32 length, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + UNITY_UINT32 i; + + RETURN_IF_FAIL_OR_IGNORE; + + /* if both pointers not null compare the strings */ + if (expected && actual) + { + for (i = 0; (i < length) && (expected[i] || actual[i]); i++) + { + if (expected[i] != actual[i]) + { + Unity.CurrentTestFailed = 1; + break; + } + } + } + else + { /* fail if either null but not if both */ + if (expected || actual) + { + Unity.CurrentTestFailed = 1; + } + } + + if (Unity.CurrentTestFailed) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrintExpectedAndActualStringsLen(expected, actual, length); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertEqualStringArray(UNITY_INTERNAL_PTR expected, + const char** actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags) +{ + UNITY_UINT32 i = 0; + UNITY_UINT32 j = 0; + const char* expd = NULL; + const char* act = NULL; + + RETURN_IF_FAIL_OR_IGNORE; + + /* if no elements, it's an error */ + if (num_elements == 0) + { +#ifdef UNITY_COMPARE_PTRS_ON_ZERO_ARRAY + UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, lineNumber, msg); +#else + UnityPrintPointlessAndBail(); +#endif + } + + if ((const void*)expected == (const void*)actual) + { + return; /* Both are NULL or same pointer */ + } + + if (UnityIsOneArrayNull((UNITY_INTERNAL_PTR)expected, (UNITY_INTERNAL_PTR)actual, lineNumber, msg)) + { + UNITY_FAIL_AND_BAIL; + } + + if (flags != UNITY_ARRAY_TO_ARRAY) + { + expd = (const char*)expected; + } + + do + { + act = actual[j]; + if (flags == UNITY_ARRAY_TO_ARRAY) + { + expd = ((const char* const*)expected)[j]; + } + + /* if both pointers not null compare the strings */ + if (expd && act) + { + for (i = 0; expd[i] || act[i]; i++) + { + if (expd[i] != act[i]) + { + Unity.CurrentTestFailed = 1; + break; + } + } + } + else + { /* handle case of one pointers being null (if both null, test should pass) */ + if (expd != act) + { + Unity.CurrentTestFailed = 1; + } + } + + if (Unity.CurrentTestFailed) + { + UnityTestResultsFailBegin(lineNumber); + if (num_elements > 1) + { + UnityPrint(UnityStrElement); + UnityPrintNumberUnsigned(j); + } + UnityPrintExpectedAndActualStrings(expd, act); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } + } while (++j < num_elements); +} + +/*-----------------------------------------------*/ +void UnityAssertEqualMemory(UNITY_INTERNAL_PTR expected, + UNITY_INTERNAL_PTR actual, + const UNITY_UINT32 length, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags) +{ + UNITY_PTR_ATTRIBUTE const unsigned char* ptr_exp = (UNITY_PTR_ATTRIBUTE const unsigned char*)expected; + UNITY_PTR_ATTRIBUTE const unsigned char* ptr_act = (UNITY_PTR_ATTRIBUTE const unsigned char*)actual; + UNITY_UINT32 elements = num_elements; + UNITY_UINT32 bytes; + + RETURN_IF_FAIL_OR_IGNORE; + + if (elements == 0) + { +#ifdef UNITY_COMPARE_PTRS_ON_ZERO_ARRAY + UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, lineNumber, msg); +#else + UnityPrintPointlessAndBail(); +#endif + } + if (length == 0) + { + UnityPrintPointlessAndBail(); + } + + if (expected == actual) + { + return; /* Both are NULL or same pointer */ + } + + if (UnityIsOneArrayNull(expected, actual, lineNumber, msg)) + { + UNITY_FAIL_AND_BAIL; + } + + while (elements--) + { + bytes = length; + while (bytes--) + { + if (*ptr_exp != *ptr_act) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrMemory); + if (num_elements > 1) + { + UnityPrint(UnityStrElement); + UnityPrintNumberUnsigned(num_elements - elements - 1); + } + UnityPrint(UnityStrByte); + UnityPrintNumberUnsigned(length - bytes - 1); + UnityPrint(UnityStrExpected); + UnityPrintIntNumberByStyle(*ptr_exp, UNITY_DISPLAY_STYLE_HEX8); + UnityPrint(UnityStrWas); + UnityPrintIntNumberByStyle(*ptr_act, UNITY_DISPLAY_STYLE_HEX8); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } + ptr_exp++; + ptr_act++; + } + if (flags == UNITY_ARRAY_TO_VAL) + { + ptr_exp = (UNITY_PTR_ATTRIBUTE const unsigned char*)expected; + } + } +} + +/*-----------------------------------------------*/ + +static union +{ + UNITY_INT8 i8; + UNITY_INT16 i16; + UNITY_INT32 i32; +#ifdef UNITY_SUPPORT_64 + UNITY_INT64 i64; +#endif +#ifndef UNITY_EXCLUDE_FLOAT + float f; +#endif +#ifndef UNITY_EXCLUDE_DOUBLE + double d; +#endif +} UnityQuickCompare; + +UNITY_INTERNAL_PTR UnityNumToPtr(const UNITY_INT num, const UNITY_UINT8 size) +{ + switch(size) + { + case 1: + UnityQuickCompare.i8 = (UNITY_INT8)num; + return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.i8); + + case 2: + UnityQuickCompare.i16 = (UNITY_INT16)num; + return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.i16); + +#ifdef UNITY_SUPPORT_64 + case 8: + UnityQuickCompare.i64 = (UNITY_INT64)num; + return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.i64); +#endif + + default: /* 4 bytes */ + UnityQuickCompare.i32 = (UNITY_INT32)num; + return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.i32); + } +} + +#ifndef UNITY_EXCLUDE_FLOAT +/*-----------------------------------------------*/ +UNITY_INTERNAL_PTR UnityFloatToPtr(const float num) +{ + UnityQuickCompare.f = num; + return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.f); +} +#endif + +#ifndef UNITY_EXCLUDE_DOUBLE +/*-----------------------------------------------*/ +UNITY_INTERNAL_PTR UnityDoubleToPtr(const double num) +{ + UnityQuickCompare.d = num; + return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.d); +} +#endif + +#ifdef UNITY_INCLUDE_PRINT_FORMATTED + +/*----------------------------------------------- + * printf length modifier helpers + *-----------------------------------------------*/ + +enum UnityLengthModifier { + UNITY_LENGTH_MODIFIER_NONE, + UNITY_LENGTH_MODIFIER_LONG_LONG, + UNITY_LENGTH_MODIFIER_LONG, +}; + +#define UNITY_EXTRACT_ARG(NUMBER_T, NUMBER, LENGTH_MOD, VA, ARG_T) \ +do { \ + switch (LENGTH_MOD) \ + { \ + case UNITY_LENGTH_MODIFIER_LONG_LONG: \ + { \ + NUMBER = (NUMBER_T)va_arg(VA, long long ARG_T); \ + break; \ + } \ + case UNITY_LENGTH_MODIFIER_LONG: \ + { \ + NUMBER = (NUMBER_T)va_arg(VA, long ARG_T); \ + break; \ + } \ + case UNITY_LENGTH_MODIFIER_NONE: \ + default: \ + { \ + NUMBER = (NUMBER_T)va_arg(VA, ARG_T); \ + break; \ + } \ + } \ +} while (0) + +static enum UnityLengthModifier UnityLengthModifierGet(const char *pch, int *length) +{ + enum UnityLengthModifier length_mod; + switch (pch[0]) + { + case 'l': + { + if (pch[1] == 'l') + { + *length = 2; + length_mod = UNITY_LENGTH_MODIFIER_LONG_LONG; + } + else + { + *length = 1; + length_mod = UNITY_LENGTH_MODIFIER_LONG; + } + break; + } + case 'h': + { + // short and char are converted to int + length_mod = UNITY_LENGTH_MODIFIER_NONE; + if (pch[1] == 'h') + { + *length = 2; + } + else + { + *length = 1; + } + break; + } + case 'j': + case 'z': + case 't': + case 'L': + { + // Not supported, but should gobble up the length specifier anyway + length_mod = UNITY_LENGTH_MODIFIER_NONE; + *length = 1; + break; + } + default: + { + length_mod = UNITY_LENGTH_MODIFIER_NONE; + *length = 0; + } + } + return length_mod; +} + +/*----------------------------------------------- + * printf helper function + *-----------------------------------------------*/ +static void UnityPrintFVA(const char* format, va_list va) +{ + const char* pch = format; + if (pch != NULL) + { + while (*pch) + { + /* format identification character */ + if (*pch == '%') + { + pch++; + + if (pch != NULL) + { + int length_mod_size; + enum UnityLengthModifier length_mod = UnityLengthModifierGet(pch, &length_mod_size); + pch += length_mod_size; + + switch (*pch) + { + case 'd': + case 'i': + { + UNITY_INT number; + UNITY_EXTRACT_ARG(UNITY_INT, number, length_mod, va, int); + UnityPrintNumber((UNITY_INT)number); + break; + } +#ifndef UNITY_EXCLUDE_FLOAT_PRINT + case 'f': + case 'g': + { + const double number = va_arg(va, double); + UnityPrintFloat((UNITY_DOUBLE)number); + break; + } +#endif + case 'u': + { + UNITY_UINT number; + UNITY_EXTRACT_ARG(UNITY_UINT, number, length_mod, va, unsigned int); + UnityPrintNumberUnsigned(number); + break; + } + case 'b': + { + UNITY_UINT number; + UNITY_EXTRACT_ARG(UNITY_UINT, number, length_mod, va, unsigned int); + const UNITY_UINT mask = (UNITY_UINT)0 - (UNITY_UINT)1; + UNITY_OUTPUT_CHAR('0'); + UNITY_OUTPUT_CHAR('b'); + UnityPrintMask(mask, number); + break; + } + case 'x': + case 'X': + { + UNITY_UINT number; + UNITY_EXTRACT_ARG(UNITY_UINT, number, length_mod, va, unsigned int); + UNITY_OUTPUT_CHAR('0'); + UNITY_OUTPUT_CHAR('x'); + UnityPrintNumberHex(number, UNITY_MAX_NIBBLES); + break; + } + case 'p': + { + UNITY_UINT number; + char nibbles_to_print = 8; + if (UNITY_POINTER_WIDTH == 64) + { + length_mod = UNITY_LENGTH_MODIFIER_LONG_LONG; + nibbles_to_print = 16; + } + UNITY_EXTRACT_ARG(UNITY_UINT, number, length_mod, va, unsigned int); + UNITY_OUTPUT_CHAR('0'); + UNITY_OUTPUT_CHAR('x'); + UnityPrintNumberHex((UNITY_UINT)number, nibbles_to_print); + break; + } + case 'c': + { + const int ch = va_arg(va, int); + UnityPrintChar((const char *)&ch); + break; + } + case 's': + { + const char * string = va_arg(va, const char *); + UnityPrint(string); + break; + } + case '%': + { + UnityPrintChar(pch); + break; + } + default: + { + /* print the unknown format character */ + UNITY_OUTPUT_CHAR('%'); + UnityPrintChar(pch); + break; + } + } + } + } +#ifdef UNITY_OUTPUT_COLOR + /* print ANSI escape code */ + else if ((*pch == 27) && (*(pch + 1) == '[')) + { + pch += UnityPrintAnsiEscapeString(pch); + continue; + } +#endif + else if (*pch == '\n') + { + UNITY_PRINT_EOL(); + } + else + { + UnityPrintChar(pch); + } + + pch++; + } + } +} + +void UnityPrintF(const UNITY_LINE_TYPE line, const char* format, ...) +{ + UnityTestResultsBegin(Unity.TestFile, line); + UnityPrint("INFO"); + if(format != NULL) + { + UnityPrint(": "); + va_list va; + va_start(va, format); + UnityPrintFVA(format, va); + va_end(va); + } + UNITY_PRINT_EOL(); +} +#endif /* ! UNITY_INCLUDE_PRINT_FORMATTED */ + + +/*----------------------------------------------- + * Control Functions + *-----------------------------------------------*/ + +/*-----------------------------------------------*/ +void UnityFail(const char* msg, const UNITY_LINE_TYPE line) +{ + RETURN_IF_FAIL_OR_IGNORE; + + UnityTestResultsBegin(Unity.TestFile, line); + UnityPrint(UnityStrFail); + UnityAddMsgIfSpecified(msg); + + UNITY_FAIL_AND_BAIL; +} + +/*-----------------------------------------------*/ +void UnityIgnore(const char* msg, const UNITY_LINE_TYPE line) +{ + RETURN_IF_FAIL_OR_IGNORE; + + UnityTestResultsBegin(Unity.TestFile, line); + UnityPrint(UnityStrIgnore); + if (msg != NULL) + { + UNITY_OUTPUT_CHAR(':'); + UNITY_OUTPUT_CHAR(' '); + UnityPrint(msg); + } + UNITY_IGNORE_AND_BAIL; +} + +/*-----------------------------------------------*/ +void UnityMessage(const char* msg, const UNITY_LINE_TYPE line) +{ + UnityTestResultsBegin(Unity.TestFile, line); + UnityPrint("INFO"); + if (msg != NULL) + { + UNITY_OUTPUT_CHAR(':'); + UNITY_OUTPUT_CHAR(' '); + UnityPrint(msg); + } + UNITY_PRINT_EOL(); +} + +/*-----------------------------------------------*/ +/* If we have not defined our own test runner, then include our default test runner to make life easier */ +#ifndef UNITY_SKIP_DEFAULT_RUNNER +void UnityDefaultTestRun(UnityTestFunction Func, const char* FuncName, const int FuncLineNum) +{ + Unity.CurrentTestName = FuncName; + Unity.CurrentTestLineNumber = (UNITY_LINE_TYPE)FuncLineNum; + Unity.NumberOfTests++; + #ifndef UNITY_EXCLUDE_DETAILS + #ifdef UNITY_DETAIL_STACK_SIZE + Unity.CurrentDetailStackSize = 0; + #else + UNITY_CLR_DETAILS(); + #endif + #endif + UNITY_EXEC_TIME_START(); + if (TEST_PROTECT()) + { + setUp(); + Func(); + } + if (TEST_PROTECT()) + { + tearDown(); + } + UNITY_EXEC_TIME_STOP(); + UnityConcludeTest(); +} +#endif + +/*-----------------------------------------------*/ +void UnitySetTestFile(const char* filename) +{ + Unity.TestFile = filename; +} + +/*-----------------------------------------------*/ +void UnityBegin(const char* filename) +{ + Unity.TestFile = filename; + Unity.CurrentTestName = NULL; + Unity.CurrentTestLineNumber = 0; + Unity.NumberOfTests = 0; + Unity.TestFailures = 0; + Unity.TestIgnores = 0; + Unity.CurrentTestFailed = 0; + Unity.CurrentTestIgnored = 0; + + UNITY_CLR_DETAILS(); + UNITY_OUTPUT_START(); +} + +/*-----------------------------------------------*/ +int UnityEnd(void) +{ + UNITY_PRINT_EOL(); + UnityPrint(UnityStrBreaker); + UNITY_PRINT_EOL(); + UnityPrintNumber((UNITY_INT)(Unity.NumberOfTests)); + UnityPrint(UnityStrResultsTests); + UnityPrintNumber((UNITY_INT)(Unity.TestFailures)); + UnityPrint(UnityStrResultsFailures); + UnityPrintNumber((UNITY_INT)(Unity.TestIgnores)); + UnityPrint(UnityStrResultsIgnored); + UNITY_PRINT_EOL(); + if (Unity.TestFailures == 0U) + { + UnityPrint(UnityStrOk); + } + else + { + UnityPrint(UnityStrFail); +#ifdef UNITY_DIFFERENTIATE_FINAL_FAIL + UNITY_OUTPUT_CHAR('E'); UNITY_OUTPUT_CHAR('D'); +#endif + } + UNITY_PRINT_EOL(); + UNITY_FLUSH_CALL(); + UNITY_OUTPUT_COMPLETE(); + return (int)(Unity.TestFailures); +} + +/*----------------------------------------------- + * Details Stack + *-----------------------------------------------*/ +#ifndef UNITY_EXCLUDE_DETAILS +#ifdef UNITY_DETAIL_STACK_SIZE +void UnityPushDetail(UNITY_DETAIL_LABEL_TYPE label, UNITY_DETAIL_VALUE_TYPE value, const UNITY_LINE_TYPE line) { + if (Unity.CurrentDetailStackSize >= UNITY_DETAIL_STACK_SIZE) { + UnityTestResultsFailBegin(line); + UnityPrint(UnityStrErrDetailStackFull); + UnityAddMsgIfSpecified(NULL); + UNITY_FAIL_AND_BAIL; + } + if (label >= UnityStrDetailLabelsCount) { + UnityTestResultsFailBegin(line); + UnityPrint(UnityStrErrDetailStackLabel); + UnityPrintNumberUnsigned(label); + UnityAddMsgIfSpecified(NULL); + UNITY_FAIL_AND_BAIL; + } + Unity.CurrentDetailStackLabels[Unity.CurrentDetailStackSize] = label; + Unity.CurrentDetailStackValues[Unity.CurrentDetailStackSize++] = value; +} +void UnityPopDetail(UNITY_DETAIL_LABEL_TYPE label, UNITY_DETAIL_VALUE_TYPE value, const UNITY_LINE_TYPE line) { + if (Unity.CurrentDetailStackSize == 0) { + UnityTestResultsFailBegin(line); + UnityPrint(UnityStrErrDetailStackEmpty); + UnityAddMsgIfSpecified(NULL); + UNITY_FAIL_AND_BAIL; + } + if ((Unity.CurrentDetailStackLabels[Unity.CurrentDetailStackSize-1] != label) || (Unity.CurrentDetailStackValues[Unity.CurrentDetailStackSize-1] != value)) { + UnityTestResultsFailBegin(line); + UnityPrint(UnityStrErrDetailStackPop); + UnityAddMsgIfSpecified(NULL); + UNITY_FAIL_AND_BAIL; + } + Unity.CurrentDetailStackSize--; +} +#endif +#endif + +/*----------------------------------------------- + * Command Line Argument Support + *-----------------------------------------------*/ +#ifdef UNITY_USE_COMMAND_LINE_ARGS + +char* UnityOptionIncludeNamed = NULL; +char* UnityOptionExcludeNamed = NULL; +int UnityVerbosity = 1; +int UnityStrictMatch = 0; + +/*-----------------------------------------------*/ +int UnityParseOptions(int argc, char** argv) +{ + int i; + UnityOptionIncludeNamed = NULL; + UnityOptionExcludeNamed = NULL; + UnityStrictMatch = 0; + + for (i = 1; i < argc; i++) + { + if (argv[i][0] == '-') + { + switch (argv[i][1]) + { + case 'l': /* list tests */ + return -1; + case 'n': /* include tests with name including this string */ + case 'f': /* an alias for -n */ + UnityStrictMatch = (argv[i][1] == 'n'); /* strictly match this string if -n */ + if (argv[i][2] == '=') + { + UnityOptionIncludeNamed = &argv[i][3]; + } + else if (++i < argc) + { + UnityOptionIncludeNamed = argv[i]; + } + else + { + UnityPrint("ERROR: No Test String to Include Matches For"); + UNITY_PRINT_EOL(); + return 1; + } + break; + case 'q': /* quiet */ + UnityVerbosity = 0; + break; + case 'v': /* verbose */ + UnityVerbosity = 2; + break; + case 'x': /* exclude tests with name including this string */ + if (argv[i][2] == '=') + { + UnityOptionExcludeNamed = &argv[i][3]; + } + else if (++i < argc) + { + UnityOptionExcludeNamed = argv[i]; + } + else + { + UnityPrint("ERROR: No Test String to Exclude Matches For"); + UNITY_PRINT_EOL(); + return 1; + } + break; + default: + UnityPrint("ERROR: Unknown Option "); + UNITY_OUTPUT_CHAR(argv[i][1]); + UNITY_PRINT_EOL(); + /* Now display help */ + /* FALLTHRU */ + case 'h': + UnityPrint("Options: "); UNITY_PRINT_EOL(); + UnityPrint("-l List all tests and exit"); UNITY_PRINT_EOL(); + UnityPrint("-f NAME Filter to run only tests whose name includes NAME"); UNITY_PRINT_EOL(); + UnityPrint("-n NAME Run only the test named NAME"); UNITY_PRINT_EOL(); + UnityPrint("-h show this Help menu"); UNITY_PRINT_EOL(); + UnityPrint("-q Quiet/decrease verbosity"); UNITY_PRINT_EOL(); + UnityPrint("-v increase Verbosity"); UNITY_PRINT_EOL(); + UnityPrint("-x NAME eXclude tests whose name includes NAME"); UNITY_PRINT_EOL(); + UNITY_OUTPUT_FLUSH(); + return 1; + } + } + } + + return 0; +} + +/*-----------------------------------------------*/ +static int IsStringInBiggerString(const char* longstring, const char* shortstring) +{ + const char* lptr = longstring; + const char* sptr = shortstring; + const char* lnext = lptr; + + if (*sptr == '*') + { + return UnityStrictMatch ? 0 : 1; + } + + while (*lptr) + { + lnext = lptr + 1; + + /* If they current bytes match, go on to the next bytes */ + while (*lptr && *sptr && (*lptr == *sptr)) + { + lptr++; + sptr++; + + switch (*sptr) + { + case '*': /* we encountered a wild-card */ + return UnityStrictMatch ? 0 : 1; + + case ',': /* we encountered the end of match string */ + case '"': + case '\'': + case 0: + return (!UnityStrictMatch || (*lptr == 0)) ? 1 : 0; + + case ':': /* we encountered the end of a partial match */ + return 2; + + default: + break; + } + } + + // If we didn't match and we're on strict matching, we already know we failed + if (UnityStrictMatch) + { + return 0; + } + + /* Otherwise we start in the long pointer 1 character further and try again */ + lptr = lnext; + sptr = shortstring; + } + + return 0; +} + +/*-----------------------------------------------*/ +static int UnityStringArgumentMatches(const char* str) +{ + int retval; + const char* ptr1; + const char* ptr2; + const char* ptrf; + + /* Go through the options and get the substrings for matching one at a time */ + ptr1 = str; + while (ptr1[0] != 0) + { + if ((ptr1[0] == '"') || (ptr1[0] == '\'')) + { + ptr1++; + } + + /* look for the start of the next partial */ + ptr2 = ptr1; + ptrf = 0; + do + { + ptr2++; + if ((ptr2[0] == ':') && (ptr2[1] != 0) && (ptr2[0] != '\'') && (ptr2[0] != '"') && (ptr2[0] != ',')) + { + ptrf = &ptr2[1]; + } + } while ((ptr2[0] != 0) && (ptr2[0] != '\'') && (ptr2[0] != '"') && (ptr2[0] != ',')); + + while ((ptr2[0] != 0) && ((ptr2[0] == ':') || (ptr2[0] == '\'') || (ptr2[0] == '"') || (ptr2[0] == ','))) + { + ptr2++; + } + + /* done if complete filename match */ + retval = IsStringInBiggerString(Unity.TestFile, ptr1); + if (retval == 1) + { + return retval; + } + + /* done if testname match after filename partial match */ + if ((retval == 2) && (ptrf != 0)) + { + if (IsStringInBiggerString(Unity.CurrentTestName, ptrf)) + { + return 1; + } + } + + /* done if complete testname match */ + if (IsStringInBiggerString(Unity.CurrentTestName, ptr1) == 1) + { + return 1; + } + + ptr1 = ptr2; + } + + /* we couldn't find a match for any substrings */ + return 0; +} + +/*-----------------------------------------------*/ +int UnityTestMatches(void) +{ + /* Check if this test name matches the included test pattern */ + int retval; + if (UnityOptionIncludeNamed) + { + retval = UnityStringArgumentMatches(UnityOptionIncludeNamed); + } + else + { + retval = 1; + } + + /* Check if this test name matches the excluded test pattern */ + if (UnityOptionExcludeNamed) + { + if (UnityStringArgumentMatches(UnityOptionExcludeNamed)) + { + retval = 0; + } + } + + return retval; +} + +#endif /* UNITY_USE_COMMAND_LINE_ARGS */ +/*-----------------------------------------------*/ diff --git a/Start_Windows/unity/unity.h b/Start_Windows/unity/unity.h new file mode 100644 index 0000000..7c749c2 --- /dev/null +++ b/Start_Windows/unity/unity.h @@ -0,0 +1,698 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#ifndef UNITY_FRAMEWORK_H +#define UNITY_FRAMEWORK_H +#define UNITY + +#define UNITY_VERSION_MAJOR 2 +#define UNITY_VERSION_MINOR 6 +#define UNITY_VERSION_BUILD 2 +#define UNITY_VERSION ((UNITY_VERSION_MAJOR << 16) | (UNITY_VERSION_MINOR << 8) | UNITY_VERSION_BUILD) + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "unity_internals.h" + +/*------------------------------------------------------- + * Test Setup / Teardown + *-------------------------------------------------------*/ + +/* These functions are intended to be called before and after each test. + * If using unity directly, these will need to be provided for each test + * executable built. If you are using the test runner generator and/or + * Ceedling, these are optional. */ +void setUp(void); +void tearDown(void); + +/* These functions are intended to be called at the beginning and end of an + * entire test suite. suiteTearDown() is passed the number of tests that + * failed, and its return value becomes the exit code of main(). If using + * Unity directly, you're in charge of calling these if they are desired. + * If using Ceedling or the test runner generator, these will be called + * automatically if they exist. */ +void suiteSetUp(void); +int suiteTearDown(int num_failures); + +/*------------------------------------------------------- + * Test Reset and Verify + *-------------------------------------------------------*/ + +/* These functions are intended to be called before or during tests in order + * to support complex test loops, etc. Both are NOT built into Unity. Instead + * the test runner generator will create them. resetTest will run teardown and + * setup again, verifying any end-of-test needs between. verifyTest will only + * run the verification. */ +void resetTest(void); +void verifyTest(void); + +/*------------------------------------------------------- + * Configuration Options + *------------------------------------------------------- + * All options described below should be passed as a compiler flag to all files using Unity. If you must add #defines, place them BEFORE the #include above. + + * Integers/longs/pointers + * - Unity attempts to automatically discover your integer sizes + * - define UNITY_EXCLUDE_STDINT_H to stop attempting to look in + * - define UNITY_EXCLUDE_LIMITS_H to stop attempting to look in + * - If you cannot use the automatic methods above, you can force Unity by using these options: + * - define UNITY_SUPPORT_64 + * - set UNITY_INT_WIDTH + * - set UNITY_LONG_WIDTH + * - set UNITY_POINTER_WIDTH + + * Floats + * - define UNITY_EXCLUDE_FLOAT to disallow floating point comparisons + * - define UNITY_FLOAT_PRECISION to specify the precision to use when doing TEST_ASSERT_EQUAL_FLOAT + * - define UNITY_FLOAT_TYPE to specify doubles instead of single precision floats + * - define UNITY_INCLUDE_DOUBLE to allow double floating point comparisons + * - define UNITY_EXCLUDE_DOUBLE to disallow double floating point comparisons (default) + * - define UNITY_DOUBLE_PRECISION to specify the precision to use when doing TEST_ASSERT_EQUAL_DOUBLE + * - define UNITY_DOUBLE_TYPE to specify something other than double + * - define UNITY_EXCLUDE_FLOAT_PRINT to trim binary size, won't print floating point values in errors + + * Output + * - by default, Unity prints to standard out with putchar. define UNITY_OUTPUT_CHAR(a) with a different function if desired + * - define UNITY_DIFFERENTIATE_FINAL_FAIL to print FAILED (vs. FAIL) at test end summary - for automated search for failure + + * Optimization + * - by default, line numbers are stored in unsigned shorts. Define UNITY_LINE_TYPE with a different type if your files are huge + * - by default, test and failure counters are unsigned shorts. Define UNITY_COUNTER_TYPE with a different type if you want to save space or have more than 65535 Tests. + + * Test Cases + * - define UNITY_SUPPORT_TEST_CASES to include the TEST_CASE macro, though really it's mostly about the runner generator script + + * Parameterized Tests + * - you'll want to create a define of TEST_CASE(...), TEST_RANGE(...) and/or TEST_MATRIX(...) which basically evaluates to nothing + + * Tests with Arguments + * - you'll want to define UNITY_USE_COMMAND_LINE_ARGS if you have the test runner passing arguments to Unity + + *------------------------------------------------------- + * Basic Fail and Ignore + *-------------------------------------------------------*/ + +#define TEST_FAIL_MESSAGE(message) UNITY_TEST_FAIL(__LINE__, (message)) +#define TEST_FAIL() UNITY_TEST_FAIL(__LINE__, NULL) +#define TEST_IGNORE_MESSAGE(message) UNITY_TEST_IGNORE(__LINE__, (message)) +#define TEST_IGNORE() UNITY_TEST_IGNORE(__LINE__, NULL) +#define TEST_MESSAGE(message) UnityMessage((message), __LINE__) +#define TEST_ONLY() +#ifdef UNITY_INCLUDE_PRINT_FORMATTED +#define TEST_PRINTF(message, ...) UnityPrintF(__LINE__, (message), ##__VA_ARGS__) +#endif + +/* It is not necessary for you to call PASS. A PASS condition is assumed if nothing fails. + * This method allows you to abort a test immediately with a PASS state, ignoring the remainder of the test. */ +#define TEST_PASS() TEST_ABORT() +#define TEST_PASS_MESSAGE(message) do { UnityMessage((message), __LINE__); TEST_ABORT(); } while (0) + +/*------------------------------------------------------- + * Build Directives + *------------------------------------------------------- + + * These macros do nothing, but they are useful for additional build context. + * Tools (like Ceedling) can scan for these directives and make use of them for + * per-test-executable #include search paths and linking. */ + +/* Add source files to a test executable's compilation and linking. Ex: TEST_SOURCE_FILE("sandwiches.c") */ +#define TEST_SOURCE_FILE(a) + +/* Customize #include search paths for a test executable's compilation. Ex: TEST_INCLUDE_PATH("src/module_a/inc") */ +#define TEST_INCLUDE_PATH(a) + +/*------------------------------------------------------- + * Test Asserts (simple) + *-------------------------------------------------------*/ + +/* Boolean */ +#define TEST_ASSERT(condition) UNITY_TEST_ASSERT( (condition), __LINE__, " Expression Evaluated To FALSE") +#define TEST_ASSERT_TRUE(condition) UNITY_TEST_ASSERT( (condition), __LINE__, " Expected TRUE Was FALSE") +#define TEST_ASSERT_UNLESS(condition) UNITY_TEST_ASSERT( !(condition), __LINE__, " Expression Evaluated To TRUE") +#define TEST_ASSERT_FALSE(condition) UNITY_TEST_ASSERT( !(condition), __LINE__, " Expected FALSE Was TRUE") +#define TEST_ASSERT_NULL(pointer) UNITY_TEST_ASSERT_NULL( (pointer), __LINE__, " Expected NULL") +#define TEST_ASSERT_NOT_NULL(pointer) UNITY_TEST_ASSERT_NOT_NULL((pointer), __LINE__, " Expected Non-NULL") +#define TEST_ASSERT_EMPTY(pointer) UNITY_TEST_ASSERT_EMPTY( (pointer), __LINE__, " Expected Empty") +#define TEST_ASSERT_NOT_EMPTY(pointer) UNITY_TEST_ASSERT_NOT_EMPTY((pointer), __LINE__, " Expected Non-Empty") + +/* Integers (of all sizes) */ +#define TEST_ASSERT_EQUAL_INT(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT8(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT8((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT16(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT16((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT32(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT32((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT64(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT64((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT8(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT8( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT16(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT16( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT32(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT32( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT64(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT64( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_size_t(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX8(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX8( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX16(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX16((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX32(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX64(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX64((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_CHAR(expected, actual) UNITY_TEST_ASSERT_EQUAL_CHAR((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_BITS(mask, expected, actual) UNITY_TEST_ASSERT_BITS((mask), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_BITS_HIGH(mask, actual) UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT)(-1), (actual), __LINE__, NULL) +#define TEST_ASSERT_BITS_LOW(mask, actual) UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT)(0), (actual), __LINE__, NULL) +#define TEST_ASSERT_BIT_HIGH(bit, actual) UNITY_TEST_ASSERT_BITS(((UNITY_UINT)1 << (bit)), (UNITY_UINT)(-1), (actual), __LINE__, NULL) +#define TEST_ASSERT_BIT_LOW(bit, actual) UNITY_TEST_ASSERT_BITS(((UNITY_UINT)1 << (bit)), (UNITY_UINT)(0), (actual), __LINE__, NULL) + +/* Integer Not Equal To (of all sizes) */ +#define TEST_ASSERT_NOT_EQUAL_INT(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_INT8(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_INT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_INT16(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_INT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_INT32(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_INT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_INT64(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_INT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_UINT(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_UINT8(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_UINT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_UINT16(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_UINT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_UINT32(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_UINT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_UINT64(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_UINT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_size_t(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_HEX8(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_HEX8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_HEX16(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_HEX16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_HEX32(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_HEX32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_HEX64(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_HEX64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_CHAR(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_CHAR((threshold), (actual), __LINE__, NULL) + +/* Integer Greater Than/ Less Than (of all sizes) */ +#define TEST_ASSERT_GREATER_THAN(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_INT(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_INT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_INT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_INT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_INT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_UINT(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_UINT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_UINT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_UINT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_UINT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_size_t(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_HEX8(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_HEX16(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_HEX32(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_HEX64(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_CHAR(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_CHAR((threshold), (actual), __LINE__, NULL) + +#define TEST_ASSERT_LESS_THAN(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_INT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_INT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_INT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_INT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_INT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_UINT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_UINT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_UINT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_UINT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_UINT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_size_t(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_HEX8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_HEX16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_HEX32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_HEX64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_CHAR(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_CHAR((threshold), (actual), __LINE__, NULL) + +#define TEST_ASSERT_GREATER_OR_EQUAL(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_size_t(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX8(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX16(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX32(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX64(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_CHAR(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_CHAR((threshold), (actual), __LINE__, NULL) + +#define TEST_ASSERT_LESS_OR_EQUAL(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_INT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_INT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_INT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_INT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_INT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_size_t(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_CHAR(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_CHAR((threshold), (actual), __LINE__, NULL) + +/* Integer Ranges (of all sizes) */ +#define TEST_ASSERT_INT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_INT8_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT8_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_INT16_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT16_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_INT32_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT32_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_INT64_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT64_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_UINT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_UINT8_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT8_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_UINT16_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT16_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_UINT32_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT32_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_UINT64_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT64_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_size_t_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_HEX_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_HEX8_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX8_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_HEX16_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX16_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_HEX32_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_HEX64_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX64_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_CHAR_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_CHAR_WITHIN((delta), (expected), (actual), __LINE__, NULL) + +/* Integer Array Ranges (of all sizes) */ +#define TEST_ASSERT_INT_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_INT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_INT8_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_INT8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_INT16_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_INT16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_INT32_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_INT32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_INT64_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_INT64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_UINT_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_UINT8_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_UINT16_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_UINT32_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_UINT64_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_size_t_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_HEX_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_HEX8_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_HEX8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_HEX16_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_HEX16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_HEX32_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_HEX64_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_HEX64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_CHAR_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_CHAR_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) + + +/* Structs and Strings */ +#define TEST_ASSERT_EQUAL_PTR(expected, actual) UNITY_TEST_ASSERT_EQUAL_PTR((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_STRING(expected, actual) UNITY_TEST_ASSERT_EQUAL_STRING((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_STRING_LEN(expected, actual, len) UNITY_TEST_ASSERT_EQUAL_STRING_LEN((expected), (actual), (len), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_MEMORY(expected, actual, len) UNITY_TEST_ASSERT_EQUAL_MEMORY((expected), (actual), (len), __LINE__, NULL) + +/* Arrays */ +#define TEST_ASSERT_EQUAL_INT_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT8_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT8_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT16_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT16_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT32_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT64_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT8_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT8_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT16_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT16_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT32_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_size_t_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX8_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX8_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX16_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX16_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX32_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX64_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_PTR_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_PTR_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_STRING_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_STRING_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_MEMORY_ARRAY(expected, actual, len, num_elements) UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((expected), (actual), (len), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_CHAR_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_CHAR_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) + +/* Arrays Compared To Single Value */ +#define TEST_ASSERT_EACH_EQUAL_INT(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_INT8(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT8((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_INT16(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT16((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_INT32(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT32((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_INT64(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT64((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_UINT(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_UINT8(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT8((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_UINT16(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT16((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_UINT32(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT32((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_UINT64(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT64((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_size_t(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_HEX(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_HEX8(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX8((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_HEX16(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX16((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_HEX32(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_HEX64(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX64((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_PTR(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_PTR((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_STRING(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_STRING((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_MEMORY(expected, actual, len, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_MEMORY((expected), (actual), (len), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_CHAR(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_CHAR((expected), (actual), (num_elements), __LINE__, NULL) + +/* Floating Point (If Enabled) */ +#define TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_FLOAT_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_NOT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_FLOAT_NOT_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_FLOAT(expected, actual) UNITY_TEST_ASSERT_EQUAL_FLOAT((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_FLOAT(expected, actual) UNITY_TEST_ASSERT_NOT_EQUAL_FLOAT((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_FLOAT_ARRAY_WITHIN((delta), (expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_FLOAT(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_FLOAT(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_FLOAT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_FLOAT(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_FLOAT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_FLOAT(threshold, actual) UNITY_TEST_ASSERT_LESS_THAN_FLOAT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_FLOAT(threshold, actual) UNITY_TEST_ASSERT_LESS_OR_EQUAL_FLOAT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NEG_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NAN(actual) UNITY_TEST_ASSERT_FLOAT_IS_NAN((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_DETERMINATE(actual) UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NOT_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NOT_NEG_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NOT_NAN(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE((actual), __LINE__, NULL) + +/* Double (If Enabled) */ +#define TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_DOUBLE_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_NOT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_DOUBLE_NOT_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_DOUBLE(expected, actual) UNITY_TEST_ASSERT_EQUAL_DOUBLE((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_DOUBLE(expected, actual) UNITY_TEST_ASSERT_NOT_EQUAL_DOUBLE((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_DOUBLE_ARRAY_WITHIN((delta), (expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_DOUBLE(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_DOUBLE(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_DOUBLE((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_DOUBLE(threshold, actual) UNITY_TEST_ASSERT_LESS_THAN_DOUBLE((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_DOUBLE(threshold, actual) UNITY_TEST_ASSERT_LESS_OR_EQUAL_DOUBLE((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NEG_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NAN(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NAN((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_DETERMINATE(actual) UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NOT_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NOT_NAN(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE((actual), __LINE__, NULL) + +/* Shorthand */ +#ifdef UNITY_SHORTHAND_AS_OLD +#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, " Expected Not-Equal") +#endif +#ifdef UNITY_SHORTHAND_AS_INT +#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#endif +#ifdef UNITY_SHORTHAND_AS_MEM +#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_ASSERT_EQUAL_MEMORY((&expected), (&actual), sizeof(expected), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#endif +#ifdef UNITY_SHORTHAND_AS_RAW +#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_ASSERT(((expected) == (actual)), __LINE__, " Expected Equal") +#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, " Expected Not-Equal") +#endif +#ifdef UNITY_SHORTHAND_AS_NONE +#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#endif + +/*------------------------------------------------------- + * Test Asserts (with additional messages) + *-------------------------------------------------------*/ + +/* Boolean */ +#define TEST_ASSERT_MESSAGE(condition, message) UNITY_TEST_ASSERT( (condition), __LINE__, (message)) +#define TEST_ASSERT_TRUE_MESSAGE(condition, message) UNITY_TEST_ASSERT( (condition), __LINE__, (message)) +#define TEST_ASSERT_UNLESS_MESSAGE(condition, message) UNITY_TEST_ASSERT( !(condition), __LINE__, (message)) +#define TEST_ASSERT_FALSE_MESSAGE(condition, message) UNITY_TEST_ASSERT( !(condition), __LINE__, (message)) +#define TEST_ASSERT_NULL_MESSAGE(pointer, message) UNITY_TEST_ASSERT_NULL( (pointer), __LINE__, (message)) +#define TEST_ASSERT_NOT_NULL_MESSAGE(pointer, message) UNITY_TEST_ASSERT_NOT_NULL((pointer), __LINE__, (message)) +#define TEST_ASSERT_EMPTY_MESSAGE(pointer, message) UNITY_TEST_ASSERT_EMPTY( (pointer), __LINE__, (message)) +#define TEST_ASSERT_NOT_EMPTY_MESSAGE(pointer, message) UNITY_TEST_ASSERT_NOT_EMPTY((pointer), __LINE__, (message)) + +/* Integers (of all sizes) */ +#define TEST_ASSERT_EQUAL_INT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT8_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT8((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT16_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT16((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT32_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT32((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT64_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT64((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT8_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT8( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT16_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT16( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT32_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT32( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT64_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT64( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_size_t_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX8_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX8( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX16_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX16((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX32_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX64_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX64((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_BITS_MESSAGE(mask, expected, actual, message) UNITY_TEST_ASSERT_BITS((mask), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_BITS_HIGH_MESSAGE(mask, actual, message) UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT32)(-1), (actual), __LINE__, (message)) +#define TEST_ASSERT_BITS_LOW_MESSAGE(mask, actual, message) UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT32)(0), (actual), __LINE__, (message)) +#define TEST_ASSERT_BIT_HIGH_MESSAGE(bit, actual, message) UNITY_TEST_ASSERT_BITS(((UNITY_UINT32)1 << (bit)), (UNITY_UINT32)(-1), (actual), __LINE__, (message)) +#define TEST_ASSERT_BIT_LOW_MESSAGE(bit, actual, message) UNITY_TEST_ASSERT_BITS(((UNITY_UINT32)1 << (bit)), (UNITY_UINT32)(0), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_CHAR_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_CHAR((expected), (actual), __LINE__, (message)) + +/* Integer Not Equal To (of all sizes) */ +#define TEST_ASSERT_NOT_EQUAL_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_INT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_INT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_INT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_INT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_UINT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_UINT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_UINT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_UINT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_size_t_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_HEX8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_HEX16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_HEX32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_HEX64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_CHAR_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_CHAR((threshold), (actual), __LINE__, (message)) + + +/* Integer Greater Than/ Less Than (of all sizes) */ +#define TEST_ASSERT_GREATER_THAN_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_size_t_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_CHAR_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_CHAR((threshold), (actual), __LINE__, (message)) + +#define TEST_ASSERT_LESS_THAN_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_size_t_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_CHAR_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_CHAR((threshold), (actual), __LINE__, (message)) + +#define TEST_ASSERT_GREATER_OR_EQUAL_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_size_t_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_CHAR_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_CHAR((threshold), (actual), __LINE__, (message)) + +#define TEST_ASSERT_LESS_OR_EQUAL_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_size_t_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_CHAR_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_CHAR((threshold), (actual), __LINE__, (message)) + +/* Integer Ranges (of all sizes) */ +#define TEST_ASSERT_INT_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_INT8_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT8_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_INT16_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT16_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_INT32_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT32_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_INT64_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT64_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_UINT_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_UINT8_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT8_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_UINT16_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT16_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_UINT32_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT32_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_UINT64_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT64_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_size_t_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_HEX_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_HEX8_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX8_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_HEX16_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX16_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_HEX32_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_HEX64_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX64_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_CHAR_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_CHAR_WITHIN((delta), (expected), (actual), __LINE__, (message)) + +/* Integer Array Ranges (of all sizes) */ +#define TEST_ASSERT_INT_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_INT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_INT8_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_INT8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_INT16_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_INT16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_INT32_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_INT32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_INT64_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_INT64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_UINT_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_UINT8_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_UINT16_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_UINT32_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_UINT64_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_size_t_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_HEX_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_HEX8_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_HEX8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_HEX16_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_HEX16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_HEX32_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_HEX64_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_HEX64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_CHAR_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_CHAR_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) + + +/* Structs and Strings */ +#define TEST_ASSERT_EQUAL_PTR_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_PTR((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_STRING_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_STRING((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_STRING_LEN_MESSAGE(expected, actual, len, message) UNITY_TEST_ASSERT_EQUAL_STRING_LEN((expected), (actual), (len), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_MEMORY_MESSAGE(expected, actual, len, message) UNITY_TEST_ASSERT_EQUAL_MEMORY((expected), (actual), (len), __LINE__, (message)) + +/* Arrays */ +#define TEST_ASSERT_EQUAL_INT_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT8_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT8_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT16_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT16_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT32_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT32_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT64_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT8_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT8_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT16_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT16_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT32_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT32_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT64_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_size_t_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX8_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX8_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX16_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX16_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX32_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX64_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_PTR_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_PTR_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_STRING_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_STRING_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_MEMORY_ARRAY_MESSAGE(expected, actual, len, num_elements, message) UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((expected), (actual), (len), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_CHAR_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_CHAR_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) + +/* Arrays Compared To Single Value*/ +#define TEST_ASSERT_EACH_EQUAL_INT_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_INT8_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT8((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_INT16_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT16((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_INT32_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT32((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_INT64_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT64((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_UINT_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_UINT8_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT8((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_UINT16_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT16((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_UINT32_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT32((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_UINT64_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT64((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_size_t_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_HEX_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_HEX8_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX8((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_HEX16_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX16((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_HEX32_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_HEX64_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX64((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_PTR_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_PTR((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_STRING_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_STRING((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_MEMORY_MESSAGE(expected, actual, len, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_MEMORY((expected), (actual), (len), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_CHAR_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_CHAR((expected), (actual), (num_elements), __LINE__, (message)) + +/* Floating Point (If Enabled) */ +#define TEST_ASSERT_FLOAT_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_FLOAT_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_FLOAT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_FLOAT((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_FLOAT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_FLOAT((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_FLOAT_ARRAY_WITHIN((delta), (expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_FLOAT_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_FLOAT_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_FLOAT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_FLOAT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_FLOAT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_FLOAT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_FLOAT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_LESS_THAN_FLOAT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_FLOAT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_LESS_OR_EQUAL_FLOAT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NAN((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NOT_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NOT_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NOT_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE((actual), __LINE__, (message)) + +/* Double (If Enabled) */ +#define TEST_ASSERT_DOUBLE_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_DOUBLE_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_DOUBLE_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_DOUBLE((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_DOUBLE_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_DOUBLE((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_DOUBLE_ARRAY_WITHIN((delta), (expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_DOUBLE_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_DOUBLE_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_DOUBLE_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_DOUBLE((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_DOUBLE_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_LESS_THAN_DOUBLE((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_DOUBLE_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_LESS_OR_EQUAL_DOUBLE((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NAN((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NOT_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NOT_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE((actual), __LINE__, (message)) + +/* Shorthand */ +#ifdef UNITY_SHORTHAND_AS_OLD +#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, (message)) +#endif +#ifdef UNITY_SHORTHAND_AS_INT +#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, message) +#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#endif +#ifdef UNITY_SHORTHAND_AS_MEM +#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_MEMORY((&expected), (&actual), sizeof(expected), __LINE__, message) +#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#endif +#ifdef UNITY_SHORTHAND_AS_RAW +#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT(((expected) == (actual)), __LINE__, message) +#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, message) +#endif +#ifdef UNITY_SHORTHAND_AS_NONE +#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#endif + +/* end of UNITY_FRAMEWORK_H */ +#ifdef __cplusplus +} +#endif +#endif diff --git a/Start_Windows/unity/unity_internals.h b/Start_Windows/unity/unity_internals.h new file mode 100644 index 0000000..a66859a --- /dev/null +++ b/Start_Windows/unity/unity_internals.h @@ -0,0 +1,1271 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#ifndef UNITY_INTERNALS_H +#define UNITY_INTERNALS_H + +#ifdef UNITY_INCLUDE_CONFIG_H +#include "unity_config.h" +#endif + +#ifndef UNITY_EXCLUDE_SETJMP_H +#include +#endif + +#ifndef UNITY_EXCLUDE_MATH_H +#include +#endif + +#ifndef UNITY_EXCLUDE_STDDEF_H +#include +#endif + +#ifdef UNITY_INCLUDE_PRINT_FORMATTED +#include +#endif + +/* Unity Attempts to Auto-Detect Integer Types + * Attempt 1: UINT_MAX, ULONG_MAX in , or default to 32 bits + * Attempt 2: UINTPTR_MAX in , or default to same size as long + * The user may override any of these derived constants: + * UNITY_INT_WIDTH, UNITY_LONG_WIDTH, UNITY_POINTER_WIDTH */ +#ifndef UNITY_EXCLUDE_STDINT_H +#include +#endif + +#ifndef UNITY_EXCLUDE_LIMITS_H +#include +#endif + +#if defined(__GNUC__) || defined(__clang__) + #define UNITY_FUNCTION_ATTR(a) __attribute__((a)) +#else + #define UNITY_FUNCTION_ATTR(a) /* ignore */ +#endif + +/* UNITY_NORETURN is only required if we have setjmp.h. */ +#ifndef UNITY_EXCLUDE_SETJMP_H + #ifndef UNITY_NORETURN + #if defined(__cplusplus) + #if __cplusplus >= 201103L + #define UNITY_NORETURN [[ noreturn ]] + #endif + #elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && __STDC_VERSION__ < 202311L + /* _Noreturn keyword is used from C11 but deprecated in C23. */ + #if defined(_WIN32) && defined(_MSC_VER) + /* We are using MSVC compiler on Windows platform. */ + /* Not all Windows SDKs supports , but compiler can support C11: */ + /* https://devblogs.microsoft.com/cppblog/c11-and-c17-standard-support-arriving-in-msvc/ */ + /* Not sure, that Mingw compilers has Windows SDK headers at all. */ + #include + #endif + + /* Using Windows SDK predefined macro for detecting supported SDK with MSVC compiler. */ + /* Mingw GCC should work without that fixes. */ + /* Based on: */ + /* https://docs.microsoft.com/en-us/cpp/porting/modifying-winver-and-win32-winnt?view=msvc-170 */ + /* NTDDI_WIN10_FE is equal to Windows 10 SDK 2104 */ + #if defined(_MSC_VER) && ((!defined(NTDDI_WIN10_FE)) || WDK_NTDDI_VERSION < NTDDI_WIN10_FE) + /* Based on tests and: */ + /* https://docs.microsoft.com/en-us/cpp/c-language/noreturn?view=msvc-170 */ + /* https://en.cppreference.com/w/c/language/_Noreturn */ + #define UNITY_NORETURN _Noreturn + #else /* Using newer Windows SDK or not MSVC compiler */ + #if defined(__GNUC__) + /* The header collides with __attribute(noreturn)__ from GCC. */ + #define UNITY_NORETURN _Noreturn + #else + #include + #define UNITY_NORETURN noreturn + #endif + #endif + #elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L + /* Since C23, the keyword _Noreturn has been replaced by the attribute noreturn, based on: */ + /* https://en.cppreference.com/w/c/language/attributes/noreturn */ + #define UNITY_NORETURN [[ noreturn ]] + #elif defined(__IAR_SYSTEMS_ICC__) && (__IAR_SYSTEMS_ICC__ >= 8) + /* For IAR compilers supporting at least C99 use the IAR specific '__noreturn' keyword */ + /* Based on tests and: */ + /* https://wwwfiles.iar.com/arm/webic/doc/EWARM_DevelopmentGuide.ENU.pdf */ + /* https://wwwfiles.iar.com/AVR/webic/doc/EWAVR_CompilerGuide.pdf */ + /* https://wwwfiles.iar.com/msp430/webic/doc/EW430_CompilerReference.pdf */ + #define UNITY_NORETURN __noreturn + #endif + #endif + #ifndef UNITY_NORETURN + #define UNITY_NORETURN UNITY_FUNCTION_ATTR(__noreturn__) + #endif +#endif + +/*------------------------------------------------------- + * Guess Widths If Not Specified + *-------------------------------------------------------*/ + +/* Determine the size of an int, if not already specified. + * We cannot use sizeof(int), because it is not yet defined + * at this stage in the translation of the C program. + * Also sizeof(int) does return the size in addressable units on all platforms, + * which may not necessarily be the size in bytes. + * Therefore, infer it from UINT_MAX if possible. */ +#ifndef UNITY_INT_WIDTH + #ifdef UINT_MAX + #if (UINT_MAX == 0xFFFF) + #define UNITY_INT_WIDTH (16) + #elif (UINT_MAX == 0xFFFFFFFF) + #define UNITY_INT_WIDTH (32) + #elif (UINT_MAX == 0xFFFFFFFFFFFFFFFF) + #define UNITY_INT_WIDTH (64) + #endif + #else /* Set to default */ + #define UNITY_INT_WIDTH (32) + #endif /* UINT_MAX */ +#endif + +/* Determine the size of a long, if not already specified. */ +#ifndef UNITY_LONG_WIDTH + #ifdef ULONG_MAX + #if (ULONG_MAX == 0xFFFF) + #define UNITY_LONG_WIDTH (16) + #elif (ULONG_MAX == 0xFFFFFFFF) + #define UNITY_LONG_WIDTH (32) + #elif (ULONG_MAX == 0xFFFFFFFFFFFFFFFF) + #define UNITY_LONG_WIDTH (64) + #endif + #else /* Set to default */ + #define UNITY_LONG_WIDTH (32) + #endif /* ULONG_MAX */ +#endif + +/* Determine the size of a pointer, if not already specified. */ +#ifndef UNITY_POINTER_WIDTH + #ifdef UINTPTR_MAX + #if (UINTPTR_MAX <= 0xFFFF) + #define UNITY_POINTER_WIDTH (16) + #elif (UINTPTR_MAX <= 0xFFFFFFFF) + #define UNITY_POINTER_WIDTH (32) + #elif (UINTPTR_MAX <= 0xFFFFFFFFFFFFFFFF) + #define UNITY_POINTER_WIDTH (64) + #endif + #else /* Set to default */ + #define UNITY_POINTER_WIDTH UNITY_LONG_WIDTH + #endif /* UINTPTR_MAX */ +#endif + +/*------------------------------------------------------- + * Int Support (Define types based on detected sizes) + *-------------------------------------------------------*/ + +#if (UNITY_INT_WIDTH == 32) + typedef unsigned char UNITY_UINT8; + typedef unsigned short UNITY_UINT16; + typedef unsigned int UNITY_UINT32; + typedef signed char UNITY_INT8; + typedef signed short UNITY_INT16; + typedef signed int UNITY_INT32; +#elif (UNITY_INT_WIDTH == 16) + typedef unsigned char UNITY_UINT8; + typedef unsigned int UNITY_UINT16; + typedef unsigned long UNITY_UINT32; + typedef signed char UNITY_INT8; + typedef signed int UNITY_INT16; + typedef signed long UNITY_INT32; +#else + #error Invalid UNITY_INT_WIDTH specified! (16 or 32 are supported) +#endif + +/*------------------------------------------------------- + * 64-bit Support + *-------------------------------------------------------*/ + +/* Auto-detect 64 Bit Support */ +#ifndef UNITY_SUPPORT_64 + #if UNITY_LONG_WIDTH == 64 || UNITY_POINTER_WIDTH == 64 + #define UNITY_SUPPORT_64 + #endif +#endif + +/* 64-Bit Support Dependent Configuration */ +#ifndef UNITY_SUPPORT_64 + /* No 64-bit Support */ + typedef UNITY_UINT32 UNITY_UINT; + typedef UNITY_INT32 UNITY_INT; + #define UNITY_MAX_NIBBLES (8) /* Maximum number of nibbles in a UNITY_(U)INT */ +#else + /* 64-bit Support */ + #if (UNITY_LONG_WIDTH == 32) + typedef unsigned long long UNITY_UINT64; + typedef signed long long UNITY_INT64; + #elif (UNITY_LONG_WIDTH == 64) + typedef unsigned long UNITY_UINT64; + typedef signed long UNITY_INT64; + #else + #error Invalid UNITY_LONG_WIDTH specified! (32 or 64 are supported) + #endif + typedef UNITY_UINT64 UNITY_UINT; + typedef UNITY_INT64 UNITY_INT; + #define UNITY_MAX_NIBBLES (16) /* Maximum number of nibbles in a UNITY_(U)INT */ +#endif + +/*------------------------------------------------------- + * Pointer Support + *-------------------------------------------------------*/ + +#if (UNITY_POINTER_WIDTH == 32) + #define UNITY_PTR_TO_INT UNITY_INT32 + #define UNITY_DISPLAY_STYLE_POINTER UNITY_DISPLAY_STYLE_HEX32 +#elif (UNITY_POINTER_WIDTH == 64) + #define UNITY_PTR_TO_INT UNITY_INT64 + #define UNITY_DISPLAY_STYLE_POINTER UNITY_DISPLAY_STYLE_HEX64 +#elif (UNITY_POINTER_WIDTH == 16) + #define UNITY_PTR_TO_INT UNITY_INT16 + #define UNITY_DISPLAY_STYLE_POINTER UNITY_DISPLAY_STYLE_HEX16 +#else + #error Invalid UNITY_POINTER_WIDTH specified! (16, 32 or 64 are supported) +#endif + +#ifndef UNITY_PTR_ATTRIBUTE + #define UNITY_PTR_ATTRIBUTE +#endif + +#ifndef UNITY_INTERNAL_PTR + #define UNITY_INTERNAL_PTR UNITY_PTR_ATTRIBUTE const void* +#endif + +/* optionally define UNITY_COMPARE_PTRS_ON_ZERO_ARRAY */ + +/*------------------------------------------------------- + * Float Support + *-------------------------------------------------------*/ + +#ifdef UNITY_EXCLUDE_FLOAT + +/* No Floating Point Support */ +#ifndef UNITY_EXCLUDE_DOUBLE +#define UNITY_EXCLUDE_DOUBLE /* Remove double when excluding float support */ +#endif +#ifndef UNITY_EXCLUDE_FLOAT_PRINT +#define UNITY_EXCLUDE_FLOAT_PRINT +#endif + +#else + +/* Floating Point Support */ +#ifndef UNITY_FLOAT_PRECISION +#define UNITY_FLOAT_PRECISION (0.00001f) +#endif +#ifndef UNITY_FLOAT_TYPE +#define UNITY_FLOAT_TYPE float +#endif +typedef UNITY_FLOAT_TYPE UNITY_FLOAT; + +/* isnan macro should be provided by math.h. Override if not macro */ +#ifndef UNITY_IS_NAN +#ifndef isnan +/* NaN is the only floating point value that does NOT equal itself. + * Therefore if n != n, then it is NaN. */ +#define UNITY_IS_NAN(n) ((n != n) ? 1 : 0) +#else +#define UNITY_IS_NAN(n) isnan(n) +#endif +#endif + +/* isinf macro should be provided by math.h. Override if not macro */ +#ifndef UNITY_IS_INF +#ifndef isinf +/* The value of Inf - Inf is NaN */ +#define UNITY_IS_INF(n) (UNITY_IS_NAN((n) - (n)) && !UNITY_IS_NAN(n)) +#else +#define UNITY_IS_INF(n) isinf(n) +#endif +#endif + +#endif + +/*------------------------------------------------------- + * Double Float Support + *-------------------------------------------------------*/ + +/* unlike float, we DON'T include by default */ +#if defined(UNITY_EXCLUDE_DOUBLE) || !defined(UNITY_INCLUDE_DOUBLE) + + /* No Floating Point Support */ + #ifndef UNITY_EXCLUDE_DOUBLE + #define UNITY_EXCLUDE_DOUBLE + #else + #undef UNITY_INCLUDE_DOUBLE + #endif + + #ifndef UNITY_EXCLUDE_FLOAT + #ifndef UNITY_DOUBLE_TYPE + #define UNITY_DOUBLE_TYPE double + #endif + typedef UNITY_FLOAT UNITY_DOUBLE; + /* For parameter in UnityPrintFloat(UNITY_DOUBLE), which aliases to double or float */ + #endif + +#else + + /* Double Floating Point Support */ + #ifndef UNITY_DOUBLE_PRECISION + #define UNITY_DOUBLE_PRECISION (1e-12) + #endif + + #ifndef UNITY_DOUBLE_TYPE + #define UNITY_DOUBLE_TYPE double + #endif + typedef UNITY_DOUBLE_TYPE UNITY_DOUBLE; + +#endif + +/*------------------------------------------------------- + * Output Method: stdout (DEFAULT) + *-------------------------------------------------------*/ +#ifndef UNITY_OUTPUT_CHAR + /* Default to using putchar, which is defined in stdio.h */ + #include + #define UNITY_OUTPUT_CHAR(a) (void)putchar(a) +#else + /* If defined as something else, make sure we declare it here so it's ready for use */ + #ifdef UNITY_OUTPUT_CHAR_HEADER_DECLARATION + extern void UNITY_OUTPUT_CHAR_HEADER_DECLARATION; + #endif +#endif + +#ifndef UNITY_OUTPUT_FLUSH + #ifdef UNITY_USE_FLUSH_STDOUT + /* We want to use the stdout flush utility */ + #include + #define UNITY_OUTPUT_FLUSH() (void)fflush(stdout) + #else + /* We've specified nothing, therefore flush should just be ignored */ + #define UNITY_OUTPUT_FLUSH() (void)0 + #endif +#else + /* If defined as something else, make sure we declare it here so it's ready for use */ + #ifdef UNITY_OUTPUT_FLUSH_HEADER_DECLARATION + extern void UNITY_OUTPUT_FLUSH_HEADER_DECLARATION; + #endif +#endif + +#ifndef UNITY_OUTPUT_FLUSH +#define UNITY_FLUSH_CALL() +#else +#define UNITY_FLUSH_CALL() UNITY_OUTPUT_FLUSH() +#endif + +#ifndef UNITY_PRINT_EOL +#define UNITY_PRINT_EOL() UNITY_OUTPUT_CHAR('\n') +#endif + +#ifndef UNITY_OUTPUT_START +#define UNITY_OUTPUT_START() +#endif + +#ifndef UNITY_OUTPUT_COMPLETE +#define UNITY_OUTPUT_COMPLETE() +#endif + +#ifdef UNITY_INCLUDE_EXEC_TIME + #if !defined(UNITY_EXEC_TIME_START) && \ + !defined(UNITY_EXEC_TIME_STOP) && \ + !defined(UNITY_PRINT_EXEC_TIME) && \ + !defined(UNITY_TIME_TYPE) + /* If none any of these macros are defined then try to provide a default implementation */ + + #if defined(UNITY_CLOCK_MS) + /* This is a simple way to get a default implementation on platforms that support getting a millisecond counter */ + #define UNITY_TIME_TYPE UNITY_UINT + #define UNITY_EXEC_TIME_START() Unity.CurrentTestStartTime = UNITY_CLOCK_MS() + #define UNITY_EXEC_TIME_STOP() Unity.CurrentTestStopTime = UNITY_CLOCK_MS() + #define UNITY_PRINT_EXEC_TIME() { \ + UNITY_UINT execTimeMs = (Unity.CurrentTestStopTime - Unity.CurrentTestStartTime); \ + UnityPrint(" ("); \ + UnityPrintNumberUnsigned(execTimeMs); \ + UnityPrint(" ms)"); \ + } + #elif defined(_WIN32) + #include + #define UNITY_TIME_TYPE clock_t + #define UNITY_GET_TIME(t) t = (clock_t)((clock() * 1000) / CLOCKS_PER_SEC) + #define UNITY_EXEC_TIME_START() UNITY_GET_TIME(Unity.CurrentTestStartTime) + #define UNITY_EXEC_TIME_STOP() UNITY_GET_TIME(Unity.CurrentTestStopTime) + #define UNITY_PRINT_EXEC_TIME() { \ + UNITY_UINT execTimeMs = (Unity.CurrentTestStopTime - Unity.CurrentTestStartTime); \ + UnityPrint(" ("); \ + UnityPrintNumberUnsigned(execTimeMs); \ + UnityPrint(" ms)"); \ + } + #elif defined(__unix__) || defined(__APPLE__) + #include + #define UNITY_TIME_TYPE struct timespec + #define UNITY_GET_TIME(t) clock_gettime(CLOCK_MONOTONIC, &t) + #define UNITY_EXEC_TIME_START() UNITY_GET_TIME(Unity.CurrentTestStartTime) + #define UNITY_EXEC_TIME_STOP() UNITY_GET_TIME(Unity.CurrentTestStopTime) + #define UNITY_PRINT_EXEC_TIME() { \ + UNITY_UINT execTimeMs = ((Unity.CurrentTestStopTime.tv_sec - Unity.CurrentTestStartTime.tv_sec) * 1000L); \ + execTimeMs += ((Unity.CurrentTestStopTime.tv_nsec - Unity.CurrentTestStartTime.tv_nsec) / 1000000L); \ + UnityPrint(" ("); \ + UnityPrintNumberUnsigned(execTimeMs); \ + UnityPrint(" ms)"); \ + } + #endif + #endif +#endif + +#ifndef UNITY_EXEC_TIME_START +#define UNITY_EXEC_TIME_START() do { /* nothing*/ } while (0) +#endif + +#ifndef UNITY_EXEC_TIME_STOP +#define UNITY_EXEC_TIME_STOP() do { /* nothing*/ } while (0) +#endif + +#ifndef UNITY_TIME_TYPE +#define UNITY_TIME_TYPE UNITY_UINT +#endif + +#ifndef UNITY_PRINT_EXEC_TIME +#define UNITY_PRINT_EXEC_TIME() do { /* nothing*/ } while (0) +#endif + +/*------------------------------------------------------- + * Footprint + *-------------------------------------------------------*/ + +#ifndef UNITY_LINE_TYPE +#define UNITY_LINE_TYPE UNITY_UINT +#endif + +#ifndef UNITY_COUNTER_TYPE +#define UNITY_COUNTER_TYPE UNITY_UINT +#endif + +/*------------------------------------------------------- + * Internal Structs Needed + *-------------------------------------------------------*/ + +typedef void (*UnityTestFunction)(void); + +#define UNITY_DISPLAY_RANGE_INT (0x10) +#define UNITY_DISPLAY_RANGE_UINT (0x20) +#define UNITY_DISPLAY_RANGE_HEX (0x40) +#define UNITY_DISPLAY_RANGE_CHAR (0x80) + +typedef enum +{ + UNITY_DISPLAY_STYLE_INT = (UNITY_INT_WIDTH / 8) + UNITY_DISPLAY_RANGE_INT, + UNITY_DISPLAY_STYLE_INT8 = 1 + UNITY_DISPLAY_RANGE_INT, + UNITY_DISPLAY_STYLE_INT16 = 2 + UNITY_DISPLAY_RANGE_INT, + UNITY_DISPLAY_STYLE_INT32 = 4 + UNITY_DISPLAY_RANGE_INT, +#ifdef UNITY_SUPPORT_64 + UNITY_DISPLAY_STYLE_INT64 = 8 + UNITY_DISPLAY_RANGE_INT, +#endif + + UNITY_DISPLAY_STYLE_UINT = (UNITY_INT_WIDTH / 8) + UNITY_DISPLAY_RANGE_UINT, + UNITY_DISPLAY_STYLE_UINT8 = 1 + UNITY_DISPLAY_RANGE_UINT, + UNITY_DISPLAY_STYLE_UINT16 = 2 + UNITY_DISPLAY_RANGE_UINT, + UNITY_DISPLAY_STYLE_UINT32 = 4 + UNITY_DISPLAY_RANGE_UINT, +#ifdef UNITY_SUPPORT_64 + UNITY_DISPLAY_STYLE_UINT64 = 8 + UNITY_DISPLAY_RANGE_UINT, +#endif + + UNITY_DISPLAY_STYLE_HEX8 = 1 + UNITY_DISPLAY_RANGE_HEX, + UNITY_DISPLAY_STYLE_HEX16 = 2 + UNITY_DISPLAY_RANGE_HEX, + UNITY_DISPLAY_STYLE_HEX32 = 4 + UNITY_DISPLAY_RANGE_HEX, +#ifdef UNITY_SUPPORT_64 + UNITY_DISPLAY_STYLE_HEX64 = 8 + UNITY_DISPLAY_RANGE_HEX, +#endif + + UNITY_DISPLAY_STYLE_CHAR = 1 + UNITY_DISPLAY_RANGE_CHAR + UNITY_DISPLAY_RANGE_INT, + + UNITY_DISPLAY_STYLE_UNKNOWN +} UNITY_DISPLAY_STYLE_T; + +typedef enum +{ + UNITY_EQUAL_TO = 0x1, + UNITY_GREATER_THAN = 0x2, + UNITY_GREATER_OR_EQUAL = 0x2 + UNITY_EQUAL_TO, + UNITY_SMALLER_THAN = 0x4, + UNITY_SMALLER_OR_EQUAL = 0x4 + UNITY_EQUAL_TO, + UNITY_NOT_EQUAL = 0x8 +} UNITY_COMPARISON_T; + +#ifndef UNITY_EXCLUDE_FLOAT +typedef enum UNITY_FLOAT_TRAIT +{ + UNITY_FLOAT_IS_NOT_INF = 0, + UNITY_FLOAT_IS_INF, + UNITY_FLOAT_IS_NOT_NEG_INF, + UNITY_FLOAT_IS_NEG_INF, + UNITY_FLOAT_IS_NOT_NAN, + UNITY_FLOAT_IS_NAN, + UNITY_FLOAT_IS_NOT_DET, + UNITY_FLOAT_IS_DET, + UNITY_FLOAT_INVALID_TRAIT +} UNITY_FLOAT_TRAIT_T; +#endif + +typedef enum +{ + UNITY_ARRAY_TO_VAL = 0, + UNITY_ARRAY_TO_ARRAY, + UNITY_ARRAY_UNKNOWN +} UNITY_FLAGS_T; + +#ifndef UNITY_EXCLUDE_DETAILS +#ifdef UNITY_DETAIL_STACK_SIZE +#ifndef UNITY_DETAIL_LABEL_TYPE +#define UNITY_DETAIL_LABEL_TYPE uint8_t +#endif +#ifndef UNITY_DETAIL_VALUE_TYPE +#define UNITY_DETAIL_VALUE_TYPE UNITY_PTR_TO_INT +#endif +#endif +#endif + +struct UNITY_STORAGE_T +{ + const char* TestFile; + const char* CurrentTestName; +#ifndef UNITY_EXCLUDE_DETAILS +#ifdef UNITY_DETAIL_STACK_SIZE + UNITY_DETAIL_LABEL_TYPE CurrentDetailStackLabels[UNITY_DETAIL_STACK_SIZE]; + UNITY_DETAIL_VALUE_TYPE CurrentDetailStackValues[UNITY_DETAIL_STACK_SIZE]; + UNITY_COUNTER_TYPE CurrentDetailStackSize; +#else + const char* CurrentDetail1; + const char* CurrentDetail2; +#endif +#endif + UNITY_LINE_TYPE CurrentTestLineNumber; + UNITY_COUNTER_TYPE NumberOfTests; + UNITY_COUNTER_TYPE TestFailures; + UNITY_COUNTER_TYPE TestIgnores; + UNITY_COUNTER_TYPE CurrentTestFailed; + UNITY_COUNTER_TYPE CurrentTestIgnored; +#ifdef UNITY_INCLUDE_EXEC_TIME + UNITY_TIME_TYPE CurrentTestStartTime; + UNITY_TIME_TYPE CurrentTestStopTime; +#endif +#ifndef UNITY_EXCLUDE_SETJMP_H + jmp_buf AbortFrame; +#endif +}; + +extern struct UNITY_STORAGE_T Unity; + +/*------------------------------------------------------- + * Test Suite Management + *-------------------------------------------------------*/ + +void UnityBegin(const char* filename); +int UnityEnd(void); +void UnitySetTestFile(const char* filename); +void UnityConcludeTest(void); + +#ifndef RUN_TEST +void UnityDefaultTestRun(UnityTestFunction Func, const char* FuncName, const int FuncLineNum); +#else +#define UNITY_SKIP_DEFAULT_RUNNER +#endif + +/*------------------------------------------------------- + * Details Support + *-------------------------------------------------------*/ + +#ifdef UNITY_EXCLUDE_DETAILS +#define UNITY_CLR_DETAILS() +#define UNITY_SET_DETAIL(d1) +#define UNITY_SET_DETAILS(d1,d2) +#else +#ifndef UNITY_DETAIL1_NAME +#define UNITY_DETAIL1_NAME "Function" +#endif + +#ifndef UNITY_DETAIL2_NAME +#define UNITY_DETAIL2_NAME "Argument" +#endif + +#ifdef UNITY_DETAIL_STACK_SIZE +/* stack based implementation */ +#ifndef UNITY_DETAIL_LABEL_NAMES +/* Note: If the label name string starts with '#', the second byte is interpreted as UNITY_DISPLAY_STYLE_T, + * and the detail value will be printed as number (e.g. "#\x24Line" to output "Line "). + * Otherwise, the detail value must be a pointer to a string that is valid until it is pop'ed. + */ +#define UNITY_DETAIL_LABEL_NAMES {0, UNITY_DETAIL1_NAME, UNITY_DETAIL2_NAME} +typedef enum +{ + UNITY_DETAIL_NONE = 0, + UNITY_DETAIL_D1 = 1, + UNITY_DETAIL_D2 = 2 +} UNITY_DETAIL_LABEL_T; +#endif +void UnityPushDetail(UNITY_DETAIL_LABEL_TYPE label, UNITY_DETAIL_VALUE_TYPE value, const UNITY_LINE_TYPE line); +void UnityPopDetail(UNITY_DETAIL_LABEL_TYPE label, UNITY_DETAIL_VALUE_TYPE value, const UNITY_LINE_TYPE line); + +#define UNITY_CLR_DETAILS() do { \ + if(Unity.CurrentDetailStackSize && \ + Unity.CurrentDetailStackLabels[Unity.CurrentDetailStackSize - 1] == UNITY_DETAIL_D2) { \ + Unity.CurrentDetailStackLabels[--Unity.CurrentDetailStackSize] = UNITY_DETAIL_NONE;} \ + if(Unity.CurrentDetailStackSize && \ + Unity.CurrentDetailStackLabels[Unity.CurrentDetailStackSize - 1] == UNITY_DETAIL_D1) { \ + Unity.CurrentDetailStackLabels[--Unity.CurrentDetailStackSize] = UNITY_DETAIL_NONE;} \ + } while (0) +#define UNITY_SET_DETAIL(d1) do { UNITY_CLR_DETAILS(); \ + UnityPushDetail(UNITY_DETAIL_D1, (UNITY_DETAIL_VALUE_TYPE)(d1), __LINE__); \ + } while (0) +#define UNITY_SET_DETAILS(d1,d2) do { UNITY_CLR_DETAILS(); \ + UnityPushDetail(UNITY_DETAIL_D1, (UNITY_DETAIL_VALUE_TYPE)(d1), __LINE__); \ + UnityPushDetail(UNITY_DETAIL_D2, (UNITY_DETAIL_VALUE_TYPE)(d2), __LINE__); \ + } while (0) + +#else +/* just two hardcoded slots */ +#define UNITY_CLR_DETAILS() do { Unity.CurrentDetail1 = 0; Unity.CurrentDetail2 = 0; } while (0) +#define UNITY_SET_DETAIL(d1) do { Unity.CurrentDetail1 = (d1); Unity.CurrentDetail2 = 0; } while (0) +#define UNITY_SET_DETAILS(d1,d2) do { Unity.CurrentDetail1 = (d1); Unity.CurrentDetail2 = (d2); } while (0) +#endif +#endif + +#ifdef UNITY_PRINT_TEST_CONTEXT +void UNITY_PRINT_TEST_CONTEXT(void); +#endif + +/*------------------------------------------------------- + * Test Output + *-------------------------------------------------------*/ + +void UnityPrint(const char* string); + +#ifdef UNITY_INCLUDE_PRINT_FORMATTED +void UnityPrintF(const UNITY_LINE_TYPE line, const char* format, ...); +#endif + +void UnityPrintLen(const char* string, const UNITY_UINT32 length); +void UnityPrintMask(const UNITY_UINT mask, const UNITY_UINT number); +void UnityPrintIntNumberByStyle(const UNITY_INT number, const UNITY_DISPLAY_STYLE_T style); +void UnityPrintUintNumberByStyle(const UNITY_UINT number, const UNITY_DISPLAY_STYLE_T style); +void UnityPrintNumber(const UNITY_INT number_to_print); +void UnityPrintNumberUnsigned(const UNITY_UINT number); +void UnityPrintNumberHex(const UNITY_UINT number, const char nibbles_to_print); + +#ifndef UNITY_EXCLUDE_FLOAT_PRINT +void UnityPrintFloat(const UNITY_DOUBLE input_number); +#endif + +/*------------------------------------------------------- + * Test Assertion Functions + *------------------------------------------------------- + * Use the macros below this section instead of calling + * these directly. The macros have a consistent naming + * convention and will pull in file and line information + * for you. */ + +void UnityAssertEqualIntNumber(const UNITY_INT expected, + const UNITY_INT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style); + +void UnityAssertEqualUintNumber(const UNITY_UINT expected, + const UNITY_UINT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style); + +void UnityAssertIntGreaterOrLessOrEqualNumber(const UNITY_INT threshold, + const UNITY_INT actual, + const UNITY_COMPARISON_T compare, + const char *msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style); + +void UnityAssertUintGreaterOrLessOrEqualNumber(const UNITY_UINT threshold, + const UNITY_UINT actual, + const UNITY_COMPARISON_T compare, + const char *msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style); + +void UnityAssertEqualIntArray(UNITY_INTERNAL_PTR expected, + UNITY_INTERNAL_PTR actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style, + const UNITY_FLAGS_T flags); + +void UnityAssertBits(const UNITY_INT mask, + const UNITY_INT expected, + const UNITY_INT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertEqualString(const char* expected, + const char* actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertEqualStringLen(const char* expected, + const char* actual, + const UNITY_UINT32 length, + const char* msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertEqualStringArray( UNITY_INTERNAL_PTR expected, + const char** actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags); + +void UnityAssertEqualMemory( UNITY_INTERNAL_PTR expected, + UNITY_INTERNAL_PTR actual, + const UNITY_UINT32 length, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags); + +void UnityAssertIntNumbersWithin(const UNITY_UINT delta, + const UNITY_INT expected, + const UNITY_INT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style); + +void UnityAssertUintNumbersWithin(const UNITY_UINT delta, + const UNITY_UINT expected, + const UNITY_UINT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style); + +void UnityAssertNumbersArrayWithin(const UNITY_UINT delta, + UNITY_INTERNAL_PTR expected, + UNITY_INTERNAL_PTR actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style, + const UNITY_FLAGS_T flags); + +#ifndef UNITY_EXCLUDE_SETJMP_H +UNITY_NORETURN void UnityFail(const char* message, const UNITY_LINE_TYPE line); +UNITY_NORETURN void UnityIgnore(const char* message, const UNITY_LINE_TYPE line); +#else +void UnityFail(const char* message, const UNITY_LINE_TYPE line); +void UnityIgnore(const char* message, const UNITY_LINE_TYPE line); +#endif + +void UnityMessage(const char* message, const UNITY_LINE_TYPE line); + +#ifndef UNITY_EXCLUDE_FLOAT +void UnityAssertFloatsWithin(const UNITY_FLOAT delta, + const UNITY_FLOAT expected, + const UNITY_FLOAT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertFloatsNotWithin(const UNITY_FLOAT delta, + const UNITY_FLOAT expected, + const UNITY_FLOAT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertGreaterOrLessFloat(const UNITY_FLOAT threshold, + const UNITY_FLOAT actual, + const UNITY_COMPARISON_T compare, + const char* msg, + const UNITY_LINE_TYPE linenumber); + +void UnityAssertWithinFloatArray(const UNITY_FLOAT delta, + UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* expected, + UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags); + +void UnityAssertFloatSpecial(const UNITY_FLOAT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLOAT_TRAIT_T style); +#endif + +#ifndef UNITY_EXCLUDE_DOUBLE +void UnityAssertDoublesWithin(const UNITY_DOUBLE delta, + const UNITY_DOUBLE expected, + const UNITY_DOUBLE actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertDoublesNotWithin(const UNITY_DOUBLE delta, + const UNITY_DOUBLE expected, + const UNITY_DOUBLE actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertGreaterOrLessDouble(const UNITY_DOUBLE threshold, + const UNITY_DOUBLE actual, + const UNITY_COMPARISON_T compare, + const char* msg, + const UNITY_LINE_TYPE linenumber); + +void UnityAssertWithinDoubleArray(const UNITY_DOUBLE delta, + UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* expected, + UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags); + +void UnityAssertDoubleSpecial(const UNITY_DOUBLE actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLOAT_TRAIT_T style); +#endif + +/*------------------------------------------------------- + * Helpers + *-------------------------------------------------------*/ + +UNITY_INTERNAL_PTR UnityNumToPtr(const UNITY_INT num, const UNITY_UINT8 size); +#ifndef UNITY_EXCLUDE_FLOAT +UNITY_INTERNAL_PTR UnityFloatToPtr(const float num); +#endif +#ifndef UNITY_EXCLUDE_DOUBLE +UNITY_INTERNAL_PTR UnityDoubleToPtr(const double num); +#endif + +/*------------------------------------------------------- + * Error Strings We Might Need + *-------------------------------------------------------*/ + +extern const char UnityStrOk[]; +extern const char UnityStrPass[]; +extern const char UnityStrFail[]; +extern const char UnityStrIgnore[]; + +extern const char UnityStrErrFloat[]; +extern const char UnityStrErrDouble[]; +extern const char UnityStrErr64[]; +extern const char UnityStrErrShorthand[]; + +/*------------------------------------------------------- + * Test Running Macros + *-------------------------------------------------------*/ + +#ifdef UNITY_TEST_PROTECT +#define TEST_PROTECT() UNITY_TEST_PROTECT() +#else +#ifndef UNITY_EXCLUDE_SETJMP_H +#define TEST_PROTECT() (setjmp(Unity.AbortFrame) == 0) +#else +#define TEST_PROTECT() 1 +#endif +#endif + +#ifdef UNITY_TEST_ABORT +#define TEST_ABORT() UNITY_TEST_ABORT() +#else +#ifndef UNITY_EXCLUDE_SETJMP_H +#define TEST_ABORT() longjmp(Unity.AbortFrame, 1) +#else +#define TEST_ABORT() return +#endif +#endif + +/* Automatically enable variadic macros support, if it not enabled before */ +#ifndef UNITY_SUPPORT_VARIADIC_MACROS + #ifdef __STDC_VERSION__ + #if __STDC_VERSION__ >= 199901L + #define UNITY_SUPPORT_VARIADIC_MACROS + #endif + #endif +#endif + +/* This tricky series of macros gives us an optional line argument to treat it as RUN_TEST(func, num=__LINE__) */ +#ifndef RUN_TEST +#ifdef UNITY_SUPPORT_VARIADIC_MACROS +#define RUN_TEST(...) RUN_TEST_AT_LINE(__VA_ARGS__, __LINE__, throwaway) +#define RUN_TEST_AT_LINE(func, line, ...) UnityDefaultTestRun(func, #func, line) +#endif +#endif + +/* Enable default macros for masking param tests test cases */ +#ifdef UNITY_SUPPORT_TEST_CASES + #ifdef UNITY_SUPPORT_VARIADIC_MACROS + #if !defined(TEST_CASE) && !defined(UNITY_EXCLUDE_TEST_CASE) + #define TEST_CASE(...) + #endif + #if !defined(TEST_RANGE) && !defined(UNITY_EXCLUDE_TEST_RANGE) + #define TEST_RANGE(...) + #endif + #if !defined(TEST_MATRIX) && !defined(UNITY_EXCLUDE_TEST_MATRIX) + #define TEST_MATRIX(...) + #endif + #endif +#endif + +/* If we can't do the tricky version, we'll just have to require them to always include the line number */ +#ifndef RUN_TEST +#ifdef CMOCK +#define RUN_TEST(func, num) UnityDefaultTestRun(func, #func, num) +#else +#define RUN_TEST(func) UnityDefaultTestRun(func, #func, __LINE__) +#endif +#endif + +#define TEST_LINE_NUM (Unity.CurrentTestLineNumber) +#define TEST_IS_IGNORED (Unity.CurrentTestIgnored) +#define UNITY_NEW_TEST(a) \ + Unity.CurrentTestName = (a); \ + Unity.CurrentTestLineNumber = (UNITY_LINE_TYPE)(__LINE__); \ + Unity.NumberOfTests++; + +#ifndef UNITY_BEGIN +#define UNITY_BEGIN() UnityBegin(__FILE__) +#endif + +#ifndef UNITY_END +#define UNITY_END() UnityEnd() +#endif + +#ifndef UNITY_SHORTHAND_AS_INT +#ifndef UNITY_SHORTHAND_AS_MEM +#ifndef UNITY_SHORTHAND_AS_NONE +#ifndef UNITY_SHORTHAND_AS_RAW +#define UNITY_SHORTHAND_AS_OLD +#endif +#endif +#endif +#endif + +/*----------------------------------------------- + * Command Line Argument Support + *-----------------------------------------------*/ + +#ifdef UNITY_USE_COMMAND_LINE_ARGS +int UnityParseOptions(int argc, char** argv); +int UnityTestMatches(void); +#endif + +/*------------------------------------------------------- + * Basic Fail and Ignore + *-------------------------------------------------------*/ + +#define UNITY_TEST_FAIL(line, message) UnityFail( (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_IGNORE(line, message) UnityIgnore( (message), (UNITY_LINE_TYPE)(line)) + +/*------------------------------------------------------- + * Test Asserts + *-------------------------------------------------------*/ + +#define UNITY_TEST_ASSERT(condition, line, message) do { if (condition) { /* nothing*/ } else { UNITY_TEST_FAIL((line), (message)); } } while (0) +#define UNITY_TEST_ASSERT_NULL(pointer, line, message) UNITY_TEST_ASSERT(((pointer) == NULL), (line), (message)) +#define UNITY_TEST_ASSERT_NOT_NULL(pointer, line, message) UNITY_TEST_ASSERT(((pointer) != NULL), (line), (message)) +#define UNITY_TEST_ASSERT_EMPTY(pointer, line, message) UNITY_TEST_ASSERT(((pointer[0]) == 0), (line), (message)) +#define UNITY_TEST_ASSERT_NOT_EMPTY(pointer, line, message) UNITY_TEST_ASSERT(((pointer[0]) != 0), (line), (message)) + +#define UNITY_TEST_ASSERT_EQUAL_INT(expected, actual, line, message) UnityAssertEqualIntNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_EQUAL_INT8(expected, actual, line, message) UnityAssertEqualIntNumber((UNITY_INT)(UNITY_INT8 )(expected), (UNITY_INT)(UNITY_INT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_EQUAL_INT16(expected, actual, line, message) UnityAssertEqualIntNumber((UNITY_INT)(UNITY_INT16)(expected), (UNITY_INT)(UNITY_INT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_EQUAL_INT32(expected, actual, line, message) UnityAssertEqualIntNumber((UNITY_INT)(UNITY_INT32)(expected), (UNITY_INT)(UNITY_INT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_EQUAL_UINT(expected, actual, line, message) UnityAssertEqualUintNumber((UNITY_UINT)(expected), (UNITY_UINT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_EQUAL_UINT8(expected, actual, line, message) UnityAssertEqualUintNumber((UNITY_UINT)(UNITY_UINT8)(expected), (UNITY_UINT)(UNITY_UINT8)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_EQUAL_UINT16(expected, actual, line, message) UnityAssertEqualUintNumber((UNITY_UINT)(UNITY_UINT16)(expected), (UNITY_UINT)(UNITY_UINT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_EQUAL_UINT32(expected, actual, line, message) UnityAssertEqualUintNumber((UNITY_UINT)(UNITY_UINT32)(expected), (UNITY_UINT)(UNITY_UINT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_EQUAL_HEX8(expected, actual, line, message) UnityAssertEqualUintNumber((UNITY_UINT)(UNITY_UINT8)(expected), (UNITY_UINT)(UNITY_UINT8)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_EQUAL_HEX16(expected, actual, line, message) UnityAssertEqualUintNumber((UNITY_UINT)(UNITY_UINT16)(expected), (UNITY_UINT)(UNITY_UINT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_EQUAL_HEX32(expected, actual, line, message) UnityAssertEqualUintNumber((UNITY_UINT)(UNITY_UINT32)(expected), (UNITY_UINT)(UNITY_UINT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_EQUAL_CHAR(expected, actual, line, message) UnityAssertEqualIntNumber((UNITY_INT)(UNITY_INT8 )(expected), (UNITY_INT)(UNITY_INT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR) +#define UNITY_TEST_ASSERT_BITS(mask, expected, actual, line, message) UnityAssertBits((UNITY_INT)(mask), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line)) + +#define UNITY_TEST_ASSERT_NOT_EQUAL_INT(threshold, actual, line, message) UnityAssertIntGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_NOT_EQUAL_INT8(threshold, actual, line, message) UnityAssertIntGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_NOT_EQUAL_INT16(threshold, actual, line, message) UnityAssertIntGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16)(threshold), (UNITY_INT)(UNITY_INT16)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_NOT_EQUAL_INT32(threshold, actual, line, message) UnityAssertIntGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32)(threshold), (UNITY_INT)(UNITY_INT32)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_NOT_EQUAL_UINT(threshold, actual, line, message) UnityAssertUintGreaterOrLessOrEqualNumber((UNITY_UINT)(threshold), (UNITY_UINT)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_NOT_EQUAL_UINT8(threshold, actual, line, message) UnityAssertUintGreaterOrLessOrEqualNumber((UNITY_UINT)(UNITY_UINT8 )(threshold), (UNITY_UINT)(UNITY_UINT8 )(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_NOT_EQUAL_UINT16(threshold, actual, line, message) UnityAssertUintGreaterOrLessOrEqualNumber((UNITY_UINT)(UNITY_UINT16)(threshold), (UNITY_UINT)(UNITY_UINT16)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_NOT_EQUAL_UINT32(threshold, actual, line, message) UnityAssertUintGreaterOrLessOrEqualNumber((UNITY_UINT)(UNITY_UINT32)(threshold), (UNITY_UINT)(UNITY_UINT32)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_NOT_EQUAL_HEX8(threshold, actual, line, message) UnityAssertUintGreaterOrLessOrEqualNumber((UNITY_UINT)(UNITY_UINT8 )(threshold), (UNITY_UINT)(UNITY_UINT8 )(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_NOT_EQUAL_HEX16(threshold, actual, line, message) UnityAssertUintGreaterOrLessOrEqualNumber((UNITY_UINT)(UNITY_UINT16)(threshold), (UNITY_UINT)(UNITY_UINT16)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_NOT_EQUAL_HEX32(threshold, actual, line, message) UnityAssertUintGreaterOrLessOrEqualNumber((UNITY_UINT)(UNITY_UINT32)(threshold), (UNITY_UINT)(UNITY_UINT32)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_NOT_EQUAL_CHAR(threshold, actual, line, message) UnityAssertIntGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR) + +#define UNITY_TEST_ASSERT_GREATER_THAN_INT(threshold, actual, line, message) UnityAssertIntGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_GREATER_THAN_INT8(threshold, actual, line, message) UnityAssertIntGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_GREATER_THAN_INT16(threshold, actual, line, message) UnityAssertIntGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16)(threshold), (UNITY_INT)(UNITY_INT16)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_GREATER_THAN_INT32(threshold, actual, line, message) UnityAssertIntGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32)(threshold), (UNITY_INT)(UNITY_INT32)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_GREATER_THAN_UINT(threshold, actual, line, message) UnityAssertUintGreaterOrLessOrEqualNumber((UNITY_UINT)(threshold), (UNITY_UINT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_GREATER_THAN_UINT8(threshold, actual, line, message) UnityAssertUintGreaterOrLessOrEqualNumber((UNITY_UINT)(UNITY_UINT8 )(threshold), (UNITY_UINT)(UNITY_UINT8 )(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_GREATER_THAN_UINT16(threshold, actual, line, message) UnityAssertUintGreaterOrLessOrEqualNumber((UNITY_UINT)(UNITY_UINT16)(threshold), (UNITY_UINT)(UNITY_UINT16)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_GREATER_THAN_UINT32(threshold, actual, line, message) UnityAssertUintGreaterOrLessOrEqualNumber((UNITY_UINT)(UNITY_UINT32)(threshold), (UNITY_UINT)(UNITY_UINT32)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_GREATER_THAN_HEX8(threshold, actual, line, message) UnityAssertUintGreaterOrLessOrEqualNumber((UNITY_UINT)(UNITY_UINT8 )(threshold), (UNITY_UINT)(UNITY_UINT8 )(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_GREATER_THAN_HEX16(threshold, actual, line, message) UnityAssertUintGreaterOrLessOrEqualNumber((UNITY_UINT)(UNITY_UINT16)(threshold), (UNITY_UINT)(UNITY_UINT16)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_GREATER_THAN_HEX32(threshold, actual, line, message) UnityAssertUintGreaterOrLessOrEqualNumber((UNITY_UINT)(UNITY_UINT32)(threshold), (UNITY_UINT)(UNITY_UINT32)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_GREATER_THAN_CHAR(threshold, actual, line, message) UnityAssertIntGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR) + +#define UNITY_TEST_ASSERT_SMALLER_THAN_INT(threshold, actual, line, message) UnityAssertIntGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_SMALLER_THAN_INT8(threshold, actual, line, message) UnityAssertIntGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_SMALLER_THAN_INT16(threshold, actual, line, message) UnityAssertIntGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16)(threshold), (UNITY_INT)(UNITY_INT16)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_SMALLER_THAN_INT32(threshold, actual, line, message) UnityAssertIntGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32)(threshold), (UNITY_INT)(UNITY_INT32)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT(threshold, actual, line, message) UnityAssertUintGreaterOrLessOrEqualNumber((UNITY_UINT)(threshold), (UNITY_UINT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT8(threshold, actual, line, message) UnityAssertUintGreaterOrLessOrEqualNumber((UNITY_UINT)(UNITY_UINT8 )(threshold), (UNITY_UINT)(UNITY_UINT8 )(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT16(threshold, actual, line, message) UnityAssertUintGreaterOrLessOrEqualNumber((UNITY_UINT)(UNITY_UINT16)(threshold), (UNITY_UINT)(UNITY_UINT16)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT32(threshold, actual, line, message) UnityAssertUintGreaterOrLessOrEqualNumber((UNITY_UINT)(UNITY_UINT32)(threshold), (UNITY_UINT)(UNITY_UINT32)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX8(threshold, actual, line, message) UnityAssertUintGreaterOrLessOrEqualNumber((UNITY_UINT)(UNITY_UINT8 )(threshold), (UNITY_UINT)(UNITY_UINT8 )(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX16(threshold, actual, line, message) UnityAssertUintGreaterOrLessOrEqualNumber((UNITY_UINT)(UNITY_UINT16)(threshold), (UNITY_UINT)(UNITY_UINT16)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX32(threshold, actual, line, message) UnityAssertUintGreaterOrLessOrEqualNumber((UNITY_UINT)(UNITY_UINT32)(threshold), (UNITY_UINT)(UNITY_UINT32)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_SMALLER_THAN_CHAR(threshold, actual, line, message) UnityAssertIntGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR) + +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT(threshold, actual, line, message) UnityAssertIntGreaterOrLessOrEqualNumber((UNITY_INT) (threshold), (UNITY_INT) (actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT8(threshold, actual, line, message) UnityAssertIntGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 ) (threshold), (UNITY_INT)(UNITY_INT8 ) (actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT16(threshold, actual, line, message) UnityAssertIntGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16) (threshold), (UNITY_INT)(UNITY_INT16) (actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT32(threshold, actual, line, message) UnityAssertIntGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32) (threshold), (UNITY_INT)(UNITY_INT32) (actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT(threshold, actual, line, message) UnityAssertUintGreaterOrLessOrEqualNumber((UNITY_UINT) (threshold), (UNITY_UINT) (actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT8(threshold, actual, line, message) UnityAssertUintGreaterOrLessOrEqualNumber((UNITY_UINT)(UNITY_UINT8 )(threshold), (UNITY_UINT)(UNITY_UINT8 )(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT16(threshold, actual, line, message) UnityAssertUintGreaterOrLessOrEqualNumber((UNITY_UINT)(UNITY_UINT16)(threshold), (UNITY_UINT)(UNITY_UINT16)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT32(threshold, actual, line, message) UnityAssertUintGreaterOrLessOrEqualNumber((UNITY_UINT)(UNITY_UINT32)(threshold), (UNITY_UINT)(UNITY_UINT32)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX8(threshold, actual, line, message) UnityAssertUintGreaterOrLessOrEqualNumber((UNITY_UINT)(UNITY_UINT8 )(threshold), (UNITY_UINT)(UNITY_UINT8 )(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX16(threshold, actual, line, message) UnityAssertUintGreaterOrLessOrEqualNumber((UNITY_UINT)(UNITY_UINT16)(threshold), (UNITY_UINT)(UNITY_UINT16)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX32(threshold, actual, line, message) UnityAssertUintGreaterOrLessOrEqualNumber((UNITY_UINT)(UNITY_UINT32)(threshold), (UNITY_UINT)(UNITY_UINT32)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_CHAR(threshold, actual, line, message) UnityAssertIntGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 ) (threshold), (UNITY_INT)(UNITY_INT8 ) (actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR) + +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT(threshold, actual, line, message) UnityAssertIntGreaterOrLessOrEqualNumber((UNITY_INT) (threshold), (UNITY_INT) (actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT8(threshold, actual, line, message) UnityAssertIntGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 ) (actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT16(threshold, actual, line, message) UnityAssertIntGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16)(threshold), (UNITY_INT)(UNITY_INT16) (actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT32(threshold, actual, line, message) UnityAssertIntGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32)(threshold), (UNITY_INT)(UNITY_INT32) (actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT(threshold, actual, line, message) UnityAssertUintGreaterOrLessOrEqualNumber((UNITY_UINT) (threshold), (UNITY_UINT) (actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT8(threshold, actual, line, message) UnityAssertUintGreaterOrLessOrEqualNumber((UNITY_UINT)(UNITY_UINT8 )(threshold), (UNITY_UINT)(UNITY_UINT8 )(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT16(threshold, actual, line, message) UnityAssertUintGreaterOrLessOrEqualNumber((UNITY_UINT)(UNITY_UINT16)(threshold), (UNITY_UINT)(UNITY_UINT16)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT32(threshold, actual, line, message) UnityAssertUintGreaterOrLessOrEqualNumber((UNITY_UINT)(UNITY_UINT32)(threshold), (UNITY_UINT)(UNITY_UINT32)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX8(threshold, actual, line, message) UnityAssertUintGreaterOrLessOrEqualNumber((UNITY_UINT)(UNITY_UINT8 )(threshold), (UNITY_UINT)(UNITY_UINT8 )(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX16(threshold, actual, line, message) UnityAssertUintGreaterOrLessOrEqualNumber((UNITY_UINT)(UNITY_UINT16)(threshold), (UNITY_UINT)(UNITY_UINT16)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX32(threshold, actual, line, message) UnityAssertUintGreaterOrLessOrEqualNumber((UNITY_UINT)(UNITY_UINT32)(threshold), (UNITY_UINT)(UNITY_UINT32)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_CHAR(threshold, actual, line, message) UnityAssertIntGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 ) (actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR) + +#define UNITY_TEST_ASSERT_INT_WITHIN(delta, expected, actual, line, message) UnityAssertIntNumbersWithin( (delta), (UNITY_INT) (expected), (UNITY_INT) (actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_INT8_WITHIN(delta, expected, actual, line, message) UnityAssertIntNumbersWithin((UNITY_UINT8 )(delta), (UNITY_INT)(UNITY_INT8 ) (expected), (UNITY_INT)(UNITY_INT8 ) (actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_INT16_WITHIN(delta, expected, actual, line, message) UnityAssertIntNumbersWithin((UNITY_UINT16 )(delta), (UNITY_INT)(UNITY_INT16) (expected), (UNITY_INT)(UNITY_INT16) (actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_INT32_WITHIN(delta, expected, actual, line, message) UnityAssertIntNumbersWithin((UNITY_UINT32 )(delta), (UNITY_INT)(UNITY_INT32) (expected), (UNITY_INT)(UNITY_INT32) (actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_UINT_WITHIN(delta, expected, actual, line, message) UnityAssertUintNumbersWithin( (delta), (UNITY_UINT) (expected), (UNITY_UINT) (actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_UINT8_WITHIN(delta, expected, actual, line, message) UnityAssertUintNumbersWithin((UNITY_UINT8 )(delta), (UNITY_UINT)(UNITY_UINT)(UNITY_UINT8 )(expected), (UNITY_UINT)(UNITY_UINT)(UNITY_UINT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_UINT16_WITHIN(delta, expected, actual, line, message) UnityAssertUintNumbersWithin((UNITY_UINT16)(delta), (UNITY_UINT)(UNITY_UINT)(UNITY_UINT16)(expected), (UNITY_UINT)(UNITY_UINT)(UNITY_UINT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_UINT32_WITHIN(delta, expected, actual, line, message) UnityAssertUintNumbersWithin((UNITY_UINT32)(delta), (UNITY_UINT)(UNITY_UINT)(UNITY_UINT32)(expected), (UNITY_UINT)(UNITY_UINT)(UNITY_UINT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_HEX8_WITHIN(delta, expected, actual, line, message) UnityAssertUintNumbersWithin((UNITY_UINT8 )(delta), (UNITY_UINT)(UNITY_UINT)(UNITY_UINT8 )(expected), (UNITY_UINT)(UNITY_UINT)(UNITY_UINT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_HEX16_WITHIN(delta, expected, actual, line, message) UnityAssertUintNumbersWithin((UNITY_UINT16)(delta), (UNITY_UINT)(UNITY_UINT)(UNITY_UINT16)(expected), (UNITY_UINT)(UNITY_UINT)(UNITY_UINT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_HEX32_WITHIN(delta, expected, actual, line, message) UnityAssertUintNumbersWithin((UNITY_UINT32)(delta), (UNITY_UINT)(UNITY_UINT)(UNITY_UINT32)(expected), (UNITY_UINT)(UNITY_UINT)(UNITY_UINT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_CHAR_WITHIN(delta, expected, actual, line, message) UnityAssertIntNumbersWithin((UNITY_UINT8 )(delta), (UNITY_INT)(UNITY_INT8 ) (expected), (UNITY_INT)(UNITY_INT8 ) (actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR) + +#define UNITY_TEST_ASSERT_INT_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin( (delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_INT8_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT8 )(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_INT16_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT16)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_INT32_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT32)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin( (delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_UINT8_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT8 )(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_UINT16_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT16)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_UINT32_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT32)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_HEX8_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT8 )(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_HEX16_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT16)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT32)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_CHAR_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT8)( delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR, UNITY_ARRAY_TO_ARRAY) + + +#define UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, line, message) UnityAssertEqualIntNumber((UNITY_PTR_TO_INT)(expected), (UNITY_PTR_TO_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_POINTER) +#define UNITY_TEST_ASSERT_EQUAL_STRING(expected, actual, line, message) UnityAssertEqualString((const char*)(expected), (const char*)(actual), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_EQUAL_STRING_LEN(expected, actual, len, line, message) UnityAssertEqualStringLen((const char*)(expected), (const char*)(actual), (UNITY_UINT32)(len), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_EQUAL_MEMORY(expected, actual, len, line, message) UnityAssertEqualMemory((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(len), 1, (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) + +#define UNITY_TEST_ASSERT_EQUAL_INT_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_INT8_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_INT16_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_INT32_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_UINT8_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_UINT16_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_UINT32_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_HEX8_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_HEX16_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_PTR_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_POINTER, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_STRING_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualStringArray((UNITY_INTERNAL_PTR)(expected), (const char**)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY(expected, actual, len, num_elements, line, message) UnityAssertEqualMemory((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(len), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_CHAR_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR, UNITY_ARRAY_TO_ARRAY) + +#define UNITY_TEST_ASSERT_EACH_EQUAL_INT(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT) (expected), (UNITY_INT_WIDTH / 8)), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_INT8(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT8 )(expected), 1), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_INT16(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT16 )(expected), 2), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_INT32(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT32 )(expected), 4), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT) (expected), (UNITY_INT_WIDTH / 8)), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT8(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_UINT8 )(expected), 1), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT16(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_UINT16)(expected), 2), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT32(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_UINT32)(expected), 4), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_HEX8(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT8 )(expected), 1), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_HEX16(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT16 )(expected), 2), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_HEX32(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT32 )(expected), 4), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_PTR(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_PTR_TO_INT) (expected), (UNITY_POINTER_WIDTH / 8)), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_POINTER, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_STRING(expected, actual, num_elements, line, message) UnityAssertEqualStringArray((UNITY_INTERNAL_PTR)(expected), (const char**)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_MEMORY(expected, actual, len, num_elements, line, message) UnityAssertEqualMemory((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(len), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_CHAR(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT8 )(expected), 1), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR, UNITY_ARRAY_TO_VAL) + +#ifdef UNITY_SUPPORT_64 +#define UNITY_TEST_ASSERT_EQUAL_INT64(expected, actual, line, message) UnityAssertEqualIntNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_EQUAL_UINT64(expected, actual, line, message) UnityAssertEqualIntNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_EQUAL_HEX64(expected, actual, line, message) UnityAssertEqualIntNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EACH_EQUAL_INT64(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT64)(expected), 8), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT64(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_UINT64)(expected), 8), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_HEX64(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT64)(expected), 8), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_INT64_WITHIN(delta, expected, actual, line, message) UnityAssertIntNumbersWithin((delta), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_UINT64_WITHIN(delta, expected, actual, line, message) UnityAssertUintNumbersWithin((delta), (UNITY_UINT)(expected), (UNITY_UINT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_HEX64_WITHIN(delta, expected, actual, line, message) UnityAssertUintNumbersWithin((delta), (UNITY_UINT)(expected), (UNITY_UINT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_NOT_EQUAL_INT64(threshold, actual, line, message) UnityAssertIntGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_NOT_EQUAL_UINT64(threshold, actual, line, message) UnityAssertUintGreaterOrLessOrEqualNumber((UNITY_UINT)(threshold), (UNITY_UINT)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_NOT_EQUAL_HEX64(threshold, actual, line, message) UnityAssertUintGreaterOrLessOrEqualNumber((UNITY_UINT)(threshold), (UNITY_UINT)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_GREATER_THAN_INT64(threshold, actual, line, message) UnityAssertIntGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_GREATER_THAN_UINT64(threshold, actual, line, message) UnityAssertUintGreaterOrLessOrEqualNumber((UNITY_UINT)(threshold), (UNITY_UINT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_GREATER_THAN_HEX64(threshold, actual, line, message) UnityAssertUintGreaterOrLessOrEqualNumber((UNITY_UINT)(threshold), (UNITY_UINT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64(threshold, actual, line, message) UnityAssertIntGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64(threshold, actual, line, message) UnityAssertUintGreaterOrLessOrEqualNumber((UNITY_UINT)(threshold), (UNITY_UINT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64(threshold, actual, line, message) UnityAssertUintGreaterOrLessOrEqualNumber((UNITY_UINT)(threshold), (UNITY_UINT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_SMALLER_THAN_INT64(threshold, actual, line, message) UnityAssertIntGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT64(threshold, actual, line, message) UnityAssertUintGreaterOrLessOrEqualNumber((UNITY_UINT)(threshold), (UNITY_UINT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX64(threshold, actual, line, message) UnityAssertUintGreaterOrLessOrEqualNumber((UNITY_UINT)(threshold), (UNITY_UINT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64(threshold, actual, line, message) UnityAssertIntGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64(threshold, actual, line, message) UnityAssertUintGreaterOrLessOrEqualNumber((UNITY_UINT)(threshold), (UNITY_UINT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX64(threshold, actual, line, message) UnityAssertUintGreaterOrLessOrEqualNumber((UNITY_UINT)(threshold), (UNITY_UINT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_INT64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT64)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_UINT64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT64)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_HEX64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT64)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64, UNITY_ARRAY_TO_ARRAY) +#else +#define UNITY_TEST_ASSERT_EQUAL_INT64(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_EQUAL_UINT64(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_EQUAL_HEX64(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_INT64_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_UINT64_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_HEX64_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_GREATER_THAN_INT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_GREATER_THAN_UINT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_GREATER_THAN_HEX64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_SMALLER_THAN_INT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_INT64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_UINT64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_HEX64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#endif + +#ifdef UNITY_EXCLUDE_FLOAT +#define UNITY_TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_NOT_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_EQUAL_FLOAT(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_NOT_EQUAL_FLOAT(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_GREATER_THAN_FLOAT(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_FLOAT(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_LESS_THAN_FLOAT(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_LESS_OR_EQUAL_FLOAT(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#else +#define UNITY_TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual, line, message) UnityAssertFloatsWithin((UNITY_FLOAT)(delta), (UNITY_FLOAT)(expected), (UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_FLOAT_NOT_WITHIN(delta, expected, actual, line, message) UnityAssertFloatsNotWithin((UNITY_FLOAT)(delta), (UNITY_FLOAT)(expected), (UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_EQUAL_FLOAT(expected, actual, line, message) UNITY_TEST_ASSERT_FLOAT_WITHIN((UNITY_FLOAT)(expected) * (UNITY_FLOAT)UNITY_FLOAT_PRECISION, (UNITY_FLOAT)(expected), (UNITY_FLOAT)(actual), (UNITY_LINE_TYPE)(line), (message)) +#define UNITY_TEST_ASSERT_NOT_EQUAL_FLOAT(expected, actual, line, message) UNITY_TEST_ASSERT_FLOAT_NOT_WITHIN((UNITY_FLOAT)(expected) * (UNITY_FLOAT)UNITY_FLOAT_PRECISION, (UNITY_FLOAT)(expected), (UNITY_FLOAT)(actual), (UNITY_LINE_TYPE)(line), (message)) +#define UNITY_TEST_ASSERT_FLOAT_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertWithinFloatArray((UNITY_FLOAT)(delta), (const UNITY_FLOAT*)(expected), (const UNITY_FLOAT*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements, line, message) UnityAssertWithinFloatArray((UNITY_FLOAT)0, (const UNITY_FLOAT*)(expected), (const UNITY_FLOAT*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT(expected, actual, num_elements, line, message) UnityAssertWithinFloatArray((UNITY_FLOAT)0, UnityFloatToPtr(expected), (const UNITY_FLOAT*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_GREATER_THAN_FLOAT(threshold, actual, line, message) UnityAssertGreaterOrLessFloat((UNITY_FLOAT)(threshold), (UNITY_FLOAT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_FLOAT(threshold, actual, line, message) UnityAssertGreaterOrLessFloat((UNITY_FLOAT)(threshold), (UNITY_FLOAT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_LESS_THAN_FLOAT(threshold, actual, line, message) UnityAssertGreaterOrLessFloat((UNITY_FLOAT)(threshold), (UNITY_FLOAT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_LESS_OR_EQUAL_FLOAT(threshold, actual, line, message) UnityAssertGreaterOrLessFloat((UNITY_FLOAT)(threshold), (UNITY_FLOAT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_FLOAT_IS_INF(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_INF) +#define UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NEG_INF) +#define UNITY_TEST_ASSERT_FLOAT_IS_NAN(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NAN) +#define UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_DET) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_INF) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NEG_INF) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NAN) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_DET) +#endif + +#ifdef UNITY_EXCLUDE_DOUBLE +#define UNITY_TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_NOT_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_EQUAL_DOUBLE(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_NOT_EQUAL_DOUBLE(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_GREATER_THAN_DOUBLE(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_LESS_THAN_DOUBLE(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_LESS_OR_EQUAL_DOUBLE(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#else +#define UNITY_TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual, line, message) UnityAssertDoublesWithin((UNITY_DOUBLE)(delta), (UNITY_DOUBLE)(expected), (UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_DOUBLE_NOT_WITHIN(delta, expected, actual, line, message) UnityAssertDoublesNotWithin((UNITY_DOUBLE)(delta), (UNITY_DOUBLE)(expected), (UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_EQUAL_DOUBLE(expected, actual, line, message) UNITY_TEST_ASSERT_DOUBLE_WITHIN((UNITY_DOUBLE)(expected) * (UNITY_DOUBLE)UNITY_DOUBLE_PRECISION, (UNITY_DOUBLE)(expected), (UNITY_DOUBLE)(actual), (UNITY_LINE_TYPE)(line), (message)) +#define UNITY_TEST_ASSERT_NOT_EQUAL_DOUBLE(expected, actual, line, message) UNITY_TEST_ASSERT_DOUBLE_NOT_WITHIN((UNITY_DOUBLE)(expected) * (UNITY_DOUBLE)UNITY_DOUBLE_PRECISION, (UNITY_DOUBLE)(expected), (UNITY_DOUBLE)(actual), (UNITY_LINE_TYPE)(line), (message)) +#define UNITY_TEST_ASSERT_DOUBLE_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertWithinDoubleArray((UNITY_DOUBLE)(delta), (const UNITY_DOUBLE*)(expected), (const UNITY_DOUBLE*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements, line, message) UnityAssertWithinDoubleArray((UNITY_DOUBLE)0, (const UNITY_DOUBLE*)(expected), (const UNITY_DOUBLE*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE(expected, actual, num_elements, line, message) UnityAssertWithinDoubleArray((UNITY_DOUBLE)0, UnityDoubleToPtr(expected), (const UNITY_DOUBLE*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_GREATER_THAN_DOUBLE(threshold, actual, line, message) UnityAssertGreaterOrLessDouble((UNITY_DOUBLE)(threshold), (UNITY_DOUBLE)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE(threshold, actual, line, message) UnityAssertGreaterOrLessDouble((UNITY_DOUBLE)(threshold), (UNITY_DOUBLE)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_LESS_THAN_DOUBLE(threshold, actual, line, message) UnityAssertGreaterOrLessDouble((UNITY_DOUBLE)(threshold), (UNITY_DOUBLE)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_LESS_OR_EQUAL_DOUBLE(threshold, actual, line, message) UnityAssertGreaterOrLessDouble((UNITY_DOUBLE)(threshold), (UNITY_DOUBLE)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_DOUBLE_IS_INF(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_INF) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NEG_INF) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NAN(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NAN) +#define UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_DET) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_INF) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NEG_INF) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NAN) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_DET) +#endif + +#if !defined(UNITY_EXCLUDE_DETAILS) && defined(UNITY_DETAIL_STACK_SIZE) +#define UNITY_DETAIL_PUSH(label, value) UnityPushDetail((UNITY_DETAIL_LABEL_TYPE)(label), (UNITY_DETAIL_VALUE_TYPE)(value), __LINE__) +#define UNITY_DETAIL_POP(label, value) UnityPopDetail((UNITY_DETAIL_LABEL_TYPE)(label), (UNITY_DETAIL_VALUE_TYPE)(value), __LINE__) +#else +#define UNITY_DETAIL_PUSH(label, value) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDetailStack) +#define UNITY_DETAIL_POP(label, value) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDetailStack) +#endif + +/* End of UNITY_INTERNALS_H */ +#endif diff --git a/Start_Windows/words.txt b/Start_Windows/words.txt new file mode 100644 index 0000000..31ee099 --- /dev/null +++ b/Start_Windows/words.txt @@ -0,0 +1,5 @@ +Yeti,Nessie Werwolf; Vampir +Monster +Hydra;Frankenstein +Dracula;KingKong;Gremlin;Kobold,Hexe;Poltergeist +Gespenst, Oger \ No newline at end of file diff --git a/Wordsalad_Aufgabenstellung.pdf b/Wordsalad_Aufgabenstellung.pdf new file mode 100644 index 0000000000000000000000000000000000000000..415baba579f59da6825191b352215b0b9d151f5a GIT binary patch literal 108280 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

g%b^TKQZIbJpw9~*lKe12X3MN# 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