From 87296180eead0ccdd4e98547961b2b550067eef4 Mon Sep 17 00:00:00 2001 From: Timerix Date: Thu, 1 Aug 2024 20:47:26 +0300 Subject: [PATCH] SDL_Renderer backend and SDL_image texture loader --- README.md | 29 ++------- dependencies/imgui.project.config | 2 +- embedded_resources/tutel.png | Bin 0 -> 37786 bytes project.config | 4 +- src/GUI/MainWindow.cpp | 78 ++++++++++------------ src/GUI/MainWindow.hpp | 3 +- src/Resources/Resources.cpp | 31 ++++++--- src/Resources/Resources.hpp | 11 ++++ src/Resources/textures.cpp | 105 ++++++++++++++++++++++++++++++ src/Resources/textures.hpp | 47 +++++++++++++ src/main.cpp | 2 + 11 files changed, 231 insertions(+), 81 deletions(-) create mode 100644 embedded_resources/tutel.png create mode 100644 src/Resources/textures.cpp create mode 100644 src/Resources/textures.hpp diff --git a/README.md b/README.md index 100324b..2a0fd14 100644 --- a/README.md +++ b/README.md @@ -1,31 +1,16 @@ -# ougge +# OUGGE A game engine or something, idk. ## Installation -1. Clone the repository +1. Clone the repository. ```sh git clone --recurse-submodules https://timerix.ddns.net:3322/Timerix/ougge.git ``` -2. Install [cbuild](https://timerix.ddns.net:3322/Timerix/cbuild.git) -3. Install **SDL2** from package manager or compile it from source. - **If you are using msys, switch to mingw64 sh.** - ```sh - git clone https://github.com/libsdl-org/SDL.git - cd SDL - ./configure - make -j [number of cpu threads] - ``` - Then you can install it systemwide (on **Linux**): - ```sh - sudo make install - ``` - or copy to ./dependencies/precompiled/ (on **Windows**): - ```sh - mkdir -p ../ougge/dependencies/precompiled/ - cp ./build/.libs/SDL2.dll ../ougge/dependencies/precompiled/ - ``` - If it doesn't work, read [SDL/INSTALL.txt](https://github.com/libsdl-org/SDL/blob/SDL2/INSTALL.txt) and [SDL/docs/README.md](https://github.com/libsdl-org/SDL/blob/SDL2/docs/README.md). -4. Symlink SDL headers directory to `dependencies/include` +2. Install [cbuild](https://timerix.ddns.net:3322/Timerix/cbuild.git). +3. Install [SDL2](https://github.com/libsdl-org/SDL) and [SDL2_image](https://github.com/libsdl-org/SDL_image). + - On **Linux** install shared libraries from a package manager or compile them from source. + - On **Windows** download pre-built dll's from github releases and put them into `dependencies/precompiled/`. +4. Symlink SDL headers directory to `dependencies/include`. ```sh cd ../ougge ln -s SDL2_HEADERS_DIRECTORY_ABSOLUTE_PATH -T dependencies/include/SDL2 diff --git a/dependencies/imgui.project.config b/dependencies/imgui.project.config index 861ddfe..a767416 100644 --- a/dependencies/imgui.project.config +++ b/dependencies/imgui.project.config @@ -16,7 +16,7 @@ SRC_CPP="imgui.cpp imgui_tables.cpp imgui_widgets.cpp backends/imgui_impl_sdl2.cpp - backends/imgui_impl_opengl3.cpp" + backends/imgui_impl_sdlrenderer2.cpp" # Directory with dependency configs. # See cbuild/example_dependency_configs diff --git a/embedded_resources/tutel.png b/embedded_resources/tutel.png new file mode 100644 index 0000000000000000000000000000000000000000..b62d6365ebf4c53bb4d9b0876a68c88e474ecc73 GIT binary patch literal 37786 zcmeENWmjBHx150i1{mBSxVr_{puq|565Jtpu)!f%2<{ewySs)!aCZ;x?r`UMf5%;m z1$;Sux_9rcs;<3Hq^hzk8VWHA002Of`zWOb0Kmcig#&;QVSlc@W*z~61XDSw4;o%e z$1k3~2J`Nx7-Dug+@z$0n56Jf6X1f}ccw&;Zms=r@;0_WBlo%nG1@exwPqelLFx?=J?$#EkT6>F6NA5Q8LtA^>3lf+)-b z#R32BJSh&Nevtd4BL?puL-K_dl+TOMgaL_(nFwW67+CEPFY#l9Pr&ZqCj5~b2qs(w z8&h^EZMJrPWB`6wOBymrm>D1fY$B5gr3wBFpa(=l8RVnE-JGKl*&+h?H%}Sv?}=&a z3x5ZaV<83s1gE!p2nsI(wkz4Zvx6w$#4$sLh3^3Fo=<~kDkS3{f5HPM*2sD{`x?XF zmBLB+bMVc~dE?LWu$OY{KBU-&(eL&o?u8ETiu zqay#u-0hLpaXI?FJk_?#uTL#)LLsqFLQqxA)m2JZc>asWE_zlLMQ#?9ELQ3nj0jEU zMj-1O8XZ~bd>9)@GB5R@VworAkzydk=#aF_jyp=MqQy=HA`akAdP6amdC5hlNtWh) zs4j`Qk)G0#9{qX%f^b-;hj2?v&k-_hle4r~@E#(S?u`qHDrQaHgTC=r>V0caqf^SqK#B+eW{B?PdB+<1JN}6n@!Sx5T!N+OhNhLd z`o+zG6Tlpo85U!89nlXwR5eS;+wx=uzq=kDaJyDOr1C0JOz!8C3( zH*X&S7p4@FU~(+t;(K2*-IGT;I@(v2O;#p{(B`vn=0uxw7LlwE{$Jeblze>JzDZF* zLOxCFOc8={SJdYXUU}hGfw|GT5P#9gpz9MPXy6B`!!VxnYgd&xVb@wuYZV1qLzFx+ z#5q;%c~MqLI@q#7n<#>Uf((R^{DzJ>iV*G9#g@kt`)J|rbZsC9o5EDW4YzDQsN6dO z(y)CWA84F;K0JwMM^0w)*~^d-x89dW~Un%p}~ZX&$Gt=Z#Dn8{kwADNP*3t zUjiFE=U$Vw1;hZk%F&%1q5A+vX~;(X++)$W=gq6<%AQx=Z@x?vM1_Cf^8Pznm!aYS zx3?Gn_Ai443u;+Sp1iNbJ7s?TP$l64m%#Mx4 zq{0#-i!Tce0s}q_c5cdoy{?jf)Z+SxO)eO;;)y2_`kOZP1F(P~25BGVccjnb(;Wrt zN-}@PLBSvHeMMovvEcvr?Dca+X{l{-Y3Xyv@|xSZJ2aXPGkC{n z0VkpKu})oueFFFpi6s)$|E7y`=r?2-0X$xA_eUNVI$&_FPun#$W^Ej$B*nin z{)(z9K3~!GDm;9A|M{ISFM`}YPBeNBQIpLJ?lqfH6#t&ySs`*3wAYVZ4GbjzP+qG_Fc6P)&3^453UHU+A=sR>IqOi${rKLxNobkIm zz~LXXw|^l_@H3^*~SjKde25trmdNwNM@vhuXD=er2Dad8IY*} zArC#l`Y%6!Om3+>JFf1(Frp?2vrrL&lg9b^!@A#`DYNoPFK5aWyvVzPdn5 zn#HR+eJA2JEVK8~!h#kd*p!GCh5{UX7f&zO*>_Sy@+^Myhc`-MghZ}g4R_YPzlA#r z7~wXYF>MbGe}EZAm?;6>zkfP8*fYL(*;rU8oJ-y7Xckh}o698zeITMSO;1n=6CXr4 zIXNki)#RbC9M~6{9@Z!ZPNAMyb zbEXXg(Ar8-XY?Hm{oW;fPcgV->t0{w`ZjhL+xliX%FO99rV?@v4V^UgS*ogXpqMyB zjI77o_0;G#$rYI}c#LoTHNewjB&f0Dnc4N?K~Bm~Api$ED3o#g$Drp|^lvopPMn&% zHhrWEPvfdB3E1K!I5FdFLdNu`c{fJH4GVC7N#a7QDMFy12Wkg?O~rxq2pUNDiB2MA zv*1N@;_^RX{ckvo_Sd?Xib`7MXfdOX&Rr5cSDgE$#g|6J$FB*~_y9flS6ifZ(H0a2 z78Xi?vyYj=qU?P69bbr9d`C%yYkh6)k6yKp;xM8e>0HLBe_GNsXiHhY+6^NoNb>Sm zxAWLSY@wIO3X;X)M%g65BVk}n$N=;P;lj}|mfP8|Jy}Z^_DS+LHBA|(>eSMp$l>F{ z(6dg0LREqpRb*i6_Q$$@UEb}oUIA9ZM?oG)@6a}~VpFCV*2Wh`mQq&sy+gMAk%^D%n;ex`sKgKQ|Hk2pSjQ+W2UXbX zKc5Pn*}T>?djC#5yT&oy4+^b`Ct3kbh?~?XkVQ}cLfpCnOD{jKBMq0rv38i1WVzF_ zn)xX_LUSSCVHlZ883-u0kjvf3ZYqEHQ;Tx9*U;&*oqcqsCGIvdApUmk1ZPcB?DVCF zV}}k(VStZD!J*YKLlE#$U|_)3jMnF@*$jGjlF)+%lQz>oJL(KIlkSt(Z^OC^{%$mJ zsO0&-xkJ3xhtgI-#ig#@Ct7NU@|Z^SpapfkU2g?Vzs-!>lfE$@K`fN;?J0Lv7;7s2 zKEjv~TKgoiL)(c_rKf#k=-^7qW%5N1*zw2G11Gn6M(R_EqSJ?F{B4H_J9roo5`){a zKB-KO6}rPGui*Ztu@bmm6_ztQcku$>wABtDS2VC+90eKCdWXy+ZRjtsfR1qz7BMRz z%#aKz_;BB zQ2dbAC;+w3ti>_SU6*iERM7`mkAA^{p*}7ev;c;RVULz~hO@8d>SO7>@txH9aIm~X zCF>%u_i#wlQ`3CgLmMr8Q(2xKzRa0X22pV3b9(ip-`ZKDy?@`93mJmL4Ut2FpW;Ix zjv6joccLNvGgfrnBX6vM4U&cpG6rxL0@B zbm7KL3DGP8W(Wci+Qczy)p^H!LcOfuoR>#fAMKQ-4h)>v&!1lEUCa`{F)_d8*OXk7 z*IWLvCwbeL1l@KJ23BxieFb2~SZ5w6ZMktEGY_5P6FRph8sOlD41EKHeS)R1`X`&n zx8t;Z9E(DE1@%0ES5*se2r^tCw%(l9rd~_uE+yAY@}l5b4n_Qgm$wzJB)pbZhudyF z2Lme~mbH6d*C2>7f)F!gh!9OWoiMJe{b;1>%!?8iJ-n~>3k@8_i2HcJ&SCA=Y}1Ti z9Qf>Wb_eJa)y8ugZfi~y1^%oq#-vKSzwoa~PcBltkA;MyktpC^8r=60fxCx~y-jpx zr#Vc5VoXKA|G1Ii{iQ&)g3nlfYt_5c^70l#m!LSx^g|agL~E3a*tfs#{pRB@csniG6CPYE2+K9^g9ovNN~YC; zj?oH>^#%vF)C%uz;)N#Wpx3$*0dE4aRdcW^Vs-IAyQ{e?7GPkyX*v zIy}wJ&c^v3T-Poe3&1DD5M8MJCcL|xp*P%RwtSqyx}BrQ;UO&YZS#YVGQk$5ypx?7 zHLr5^N2-~WpuP|1c*Lq|I{G@@5H!6RPcB{a^nt4A*jRt|B>9-X#W3){9K2_adtg?I zQs{D6K2F2iR_PwBjv+NH_}IUf0*mXiq6hKxTydZ@8JtE%GqBjDT`?$U!g` zLAlNC?avNoW@hUObO~l$f-t$`%kgS-73i{kmW~G7fa@GN({WU@4eyl{t1WAja|uBk zXY;|ZKUUq_N#CK>9ID@(uN&^A)YyRx?99wQ!8YmZ+z@K~I0bqb>`9zPca8hzmK0uh zSx(<0#nDXEd2S}6WbrRWMB8Md)49AVqJ%O2f$x2mUGCo0Hq*X4Ex!EP;fW4`_|6~Q z&`E({E3{0To72)<{rB~M<6N^41pxT(vg2NGYjiFYsAq)jLPJ}mR-yJURA@EBF&_~;Bl%kK~_S1S=@_aHObk0A#C2N z`y^>g0%ikkJqPUf@|*|(t;>sxb+~zXZ(q#0Y=$EuVHB@uWkt`!8q-x%(s0~$!$SMK z$ZIywZARGo{r6vg2re$kf}1ua6Mh;69105B43a^yjdRa?2j;+GZc=D$A@R(+EGzB zV3c-HEVrK-n(znbBP~&=G~&B2F{-JOA!EOsPe*=!^TEP$XDG}J4h~lNfZhW;gK1{N z$=Ek9MP=!{4&`5a8{Ky73Eu{bV@OrvD3eCk^gMiU9S>NfO4c){l6xS8ba~}eq<9Qv z9Px@A`Jeo1o{T%ez&UZR37K;pI5TQugisW=I7m`B!jc-*X)dlD8OCjv^o+ zn8DsE^uNsG5|_&jd1qj76UO&m#AbOV)%{AQ`}}*T;kcBEzOG&$B$1t~=Au%f*?{|v zpDagW)Jvlqwt1Xr%xM8FaApO(%490^n%?c(N)aGRj2hOB?%|penexE{w>5QDRp-yv z*4AAS04zW+1V%l$#jNb@N1czx90h*7(Qn<}sBOlC!+OQ(MAmv+1EpwdBgEE-iV3Qx zDzXUjf7y3X{^3X+6ePjUapsvq&!!?hb3XIBrcQBmQs zp?zG*u%pe01BTiju8jGtx8Apzti(IO4tS9CPt+oF6r=)Qx zGrWR%Gq5FXwaX2*wXdARP&^S1B}$P&w?!iM)3@^_<{E{0ry|n;1Gf2Pmf^cAO=-zI z6CEnxe{cG9`2_rGr*K4&yFc%RAN>Y<*l3Y-^c%fAAW?3=xd8K(>CZ83Z;UJg6O+>W z#%5IwdkTDueltNQVMnU&#wq0BA{81FyWHY_sOiU#;)7^IpzRH2?$T>Hy*~G0LyI$E zfvs16-4ZPH(0s0H*c*q=H-b+}MGs#RroNmNrNwLJB!TxulEuf@bmpS-mkXSiS3?Cl zNK`=gDF5jsRn0w+-M~U|mLq&7(x<>EKO_l!*mm{GbAFRoK~a$<`P%6te%>yY8-Jxxuoa%?h$412Lbcr1FC?aDvnRbqz6 zytzT!NMovv`#gU1JM*GSF>cuEx*wNOF6%JSi^c_`6qG;%sF2^=(bhC#u}Id>BC*l) zpW~u!a8rn#n}5z!e;1Jnb9m>&Dq4^gPNdVm5)(uP5BSJvi@mu85h4?9ciS>RGuh-L#ii{n*pZZ|afJM_Eh z*;~@;r|T@mF|UA@r`OM^DVjGl(vLG2dF%XNyB|KnOf^LVEP!hitG>9AlMwLbc_I+g z=?F5h*@v!I`!l4iwY8;URK-l|12BP!W=n#@8^|xt0B3yV{Zl*woBD6G*VL}HnPeZe z-c`j2#jZly6;2cr&XWk1b2EMHc6jalq|<>s23(Y(E3bK$@(BE+GA))cv8=hq-YQRr zG|#p~u4*YNN?K1Np~{OdXeoO!q_p^bjlV0Uj`4+HIfUo27pEhmj7iqm?;lnq3?~OA z1%*C1IFRx?Q-r{r#e=(ec4E`!5^*~`K;9{L&IMl%IjcP{+N?>cMhTC0txTxpy-uAv zquMXIa@-GBqmUT73L-s8JG4G|PBl4-c=LWL@%Q;yL>5v5gf)aFg@k&>*huPFh*I5o zFPxeDKL+(0-~OVLmma;l8eqTz!c(HsqtkL=%J0njm;s_nNv$1Vk=6-pC^t5JjJo?* zLu2IQZOIo{k2tr!8{GBRWt6cDm-J~zW!xTSXkvs)P{FPr|56>6;p*+QK}jTj5!d&{ zzdFYWza{eGd|LJqn`>X&)+i&KDRnSZ`PMFvWtSmmM`y`V$s(H3;zAxUJ6r&0%<9a? zA%gD>CYFRJrtXXOiUuNnG&IJ<1R~x2!5j&?pqKBOM{B~%E$_`tk)6T$1K&gK0!x6N z+RLIT3Rgj@>YuCd#_?dF=~w*i7UNi$+U3SR`xWeb_wsw*m;^)@N}lu8;oNZj_0~VF zgbHApA`Y0DoK!wJ!8$#QqmZF3Y^<2~x3)X7l)P}zGsA=Tm;A8En_K0!c}0`-B5y_> z#~Fr5__FsNQG)owy7fzU|ATv@NI)NreQTWw)q#~iI}3u2+=d26;99`}i=V|m*=zu} zs^MPu4?Hq2Un)?@5Vu#4#2vR;E)m`F9AC>s;+YF`#G{`Rlf&Rur#5yLP4Mzrvrtin6S^!pu?nHc?_I1RmbQhx~d#%(i29L)Gf z{u4X&ar9hoPhe+$TwZtl?rlv}r%+C3n0Wew{+pAy(W>3s@<%!%eR93`#^nz%aFgyR z6{ebNh{#=P5P8?NLB>6!1VL(vf`0b@l+bU~=KC;)JMggpx*U(2&V*KDGe4Sy^%_5C zy{*OS%dZ0^=n0cXT-P_&?GYK^^05Xgt;`l46d_j1zoLB1nd(+gG@EzEB=}cReOj@A zlJLB-q|w{G4;n_AMCDFj@+?~P55eGhTKq|`TbTPW-T=drrge3&h(OPf{N$pa(0F-3 z3Ctgyp?(0scIu-Q{RZ0o5K(2}kIVR8&8Fmb_tk-K>odfjM2OyO%#Jm=1N08p$a_yL z?F)E)u&EFdHJYYR^PzM~z>}P@K>H|rekouPN|?_KTu8dW#0%VBZZcIwlnPu0seiT7wuCqpqBvfMd!OD3y}yYymZqf>@WLT+)Z=TYPpsAN?Vuxpln@eUPJ4kf!+kM zD3d!>PMx{YI3)SMiuMZz6xsi1LZJ@8BA)~>StK?7tN=SpKg6pYMM2w3l_##!4rMwc zM;5)`<=Mn{pv}Uh234U*_g;ZfKAT_I_wMqyB>U@*F`|XcH$XGzaw7r*A*g;>=Vnud z?bVR#k;n3Ov61lgfDklI6CGnMd}9q77sZzr{#!L}Z^N^yU2X4l9B7}by zoKJBO)20oPmbH97sX6YBx`cB0Sd+j4)>mDTCic{}rU6Q^T1rSy`anZuv}MM0Y+h(%dT3KmZ*sE|ImpOWx03Df1Z_;q6Sq9nAc`>!|vnoXO4m z7B}7$;C?c2*;Vi0Na~ct+@^&X3N^*lOA&JUL(&0&@A#v3t}Rr(i=P8g3p;KqmjX!*y#E?UYoZ@Lg(AC_B!bU{!CmcSWj~?0M>XtNqu7{gs#9Q2_E$6fqm9Q>K%kMrR>Wz4#Y4P^?!S|s<67UxwBl|v(5UrRAnSMBoV&C~%SdMnnRlcrzsF?n; zRjM{E&hz_&eRO*)`bDi0kxdmiv4~u*TPIU9c^t6OQLwBS{#fl$CkY8~j1J<0)?f{k z`LIHaCa6HQG$7br>YV_l= zj-Sh>B{d?O|HAfsG)@@1e#b^BPQV9L?Vu0EZk?KJoP4_QS+n#f2ob6eV;m5ZmH*Pd zl{GC_j6ul2q(%77WFa|PiMRdi5Ru;YF!LiFkr}neShhFS80;P!X&&@x*K@EU&bvN4 zj$Dqy&0`m#OxP&2v0*K`OImv7Jy#g8@vo?NS}}=fBxh`o$E`{h0gi|D|r|8}KVl6rU=o^OwRm6T*W5 zefdJC6GFru)dTssp8!d$#Q4{0w;cuJ_GzE}S^l7KEB~|g1FDsWUt9JvVLDhM0d8Ga zXzL{R7V@Q_F?HZXOQ95ATxpof%kMBJ?0w#4OHNwXXtQwpciu{4pxQ_^aW}>7!9c>X z?7yb96u_vImdW;+EVJ>9O0H@fGY4JBvLy{pw8oEkd0U!A~OU_>;$JK5vxw#}=XC%n_xqk^IO`U{8`C_28~m}1HUU-#=W=Jwj~4Hj-glNZEbBk3?`z;P;m-z2mN3-r-MgN z`{vQNvyz`|I8_0sGVn6tMC>Pul*IAw=_e803lRhH*@RSh!QND2z zpfxX5b90yDniRgrmXqQ7g%xMlZx$`3NKK|fa$lckweNEFa#`lE9s5=&b}*1*S6S6} zhIzv3h8XmAeBTN@wp_Y`o#PKgH$9GOSPh>dG|gMZPojmYB| z2hsJa`^nyR9$X(_wUsGk_hjP3&WwMluCd-C++bt6?jB;A{d$@~Ye5iU3KFgZ%QkfA?M)*wz=kSYl zEeUmPWg7ibH8M>P8GDMdy3qn-xtv9w|A{4c_LYu>+pPxNFU`YUFQ|_V#QC=#Se1JV zD1^PW)8bnkdvk`?eA2C|qivViQ{!(I3mYsRlatDY8Fx}aSfq7Wakf9p-R2&45RIar zR&HNYs%~@he)E)3;Q&Yw(Xs^w%E(szH_8pr+6BBljjfg&0VhH-!(y)`bM&lH8I+W7 z-Z6b2ik-MHqkcJ|4#tb$Uf>g2TYK~zsS}dbnig7mu7ro%N5?E2OmqzV=H9b6w860? zNYOXd3}+`G;p6O6*O9q-;=k_Lk1qy8TWA1{4o5$K=;_@xdh&^8D;_d&zM}qNt|--X zZUyIEO&$6)GO#G~k#Z?XcunA|=nqERtv3n^-M!LxWMMWuB-m6xOX?lIZm+A;_LvIVryH+sYBe;lpnj(n?2<5`_jaOnrF4r^W3xw z($40;1c0^E-L(Gc6+y>QaNr;NsFa8c0welOO&&$p#_vgrTjg{3Q zGn-XB9(wo=a7PdDyqMEaihA+SSbP3!qcxfw54Pjqd}4%QxG+Q-?C;FJp@_tK1~7w+ z+Em}X%~>*xO{dt&W9QKUGeRCMoK#5$XZ-FaRJvnV4Pd{z^r4e!zHQzk@hzcIH@b_% z<~d3V^e@;`TlWOo^*1o^yZdTmWAD+(1m5phu7{*5nyrJw*qzsR>nJ9<^{}bAx!j8> z-zG=P<5I}NnH=$ot+sZSv^WHx(Kr4kBl0)ZqoP27pnU@m(y}#4m_?xyi+h>)(;~0U zOc>4aUrCi=-^H4!Xh0ME?KyIX|y-2dO*N3nu^n4gMS5U<)EC9f=kKa(hupHD~67vH)z~vzB?gaHOT&KN> z<$tXs!)w_ljoE>x z%QH=A9>Ysf{Fq;}bqFaaJb1&IDK+*wfIB+!ExEG5Bo#EB8&#FSyKvy3MU=7@rKa7; zot=p@OkuDH=bfL$X(t}1?^D74!Z$4cW>Z9{_04o~JAjU8=t4|==)y4yXWgtY%Gsjy z0|Az*s`bVkAMUO%8-sL-RSv&PnfguV%q)TcN~#idySrWZ<39OjRbPCqSo}oScjViX zM(5Ldjmlvp`>4sAt9V@n%=T8@iH7J_Q@}v8sYfeVnZD;h&Dk5wmJ&3b#3pv)To}`4 ziVaD6CE}V|-kv3)iF?a$G2l%bXk+Uz3XVoa%y8LqhJzX7+*H+RfrZ-@fv&=iic)cB zf>^$;^Yg)KcDUW;@5bC-rJ-*>O?GwC*#8U`z{z+H z*-Z0d?PLk5fc%VUO@O&p&B7>T>^&!+U{3T(cD*UzC~|@F#>IExxUPlKHM3S+o^b`f z3rng24sg`+3L!+7s07w3^q*eTtbliPQf>->+gu|q^_os*^}5~+4@MP5`R)$H+=r+t zO&qM=pKetx;0u|T;c^W<>XR;9xS{l!VgXxtm~b}t(unB{AT4bjpg8TGBkqkGMz3}o zvok`BKM5bU+rB>D8J~F`U0??G`xaetKzTBJy>3&|A`dy>tBxZ-PiG+r#K2Ws&hQbu zo`|n+Yy;F#UpTEqke!wGh#x1OW{sQuvOT$mTe`m6jN=rS@HwAG%P`Sy$G64cfyv|) zeO#>&^^#j^TKmFxE!f_(yBBm0#Yi_OCq60R;**?v;k_HXUVM`F%%(Ji)LFb!l=zSr zSXZP@B!Chj&9g!ln!kb%rlMj&3B7h1_xl>Kj*8kgVy%_aKUd-Z^@s$=fhTaOYO&Gl zO~ON!X;t~&t*SGXkamO>2tb7SPYi54Y;*B@WnA;2i$%E$Fi~Y@Z@$~YE7ff>DB+jD z%)0f3N1KR&`Kny>uKh{@bQi>ip4b4NHl}QHrGHx3UHkjZT=)1#A&ogsN=EgChq@!e zzlg|xHEFtFqCdX49w&Ak&aGT#O!gTrCQi7C%a$Md#ns)RV%T67=RL-ZwYL`6@HOcW zzQHMc%it~S(4-?JWaM#OJ8H@ADKfnPEr)YUd&4ZDtX}Z|$MK_jOHjJ}TmSBlAaN^` zo~5F4Fm!AT@WP?DYvdXA=ESO?)xhC%ThO=$>t>R)AA0BO@k{bK#J8}0O3ERa+bn2n zHYLBsr~s5(+88O;_&pe)iwzJD*SvS((CdF9u$=wQQEgusS^K5MK`_IdNnoCfb}x31iHlJb_8SlSWDSTf>tR5+xyMW2>`{XA zGIuj>8aNI~AONPrljDHJm}ka=;iF6w_PM1p=qYt#bNRLSD8J-%I+qe^ z3ZU>$p9Nlo^|({R0*YSyReL0c5e65=2=^fq6AKYmtE@X+%xhiW*{u<^oWA=)+v&%B zmQl6UmiMJ>q%E0-;$oKg@f80FqNr-(fPLNaW)TKc0Si;epyb9*B=HK^)QyzB!0WWh zT>@)KfZfq!XOUCmavre)m+d^&Upn}xZR4;HsyI1Xx1|UNd2BY^pH!u=ZSg}O z6(z|#j?E%z$TT^yvOi0Dn;#_ug08R$=voRnQm#txG}k-uos-?O{qRu6Vd3~QPw$HkjsegrNl6F751#EC#; zRePcrephHzChp!vt3uPR%<$uMDQKTV4#b*n8_15mMY+u8wX_PT)Mfzao4_y=Q2J)%p`X+?LBgl*;e(-h@xr zIdwfFHq@T8Z35?C;NspwHl4Bck_BAOmVI?vdyyT?jB-S{inu*xVHfj5xvhp2oP8k& zO2L7TwA0(07g(isN-Q>>pBLo`XGswd$2Z2JPB$?-yHEh0h2uN*;M!Y4z@x3(ys z9#-hKfjUz%^} zzN-FxS{Fx;6OKV=(P z>@0w6S&?I`B{7|g&3AMN(F;lCa*OK=1{%I#Y3y&M-yD@X8rSsrw3$v}_fe2@*HyS! zp2g-B-3g05zkFWb2!%(ISefM+hTB+w>(FFvt0)vonzFMRhFL_9<4gBbVvxMIauM3T zfQorIsAoqP*t2~SRU|GJ0o!FDAiy2uqxW*; zVFF791i*5>(~mMuzZBo4lIrex;k+ixdT0HVyDp#)AokYwygNpL z-rl;weLng!-1IP7(N$}zeh{vEb@G>@$bpm7n6hT@eIya#Vw>y6nez3*+g?(Kq?Wd} z^VFHQj7xHbzR>F)G`9vpD!HQKzUQCD;fwT^l-U;Lz7ueVr^_ZBJW7Z1;E!@*Nc2Xg` zg={5={NaqOd@hetUj|}>)Ve<|$Vf&pd+IZM8a`0B>QdJ{AUr;bvV0-%@Ic&ueIlJ% zvP@cgY1~!my7G(aGSc6BfI7I~a4Y&9cxACY1>%3Euf=LD3_2(v2Op8V!GM4k!N0dl@vxm|aW;nY3kuE=f zaGLG!OvjaYiL)A-Imb(Jtlei*c5c;8ZGNJegLjywmRL!YBrkiGbb$2a2tevEgS2xi z?&J6`%VQdtMFDH?g!TGX-XhHsGDy#Fzr@KDEaLp{?#Y&yFGm(2q-I^ zyTY$%abDS1v80J4lFChBeIhk0l}d%{>nn#$qgsal5$^2!dco6@zHqVIwC+G2lE1H0jV&5> z*~w9bJj~PYMIX-t(wH0Vk1}V*VSQ)!FDHLjvkZ`Bj_mJ)iGv?-XEDi;Dt}Ad?%`>9*^kI?vts%AzqaqzE2V)f@;A4u*c+1JPIFxYZo|HS zP;j-W{o>MP41Mjo!T;MW0q^U@-n{=2nv>!4Pm8Oii)B|LUD1(|Uve2wPcMsj z0NA%W&Fx-gV_)vqIl$|0y9{CBH|0to%Z-IRSn15d5jUEW%I!rsh?~Abmx!8b<3P56 z|Niiqp;%p23T9|xTGm>dgF`M#aszkDM2OOGE>Z{5)-ries5p|fG*a)buNB`2bL+Up zVfOpribc};O?UcufS27-S!0ZGorBh(?{%jAsC#x6Qc2y_Zj}ftu-e@Y>ES5q(4M3$ z{`a{UxASd%C_(nO(N<5GyK=HlGW=Fe10UHuP$2d$V>Tkx6mI=>>b$*~c#v3U$?+pt z(5j7PSNgqNvw;Rlv7@tP|02H!hi4XCgC&dM!Sd4DnkZTyhW#RT?iQK_LMRVjz_W_+ zsu%dzqZ`w2(J`a$Xq|%M0Hqi+u1`@mtZgu$)M@H`b}alpyHH|-?f;y$5|W+`!1;%O@kjl?Z}S$& z{)_I&$c)R`nRdLa(}#CY*0aBU@agNa;0;3z_M0Z^_&g8eaI5!1rLukKqxZ5Sc4>@z zIH2_Y_<;_lV|@@1K8dp&ZL5u`{&&IdUOd<}2W^zQYq$!`f2$|#`9~4*r{b>hS<4xF zeQE8W=nzd|l=dd@&i8ma(2s;yQ`lVJAZ5t)HRE(RBtE4rPA8!Rh2LU&ZV_37hlM98 ze{_+Tja`^%_yDAZve3nc{&%`X*; zAK+PsSGYZty@XM|myrNRAbqW z(sUbADU7&KOPjSpu$kZH|B`T&t?Q%z;K5utzl6V6YLH(0rCO@%91;G3^1rq<}QT@}` zS&KM->!U4tb-B*fzge3|fK)n{yVD*5CT7WmI!g5y1QC&wdPnsK!$sjYdcYryqHb@O zrU;G+r@fsEOQzrZVi`~H_vSyagwuO{^IDaAw55I|@`m!{OLHL4^T}Hq2wz%E;-@zwA*B zqxL$S2<;Y=R2?S^mo9C(&HhPqqYwl+pc%E`8FprB;3QUzRFJD<@ziDu&61YT-k%0> z#N@^_FB@5=qRFICTFMY_QUsl2nX~x*=*I*Oc(XoU#4&w_vJtrpwkwA-6ko@yj#J{% z=K+mxR~5`C%)zl};os16-tCV)V?moLg5?wXG#h`9ES3?ua7sHRbT!okdB+ zIK%<3r}pA%NxJA{Xa$g33n-2b6YrLv{#ia;HMuG5LMtHReRbihfAnngm)rTnI5S@? zkxuPO;>0b@5E3QRKX2UJSp?TGi8vqxZGjMNS>OS(Nf}dvH8z~3Ow`RsCiwV~gD~}Z zT=6EQ{jHDn=tP(BNhjpWa;sGY8>#c*YU*kXJTt@GEJAZ}kkLxE9SSwi3?Y#Qz6%jQ z8YuuA96~QLX=1Q}MPE;Rqaj?-f*t8Xq5R2Hxw!L07JZs6>YV{S5!91_tKW&%mWjz_ z?a=_t9hIB+h`XyV-f$D`{ohG|LEkB@N?mH0sap(R{22SqJd{Oc*Grz;E`H(yOJ)La zAJ}vf(B4#Z0r$Ql_QbXi_P!KF373{8!_NQOP;_mUfDh1b1buAN|Hi71 zWVwBXi@Vc<27qf9m9RjS%^L|sS#m`2mSlOET2Z{tRCO+;)q$Hh{hh!kPwh?& zlN&?=w@$hy&WZM!G=jZPuYVuxXhcLMEE=SMwUtyMp;!nL(aD9UX+B#h;N1U?gCJ+UJ^Ciy#yhDO?L;Is zSY(+ZDwB6kBZf*nf#8$^I8Rh{esNrweV8!tPrCSou8&AN-@4AU`LMd^j z;K*KVYOB3vDRH|D9E%;9S2}vEYOfX?BV$Kb-1qPm!&z5?5CgqRRf?TJr)r|B=-ry? z>WTEp_K~c3=0N(`eyg4PcrbsxSeOQvVZhG5om_P6ziJgoV9)i(K+aZA!L_$U5R@I4 zb~<-=k!iw-u)Fl8G83)R0qEpk#D3PHml9Ro+Lu-5LIw9t9@my+)Z5`*+Vm%YgJkpA zSFDf{RW-}pX185*t$llx3!U4JxI7?gQE+5bK$BYZi_Z^%k6p;8E(fRMrJ*HcX<(BChSi4Cc<3W=ozIgNj`ATR;^!Z+3pN+U5GkY! z;zYjOJH1`9TQShkT`BdL(2M_@PLJYFpq{tjOiT!06|CuKnB|HI8GYO@|F4&I ze$gjT`)=%12~^lkM`FC->fc;dME|}ZK4YdfN=gFcoRq(4_zRTVIv2>-J}YFmqmz-s z@BG$=n#(g@BCVlix-ojjl&V?N4{5*h3q?JAp4S#Y`4wRWBerDdwu)86^g^n zTFUK0%P~C!Euq;?IvsSMZ?l1G%Z?e}fbU!Yr#3_JQFN{n>Bd}+KoRx|oB( zgqKT6uhr|XcTp*YQDY-te;Z-KD=9G9baq1RHX%`|5zVU%#D_ZC& z8Tj@<0?S;{+*}%$ll%xv&b3}hnhh?L2-YkQ!5BUEb$oAc_I5g$c-vHf^y4F4Evz#g zEURByQKeY8dZr}(+x%o_^^VnFD8h00hK3WZcR)y(fsNDo+623V=2txyPN5Il43FS> zyh_r>E#LiaPB;pz=V8U8i9j-#xJX5Z`*4PjGI?pf^?XQ-G1Lc0@`n6QS;8vA-1FT(0B6qGd%yLpwI^>5w0U}$A8w9PpJo_- z_spenq}r5!sxZg>d`|lOD}0{$F5p-tfNaf!Nw;h8bEKE`zA1EFL)K);0{*>o zG675;f_J9MM*DJZ`_2N|aa{b{aRSQNU!T1zyz@p6rG5In&=5iw{=<+UHbWSQYSAGw zC~Sk*O>UD57Vp;L2FG9DQ^U&;tN*HRN9W7CUU{Rh+K?W2_tBfgytV@`t8cwwxu$5@ zHKjglnMNuLog*-cgUdhbqH~_VmbGp~@>Jt!B^Nr~z%r1OBsze8xB2E)i(%`V!utaw zS(ytgQ_iZG`dJbfjUU}4;6y=}Oy7Z6CSvZogAOm?Kzj}KR5b$5{1&vjhG4B3oO>3S zqsNvu>;hr`!L4OtE5oWx{c5HJUgf#^O-&AwI0ugc-tkkQrRJ7cFaqrO`uN@U@($rt zek~s5yctNHq@bct>f2y&30p2OFX5EevI_F0R7N;)_S_|reBFQ9|BBt{SXwt%_6t&3 z0Vov>gdn9=jsPi;VgFIqnV^JF7Wxi2vYCl?7!hwz<1CK)ZZN)bA(2e2k#>C3GX6S? z>}WH@%Vszw{@4z@{Vf9~Mo`}lgVckQ0P|F!V|KM)AU%~~Tez!va^K^c*ilPAhHOci zpperHUs(~@P!@A#a%c|h+&Ui*fq7$&h7EO@;HAF)FN%@ZW>BN{D9n&XA!>8FT?CW;*wX6%v2i-2u`(=sq{QQw4A@Ofn5WYFB zkcVMTFoO88rpPiPnzR9Bn#=E5f|?)=LR)nv-m6V4q~&hr zUWCB1APYEWPGCq@wpMt|W|B|r`usQOMuKu;RX-LmgdnT?)QQ1?(>c{1rNC$E|B(=Y zNac~&9qGU1Dv>HWCCu1-ienZ$M1z3 zXnWBKd5NUCX_=aw%Z+Pi_*6}Qp15etBK+qBciuYehW#`9Fl_LjVFK>B#riFn^X~~C z7A;~Q3A@FT;LH|ti?yC9+acE-<2OZuy-`qrH)UJ$ z>%|P4a;Kd%OQrztlu#nUuPI&FsE+@PIdA6v=LXONuJJA>kQcP;8`zaG2NXF%5?cw# z_u9R0rAJ0m=i*is4&xFLz_P5xU&y0{b_baixWqCaHupkzHV6zTVS`MPg8$5Axk zlrr{k(iZP3a_$p>`rU+Tf;B=f{c+g39bbP+>YNF?=ot%i-t#!1RJ-SB6FbB)Ep0{2;W*T)DBjMK{eBYC2GpD~dMxvb`8dW_+ zoH*hq1msylHrvTtu4C2hlaV1ZyPhY0-yj;oV~XgG2KOK53nOxIB-i=bE*pSnhXsPZ z0!l+PL9RcZ@l4OU2gM|T>_0C1Qs{wwVR+$#5OMP!wt<$yhMdF;rlKOfm~mk~%9JQrp*3DhGiCj35nw-Gnfi1!URDIx zZ7IPhF4ZqxV$Fm%y3qz-iqlLSDS$J8*E%sAkb8XXnJU}=@r}mVoK$VkB>Sj|-}D#Q zSa4nAJ?oH?_nbqPv^Srw$M3Z@Ns6xvyuJUA*F82=*@>ti<&t_K<}Rg4C)v@Q4=Kuc z3X%K?UFid7hr7$|yb0F<>4e6kbaGPGjnO|u-2WT~?OKQBzwDza^xdw1bti!<;_}2U zN~z`Ya(+?G3SJbz`IDWyolW|RZo7}+8uS{Q-~UthL$uk_-|E75`5nnToGcbihgwup zVpHCavn;-erDg`0^RJK%bC&%RQ8#7y%LE#uqZj?y0kP4L>-Ii!1emYErkGw3ldHfd z3yB(Dq}?KpKRG%UVa*G0`$MAAW~^` zP7KJ#Yz5FYR93yK9E}!(F76Lub#HM+d7Zz$-!1ZUy();5sqc!48(q!VRB$$g=)#;U zeN6SSD}&+Z)2J6$XUG89LP}o4J>vqfeGGX4VqiEO68}G&K$jj&mK5Arp1cQZ%&q63 ze(&G5S~>eM9zPKf*_y2urNNc`$hog;B-BC+!*X@89_j z2Mk5rtZZ0ibUmk*tlwiGf-+0{fFZY7se4mtM)lW@OARAcnlxm@%B5;7L_~t4+T_6L zvV7maWR#c(W{%9)YJowbJID82m0(LMIZzZ7NF{zh8&LfDktC_r);r!07l{jfBJg%q z;g0iP%NW9fUnIp32NL!s*jgwtl8&{css(gLk72&{XAB02VXEpcKRgUFjbI;<(iWJ& zkCn%Fe9YSe1ww^*6h8&;_h9igX0uyjr-yRk_83sNe(vw54?8cwiL`%)jJdlS@kN-jZ{?rkYvu&~`;jtb zO#`Pr3GyB&584hbMfbBgvS@yEDX-eA_hTkCj%Hj|MNL}xh;>()9*+V&(?MJUyutE4 z0DJv6Cf@wzRDyKqSqEVP+D{lxzuxnz^3z1yB{NFJ%ATxsnx&ziBp#P*u$J-F-49cj&S(3Ey=}%wTF7trSESQpsfVKU!MLKwP_}hDHI95y7VZu-*=Kp*tiDb<0R_4N*_hLoZ z*m6?RwO_S+$<6;*8k;y2uDj5P+1bjW4bYKKOA3b=opXe!3}n|p7l9;IsD?Af&g!%C zaEmzle+q&%UUyv){6Lc|M{vtiY>?-XMqbdP*%Z-Bv4lAn8V8%HxDDyAL?73k;U=nFdf zLm4ytiu_<>3Z+8-a7@3DkvA!h*VNkrx%Ru23pz$9fg(O|2zWG3tN@M%J*Rhs)&uvv zNYTjjc-<}L_5B5pIOoR!)7KjLv8bV$6o}t`Vkjw0*_9kU`{M#87$+{C{T^n@qq<_w zLHYOg$U#rcBr`!%W6CJJHrp%1h4-;rI6E1VaXoc&WG}q`7^0zt_~C-x{mhd_b#Hkp zJ=|$T`*(Acc|Lo@AF$IK;?_B*5}JRLG$GiXfh|`Ub6bNy{>cSos^$vg+Pp}XMVK}{ z9-5!-5@2^-_Y(yvy=Fq3e~*f-)maD`#}{q6G@KCtGNxspLqnuXGCrUBsQL0ilA?z* zF!St>z^ptGQp9|kyO7aM(PCwOD*n}D++X;YyO#z6FtB8)y3de9&?Ha)j@4N$w=@1dW&Gs zBmelQCS>waIRq-4>-y=h89oFy%=O=KR?cAS@moUxZxD?+erv)}YRy}7lFjD!wPKFUa2v#18_lOU6hzgE&h)_mgPAI;hhP#kT z!ljXuYbP}P3vU*B6X9B{s~_42-e;>Nm(RQZEg{)882!}Dt`G!4=Z~Mt5ts)IJ5;?~ zl$l6TA<+egB`iYDaaUqOM2e=>62(^)Drd@M$y(bn&#d z&@*E<+NQQooyoZXLNL>61XSj)CB^E~E99V+00{Me(auzvCFv_(^jN|U6hKIVi;#|j zX;M@B6fV^DvX3VQOF@h1U&+3gA4Jc8G$teeN?EtN2dzUVpzjZZU5*82F{N3AO&NT5 z@Yw(RArcK_uIyK$%-lc~$e-}iPG7(FWZ|FC#O`Ie4?eFzvt8Uie{o%s%*PI^yy$xN zB~DTIx_IgoE8SImU;dEhU(A2ebVs=TY=BYS#n+!Oyt~l( zBw|o43qA2WTLNWk_YC1smz4np0>Dd{mhlQ`Fi8x4RW>Pua*Iw31hZK0aSK{NB zmtXowMFdDDR@``0`<}n^zF8l+7%n0o#$j@86HHFAEAB6-u}LAZCaV8%klS!ThhjpA z_E{nHXzZsgkNv2L!3tLKeUAA=Vm3(6kB0hj1E24$o6QY>^c+RD6E`p=>X#)Sz5LSo zM#Th`IfkecXb#<=vTY_Y0W%nqy8se?kr@`y%X14X9pBE7}`rDDB6>1I!5zc6qztM13NvdfMW&AVJ zv-LY?F)|eQy)`DLv3!)7oGq;dO*beu?Z5JIR$|1*Lf>}3kMrC7({2L}lIXIv**57m zh{Ab+-BSi#g05Apv!&e1+wP6^kpNLw#pcoY^E2Ic+6JDSLWyP)SL{;~Vug+f*-aKC zZo7n}K6_n^th(E&5tZWn4RpNnV5PvbiVpNbDdhI~C{34Q?BL%wE~M@&3Y70ZcrPIk zGIhPJ$@y1%Y?}9#k}T5S1`!r{#;@@zgXI_AY>yK_nZ#6$X za65K2bJ@~rm3kAM;r&QX6?v-5*^o8Ru@c30_}(U=Td-9 zS8R97XuY8!l?5qtCkCih2FGV_e6QlYEa|51J5mbt(V37s`NS;o{50t5m%4sF?f&M? z!k`#*Jm1`>BsxJ9efH(Aox+m}!*6mwFS(kX1jNh0unFI#)UHRLGgb7?VSLioiTP>k zfnUekc1F9ShJ~jMPVXN7nlGRHJJ?XpnZuL1Fn1j>Ak+e5vxh}bVgBOJyq}-e`_?#_ zM)J;+fENC=dDhPiZ{VZc#J{3~AoQM=I!xt%(FVkREED(Z8+9d-Id>;Q*66Q^CoMi}25sB)8xKH5yHn4mu}$rm7{P zv2!0Yycqf1-(}~dqh-Yu%0aS20IWJAYW9(1KfKbG8A45Mg{6(07!@qXmQI@8>wQ34 z&5={Thk!Pp(;TJ~<94NwI4v#^Ly|`-zctFxkedaz=JlLWW>a+xw8TrVyxnt}Ytj}f zDoUI6KY|HbB7i)8Q$WNXZ)8M_7=UiedO$Z$(Cq`d&Qf+g1r{m%1ptJeSGIJ`-nGAP zdzj>IP+vl7nT;^`U~ci^L`IB&{-4{3j`kEn*yuFbfd>=(>~LtNF@UtX6JM6k;!qyI ze*i9bar1ZokSO}jzw)?)87u!&Bu>Sm*$%$U_h;zmcab9|+nCiWnzw$tlHF#hp#MPH z^}uQpd3kh2oKiE})|h=cp2?SUj-IE$c2f1xtNi**CR*>mL$vQ9!6D631#s0jmeW~e zKn0++m6@xcnZ<&#KJzzZoY7r0LtVYiJvY9ndJvd-vP>bT0OEm?02XS@bZPzdgQ2hS z68Grw9n^Z(xW0*4VjfGU)n{ja#`?wWe@Ft^UsSX6AWFZ^Q$^}#!^H>XNAji9JMY?C zVw|QR7ffJyuIBeSYr>xq>SU&s8;#@qRzWS4euKnFU_>~!8oK?dO!mi8HZwuMC;|5n zV2zQr;!TEzqYn(06Ba)=GsK~j#Ea0ID7T$k;UB7(;l`S_m4DG_rI(WmNWqBBXy0+2 zThHppe6n)gyWB+;0qsGsp~4%~4Ta^yY2(WcnzFMK&|wwti_mcIT_g#y%X+lW;smnn zLtHlcTlp*jHvU`f=&k^eM?>TE94;Ks10+{{Qj%L9&irrPXo(kqp+s`>mUuFbrVgEa z2yxpiDj=$huP^%|RFffnmzU_eWpT_4}88I?d_tRTmKp? zSSTq^8~mnM2L6k(d7PEOwsgoj95PSjBxfDdvB17KoYE(yP{Rl==TNT@4Cqp)`DrIM2)yV%lhR~svI7SIt=Wry9j%?v6q}SE7YuH{M)Z}tL zRQ>$t>jq{Hl4j$K+OM#k&qA-V&;OZScTxeJ(ck5Y^g=fu@d0E$L1X*p!pT6Xy+K@r z4fE!|E|~^)uf8UsY67FMLYDT$L}-=687zDS-2ds zD&sk3191P&-*Q43+u{BvbiMQgfYL}M`(E)G*fXdogJAt@WAQo*P}vmnaq|1lhbN{o zMo@^f>zhAHbwj(L!1w8EX#}JoVoooMhc_e<{Q|zXOn@5mb(!B=K-#J*cO5i+*ptR*9s7@>A%)m(y$FK&+;-azJQ*sLl*j$Fx~i-(M9~yQ(oWK)(O*1Og})qyVAPM_o@qHwITs;$9CNFBjTt zwi%dYe+U9xCja`b-uG6zu)rpDl&8w78)@Fg?)+nQ?C1|&+uRO!;x4p|^HvQ-XxTt^ z307{#RIfEYH3Hy;mHks)J@iEEF~Xi&P5;|)*d`>-VxkTW0z=;RUZX<}#(qSZ1~C#B3=oxcD1 z+Ror$=rZ&&ZZgeEW;dK!an?-{0nq>WaJlzv^YRvI#rFncyc}u+M@W+D#o&NB7Y8}~ zc^!9tSTo`s;44>HzJQex*+YIkgrE(M7ta=h87VdmUv(iaHK0i8=_Rd+yjY&HjZueB zo+s;y@JrLMt2Thg-VpjGs#ktT=bc$S7@9%BkVVQ`(_@dVEpj0IDdG=&fDxizu~p_M zv?d#%90XD$W1)N*?-2#D&-)wCfCid*^Jmk4PEfUj;cZNZ-fN#Gei}2=0ouVGjZ$BW zNSOl7&1xohCdt?9D6b*D_t~*}96nrWa~7+B;TvIwD(6}*nZA20&NS>3a{3^d%C-gA zbdyZl8&F#7c{7lwVe}Wwd3wHoH?$lT--|&E=F|sh2c-l(w~51_zJl2h#uBEl>1~=? z`z=D92ieOyF*l=T_i({E>WAsGvzeTG4_us&M)eBFlxtaIQ#_@`SrZzBL8of_b?VF0`$p-<sag+ApJKo^;}ss%ui#o+g7z!(@%e7;ru zz{?jVckKRT6~Zm>(b9Wn2yo9yu8H@KGf&*Q&$_oz*c52Y!ZZXR%VVw}wN3(TW@(2B zhuvyI`_Ml4bKjvdtOn!h;1@H$?IR-KlMR74)8oJw&l_M>B?dgv$U96mHmRw25#Z8? zYd}xGBaIPSFmXu6jid;P-Syy#2CBm^6kI5l)%^5$OTb=1!!ZOx11ZIV(!ktOkc-vd z!{4MDIj3wXHQ!f*hXy%PQz=NM{~bO|GBL@oQvf39;rBamq8!U1NqWTXo?z$AwuNr$ z9(7Q&OacP(PARylSSNTTPwQWYXY>8VGeOa@LkZcYZxmEc#&T;44Lt^v-N~yzf6(+q zOtFF*0ZNBE*X(7%9S`h5;8FWSi2;e^C^Cfo)}!_aJ3jK?VNGpNXA%l}4Aw8fc1@FW z=zRIm`8j8twIeAXzL>zxlYJOOY3xg16U~nO1ZK8f4J!x!^||lCfu|)V_}PK0(&mN+o8eli2E0iM!!| zVf93m(9C%aaalx~5u@hEA`#~x1L64TcZVXzq%9OAf-*17!p?mqV&MAQKd?`wkzIjjC~An0u1H`=!4ZI>EdX9i8^ZTd z&+p3pr6X`m0fNA|&-9TZ=X-@)&yEhs_%+8s4sK%N{d(3#HLL-?oS1{E;8R5bk9!4; zW|8_Gy~)`HPnirt`=;6CE!`5#E&oVr_JataTG602+7k$bB_zWfzGVi2gy=O+3PMQX z(M+oyrg};<`$01&U5UcES}tqHKeD5R=*gC%2InHgi5H?2`SD-H>%Yjf3mx)D=dJJllKfBSH{g=fC=0m;IBOTQjIHHRr9E}rDpt@`-lEb#eS0F18nC?K=XT}b-%_dPUhpl%;B^4+~b;ic!*OPxAX`Sl)|l=oB>%{2|Xo*RZA6cY|B{b(DVE#8J#xfz0DEO2VUj(Uvhx$u*#~q ze%oC95V0UoskLm_b3*WGU7YX5CHhv?up8Lbs3TQTBFl4RH-l}D^e-=4^H7r-55%RR zziI-@cW=Ky=E+O&QE%HW{Kkz~ch z*U`$z+lFDG=FhW|#QL3_?_E4Y@0J+RY0#>fsgR~}vrG~@fDVUjJ&?m;;zXm5G}=m< z_n0_`f8jym$5LlEJs6rxqiSIHENa^fFSI}cY%PUhe8XSKE;zN9TULVQ`FS-W+%hBX zCJdfpC2XTYds{^XYy=?BvRoU+wqqyTp*Z>4px^YK?+` z_~002&+zT9qx6mZ&GA^n zd|7u&;7IKIYUEE!u?Q4$5!bfw>!f(i{|;kNkTLb{>auVMXc{{gw)}!tYxeHoTIPH1 z+90Z|s`BwskR19AAvc87))iT}@2Lj4KE0-*r(f%)Stc49D^cltMH#=a=m(&Z2qCUn zy_#VJil1Ib*!CRL=?E4Zz0`r}ipZN3hJF%GG0P^7S8X92BXTn zMkzYxoTvcB6@xqP8V*?rb?Ku`FPLxlo;Ieo%;1pyX&WuTO@J!t6qxwf3a2cD8uG>2(Tude+jl~8r#U=(WWVT9a;vQR{1^HY*)9u4_e8Oc<1Uj z_s%D60UNN6{Lhtc(20uOG#xepdqWV;2sU>1thFrgerOeZwhjz$q)-FIZ95*b6^l}U zC+U*SQ_swU-sj1MA*lmLSlxD4%~?z3)wtYkcGQJB9zqDHMO@08Yg*8#_^DSkCkzNh zI!nU66H&u_Kr1Z*%pQj7B&X=akdl*tzddL0a3XRyX;##gKGL%KUE{f2$F~S5bve9N zXP(e8y)g*=QP7?|9)(5Z$=npP-0|M3^jTH_nvjlSwmxGz;eU97kr-VpTzCoBfELUpznYhJ6+*+# zP^R$qdeq1;>fL`A`3FE5%^&sd}j8A{@mU`>!!lGR;9G5#+3-PeOXG7esCrJJYHQR zoP!+MFQrwBP}soL;~i~y;Nc;)hUru$==r2Tb?YsG$l^4>EaqD>M32#O)#%gr9b&Uy z9T=n+L12YG72c}*p`fN=L&`pU45wd`+mG;Bz1no=uDKieW};P{LV+Xj*fLRmr95Vu zRqta>)8>yHp+5Ly*!?v#-egO3a%kraX6l zmWX#Hx-q-EmCc)afMRhn_gTYNHpK7#Adt2` z?{5^aV0GAtHJvrhwfETJPI9ozHDKLPHUHmpdz-f`F@fA@E}~n&tY@cK_zG73OoD3q za3}{^&vVd%=Ac7eaY-qgoYad0SDUK#awk{_@MzfO)L*BSiuLt{@^8PTVRsU&^$kTz z)7@QSKU7y2Cu3@b_;JAMZzp4?J-j9>S)`^g0>Gi>o6kKn;RKvzn+L8x0+j?E%!AD{ z85q67!>#X!37!O;KW|q(0H{HFWw3fV!pH>P` z0ce4aPD)>i1tpVd6c5Vfl7)6n0oJ7Ea$O2gU;k8ww7*OFc)+u2gpZD-X zO){s;o+4x`(n4cY_!A@KhYQQSZskhYYg9B0IZ%$6dB5_gKH4=-WpId0-KLvy| zbu+4_xvJl=;=iGKJVb&oH}N^6gwlaZ2Z1kA#lkKmjV+i~k`0x*gOv~mMi8z%r zvHPhfgbT|B!unsbpnIaqZe(8gU9Kdt?O=OVh~*YHWz#i6w^YITFZ zM0hk4(;L8%&viJCfPpb^@cz*lQtsgdi?BgTizQT5eB2_j%aEJ)@);9Dh! zaP=4$08fyv(*G;^{rzIqkW}xQQ?>~mV%S4VK|%r-M^45^s0?gs)=dMT-@?-w!5^vw zXB(EG)ljLAz0HbD{hDW8^R?8A96yfF&+;e$lM{`)wQkEKlBI=QQrW%Qp@#KC+OX0x~oy$PTMTJS+kloObeBf6nGxF}q1kTe=*h+WcVh6panZvuHK=g1 z_14Bln{IrP)$ei?OUi0CgA}IV3jxV4lsv?kp`6U22^!hR3eS*WqsE#-gb?d z?WUTLaw-xGytn?h@$z&yqy}=Y!aM`smM|{b>*4pkqMNmh7ijj5i(g9uzjAT93Rz)> zty2U5{s!Nb3!1bF8pHyeToCe4G-OfCcE?d=eyzNk2p5A2drnKN69GM#m|H3}|8`4v zw=``A6XbB8U~2^C651p#Bh{Q^hn{^podt3`h;^Y;8i4trG)HpyHumi)>axBO+9C-W zIQ&7HiJ=7**0WVj~_@DE$T`q^p-nH*5 zPb_eH^=E**Ay^<#$R9YGMz+TNl3r_DeUcU+9SyRIG~VhEN;_Mmf0nZ>I-Hy^ zW&xJgPcF1!901s><7ytN&LAdY<7*b{h zlR$aMfS9C)?Gf&MEpk1fB6{l5RQcA9Sw41O3HWoHE0_Iq`1&Jp8P)t|U!__h=9fGK zY>PsG)~0#BVRHF37VL+r4WGoO#`N+uqi9(el@BFXUt`*_+*PZM#!8 z0XeKy>Ee63G;ZnXKGN}t?}8`r6ZvMFR)Zg*!F_Zg<}n$PM&y{^3J>!oZ`A61?zelN zoiDgKzn&t8Y6;~A7@Oqz?u;@I1$M#GuSBCYX=g#^96rvymI4iSAaiunE_1{ZB6PJ_ z&hT3{2STyDxQJVW*FRY0K`h7okQv#2@r@0wXwXCg8qk_5)CU56tBE9Ucdc*d)~Tyo z`QOV$q`o{NGFG#4oPTb6-}H=^x&L4ob}b{>9WZvPJd;($}reD*rOFe4?8SBKl=!x@IM*KNo~-k@KgfzD}j)2Wh~vWxFE$CJT)Vvqak4{4N#=Vs+tgBA9+Y zYshq9H9X@n!)6q8TGA*E!!1&w1J%FALMv)#ixFM)Q$O7hzG@7cG&VY4`_8Z83{A?< z?owVtP%5!vC$5N;bcW<|$PCgUO;$3cSM$_b`8*4+hd8>%*s1N?59`5 zFt$B4kk+mr0={0qNF%q0JZtLV0xcRG|D9@$Ex(h1ye<9a@@JPUt+K|~7-$bfD7Xi? zbx84kcNO!~%cr!dsjNEe+AN&REdj{EcDENm!HCAPk<4N(q%Kls_sxp({= zuZAS0+`zeP4cmZ}-Sb+z)H;vyz$+W2-aqdOon}x2{Vq31V8ffI;&h--)3P|>q-bso zzu_P5>ggp{ylpS3E89!{zHb@~|70XJB91xFV8zzOHj!YP=w>NtK9Q>~BTZY-kfUi@ zuBnqF(a&sbb3rz8btyuCmx`#gqcp+O^;8*&{o)nOeWlzmhgyx-D~m%(8H8G}^y2y@ z9yzMwQWkxMjhP}WsYnGl9rTKJ2{C*#Bh~4MJ3=N!b zT45a33jyv#nSo&L699Jw`J;ptYRee-tS$qjaeoU>dE&o{5wQ=*bfKAO%tj|W@1qZ@5r5HMe;7fDK!7Q+yPa`%4n`*iHQu=xyfeRk_s=B27b%b(z}s%L&N| z$@Q+f>!BrW4v^_(hIpOQ!2Wbo1-KvWjaaTVM_zr>&Bk~@C`m+t=096qB1Forl&6NZ zAe+;Y-7WcCfs}%=2wYpEIwV4XlD{T%`z@$L!lEo?gtS}I({rcvHQ^_VeukO|0oB#v zcT0)gkAr$ag#-t%^r0|H?Lax%;d{kI)$4`k;94xXo~VhOa`UwwRLM<`JFo7WD@z|X zZQ@7S)w)5A#OLDf{r>Lvzi5XbBa9XE;4oKvCezbs<=ylXimPbuw$&O4tTO_^>8o5R zl52akiF3#>#??KcPp4T%ptDEa0rPB{g zwc+l{cW+jPBe6dmOtA4x4MBo##|4=ObyI^1d3HV{-T0HWKOGRRQMf+P8s!#^Im#%2+d}XTDPz)iDf`s6Wnz?ylFrO~oq;5~kI` z$HT8vE|XYun*2%k!Tj{)ZdX-;3W?ntVcWHsiiLFUeD$;1S^_&&E?@+ARGaE_TxC3h)5QM}P+u@ik2 zf6Saq^jjy|imW#rJ_{9ZV^Mo9cv4)*5oz8H6qS~bF-w$bzZOt^gAl4lz+Eze@w?dk ziwfSCG3Y#(Sv-Yv=-lBtjWPzJ_Abig{TNG6JRPIYx_j`vC66fpcOs~Ynyw089Ce-b zGRIr}8F{#lZJ0Mua##%WStDWoG9F^!C);I*j5%PHtWH_7t>4~tkF`VoLJcf+AZlv> zdsBLN8oS9po+#-8@aZAmMo0QQ8&l4<=(Gw_S2aZG@i`V9aWZbL!{FrQ%v0gbjUtoJ zcv*O-6dMt}B`Zgi(f)|ZBENTdoG&Yc@TQx`Uy5t4n>UB|(4@0be>!IuV6xZ<}=U)}o@q{_St0Sp>_P#2!GB@Zwl6}H3WBSs* z$UZj-(|N-C#$1h^Ph0`=zUckDFP@=4M9xOL6C{mmlK_?iEQY|nO+q$bf2F7{w?j5W zZ`P+ML;Y?&aVWR^Rbm^(SK||uL?2e^pJ$rRa(wRvnb8)M5NT!}J;SqM zFZolir<(7Y%uu9Q2zR>S5LolOdkAjWvG*;(&?Z;(`*%*lIe(HWAJRHSBR-#=QY}|H zZp;UGIPO&m&=``*1kVQ76wi9YCrqdYh(XD zF)!~~8QHi;5rh{vn9-@SW@z&rfcSZCX%NYnF1>YoqU`5r$LCPnyf9CF|CI!1oTdhP zo+s2^P;BX|Jl&qo!=^s(%i`SmldaG5Uuti-f5ydBkoi1zJWVrSyilOYch2xDgb-xZ ze9!uu72R&~ga&v^NpF2$(QS1F6KF^K*U}XFx|Xf4-eox$LdySlF-rSB1A%L zaM_ZmGMHCZ`QZpV(34r8=M7wH|7mNwqN28%TKNgQJG^euYmbb$ZN?QO*8}{Qv|wEH z6Y|XpLe;l*A8?7k7BH7YrE#0?=Huz22Y@J>*#peZF^#QHg}!9GD7`V?ww} zaL13oq}30(VZ%YlNKZrYFUdaCq=K&_>KF}0OrrSTptD7=oppEbuFK-=YcSYJqeD$z zDDQW@GCKR~_M}vB4|q%IDVvrAhOuN#Xu=7~i_aJ-#34RMN9J_MjRyqbgGKZgx`p__ z4Y8WhAQZ&ysw&`0SMpYy2D6=+S8Ue0O2}ql#4)IaT3SKx(S!e2SqycM;~Mcdg2M=v zMviv1(h`~p%jVc5Km-zg*VV!7|2mA9(=!rvNphy5^F@kpHU2;f6p14`(#kN1+6LGU zdHRHW(Ci5PsrWu~1r0G4^mm#qxMPN@kNyR(Bgkigatx~BklYZ$mFT9=Jv=_1{WSy? zhic(G&%uj&c1Keb0-}?%xfNVFvF^HqjYH%0AmCvnKs0YDV z_TBJc%+7OJfz7J#~TIOqr~`w?GMU%9Rm&vG;XKU9zoRwoGr!5OXd4GP9J_8d1HM6OqOX4@yNX|DNb> zr3r22L>()=7F_Aj_R4>Jwq1m=k zkxvGbvi){3MRY({QXZq9!6r+TBtwS4hJX90-vJVh0`edlso53|8mOnCxUplr zXkLv^F7L?0jnsS**XA4b1Y=ud(Hw<y7S&<+*B%2U`T z%k-1bPem3;H@98}5>A#y6T=h}I^e#`A0LOyhyOKqdD_qWdmCN+qlJTp&^stC3&vO; zo;s`Li#G0mZV3&oH3f$p$rUrp0oOX89h%i(0G2kJZJyx(SRzp}Dm&oJ)bh$TRBOVX zb_aRe{`{id*+6$kNf@6pyD-PUG zgKW3(sFYKwtcL)uMCrzv{0Ujy_QTL=)wwb*^sENqZ#tKGBm_CyI06&vkR+ zqWwPH5{uA3EXl_xB#;I4Q7J2fG{0muZda=Rh9D{U5drcKl1lIcjH4Yw82@ z*V>tHaJ+)IF0s|g!JQTSF6j?K^7JQ~M`z^s=cuAj56O|hH5y^Jw`eY~G{!sSdw3}Y zQ?g8b^H!o`19NA?D=(9)scQUJ1RkCym(AlrZ>Fg%miXz^i*(-e{&11Nwr`#D^l3os zNq>uAQTQ?1czWV|?kfhRavDl#aM!a_b2dDzpRvPsIQ-N>AbqRA8Yg!y9sPiSInhY+ z<=86#R7_!}esp{{E3WRT$iw=t!bQMbE%M{U@RY85bQOoI-V$F>3&GK?!hOG)WHIu1 z92X`Jf04k!zudG3u>fUdWjl!1z2AvI8a&=~#>A>j2(H?f2gvH`tHxAe?s_m2MHAd5 zP_q+;=FWjqu=S-#))zs=HDkY%+yDjJvN(B;WqgnmblPc+g=kl@A6Lrv<_EUe2Io)^ z`1vC8$z#6SXgKqMgszy$-k8Wf>G6Y!+j+C()5=-LjTlK72zc=1e+{*ZTstXP{|@|0 z7dwv9^6CnuXlN|cfZ?>65fPMe=i`vY2c+|dfvcWSoCqr}8>OYC;K*)Q$87sA>%b-9 z=KM;$_lJ_+_v^zFPb<&4ei$;K20exQPHKJMpX=ti6-#pJ;6L_`V`j|p9L&ta!bkNQnsy6Q!<1Ig76Vm;xNfLO| z2$MuI&(HyP@J&WVVTCr>{~*!0d41}?_tOuyt=N9Y2q@ru#1*b3vVguHmpCg@%%T)> z4?`!D**G7>;9}%#_|Em(E>nGma-qLczA-0Fn2;p&LM1+dgk_N*AhlqoEg_YH0bjXYe z4^tzEhXJuoChoIb9?blAzkDNXcxg);cGt9+M!?v97~3m2M>*gv-$CDD@X@f%7z{R_?_!PL3>6T@ZU#8-A`F-uwOfkK}HU@_LJ_Ff%2>Ug7$@Q z1+*{|&eOJw`z{mN>FzqO`~9i4Kc}wmGLdxg{7<)l5Kq)+oUd_h3JQ}+lT)rvS0H{b z%ez$4GScc~#KLMmzcNS?gI`{!olXypGs}$mrbYH6fhtt4foJOWl-BwD1}6}H*e*fv zis*R@$N$HEio*Im4FZ4qV8*N3XYLz<%}#BoHLZE3hw9p6iOF& zPwmy`XiL8uw4=SG;JcF86YaKw@I(-zX;Pu}7myHtbu@nr!M8#)E?4P}(v`dhsJ4y- zYUlT7kJHTAmFPAX|5` zNIkkG%k})toNz`f(t%=-6A}$3oBVJ?3C>5ht|te0;3K2cF7#A0bZQJA`y0ir9UD=n zXHs{glk2nRfeUZB&s)%0_m)P{j&!$E+Tu8V?hj-rf#H&OXCNM^KCV9tnKgAx$!dh$ z?pvUbyNT@~w`#jsJr^t0YWh?l4sz0R-C*s@2>|cG=58$$8c&p$I_^TpojtwZdy&Vi zHYnt3U*MI9CVk9Rml)EaO2GZ-ZTe9tLRXUR%!f zidVRA0WOqwN` zuoY%O1~6-Uga7D*e}pBx=) ze)rLDot`movxkC-R&4LimE)XzzY!myzF}*xJrtH)J^R4`X^8X#ovjcXx()>bDIroC zEng1**EDjyh(5v&rqZJ>aUC5ewfVGBppF+9n_<9{fAY9t7^0ZpO&r=N@($kHS;X=ic68EsJ1;qEHtnX1bzs@AJ+RBC)T zLEQsSlrp8nM8a|#*6%!?j+4kopuK)-;d{<&8vI4sYC@$LB2V5tc$w;^G?$iGe`AOCQO>w zM*pfb;`a#UqmyhEA?U^LwL~Fz1vO7aLEhxB)VQQzm9?H-0s=&mz}VZ_Zr^+hCp88z zmlb^^(J2}&G_jMS7qeOXg`{KDmUx>7E~!*~qig8Q#}=WHF=GPxcA5-lNQxhr-!35< zhv(TiXO|r0FANVzi9?W(B{_F_UIJkgIY%u@8s3l+gB!<=dLKmZ@Xvo@WE#{0a>`pQ&k%=Zf#gS~mv)a|tPng9^ZuhroeE z(?vQnCs>85>#g8JP&#_(xqYChO^Kwer>XAGAx&JkwSHX8$ zb^FqDW%G;KY#xY?trwsi^}3m)yD6LT@6d;o$(=KLC))F*Nr-#bVvDE!k35dn0l*sZ zLtO3_Q^&9r(lY;t6+PGoK#WCB*d9>sfBe`-TEp5R_{CdSztIYKRtq{P)SgJGb~;v! z42&IiZu#jyGgXHL*MM1$+ns54;7b;B7^RIo_D1P3Cq-YNG%pfB~d&p>p{ z14T_N!Xi+2i+x7X1+6(Xcy1{k!#c-`o-KS<^!W2$hs=P*18+L3=)z7$amqjC5QsL_ zWx(+eszTtte{E?Es2^phZU}rb^YVKCTm`Tp8{3Z`b7yw5+0xM>K;IfLx4lYLfu!Bb z4zYa|n}aRQsp-mSXx7Vl)82*@0~V_FTYnI#57UCPgPJ>RevFkm2=(z1YZ|?Jqr`#i zc|LQTOjb@umHdM4Y#p^v^)Db>*c6MWb1o&tM78nvZ34R4Wq*FnQS;TlKbvLLy!08X zL-i|_mE6|O8)Alz>s;~X2Xw~|n7h9jPZa2kxR)K2jz?JI4Eg57+%v!Oh;E9oqS;su z_PEMc9k7@HyrY0&tt+j!@q{Bm{L`2DhrWDAwzz3KCPV4JhPqUo`SYIwb5d3a1CyQ? zZEbntJOz@r`FHADHY)Ys733zN&UAZS>G5tKA?WLetqCoy^yQ7vQ^Ut0;ibZ8x%U|? zZ9;ioj7svVP}1&38aIPFIOcyyrWcBao8d-Z9feR%Q`h4(Yzq%9UII>>co)rhlv47M z5GWd06}rMhFLaa-(2&oH9a%*=LaL6rGk~w^Xb;6vZS>v2!su#8T7}!W*`1b=SwrEZ z4&;5;0QEl-=0*4P1DFisSFC5FkBwk;&YGH+G!kq6f|-8QKau7034jy zB`%ic7PT)g9=AdvU*I(0$&yxEx53`$H~Yd{Bct-IT?4qxDrxq<0{GiZeFHtVjMet=NQ$jiRfhs{eJW9B1Z zYkcmgQ=w$ro-i;jA~K4^C0n^oG@RX>AFmhVHjsWMG=B@MNZ9N4E-o?B+>H_3ae`>2 zc)H+_7%)^?#_OdQFM~l%O7wCw*66K?8~Id&9s6nZm(fg2ePEe${JnBty_n$v(9O$ygINIPDMend!*apNIgeQIiI9vWdMCIJMOGqkQ2JWD8>9CgnNgiC$g zCmGSWuwop^hMk49ZrysixgBn6M%u%xQRiXb%TyLFDMzp4QNc#-pEe5!*7&zf*E~|; zr~T$m&Pv-H)m1ullkH5aZz>)xl@jnn%^9EJxG2x|G&dJy{?>qd?&yd|YGJQ50eo}Z z59Q=#Tt%AXM>08z{&V>E+$Yi!TTWhxYd1KmbvIH<`{&~G z@5N~^PhAM*WH2LC@AXZU8yN1r*=Qxj1< zV(|2)u$q}Q$W?hHZRnjc!5#vpx^fK{Da+JRR(z_Q_ltnqF=`|aeHDxORc>I7I9+kF z?UWSn;8=!vG_Z^_jo@EcpQG6Ch!NqqiG_~&{>v5G^qQEWwRGCn_$^#=2M(Myxrx2< z=IpXBZ~u5^C;v$mXhOjjhR`)|x7BmQj#f#iCT->C?kz*oRcjF=F)`J&Kr!%*Rmbvg zH8ffxn>}m%wDPieXnOb3#`z=ZvZ+vJs&h&7&!9!z<-aK)zvmB83GU*Vs4cauA`knw z9xyBV62C=IQ2JGeT7+{gSaqd;ZDa0%fE>(>yA<#&Y_j_^vSb95{C;Dyx6|4E#L3;@ zr2&&j{x(^lPt1|fG^=}&zVnlCvUg*}lv)$*ayoMF4out;>o>264!Ya%WrE?lJbm)> zM`<-a-CZwXtNlS5mO$5k#PvJHDAGK+Lq}sAR}TwH0QX&%hw5Zy8j(>Dn7-hskLMHv_zq3DjOaTB$@J28>*bC-ao%KKHhGW3zRdZx{s)xB zm?{h7w27ka?z^l)XVqOepT2$#Kh@;Us>u);U-gB?!Gy4W{)E)eA)o}$T@6r#X0T|1 z85Dcke-W-VvVGtnFekS$eXr&A=O8a~UBV@{lnTcVw6&eUXu_*!;Y_NG-bie%x(74U z4(O!qzcV``+r6~%6h8Xu(xZ>s!aVh{t{BYlSI~<^IZo(uWd7vP{x#b;H^H7T6I}D) zLcosy9csf;}g3f ztFf)S>udEtS|itbm=H>f6XCp;85_x*JUYXxwzlc|5YKdj+;in_Q_qF0v~r9CmsFXo zkgLx4nnkwzpALf_FS&YDx@y&hOy!;uJs<1oqvWQ03tEBtVNk~B@`$fe52ODnLM;-W zH6Nl}`tT+MbZ(E?y0M!mu)>NkS=-&VnYX9~^8$F2L=AEST}34Tz-C77xuH+2<_*o8 z6+^$)>q_(EBhn}v;TW%r8cso)ItNFDjLd#fn<}#0UEFW_UDVJce$dCRhiYLz_7-bL zdjCkCt~Fmjb<3irFReTgL_6E;=P667gAoD>AR`N9?vpBb86TOK`Vqyl1y^@pJ67Hy z=4FLBREV!PR;5q9lxIi^;q>3xZxRb-&cxjZfVsNri!elU-QeaFE@KZiX(PY;LF z+8Q-eFRn1Z(dYd$d!2N61xZ9t49j`zg$LBGw+4(CS{Ii!%P(ToS*BzGK>%RhMSXC9 zl{%+@rBcSZWIY7r`1yV0AbL#r$@H~ZH^NS&(}gl7AMpSEep&756#eaV?#Tj8{J%s1D$bfQvd(} literal 0 HcmV?d00001 diff --git a/project.config b/project.config index f2768be..ee7dc2b 100644 --- a/project.config +++ b/project.config @@ -35,12 +35,12 @@ case "$OS" in WINDOWS) EXEC_FILE="$PROJECT.exe" SHARED_LIB_FILE="$PROJECT.dll" - LINKER_LIBS="-lopengl32 -lpthread" + LINKER_LIBS="" ;; LINUX) EXEC_FILE="$PROJECT" SHARED_LIB_FILE="$PROJECT.so" - LINKER_LIBS="-lSDL2 -lGL" + LINKER_LIBS="-lSDL2 -lSDL2_image" ;; *) error "operating system $OS has no configuration variants" diff --git a/src/GUI/MainWindow.cpp b/src/GUI/MainWindow.cpp index 12ddf4a..533e44a 100644 --- a/src/GUI/MainWindow.cpp +++ b/src/GUI/MainWindow.cpp @@ -1,16 +1,17 @@ #include -#include +#include #include #include "MainWindow.hpp" #include "../exceptions.hpp" #include "../format.hpp" #include "../Resources/fonts.hpp" +#include "../Resources/textures.hpp" namespace ougge::GUI { f32 MainWindow::getDPI(){ int w=0, h=0; - SDL_GL_GetDrawableSize(sdl_window, &w, &h); + SDL_GetRendererOutputSize(sdl_renderer, &w, &h); int sim_w=0, sim_h=0; SDL_GetWindowSize(sdl_window, &sim_w, &sim_h); f32 wdpi=(f32)w / sim_w; @@ -20,40 +21,35 @@ f32 MainWindow::getDPI(){ } void MainWindow::init(const char* window_title){ - SDL_TRY(SDL_Init(SDL_INIT_VIDEO)); + SDL_TRY(SDL_Init(SDL_INIT_EVERYTHING)); SDL_version v; SDL_GetVersion(&v); std::cout<0) { draw_frame(); frame_updates_requested--; - } + } } // Cleanup @@ -228,10 +218,10 @@ void MainWindow::close(){ } void MainWindow::destroy(){ - ImGui_ImplOpenGL3_Shutdown(); + ImGui_ImplSDLRenderer2_Shutdown(); ImGui_ImplSDL2_Shutdown(); ImGui::DestroyContext(); - SDL_GL_DeleteContext(gl_context); + SDL_DestroyRenderer(sdl_renderer); SDL_DestroyWindow(sdl_window); SDL_Quit(); } diff --git a/src/GUI/MainWindow.hpp b/src/GUI/MainWindow.hpp index c4c8c20..7e375b6 100644 --- a/src/GUI/MainWindow.hpp +++ b/src/GUI/MainWindow.hpp @@ -1,7 +1,6 @@ #pragma once #include -#include #include #include "../std.hpp" @@ -27,7 +26,7 @@ private: bool show_demo_window = false; bool show_metrics_window = false; SDL_Window* sdl_window = nullptr; - SDL_GLContext gl_context = nullptr; + SDL_Renderer* sdl_renderer = nullptr; public: void init(const char* window_title); diff --git a/src/Resources/Resources.cpp b/src/Resources/Resources.cpp index 6c9b014..1767e48 100644 --- a/src/Resources/Resources.cpp +++ b/src/Resources/Resources.cpp @@ -1,7 +1,7 @@ #include #include #include -#include "../UsefulException.hpp" +#include "../exceptions.hpp" #include "../format.hpp" #include "Resources.hpp" #include "embedded_resources.h" @@ -19,16 +19,27 @@ MemoryStreamBuf::MemoryStreamBuf(void* _p, const std::size_t n){ setp(p, p + n); } -class MemoryStreamRead : public std::istream { -public: - MemoryStreamRead(const void* p, const std::size_t n) - : std::istream(new MemoryStreamBuf((void*)p, n)) - {} +std::istream::pos_type MemoryStreamBuf::seekoff( + std::istream::off_type off, + std::ios_base::seekdir dir, + std::ios_base::openmode which) +{ + if (dir == std::ios_base::cur) + gbump(off); + else if (dir == std::ios_base::end) + setg(eback(), egptr() + off, egptr()); + else if (dir == std::ios_base::beg) + setg(eback(), eback() + off, egptr()); + return gptr() - eback(); +} - virtual ~MemoryStreamRead(){ - delete rdbuf(); - } -}; +MemoryStreamRead::MemoryStreamRead(const void* p, const std::size_t n) + : std::istream(new MemoryStreamBuf((void*)p, n)) +{} + +MemoryStreamRead::~MemoryStreamRead(){ + delete rdbuf(); +} static std::unordered_map* _resourceMap = nullptr; diff --git a/src/Resources/Resources.hpp b/src/Resources/Resources.hpp index f54056d..65c73bf 100644 --- a/src/Resources/Resources.hpp +++ b/src/Resources/Resources.hpp @@ -27,8 +27,19 @@ public: class MemoryStreamBuf : public std::streambuf { public: MemoryStreamBuf(void* p, const std::size_t n); + + virtual std::istream::pos_type seekoff( + std::istream::off_type off, + std::ios_base::seekdir dir, + std::ios_base::openmode which); }; +class MemoryStreamRead : public std::istream { +public: + MemoryStreamRead(const void* p, const std::size_t n); + + virtual ~MemoryStreamRead(); +}; Resource& getResource(const std::string& path); diff --git a/src/Resources/textures.cpp b/src/Resources/textures.cpp new file mode 100644 index 0000000..a469cc6 --- /dev/null +++ b/src/Resources/textures.cpp @@ -0,0 +1,105 @@ +#include "textures.hpp" +#include +#include "../exceptions.hpp" + +namespace ougge::Resources { + +Texture::Texture(SDL_Renderer* renderer) + : renderer(renderer), texture(nullptr), w(0), h(0) +{} + +Texture::~Texture(){ + SDL_DestroyTexture(texture); +} + +void Texture::loadFrom(const Resource& r){ + auto s = r.openStream(); + loadFrom(*s, r.size); +} + +void Texture::loadFrom(std::istream& s, size_t size){ + if(texture) + throw UsefulException("texture has been loaded already"); + SDL_RWops* sdl_stream = SDL_RWFromIStream(s, size); + if(!sdl_stream) + throw SDLException(); + texture = IMG_LoadTexture_RW(renderer, sdl_stream, 1); + if(!texture) + throw IMGException(); + SDL_TRY(SDL_QueryTexture(texture, nullptr, nullptr, &w, &h)); +} + +SDL_RenderCopyExF_Params::SDL_RenderCopyExF_Params() + : rotation_angle(0), flip(SDL_FLIP_NONE) +{} + +void Texture::render(const SDL_FRect& target_section){ + SDL_TRY( + SDL_RenderCopyF(renderer, texture, nullptr, &target_section) + ); +} + +void Texture::render(const SDL_FRect& target_section, const SDL_Rect& texture_section){ + SDL_TRY( + SDL_RenderCopyF(renderer, texture, &texture_section, &target_section) + ); +} + +void Texture::render(const SDL_RenderCopyExF_Params& p){ + SDL_TRY( + SDL_RenderCopyExF(renderer, texture, + optional_value_ptr_or_null(p.texture_section), + optional_value_ptr_or_null(p.target_section), + p.rotation_angle, + optional_value_ptr_or_null(p.rotation_center), + p.flip + ) + ) +} + +static Sint64 istream_size(SDL_RWops* context){ + return (Sint64)(size_t)context->hidden.unknown.data2; +} + +static Sint64 istream_seek(SDL_RWops* context, Sint64 offset, int whence){ + std::istream* stream = (std::istream*)context->hidden.unknown.data1; + switch(whence){ + case SEEK_SET: stream->seekg(offset, std::ios::beg); break; + case SEEK_CUR: stream->seekg(offset, std::ios::cur); break; + case SEEK_END: stream->seekg(offset, std::ios::end); break; + default: break; + } + return stream->fail() ? -1 : (Sint64)stream->tellg(); +} + +static size_t istream_read(SDL_RWops* context, void *ptr, size_t size, size_t maxnum){ + if(size == 0) + return -1; + std::istream* stream = (std::istream*)context->hidden.unknown.data1; + stream->read((char*)ptr, size * maxnum); + + return stream->bad() ? -1 : stream->gcount() / size; +} + +static int istream_close(SDL_RWops* context){ + if (context) + SDL_FreeRW(context); + return 0; +} + +SDL_RWops* SDL_RWFromIStream(std::istream& stream, size_t size){ + SDL_RWops* rwops = SDL_AllocRW(); + if(rwops) { + rwops->size = istream_size; + rwops->seek = istream_seek; + rwops->read = istream_read; + rwops->write = nullptr; + rwops->close = istream_close; + rwops->hidden.unknown.data1 = &stream; + rwops->hidden.unknown.data2 = (void*)size; + rwops->type = SDL_RWOPS_UNKNOWN; + } + return rwops; +} + +} diff --git a/src/Resources/textures.hpp b/src/Resources/textures.hpp new file mode 100644 index 0000000..37b0dd5 --- /dev/null +++ b/src/Resources/textures.hpp @@ -0,0 +1,47 @@ +#pragma once + +#include +#include +#include +#include +#include "Resources.hpp" + +namespace ougge::Resources { + +#define SDL_RectConstruct(X, Y, W, H) (SDL_Rect){X, Y, W, H} +#define SDL_FRectConstruct(X, Y, W, H) (SDL_FRect){X, Y, W, H} +#define SDL_PointConstruct(X, Y) (SDL_Point){X, Y, W, H} +#define SDL_FPointConstruct(X, Y) (SDL_FPoint){X, Y, W, H} + +#define optional_value_ptr_or_null(OPT) (OPT ? &(*OPT) : nullptr) + +SDL_RWops* SDL_RWFromIStream(std::istream& stream, size_t size); + +struct SDL_RenderCopyExF_Params { + std::optional texture_section; + std::optional target_section; + std::optional rotation_center; + double rotation_angle; + SDL_RendererFlip flip; + + SDL_RenderCopyExF_Params(); +}; + +struct Texture { + SDL_Renderer* renderer; + SDL_Texture* texture; + int w; + int h; + + Texture(SDL_Renderer* renderer); + ~Texture(); + + void loadFrom(const Resource& r); + void loadFrom(std::istream& s, size_t size); + + void render(const SDL_FRect& target_section); + void render(const SDL_FRect& target_section, const SDL_Rect& texture_section); + void render(const SDL_RenderCopyExF_Params& params); +}; + +} diff --git a/src/main.cpp b/src/main.cpp index 08fa535..540b7ea 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3,6 +3,8 @@ #include "std.hpp" #include "GUI/MainWindow.hpp" #include "Resources/Resources.hpp" +#include "format.hpp" +#include "exceptions.hpp" using namespace ougge;