From 602d2a65dd628ea75801c79bfdf960b081696e34 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sun, 28 Jul 2019 15:09:01 +0200 Subject: [PATCH] Reviewed new examples --- examples/core/core_scissor_test.c | 34 ++-- examples/core/core_scissor_test.png | Bin 0 -> 15348 bytes examples/textures/textures_mouse_painting.c | 183 +++++++++++------- examples/textures/textures_mouse_painting.png | Bin 0 -> 20070 bytes 4 files changed, 132 insertions(+), 85 deletions(-) create mode 100644 examples/core/core_scissor_test.png create mode 100644 examples/textures/textures_mouse_painting.png diff --git a/examples/core/core_scissor_test.c b/examples/core/core_scissor_test.c index acc84202d..55221330e 100644 --- a/examples/core/core_scissor_test.c +++ b/examples/core/core_scissor_test.c @@ -5,6 +5,8 @@ * This example has been created using raylib 2.5 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * +* Example contributed by Chris Dill (@MysteriousSpace) and reviewed by Ramon Santamaria (@raysan5) +* * Copyright (c) 2019 Chris Dill (@MysteriousSpace) * ********************************************************************************************/ @@ -20,10 +22,10 @@ int main(void) InitWindow(screenWidth, screenHeight, "raylib [core] example - scissor test"); - Rectangle scissorArea = { 0, 0, 300, 300}; + Rectangle scissorArea = { 0, 0, 300, 300 }; bool scissorMode = true; - SetTargetFPS(60); + SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop @@ -31,14 +33,11 @@ int main(void) { // Update //---------------------------------------------------------------------------------- - if (IsKeyPressed(KEY_S)) - { - scissorMode = !scissorMode; - } + if (IsKeyPressed(KEY_S)) scissorMode = !scissorMode; // Centre the scissor area around the mouse position - scissorArea.x = GetMouseX() - scissorArea.width / 2; - scissorArea.y = GetMouseY() - scissorArea.height / 2; + scissorArea.x = GetMouseX() - scissorArea.width/2; + scissorArea.y = GetMouseY() - scissorArea.height/2; //---------------------------------------------------------------------------------- // Draw @@ -47,22 +46,17 @@ int main(void) ClearBackground(RAYWHITE); - if (scissorMode) - { - BeginScissorMode(scissorArea.x, scissorArea.y, scissorArea.width, scissorArea.height); - } + if (scissorMode) BeginScissorMode(scissorArea.x, scissorArea.y, scissorArea.width, scissorArea.height); - DrawRectangle(80, 45, 640, 360, RED); - DrawRectangleLines(80, 45, 640, 360, BLACK); + // Draw full screen rectangle and some text + // NOTE: Only part defined by scissor area will be rendered + DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), RED); DrawText("Move the mouse around to reveal this text!", 190, 200, 20, LIGHTGRAY); - if (scissorMode) - { - EndScissorMode(); - } + if (scissorMode) EndScissorMode(); - DrawRectangleLinesEx(scissorArea, 2, BLACK); - DrawText("Press s to toggle scissor test", 10, 10, 20, DARKGRAY); + DrawRectangleLinesEx(scissorArea, 1, BLACK); + DrawText("Press S to toggle scissor test", 10, 10, 20, BLACK); EndDrawing(); //---------------------------------------------------------------------------------- diff --git a/examples/core/core_scissor_test.png b/examples/core/core_scissor_test.png new file mode 100644 index 0000000000000000000000000000000000000000..194872bb7e74791dbe06617f356af788ec91903d GIT binary patch literal 15348 zcmeHOYfuwc7~KHkDgk40c!ZGvDvXcPfI+N)jf4iMN)b^Qi<;MXiBA{T=N=Ou{;K+z=c!*j+pn`Na$w~|f&N!XXcJ7~@Y?x)vJ>U7x zy*c-8vb&qJ_H^=e2!ga-U7S21NZka22-UDA`i;IHzaE0@F1k9c@Qm8zH}dyDcN}L8 zm8^!Cs8ug=Tu_AAP809Lm@nqLhyXA5D0p{m9@8StxkV>C3bX~ zS(6sOddfGJl{Mex^qiobBd&`?UdCJ)+AaD%Ag3WEO|KU@JS@*C(I4hoUL~)NQ(a3f zf}Y1#Gn$8M7q==jxjW7J(c(;7wvigr8AMA|;Ep&*GRPtru6{J>zuR!%sfP=PbVL>x zQp6>Djg7@~I`TOB=U(NORhAs^@_F@h#8BhHA9U`HP<@0(i$+Ob3?kt|dDvVI^w^ZT zOx-$jACtkNX(+ph_0;Cxjt@N;Mb^7%k#}Zm-3j9#M@81hTX`q%)KkyBGPAh^4MLm6%u`^tX{xU891} z`3iO)owX>q{Fo?>?bzkoX1Ah~2t_aD*)=WC)GyFg6Y0cx2#ro$HYn(KXlbJG8xjR0 zOWss5{iT$~fXQe)a+Q2nl$l^M;CWP#v9CSjWkG4#ao(pQx6ktKId2;j*p)UG`55rG zD{v#$S3?$?Acb3%v&Lk^e``t&3Z(Dd*yr}drag~i&ktM`n(<{EoL z8+dTLc?e4^}n zc|ICH*1&iM&0w7gnt}EoZ-y`}!Vy6+Y6$IQwbs^FB+X9N4h%Dm%jimrycX{xUzzzN zg~Rqj8fAYw?&Ts=lkm}wAR@j-+B-c#FwYyA7W)CW=m+2u00O2Dzye?a|5*dH0JH$K zfG^g87JwFj78G+4Fh>Ai0KNcx0r-NlnD5_n$9hr}EzV3G*6rTmac4#uecs(sM%!`Z z_Z?A5RW1$ZkAGxOv&k*=ofZGx{?~K0CcxGwl}dYS`INxA3Q&ajCZ1zI&xZ z#l;(0!z%{$bDf+{+uhLi@_k|vaXrOnEUhcnu{Yl9xzYk;&BFB zn)CiKY0fJP!{bfqJ*%cfvjovk;nG_c5$3x*W7v<~d;>X}3yebpjDyRQ+;_H<%Pp2< zf89$7>5MAKi*Zb}D11)cV1Va~F4H9Oe93Z!9P;%o7SCgwO=zMSKTB=**4p%z(oXf+ z$&71R9UNWLvD}kJ!HIRDGnxg}fwH2Y#QIA&aDJt{l}B_hhXFsl=eO%}9ieSLBS3pN zbYr*MSqFnX={c=p2OH$EXuP&mG~7Y=BRlM0!&697<X~C-)jOTe3 zga?0A;UJ2zC|u(hY)?9s-RfY_zt1)}VAF;~N_j8x;(@-ea8#UqRM3U%L98p;dYG?r z>jBk#)zCn9^BB^O?oifPXdrZRhFu!&tHUPWv=!COD|dJ{gBpQNPr;PKXk z@w_#u{s6*q00C1sU;(gz?-&6s04)G5;A1;xX8V2%L30DJ-X0`LW8r`>=% z0(S)N2;334<2$({7I#1IZazEaToZ$)<9=}H_U)<69z2RnCP8= MAX_COLORS_COUNT) - colorState = 0; - else if (colorState < 0) - colorState = MAX_COLORS_COUNT - 1; - - brushSize += GetMouseWheelMove() * 5; - if (brushSize < 0) - brushSize = 0; - if (brushSize > 50) - brushSize = 50; - - Vector2 position = GetMousePosition(); - - if (IsKeyPressed(KEY_C)) { + if (IsKeyPressed(KEY_RIGHT)) colorSelected++; + else if (IsKeyPressed(KEY_LEFT)) colorSelected--; + else if (IsKeyPressed(KEY_UP)) colorSelected -= 3; + else if (IsKeyPressed(KEY_DOWN)) colorSelected += 3; + + for (int i = 0; i < MAX_COLORS_COUNT; i++) + { + if (CheckCollisionPointRec(mousePos, colorsRecs[i])) + { + colorMouseHover = i; + break; + } + else colorMouseHover = -1; + } + + if ((colorMouseHover >= 0) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) + { + colorSelected = colorMouseHover; + colorSelectedPrev = colorSelected; + } + + if (colorSelected >= MAX_COLORS_COUNT) colorSelected = MAX_COLORS_COUNT - 1; + else if (colorSelected < 0) colorSelected = 0; + + // Change brush size + brushSize += GetMouseWheelMove()*5; + if (brushSize < 2) brushSize = 2; + if (brushSize > 50) brushSize = 50; + + if (IsKeyPressed(KEY_C)) + { + // Clear render texture to clear color BeginTextureMode(target); - ClearBackground(RAYWHITE); + ClearBackground(colors[0]); EndTextureMode(); } - if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) { - TraceLog(LOG_INFO, "Painting x: %f y: %f", position.x, position.y); + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) + { + // Paint circle into render texture + // NOTE: To avoid discontinuous circles, we could store + // previous-next mouse points and just draw a line using brush size BeginTextureMode(target); - DrawCircle(position.x, position.y, brushSize, colors[colorState]); + if (mousePos.y > 50) DrawCircle(mousePos.x, mousePos.y, brushSize, colors[colorSelected]); EndTextureMode(); } - if (IsMouseButtonDown(MOUSE_RIGHT_BUTTON)) { - TraceLog(LOG_INFO, "Erasing x: %f y: %f", position.x, position.y); + if (IsMouseButtonDown(MOUSE_RIGHT_BUTTON)) + { + colorSelected = 0; + + // Erase circle from render texture BeginTextureMode(target); - DrawCircle(position.x, position.y, brushSize, clearColor); + if (mousePos.y > 50) DrawCircle(mousePos.x, mousePos.y, brushSize, colors[0]); EndTextureMode(); } - - if (IsKeyPressed(KEY_S)) { - TakeScreenshot("textures_mouse_painting.png"); - } + else colorSelected = colorSelectedPrev; + + // Check mouse hover save button + if (CheckCollisionPointRec(mousePos, btnSaveRec)) btnSaveMouseHover = true; + else btnSaveMouseHover = false; + + // Image saving logic + // NOTE: Saving painted texture to a default named image + if ((btnSaveMouseHover && IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) || IsKeyPressed(KEY_S)) + { + Image image = GetTextureData(target.texture); + ImageFlipVertical(&image); + ExportImage(image, "my_amazing_texture_painting.png"); + UnloadImage(image); + } //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); - ClearBackground(RAYWHITE); - - // NOTE: Render texture must be y-flipped due to default OpenGL coordinates - // (left-bottom) - DrawTextureRec(target.texture, (Rectangle){0, 0, target.texture.width, -target.texture.height}, (Vector2){0, 0}, WHITE); + ClearBackground(RAYWHITE); - // Draw 2d shapes and text over drawn texture - DrawRectangle(0, 9, 380, 60, Fade(LIGHTGRAY, 0.7f)); + // NOTE: Render texture must be y-flipped due to default OpenGL coordinates (left-bottom) + DrawTextureRec(target.texture, (Rectangle){ 0, 0, target.texture.width, -target.texture.height }, (Vector2){ 0, 0 }, WHITE); - DrawText("COLOR:", 10, 15, 20, BLACK); - DrawText(colorNames[colorState], 130, 15, 20, RED); - DrawText("< >", 340, 10, 30, DARKBLUE); + // Draw drawing circle for reference + if (mousePos.y > 50) + { + if (IsMouseButtonDown(MOUSE_RIGHT_BUTTON)) DrawCircleLines(mousePos.x, mousePos.y, brushSize, colors[colorSelected]); + else DrawCircle(GetMouseX(), GetMouseY(), brushSize, colors[colorSelected]); + } + + // Draw top panel + DrawRectangle(0, 0, GetScreenWidth(), 50, RAYWHITE); + DrawLine(0, 50, GetScreenWidth(), 50, LIGHTGRAY); - DrawText("Size:", 10, 40, 20, BLACK); - DrawText(FormatText("%i", brushSize), 130, 40, 20, RED); + // Draw color selection rectangles + for (int i = 0; i < MAX_COLORS_COUNT; i++) DrawRectangleRec(colorsRecs[i], colors[i]); + DrawRectangleLines(10, 10, 30, 30, LIGHTGRAY); - DrawCircle(GetMouseX(), GetMouseY(), brushSize, colors[colorState]); + if (colorMouseHover >= 0) DrawRectangleRec(colorsRecs[colorMouseHover], Fade(WHITE, 0.6f)); - DrawFPS(700, 15); + DrawRectangleLinesEx((Rectangle){ colorsRecs[colorSelected].x - 2, colorsRecs[colorSelected].y - 2, + colorsRecs[colorSelected].width + 4, colorsRecs[colorSelected].height + 4 }, 2, BLACK); + // Draw save image button + DrawRectangleLinesEx(btnSaveRec, 2, btnSaveMouseHover? RED : BLACK); + DrawText("SAVE!", 755, 20, 10, btnSaveMouseHover? RED : BLACK); + EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- - UnloadRenderTexture(target); - CloseWindow(); // Close window and OpenGL context + UnloadRenderTexture(target); // Unload render texture + + CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; diff --git a/examples/textures/textures_mouse_painting.png b/examples/textures/textures_mouse_painting.png new file mode 100644 index 0000000000000000000000000000000000000000..a3dec5dad57908321d7b2e305e6e4b425590d445 GIT binary patch literal 20070 zcmeHv2~bnn)@~AF2pS-OLlVXaB6N!e2!l*Uzywh=qTQ`H1wlLvDk`GV4q-5$hDi_= zMZu$pQ;QmHr5!+QMG@oxqR?uCq6QS4aGu`U=V04?|Mu0ZSM}<>SM}ezm5Xq)&)RFR z;alHY`>vBukm>go^rg{g`eOt9gK0D!D;kY{p3Q>a3<^6`MWan{80$ZJ%JNxZAKtxu zv_>^aBw*meZ+yhD>BWTHLO+q<^8WRMp0KtY(+w9NN>`O*Z1ulyYbWdV>-s4|MXB-yjm?@B;dY(d+o8#A3q1rQ#^J% z$2hX{{h61_fg79`9^`Z1H@Ntgzgq0J#W3yTY|{xzT@GHqyI8$?y=_(Un{)TCmA^U1 z3LX=CX@Mp0{h*(dy3XA45VakiuCMobZ1+&z3!hhb3Omk*99SZGyztDA1}9$M={`$8 zGW+szcFe+`A{&)AXE&YU#4J3y`MUDvxy64t2E4Ouef87Ag-?`k&Ye8Ti&+>K*8_iv z>j*AAqjTJtcH`=2#k8%;?}O839+A`=51TqqIm>oi4`Z@Ha2eEN_bo0&GY|Vy|B&#p{Rw<4~qGw)#Bz^g!mg44PW};tB7NTi+{-c z7i%SjsdHdTJ+1I{{})Bznlp0mRQV(rwPABi|JCyng#yM&51qp5zIvBKf2-r}PR*JX zm>i|iamv5_Z*~d4W2e&2ZX<~M0b9=$UQd67k1LfP`{P@VNxMy{>04gKHK4~F6O=ah z3w#w__-Id)x(daC-@bLY`t%v^-4%B#jx+n6xTZ7B;>2g2&9kEV5L)Ad#ADZg_kC*- zQ&GUpx0+zaQ!n34Fr{uqnYQ=8wIChRfY##6-jvQv={yUm z$)$hVH|@9|>HI<8uv3iv|A6!VuZU3Yltf5~dq@N;wkYjJ?SF*``+4u#@`Pl(36Zkowy1V{Y zBI7dl%$dXu#(oNfdb+;|q=bJ@c3hle<#Knm#>6=!1!8@xKD|3{l;7ZlvrTosjuVwJ zqs2Eedhs7Er5xKECT^bO3Cj=0BcsGjmMc>gI4`+gzDqi9E?Rtg@8U`oh)D2)X6YC) z@Pce2&P~8*Ut1o~;a~Uts@BefD4Z?P_HIosMDpU7F%i5;7A~Hdp`t++^BkD`{Sb9G zonN!HccYRBh=U%|oLYq;eX78`D@|Q|J-a`=Aicu!50tN+B74#BQ;>CNn0N&z6^bHw z>|Ps>ft#lnnI8DZV_CimO{HVLnQ93v>@RI_a}-LVDtA~6wM&n8RsGarep|;WWMFR& zq=`T#3;eReMpdq@KS;z)JfQL(Qm~Pzz4&zEX0-0ndF1OaP%l4{siM6iU%x%qvE`(t zLm!qOTRpr&5R^*pr_u@5GsX3O7BkZf6Nx?3Dm{;*?Tt&WfRux<`AG8I4uX*P9PhU5)x%kg#s`yq>dId68k;}rFZaxF5p7R8Av+%{CE2z;j1BoIYRf-fzXTg?4D(Qt;wIX@$! ztO%5Co?T%%9WTfvoaUAQlCYnON5+%eu7Yh}NzP!kbza;7-{+ zN2J@<-_M#C zjv>LEOVlwuLdQTaQ_&neEbwDy_`2m&f2^x)J)28pu;Dhzd=3QMLnBBbAbZ~ zVf{VpeHA6wGQeH~CLSSmu)v+t!75VNIx(~4`ZHcvoZ7aL;3^cz{?$`NAZkrlr8lL4 zl}H1q&}@0e3z`b%@*BJ?jq_)t3)<00sV}=!Eq(FDJpm%ZyF0+QFiS?2bCTZ?XU6wK zrJEztALM~_TPZO8oIKbPV@9KPxqA39L692OUCriPpO#HbU=Oa9%^M{hr_44cO`MCw8ZyZ4geE|LO60Yxu@O8X4SS^KrRm&5ef#QmxG$c192Y8jjJ$RME2e)!QjhyQ&12UZ4OFtUWu zl}U_;xNU9Clz?Non>w}V@oN%c&nx{DH-}XW{`J`Cn8u9wK=G>5F?(8A!34_a6h2t$Mb`+CmBLR)-6;1R& zq2R%<5I4AbiHY5Dt$m9LFjJvZuAj2S+)zGMU7MhOunsiXLVjWXhxB+K>A19P3x?ku zR(NT=SHM^=ydal2AAtfkCpwW5$^3mrC0lTv3UgC%t zndcC^Pn`t(3f!ZMjHz4*L#2z?QIORx; zJlsYuZ&*QAo2Z`?SVqkn&{CC$6<%Q2IrK7NP>s3D3=+{w31s1C%QgPx*V(VbMjih4n4YvdbEptbkHvJ=xKOV=O&%s zwVYGa?$#pYhdh&R$k2sc{p1brkPlgZzzKob`puvG4v_>;z}{#}C7^)Hp&jY*0jz~H zGTD+}m6*CXV(~0b@cG>q<#r>G#6RGIY93c8qe3wls zt%PG{;I=2T_%7^1Pbg^st^yQh%K*dhC|m``xl;Y$IND)iA}5iU#{Ez4gf0? zJ1?)ls=ay%`$W>Hg;KWiiZRbZpGwRSK_K)03?%IDN(kvgQ+n(QUqLtmWm}Q@EgZw< zgf}~t4GI?rL9hq3wjb=nG#kIXeIu6_H0na?9psOPN$=w9Au&MEVKRbhg_2Ex6z(k& zhfacE(}9T{2selHTF~}w(w=~!mgKtO#~|+lB4N#=pvuFLkWy#}Y{GXGa!~TnlvjjP3zt{(fqW3aU(c+KE*`PY`L$qkPuJ3Z2S-rd#f}#L zz*ZMKG-mCI7~+BK_gCt9a|V9D4if;H$%fG2Y=!SzBPSK{j&Kg?$c%VL+C_yiqvyL! zR>HvcX#Hwz7kT)SzV!9O2b;||%P1ZKI|(>fniaC?AyURQIKo!F#DyWV$1djFaOn;; zUDZ=|`st$^hjj+3@XbaUc|OQ_5{co!6Yz|Mw9dyFjT5TSS99R2b%yj{Pt%(#)ivt2 zdV9Kl1}D$7QTBo?LTO!o%Ew^8&6z~|NUl(1>?tHY9atm35zG>z&Fa#P$|67CM;TR; znk03tQk@r0y$imC;Ciw<8Qv~~o2e$SIaBuPj7-V8Et=wKt=XYZ-*iCdRR3u4L^7?5 zMCt`VDE0CC4hWk&0hzxLt1R)YkjODpMxpexLc6l?{o>NH4O?y&E^wbPb{Ms3U!ECaAW5tu&sMt?6b3Oi<1!AIV@O^yeNQ8$gBDwf{Bq(jXh zfE)Vr^w*Xa#-Ea1Yko-7Xz?NS0fzLAaJtqtI6tBkJg~)VWaN?(@l%=SV88E!AYF*= zMcc&tN~7PBPW~>1Jl#O>nbCm6j#-|xW;AWFT%UfS=<%!UV0Q${AD+pcGFDxiq;}PV z6GI7u1z-_?RY4#A4!sC>7Xz7TS@MYVjEj10?)=B0;@r)1(tmsb9*n>cbPT${V6DKR zat@2E>8?vew~V#1FK@`zdx=`zXGdJY77l$!W~CB@m$HZ+I4D1Nrs~my7uj_pv-uwk zVlJBMuc@zGvwNwpHrrR`hG)8tmO{7&D{J^v+BdQ2BquuVm5z&E#%@&`X1!cPgM+Ft zg|M(q20nNSm1rn~-Udmy`iX6>?;V3T+olh{ylV~1tm{p-17_U@IUP!=gP_kOp=f)=D5+^m z8q-}cP*bDE+s2)FYOX)7bMJLx&s4l78&#)hhdz%1v_ID2!?~Kjyp;D=Y8sEPeU7o^ z7K}!--TX7A;o>onEnZUk-cRNy7SzC|Ehm##iDOE3+Q=&7+Shi(dJl=!ToJ&Qxa7id zU@tmcMy|Ryz^VCS$_G`YBABNRj-ugkt#wJF1biT~_F*FWPA?x04N9Ml<3qH*)Y#LT2shyJv z{xJD-Y+sT!=>ZM;fu>)tQQKYzuH6SBa&*r`2RwAbdy!>ViaIapA9bTL0%Wo(T3wf+ z>cCWx#S`JbcdB(eQxJo&q(Tl-8bI@bYz7yOWvg9t`BKk#d_^=Q)k$p5uhZJm-d+i= z2qiy)yp~niE=zs-I|#ea4-ox{mHr>gC5%k{QMQ{-xbAzuF$mZ@qvdlsk(YyyA0P_hUVwR?qlG?@wijcG@f1QK&De0LF4b)Oycy~q#) z=l%`?Q}vHPYvGq6p|Hk~)@O2;)W;9dytA(>AF`V$O-=cTxpQ_vdF6YaSPu(H{b;k< z@;y3EWt?bnwtg`HtW3OPQ7?KVwJ%5UB1}AnQ_L-FfwY7#6o&%qvlM>)_Bys6{Pgd8 z=YcsRTsRXRF-PZ<DzCe_p^yTHfdqSQGB}C94q`!Uru!f~|f0mkjf*3I#A?4uZ>!Za!un>w8FI@Ar ze_x2^LV8ni8l3TzCrU^uQUL92^+7K0_6M)!cYhWSmyX-{RWU_e#uSLC=&_Gb9-{iY z8bPBu`};kI8O4s`Jy~veLwjwQ}6Z5 zG*bW>)%z;H1B-&XC>(qe;!-Bp>iEXgeU=4A{GgpEB)llcLTurG-3l{{H&?(j2x(Bp zE;NFWEXv53kYW2AMd}p_u{mkGoXu4BxGywk_=SRv+*>Bj>E##8TcLbCvkbQfU(=d0 z`Xm3Goo?Hl2!ZO1rS;IRNw|qyi;S(sAV)=R+o>CN zA^l4aE^+ke=M)m5|2u$o9lV2L@=n4jfHmh^ zEQZyg{C<=rb8bh5N6v=OAYt|}f&Ub50r+b`5+>&@(f}X4DB8qb40U4$s~a}Eb#${xS6Cwb3R%iBtymQvHc!g41; z5Nv-7m_qY)EaAc+Mya&_kpUkO*W#@YlRaI`6Q-IEuMG(uV6~@Hzw_r)c~~u7!RBv63`l$pWg_ z^wa@MEy!%!M3b4?^kiNmM3xR0dc!y>*h47b@L0LFJhpqK`WGFG8Xzx4P_b){Nzb_R zYePpS*u29!z~VGi8vf2Si?qwLdJ8q#vU4ZR^`q-66U0~TCho*T-CJVGBQFGbp@fZ0 zgJ=fl85Bnvk`91VeeAj48u4T4i*8bKWcdBT@cq%K)pGUr3#_Q!oEwuuLfxH4t^ zoeX>?=>F=|yaW zET|&G7b^_lL&>_#P1yr~#7zlVHGs~-`Q($6Z;}!P!Agr{zoobcPBixWgDABz%fmzc z6B10l^%iNsb&voEK?xCf>NiZbV6f@@lk!pBfF{M`JErYYLvoOwCzo=dVDK-bs9ArB ziViEC?}>-{PFrsd6@bGF$cxJ;8FXRx1#*uQv}CPS36P-jG&O#B+XnWZL@6Zt+qzCI z60m$IG7%VGN_-mXNzEx9l=4`QcI9@X!`aK*@3|d1jBi~R3KlTMq(VOK9A04X zJXnC+-?#67vuRhf)58UCokLDQL@I;;2LYAofq|03Jf9oi!;&%hTJGeJ@@ePAWsOl9 zK$R$F#!v>3lMK88xtZ+kLu8)ee$KCSqjlDx?ob7lnVP7~R5Ka~J*2p*fU9|6vqhGV zN?D&J7w;=#E3xAqWX2INV1DJGx0RKj%yb>TZbK6k1Fus6ItWKCRclrO36hyTDX;#! znVH3wEqiw&dcLawOm{VqTx#wd2y8QpNr zB=`JC@)sDNQF{Dwr9*D&fpgL&mB`Y`BnBS{Gj4-+>Xkz9jgL}m&uoLelkO5mPY4Fp zctT+e*5vU}bl9f|AnglGa>_gd>BJ!dhj219u?92GHmQF(Y8kX5*^SJx!z%?rEj>V9 z0?tp+0fwa`O+Ea$pqGg2%~Hs0f4hX+hmmgyP|;#WHYol$=u>tzO6>Oq5s;4giEH(q zH!D0$CM%ZZ@V)&Mc2`fQTU2_AR?I2%uttqLCy2PJh0tmVTOR6o{`T{E;uXk7sHE#Z zvK_(}c8Boa@IAB6lYwtOmkx|OB3QqCtVG-(8}m+oBVt$(B!wr( z3TZ8BA3zKF4|Jj91!Pw7WpV){09Ms|q$VH!u3SzGTMaViGg8Ch*^}wEx4yiLO!7b~ zX11FL*(W?~TjEi@xHQuV+O5#O+Jp53hr&&BP40kAyt)RYROjT&st17l@l6 zW*e9%%<42iY55;(a9#l9Rk`F}(4EYdpV4tb`zVJNA<1|CV}LOY)CLC^$R8$@P!|gG1wydxwQw71MozVe|sU|enoSd54c0k z2pw~V7)FJl=(K(McXj>ksPyU3h{M&J990DkjiVVuLl4 z^@r0zgp#HIJfKeScX&}W{;S%cEeB5(Ur7WoH)JZ_v7px}{>$58+_cD}3*O^y0_Bd;leueE&iYkxK$-pgRGAtBX(0|FkASJd0Xj4!aKM@i_Y?%od*u z(IHmWKo+Vfg74tcmU=y1>LVFGL|TJwuXkmhoc>A8dIq$CH&csPcqn_W$b#AG1yal2 zKB2V(v#MhXs>EMhhRvXo1E?LU2l7>9Xi}y`c(JGX?)wCz%P_?X9K__SP4~Sn}itfL6eMi~nvwi4}-y%q-gGD?|O$ zYDHgqUPbE`V(EK)>zCFDsVWv^`2_}+K}F=|8v7>FccS)^+V;UeY!iM{j8Z%T>zx8f zH-%K$#DOkoZ>)o(uRQi*^wm3V3l?+}+PzSrgNQjd6`Vx+BeL>yz7WulE}!ca(wtHJ zo?O1jn9)A`)ZqJd`ddPJjz0U`LBx@DjA*-`LP9pLi1Ac4*!!B~5lp-0hodh?t~u!e z(0OWFXWH+Xs#cn;Z~!>0kc^VPgqJ}_cCVRO@<1FIX}T@j&B zGa3H6Je5|BG5;gVaXxc-kIgd)aR5wgpqf6P^)tH;NC%Jij`>Dk*My%Gz6v|&mIE!Y zq#E4g3F+hrEUpDa2G9x_R~phCTsEM2XVjag*Hn--FK)lsE`=5ZNemz;>NbDf6SR=A zGv~s@4!wa3b#q=rWKRwqz(8DK7}TPa5G&bPP(Z=FfW_Dd;5;->O}`ULj#1SgMY#1E z8NCH+u1RJ1J`UI;yf99b>#MW{P=~sFh%kIcLA&HGa{qO3lML=itS}O@5Xf6Qptex_ANJH52W8`>9%_vf}Fe5^0@fw^) zA(ywHx)eJ;D*-(_CKV=)YU9<#3j?841M27_=Q_7A5P~)QtOMP&`$Ae&n!0;Uxp@YX zV}|PtU**7pmjvIiv)CX+zeL`!2`SZSkzFd;OarB|cpQ-abC@D5amS{Ym~6i0Du2CD za=;6^-Mkt@QX)SfT489r_z#e%oXe}-8%j7$B}|v#&N94tc`4Y7$9-5gds{ae)2KdO z1hgLu~X;{H!~2N#jP z*@Q+U2eF_-MfLh&Z_lV=C(XdIwdyoPZCec)BlkZmwc8P(F2i?bupsk-m9b7tRFZIf6@JcqYc~_INJf6!kGuVq8GrLXsE5=kP zv@_HhX_-G#Bih!E%z$o^fQiT@%Q&TAOyzv>j*ZeL$oj=99Wu=0T0YkAX`AYs;VO_lI+FrV9!%czoe8hd5KyFiy?dM?b+=hj7F{o(sy;>A3@B6~lg+aGj;G4f%$;Gi2ax?>l> zfU=$5J9^Xyt&Y-hv5}eP;P(d{0a|aCwBbrGG^ra!ReQIyKw#**uiKQ%m2{`5YuBrb z&3gc>?9M1gqbp=yJ;}A&PeoFHT|c(69#QFHhm9r>m$HktE{I)f9MB=ph!?9S+%kN4 z|EKoiN<_~ry%P)H2IQyl-c6RE`3id=Wp94(o382!Sid6h^?Nj?SN+#(ZVAi9tF2RwvE$fpS$gAqfgG9keSyBjbRdQbdm7H3I;+@)E@$+ zKIcZSo&en<9<7IpDQqAa2m7@O8>SP1Y5D7FHh^_}TaIN^~NA11l= zm$_tn+O(&LhUj+?(l=P57mO~UXmT6evkEK+im!dE15(RlZ<#QnQqH?JCrR(B-gn(d z9!cM|jLqs4JIwL4^?Ru~Ok~`^#y~{gLdHVz51fZoMfgMrr)Jt9GjTlQOKXx}yk56g z>L)m*6S#jxPgK?91GqDaGr!@33^R%muGuP7F4Jq$8gC|I9H+ow-JT!XRn6Lj_KMAY zM?dqczUX|YX0O;kwA!A^GaY1Au*c3%o=AUMA!xD;`3jZ^`)M&u7nzRv%W#C z*3A2UMEd~oO#lkk=kWms!ysO-Ru`{@uQUsl#~}4*nbrvWT$rlKE#~t}(;rl#fanac z0-6(4KJ=qeyaU1loNO+ya~mN83F3b=?HZps@VK=-u<`G)1d#Cy1%u{2k&Iu86HYCa z@tr7!3o%fNo2v5I8B+HIn8~vyy>?Q&s062`?hIsKg9|D%{FFaNnud4BUU9Q7 z;vfhSQVZ#>jav?i0eUb$PBjh`lB6!43v&_J!>I7R$6*#CQb4PO4s?hURY*N1V_6Ly z)@DM$NH0luZIm6m1syy%`?vFA_wGQU=oZ|_xj>OQdpPgmD}-rKJ1I`3J&e;pA^$?0 zZ%A$jjtL!1KlrP^FKtEm{GNb2L^!a0)`&@Ykv!rPIS;s}x8nvjI@ce}d{|ZMh6eC3|xGOHl%)yDqesGqylZ1&YFYh0OB@{CBEgXl2twuC88rD3qUm z2b6V!djBnWe+u}6{lK;={F2=>Z9os^=-b7$at%r^_U=@D(3aO?vtYUb8sli~J?Vfv zIsqa^tH}l?WUU0Y(gPTc?8I?{@cYlP9pHua6hRavg~5m6zYAten(#s#kbJ2Tmd=V?#lhvb5hko8^k$wdv z^8iKZ6)l`m;X(I1lr!;~TmVKBk_0Wpj}ZKzcxnMISHiYh79gD`!?w*(1>^nyEa}GX z36^>A&Gj$sOvTK7db-m%58qgT@wKdky*>wx8$$mUMz4&06{0Tl(T6`sWlyx5b7iJP z`&yTTlj*8^zdy6nR5HJH18 zjM4b&4CpuLF1;I%x^xj&Vmb7K<4Psf<5ho5+Jj#P-Uc&bB+p;bq@9&T#Q8u6QiG3n zk6<~e>$-~L4p+%HJR$h)#8DWyfffsD8QMcdThgDQb3M|spij|kV~hFz4Ymhml}n!v zsBEuQ*DaRLElsJ{-pM2)fIWhKJ;Fs(K)+Ksi4~>d=s25ΠB~m5a^rG`-YpiyxD( zf4&fJC-uD)W;HGkRr^7k+5i#l1@zScd4DvR)8HO2$7pwp>V8pmY74%H=Ga3_H|9kRIURnqypGiiE(2UnUb;Jes?;+IpW6okA}B8=s3x;p zA1l>&mWlG~pe^^DTljF}!M5eYo+zTWq`MlgyJm=ox`ZSczyLBTilCuRPKbktLfb%+ z%H@?bLucWskoGGr4oy5vTBpH=J@P09cZ}+(OyV@E-qRE&dO* zX+DeE0uRLs?AyHae^E_%=?sNS3$#+`os_qZ0qM>C6jtCv;8tVF$zveZL~t@OW z|LSAtC(^<9VH|k#oJkh@3R!ox8+Ro-SV&Df@ZX&e!Q6%66~rCAxcIl$JiRYH;aUnO z^**Zy%L)eY9_%#8;oe+e6hizBfwAfaCBb|t4116n8i=DFu*-O%quKNF_4@>IDPiGKO=XjHN;6U~A{$*zOJKW?P!iAL`&-=X_c<`Ifr)SfWGR zItQK9^H4EE%+zz9;-@TuN(%H0OcT`7v@`QYtNdov@1nbTY#g=R(^9lK-Sw7i9E?oD zOe5-KkA_;<59JfM4+XsmP7(lUL#KQWoc&1%G{D&OhXTXBW;H6bUz`V+z6)Xj9Dp7S zdBVh)rZc5AM2f~G2m8o28|xps<(+HTm)9lH|D9d+Ci&|OfgWY9?82? zIIh2D#`{Y*EQ(4gmv^pI4?iaedg15I41m5QVo{!g!Xc~7Tt8+O&!mBEKEK4^iJ8|; z&!xEY>}0o(XjZYQ8=m=-tKjQX1X;ETqcAXU+cwk6%ECQ*a8V&MmKT`rl{NibxRR!iJ zpUU=VG_BL=_(T<3nvEn0Th1ZR5z4I`GzhSr%QJT|3+gK6@`mffHH-49z=jKXp}6cx zM&42|KM_@MJx2vsYPkeJ0Fp!`b(>&#_%5bta1J^1rS9*&AfiUO3V{uOp=he$Q00+l z<4252e2k`wXA}!Epuf2mt~qdEr@*rJ*50k0#J0FmRr2)_@_S1QyN~d?_2+H*j2WE; zYC7@ST-^Crd;k>XoOG^&`OBIQ6RY;YJe@QLLA4lm&$dnpxBCY^3@f?)(J|peH}-uv>P*8;Xfb&;SOOPvWCJ>O2C#Nzd)5n@ zb`Reqm>J>{GWAOtgaRnAZ-LNbHL_q7W=rNo0RFo26vj(^c1^^lHEGqCS|`4*TmgK> zV?-aLOG1!0sMXK0HKLnwK) zYU+hwQY~h#cM$6qyDute!=O>p-@!rzjBs%Bi#>@!Ubr(KMu>JJ zj2I@af#TsQ)bmgURIho6P|_{AsI5Oh-azxS zCUs=Llw1S`xjamr@=wC6#7s1t4X2t9GYD+}dC@4xb8?r^&lLo>Qq#%MgmW$qFTL^ zVLT3^Lj|`mVrY2Wnkp=boOz+Gr5zjwGw`hw4QEG72OUs9*wQwL!Sp02_wJGFqn1>O z_jz{@sHjUo_;3~NI7=v*TaV_-hl8ybL0jW?Cy`6_*5lanu!-!WbMg0nQWF@_g{V>Z zps*5620R4suY=;DL*L9!dF{MfoV7sKLCUB?VSYOXJ;<7S2Li}ePN5xBk=`e8;rOBL zX+(M_t_KzYGiTb7rikMQqDLrl@>LpbY5r_-@A~=4Gw?`?8CL=Y>yW&Asf;8T2*)4-l!YP|_u^>!PO(tZFMIS_pnNkpddu4e{Ijl?eFD{18Z6;I+u= zb;-5rhA~;YtQpU*V)Meqlc-yV+J^gZX)AZn__{@>@#<3PlGm|p`mWc?axYJGd!P-T zTIHv3cUZIg#wYGnPCDp$$s>#{5^+@4hk*5L9JdY~_6%<`3WQSQOK{`9)WsKTw�a zL>)VHA?LLgB239n2C9CmkHfT+&7UbgW&Bm>9l(>yotfI>dIL^W#FvV%N+%PLO}}HZ zs?{Wgm`*+d{;_ehB9S9N4LTTzQ~JQfp63UA+;Qm=7;`{Fq}wjbX07K#WDN-fd}S4_ zH?U+9nkEf;Lk2NTUwU1Yy|<_EreGodUM6jLEoajc5Lqskz97kZ+Hu$i)FdI`AETiP zU3JRZdt%-BJO~Iw@G+GN13-{o=sG6V8&Kv^aCbJjd@{6g%B+*j+#6$h(rZiA5njO% zrWzdcBeLM!oZrEXqy0i!;BVnw^u!g*5j?$%;1krdp@t_bH{E&fr`>uH-G3U=_mIcw zlfLnB#bMgLr-(CF`2CA=Xng3V?1D%O|6E7iV!I=hlvIdwJ?(PUv6=C+RI6v1-M;1+ zvV%-)oY&A8^O3AJLl~xs#4xHKpg@zWUc~4n>^6!zoe?i*&33X(%Q+yO=cSsRII0ZN zm$Bt{LfWI1%3I?I<6&D;WiYgD3)D*?OkxZ_w`*dQU~GYjuh64qWYNTY)2>)`Q-2M# zuwjb1BN~P}7e7pnGUsNEMxz19L37b`RPv{Nn8rG3)K!`1(DprJ6XIN@^PHv8Bo7A= zbR7)EY0bI&9V!F}oN6gi=diQt(@fVDY$Eo|OquL*W}Yj$T{suP ztHF=7mtJBI6`D9u8q~-9paU=t^v1(dj2Zy&f{!3AnkJ!r0`R8h?C9^*vX57DsFKQ3 zkw07cD&-H8i@}3n?Om|;d3Zl`bOI%?9KUELTyvVCesBcc6##{LNv?6NieJzd8~)%{ z6!xN3yZ9ifs9Ut&&+dLIo}w)2;Pk7y{E&r3+59Vsv@i<3z5NXcO9h2VFP z!^e=pfr=353a1e7NY4{W0w3zM8{}U@k)YRsXb`v|_XSeOkA#1~f}m^D-chNveFcVD zALAa8&%@~B8*6kq*YZmb4P{bAAt(-dv8;VYjP^J$#VaSmv#-=t0oJ@5L}{@MdQZ9$ z-kpH(wYe^aIbZpzP7uRnw zU@z{U2@S4(J!q5^hB`FV?Qc>D6mH;d;hfc08FMX+&AC&1G9Y00dkZ~Ybdy^HR|~(& z3;b=1JzubIPT`XzelVCI>}!%+9sCw9`@-$UFZ+T@20^hvme22;6V*dg!*!V>1+sZ# zq#H(ufOqc=6Q_TjvOsi%pF$KD$l5Af8lWwR-Fb$O~Uq66x9Sr5J`NpLKZa_9yuy=V^HfDI|x33L4azSdzbjkfBPiRq%!J2PqUpRr>m K`2XUoNcta!`NkLk literal 0 HcmV?d00001