From 3fdce066bf4c647183e7e74b9f5c149d4c37d8ce Mon Sep 17 00:00:00 2001 From: Jopestpe <47086979+Jopestpe@users.noreply.github.com> Date: Mon, 6 Oct 2025 17:35:18 -0300 Subject: [PATCH] [examples] Added `shapes_recursive_tree` (#5229) * ADDED: example: shapes_recursive_tree * [examples] Added shapes_recursive_tree * [examples] shapes_recursive_tree: adjustments * Reduced tree depth from 12 to 10 * new shapes_recursive_tree.png * follow the conventions * follow the conventions 2 --- examples/Makefile | 1 + examples/Makefile.Web | 4 + examples/README.md | 5 +- examples/examples_list.txt | 1 + examples/shapes/shapes_recursive_tree.c | 141 ++++++++++++++++++++++ examples/shapes/shapes_recursive_tree.png | Bin 0 -> 18375 bytes 6 files changed, 150 insertions(+), 2 deletions(-) create mode 100644 examples/shapes/shapes_recursive_tree.c create mode 100644 examples/shapes/shapes_recursive_tree.png diff --git a/examples/Makefile b/examples/Makefile index fb33b4894..a36b9e447 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -559,6 +559,7 @@ SHAPES = \ shapes/shapes_logo_raylib_anim \ shapes/shapes_rectangle_advanced \ shapes/shapes_rectangle_scaling \ + shapes/shapes_recursive_tree \ shapes/shapes_ring_drawing \ shapes/shapes_rounded_rectangle_drawing \ shapes/shapes_splines_drawing \ diff --git a/examples/Makefile.Web b/examples/Makefile.Web index 0dbefadf2..2d3018abf 100644 --- a/examples/Makefile.Web +++ b/examples/Makefile.Web @@ -559,6 +559,7 @@ SHAPES = \ shapes/shapes_logo_raylib_anim \ shapes/shapes_rectangle_advanced \ shapes/shapes_rectangle_scaling \ + shapes/shapes_recursive_tree \ shapes/shapes_ring_drawing \ shapes/shapes_rounded_rectangle_drawing \ shapes/shapes_splines_drawing \ @@ -868,6 +869,9 @@ shapes/shapes_rectangle_advanced: shapes/shapes_rectangle_advanced.c shapes/shapes_rectangle_scaling: shapes/shapes_rectangle_scaling.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) +shapes/shapes_recursive_tree: shapes/shapes_recursive_tree.c + $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) + shapes/shapes_ring_drawing: shapes/shapes_ring_drawing.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) diff --git a/examples/README.md b/examples/README.md index 70e07df2b..d852e7105 100644 --- a/examples/README.md +++ b/examples/README.md @@ -17,7 +17,7 @@ You may find it easier to use than other toolchains, especially when it comes to - `zig build [module]` to compile all examples for a module (e.g. `zig build core`) - `zig build [example]` to compile _and run_ a particular example (e.g. `zig build core_basic_window`) -## EXAMPLES COLLECTION [TOTAL: 172] +## EXAMPLES COLLECTION [TOTAL: 173] ### category: core [40] @@ -66,7 +66,7 @@ Examples using raylib[core](../src/rcore.c) platform functionality like window c | [core_undo_redo](core/core_undo_redo.c) | core_undo_redo | ⭐⭐⭐☆ | 5.5 | 5.6 | [Ramon Santamaria](https://github.com/raysan5) | | [core_input_actions](core/core_input_actions.c) | core_input_actions | ⭐⭐☆☆ | 5.5 | 5.6 | [Jett](https://github.com/JettMonstersGoBoom) | -### category: shapes [23] +### category: shapes [24] Examples using raylib shapes drawing functionality, provided by raylib [shapes](../src/rshapes.c) module. @@ -84,6 +84,7 @@ Examples using raylib shapes drawing functionality, provided by raylib [shapes]( | [shapes_following_eyes](shapes/shapes_following_eyes.c) | shapes_following_eyes | ⭐⭐☆☆ | 2.5 | 2.5 | [Ramon Santamaria](https://github.com/raysan5) | | [shapes_easings_ball](shapes/shapes_easings_ball.c) | shapes_easings_ball | ⭐⭐☆☆ | 2.5 | 2.5 | [Ramon Santamaria](https://github.com/raysan5) | | [shapes_easings_box](shapes/shapes_easings_box.c) | shapes_easings_box | ⭐⭐☆☆ | 2.5 | 2.5 | [Ramon Santamaria](https://github.com/raysan5) | +| [shapes_recursive_tree](shapes/shapes_recursive_tree.c) | shapes_recursive_tree | ⭐⭐⭐☆ | 5.6-dev | 5.6-dev| [Jopestpe](https://github.com/jopestpe) | | [shapes_easings_rectangles](shapes/shapes_easings_rectangles.c) | shapes_easings_rectangles | ⭐⭐⭐☆ | 2.0 | 2.5 | [Ramon Santamaria](https://github.com/raysan5) | | [shapes_ring_drawing](shapes/shapes_ring_drawing.c) | shapes_ring_drawing | ⭐⭐⭐☆ | 2.5 | 2.5 | [Vlad Adrian](https://github.com/demizdor) | | [shapes_circle_sector_drawing](shapes/shapes_circle_sector_drawing.c) | shapes_circle_sector_drawing | ⭐⭐⭐☆ | 2.5 | 2.5 | [Vlad Adrian](https://github.com/demizdor) | diff --git a/examples/examples_list.txt b/examples/examples_list.txt index 50643bf2b..5a0c679a4 100644 --- a/examples/examples_list.txt +++ b/examples/examples_list.txt @@ -60,6 +60,7 @@ shapes;shapes_following_eyes;★★☆☆;2.5;2.5;2013;2025;"Ramon Santamaria";@ shapes;shapes_easings_ball;★★☆☆;2.5;2.5;2014;2025;"Ramon Santamaria";@raysan5 shapes;shapes_easings_box;★★☆☆;2.5;2.5;2014;2025;"Ramon Santamaria";@raysan5 shapes;shapes_easings_rectangles;★★★☆;2.0;2.5;2014;2025;"Ramon Santamaria";@raysan5 +shapes;shapes_recursive_tree;★★★☆;5.6-dev;5.6-dev;2025;2025;"Jopestpe";@jopestpe shapes;shapes_ring_drawing;★★★☆;2.5;2.5;2018;2025;"Vlad Adrian";@demizdor shapes;shapes_circle_sector_drawing;★★★☆;2.5;2.5;2018;2025;"Vlad Adrian";@demizdor shapes;shapes_rounded_rectangle_drawing;★★★☆;2.5;2.5;2018;2025;"Vlad Adrian";@demizdor diff --git a/examples/shapes/shapes_recursive_tree.c b/examples/shapes/shapes_recursive_tree.c new file mode 100644 index 000000000..3ec46de4b --- /dev/null +++ b/examples/shapes/shapes_recursive_tree.c @@ -0,0 +1,141 @@ +/******************************************************************************************* +* +* raylib [shapes] example - shapes recursive tree +* +* Example complexity rating: [★★★☆] 3/4 +* +* Example originally created with raylib 5.6-dev, last time updated with raylib 5.6-dev +* +* Example contributed by Jopestpe (@jopestpe) +* +* Example 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) 2018-2025 Jopestpe (@jopestpe) +* +********************************************************************************************/ + +#include "raylib.h" +#include + +#define RAYGUI_IMPLEMENTATION +#include "raygui.h" // Required for GUI controls + +//---------------------------------------------------------------------------------- +// Types and Structures Definition +//---------------------------------------------------------------------------------- +typedef struct { + Vector2 start; + Vector2 end; + float angle; + float length; +} Branch; + +//---------------------------------------------------------------------------------- +// Module Functions Declaration +//---------------------------------------------------------------------------------- +static Vector2 CalculateBranchEnd(Vector2 start, float angle, float length); + +//------------------------------------------------------------------------------------ +// Program main entry point +//------------------------------------------------------------------------------------ +int main(void) +{ + // Initialization + //-------------------------------------------------------------------------------------- + const int screenWidth = 800; + const int screenHeight = 450; + + InitWindow(screenWidth, screenHeight, "raylib [shapes] example - shapes recursive tree"); + + Vector2 start = { (screenWidth/2.0f) - 125.0f, screenHeight }; + float angle = 40.0f; + float thick = 1.0f; + float treeDepth = 10.0f; + float branchDecay = 0.66f; + float length = 120.0f; + bool bezier = false; + + SetTargetFPS(60); // Set our game to run at 60 frames-per-second + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + + float theta = angle*DEG2RAD; + int maxBranches = (int)(powf(2, (int)(treeDepth))); + Branch branches[1024] = { 0 }; + int count = 0; + + Vector2 initialEnd = CalculateBranchEnd(start, 0.0f, length); + branches[count++] = (Branch){start, initialEnd, 0.0f, length}; + + for (int i = 0; i < count; i++) + { + Branch branch = branches[i]; + if (branch.length < 2) continue; + + float nextLength = branch.length*branchDecay; + + if (count < maxBranches && nextLength >= 2) + { + Vector2 branchStart = branch.end; + + Vector2 branchEnd1 = CalculateBranchEnd(branchStart, branch.angle + theta, nextLength); + Vector2 branchEnd2 = CalculateBranchEnd(branchStart, branch.angle - theta, nextLength); + + branches[count++] = (Branch){branchStart, branchEnd1, branch.angle + theta, nextLength}; + branches[count++] = (Branch){branchStart, branchEnd2, branch.angle - theta, nextLength}; + } + } + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(RAYWHITE); + + for (int i = 0; i < count; i++) + { + Branch branch = branches[i]; + if (branch.length >= 2) + { + if (!bezier) DrawLineEx(branch.start, branch.end, thick, RED); + else DrawLineBezier(branch.start, branch.end, thick, RED); + } + } + + DrawLine(580, 0, 580, GetScreenHeight(), (Color){ 218, 218, 218, 255 }); + DrawRectangle(580, 0, GetScreenWidth(), GetScreenHeight(), (Color){ 232, 232, 232, 255 }); + + // Draw GUI controls + //------------------------------------------------------------------------------ + GuiSliderBar((Rectangle){ 640, 40, 120, 20}, "Angle", TextFormat("%.0f", angle), &angle, 0, 180); + GuiSliderBar((Rectangle){ 640, 70, 120, 20 }, "Length", TextFormat("%.0f", length), &length, 12.0f, 240.0f); + GuiSliderBar((Rectangle){ 640, 100, 120, 20}, "Decay", TextFormat("%.2f", branchDecay), &branchDecay, 0.1f, 0.78f); + GuiSliderBar((Rectangle){ 640, 130, 120, 20 }, "Depth", TextFormat("%.0f", treeDepth), &treeDepth, 1.0f, 10.f); + GuiSliderBar((Rectangle){ 640, 160, 120, 20}, "Thick", TextFormat("%.0f", thick), &thick, 1, 8); + GuiCheckBox((Rectangle){ 640, 190, 20, 20 }, "Bezier", &bezier); + //------------------------------------------------------------------------------ + + DrawFPS(10, 10); + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} + +static Vector2 CalculateBranchEnd(Vector2 start, float angle, float length) +{ + return (Vector2){ start.x + length*sinf(angle), start.y - length*cosf(angle) }; +} \ No newline at end of file diff --git a/examples/shapes/shapes_recursive_tree.png b/examples/shapes/shapes_recursive_tree.png new file mode 100644 index 0000000000000000000000000000000000000000..88932c204bcd24be38c10978b75cda9b002234d8 GIT binary patch literal 18375 zcmeHvc{G&&-!~IQS}aA$mL&-zB-tf9QPzyLkY((Hu``t-j3rBCDP&)=jD4#xL?ipY zWE%!Ec8&G9rsdoBKF>e*AI~}WdG7ObPN$l=uFv(}->>&_3B9MKa{46mNis6B(`u@U zI%H(WILOGzKT#bAK4G#fYy%tUUoQRrTICkYlilg99uw$dQh zC|;Gxp}&kL3(!uG8{ugc_as&n1v;>J+t>Q)=}9ufimX3E-oqV#-puy!}z0zLUH~S zewvbOq1ZosN;3Qae%80Q2aJl{Uo`nsE(eW?S12q0L;qVTa%xrhi zSGnO_9OM^y4Sdx95xj*LIU(p2yTY;G8dPTZvAr^CpHO+|=j>N(sgAt#RWq=IG9G5N zOF((UT1{etV$nU(f5>=*m{TBx2b;UvuzDFIh;>rXGwSkAQYojxe=&05zQt0J`>c~k zW@pHiT|Xgm>bCl6yBohl3PjNlFaSGh&^-u9dDFJqXfRdbVP{_w>L#2Cp_FTn@u@}Nfwf86aj-O%1v!D872 z-t(-&-jI`7^oPSuB9XXZ*>XDh*V$fmO=vVap|Y~_I}37uAHPGGY~25TAe0?W)DApa z;#;wuH7AMx$NJ&ngxCw#sG`pqus^H^Qk%GDC&?ffLG)3Kc{uLhy47Qh3er2SKW+_b ztSzuU{Wp?utlk2+pHXmX`h5bRs3L|{ssWE}$e-wFa%F06wPS&O@&m=}nl9OI39Kq2 z28(%!FPhGS0-o=j^l)KPcSY;Q$#7H%O+brQPx!R{(QA-=br41780L?rNLFD5 z$VuemIo>~3$RYpML>{E$gjN0Pbrd3i(Ii^D{1@H#z#Qa!m9W1-og9=1@T_^g{`UnI=MaqtYh4-cVzp@`M<|PQ zZSn?9kV|wyH2yx9O^Acsd;c8SU%scL0abVpK>l$^j#ZK$NC%uG`|Sr1D!;w$m5!yr z!b79{Mvpgzt?3gLpkC>*BzE7xiFBL)qH|h~Z=p@nA0J$4**Kcm-5L2D71YP5&;Ex< z6$?kh%uUSZK4!abb^@epLA42l{l&{CcYjkPt#C{fu70rjlYeNdrXR(`tjP)k+b z>BhTL!M`MW;m+F^N>dkfe1;XKa712mJ34)jKXUY>C^92Ec?Q7`sLl`vee>&%Dpb?J z-i2y{odb`6P5lkOB@P)Emu~Ojm-E?OU0rF$`bB2H)h=E z8v~CH=gtxWFFx+9WE438xt;vn>&rj!Nrp@+hvX*l_fW)x9rCToeTbU`;Yc~K-KWK zJ70vDk^~u}wv>yqcuDB+f`{er_*cU)RC9;5+E}oC0i68V!`2aw7YiwrlM|7rZljYy z|FQRL)U(`l64v}4+G65NA>2)<`4o!T`B&|$zqmjMQ@Am~b8U9f7f@!h0GwHG&bcJ| ziyfEHrimGW>c}R*DXK#|d1#qsOgXkvyAwASe|m*B(>IRajK5_-L`FsmIXgS2Y-Tx$ zR|Hru?d=fE4_6NpY9ew4ji-PV0o@kPJqF~5wYh@>8U5v+u9YB@FU78Z{7QzrmVHa0 zzfVgZ)Pphj`bP}9fIVirK@09p!GqBfzcb}8>l_9GtAogif9dSrwJExSf64hcqwN}K zvx%i9ARTZbMTfh86yQVWbpVM8q%yfYW#d(RZ}7@5KE6dXr35~&yky0C`8vbunUKZ5 zQ81{<4tQK|j+o-#v=Kzn%Lt=+T*f(f8khv;d-HMm_(RjYS2$ zKK5H0Br21ytnT$fdT4)3K1iMkG}#zPNN1PqR-QUIsK471XAi{vCwixUUtz&bN({(8 zQ~%Q^0qJu+Sg(0RAGNfM()`Uy)h~arc7#^Fmp`Hofy+Z$&By=s$o>C<6#&xy@L|fg zdUV(kxCh_Z2uwR%-LmOTEB2Qq_+~EG73ujy!KhKyE#A4_Yo58DTxTSNH6=1zFD`0p zUCJ%xOVbPV|CND#&iz>2*x10bNo8qM*wbi+RUhpK9uC^~Z?sGpBoZINcX#ysb89L{ zx7urVG%s#V7Va7|7x!JzNlOTK?Yb<6)C=Tvm4dOoZ=HdGC>s2Tzwoo?$rh3~_F_iT zlq5GKoxGPv(hB>xcFz~c)gAHlgo`|--k&5K&2+3Ae#r7J6_ZoPTJS}%k{tCkZZL4sq>vT#%b$MI&qXfCT19nWZ$f ze>7T=vz<-jz>{ag%cje+e{!JLX7(=nsD{QA+8tjrlcG^IP?>b#zm@IjUu`L!;kP1O zf$X@rv2Y6R2;@dB3n<*mdC)4r#uqm{@~F(TxL=dQTpkqTJWmB`0T~mX*2TPs(BNX= zTHD9<^34V5Ga&w>`Pl}ST3)pxD5#{>EmEat5BDG-w|-W<3guUeGQfj|t?;oaj3)OR zcW@A67N>EP)39=8qi)sqGV=KivDU)f!Ej@=S4T#IH}~2t$xE!-QxHTw{6>ZBsJdna zTW^i$GYG+S3a2>OwYn{PXVclxqTyDAYUDr z>AKSd5Obot(N7ZymlfIXL-Ku>qI3JS&~;z+M50HPzgRf#ch5rc^>EGdvASZFT@=d( zR$T>2}m5St%pOQr6vnNzL%|aUTfzVeJUB6g`Ts9~W^u$tsq${;6@wFmP zvTuBR3AJa$Z}<9A--6}cGQD(NKy34~eUnL(iG3_v5{w(fNM>^+IdzCJI3 zW64i&O4&9&9fXo-+NKIhA1v-v(Vg13c-mnc}`eu^A414K6APdXkZ<}#B& zP4Sxb4s|D?NXWbs@9_?`^<;H|6*mE=t1x?M-uiZs+ZD=I-*76oYV%fBq3n)q2J^KQ}`HPz@N4!PAHxaYK@D zyWP`bPN7579L-o;+^}5(D@%sGZ%6BOQMo1(xWh}|PQKK@`A#P*{0z@U=T^_O#qEw9 zMl_Yb9Wh?bV*K3E;v^K-J{LCH(c&E$*&{Fs4{4Yw*+Hs0!$0}HPvGfOYmQXgOp@by>Us@zKVhrW}X ze5b|}V9emm*4u~F?x@Oa{ee3w)w~84+^Zc(o0A^$CHfr>Pwc$ky6{}~@}e|J>cy`ZKz5VLA<;7oVtCwOo2rwG{H-`^+7 zein|2rf?&CQD)T04R*J3g*>Xd8Lt9KVlm%idkr{KH?X-k{j@Cf{vehNPxD6VQ@m3=o8J{Y)6Ni9KmsZfg52h4O`5E^ zBlhS}a83qwr(d_smiNTuoKw?!8BrJ-Ny)lGfU+3VjO&@ihwT=oM2z{&S9H%h2+bR} zqsKfY($ZbMQKQ$uD)Vb2a7$)OcTAtEOJw-R5|ZP)1Oj$&U^#X`Wlod27-*a_UZWvp zP8B~Ukt)=jK~wI{UWrT;a)>-`;b@ZE;-B|5q#t79M*kF*5~*5{-Jr5tC5EY2nbf%% z-L*6AYsD6a^uCyYl3ngkVMqvx{MGlc&~B3Am`7WKjA{D#a)%(-zcLwai1x zeJj^vmM7QU1tS<_e{qhm+ufL3>u44h&*J;c2bQ4Oh@s%XrCbx=5}&Ix(8gRCjG00a zKAFks2n()ge`y1P*XCtXH7YBa&UBZ;=jaW-{#Xz9@->-jA5bnyLJu?;y>kQR`Vw_- z#_8QXxR$%&;b2wr+IT0a9|985o*1Bi&bZ>#A{_Tku~iT9IPsj~Bl;AkT<_X_Kat6e z9J++D06y)vh6vtdJ5hHzwz3;jULvwv&-yH!S=kmw#u3MxR~7tI~l;Ta)zm2caI#HhJPBlR4V% zvI4K(7P=~r%FIX^irhq#U|Q1<;LRm7;+g~vw!22g&39?=3!iE!uA;oc!4vagjf*LW zdZlGO=e&ct*E(}MBPMt=#kz{=(r`6o?>_7EzS@(<{+)INeU&~bND()<5W5CZh@a70 zuaD@wY)yi6QzXo4gFf2q#)7K`809y(xv@p=c#AyRUm+%$X$dLby81P*xTC>(Mhl<;zst zD(D3-kRWA)|K7IsQed&Cd0OE?*%nq808N7EOnd-kR`r0!*@IKgLeW)5a_SR;3(*$k zu9>OB>~_+=YLlunUSF5=Onj2}jQyGUF0!}lo2T(!*FNXQ_<}wh`!$Z43zKLmHlopg znOu#UC~a&}EpH?nATm8Z8NFM#b#=hZr1a_7YEWT7QOndBS36as_c$VQBv!Nj(412z z*pP?9lQO=&)eUXsy$W&b8U3W&MqLN6I)B>(F_-SLaz6_fk$0Uh>SafN7_ks8QG_?7 z-zKM2);?sT<-Aju+vJwO9plp3p(^VnDeQDzfV%DUlUqHsS+yICasEmxxT-#{=sKZp z-%Vu`Je^90S87vim6yqqcL}?7vzY=rkB&GFJHVwN&O9A;r}`S0vD#mY$#qc_?4!iN zc|A~%U&rhs$cAQ!T*BDI_vl>JF0%Hz15I-E>ZXReKc-m}E1w4PQL;FNK*1H~WfDTd z>Cn8}I;0v6eq){p>a#Rj0Wp}~!vq%E;qIkp2y-F0Mz(G*n99_NV@9=3^X5ByvoVy#(l{no1 zPyWFkcC@s>=<40i?<&o9NsMIlq{=BJZNyR!3wp&He-Tt5@0DNsQ@);m8m+H%z>Rx70z$CQ*eZSr6^$v=Yf zz|CgPHf3Wxifdy|0q68ac6w2TtLAh*5~%VlRLSK&OIZz#zt_>Yn%&|h?thc@8#O;kptXD9r+j>n2{6~kyZcXu3~l2b~@ck=t(j;D}aNB}wm8;*DN zh-x}b0o1#$Pw!v&6at8VF2hqNEhFrpUPUUNCceH@VnvD3fLHkRu;$&yInzz9$X(6X z-PPB*57knT&9|oO{PtaoC;BpCqPMlCyH6p|Gyp!4n;-*p%J#7ab2uO<#6D`jR;3gs z>C74%c*==rJKnv9Aw2GyoXpWD49o{?teb z0bfOqoi|@H{Mu5)=b~xBHp=BHJ3ynN4f2h=#Y#k0hOa~ig#OI$;Q(~FDD?QQub=zn z>*FOws0V5?u!(as&*K`WbwqEfOkhJ-2bP^P>uY1%y#-3$J3Dro)t4lEFno@Ku0IoA z3IM5!$_ROLMAP0e%8zyX1L@q^n8Mv{##$6(zbWN=1sk2NrG%T&K8;fgWrw~5`pgk9 zYcDHuv`k{1HE>v<@v{o9gNU5G3~v2dlsA%K9^KKoA>Z&Ts3~J#7W*Y8R~?$n7%7|z zQ!P9Vl>1{2DF-nRtD5C5t)5}7_u~fl?m&q$9YixH9=2#SXXS|Nv4@+(*+&3@Z9s3? zAazhsy^F~;nsR(#d;!(cypEZt7sxImmO#Vav|%~~L7o=0uu9c}ouq5tbw%@*k{iJU z@|aQ98pZ?^;l~80+>WnAF;t@1Z3%LmduQLhHi(&2rL%EZoR}rQZFcEV`y;1R7lBui z*8aX><8vu%$-!$Q(^p2e83?7yj`J`pezp$o>vII~mY-P1he#Yjq=Elf6 z$!w%SD+T1XwsKwDw~SkhHup;QogBx5+EV!GLrsL|0I&XyeoPLu9xa0Gs%iPuY`5{> z;=%3%t*LKo1(_wdjt(KG_T4IR<)Chr^%gDC@-H#rhH&G z?Xi8XqvTeN{MgG5y8L>}LB>{<5lPXT60Yqlg9G3hw}iaryc?nItatMES!25TF8FIr zIUpcvcUG+C9ZsyI0PS&!$^BBs;)WmqXI%X>F`ex}FG8@y370N-K@#{)XTgHHH2sBD zvtX}COnWVwN78(o&Dgi!^#(YXNV{U=RGqQGRVhOfg!~i>fCD8k38>Oa4nflb@Ck-o z8|cT~-HpN)!i2Cd0agwX*lHLORBPJ~PjJO}S6VoJtgU!$GTI%2$tIRWTNdroSKy5? za6d<05#|JM&N6EwXn}-f&9$Nt9>7fyZsd(m^qt^gTrj3n#&bKsoa%e2r-}VwhW-<} z)3!xMGxaUjR&+J-Z|B((q)w=}!kVRg9L~acc4`wL`_3&QJ7eD@Lql6t zB|t(5-oujvOC`BUkrw@V9pQe@ftjyOvo}0eg-NYtb{sjGZPF*ofoFHkiDW5$)$27zBwYR9T(k(EqkV*&iyq>{%Q2$j;s zqj6@w+*~$MD7=p{Q?G>|> zs8h#%3Dqb+G=rC<9~dIZ5au+%WWq7dYDtIT0mGkNfUcc=GjuEq@0Ej-`$dyQi$;nT z0ce*c{CB?>j|fg)?c-=s#s@NBO&>Ld3i_9#)AWgHf*l1BB|BB+n?w0hDA@fna~_z` zR@?XlcqyL{y|G2NPSHrElrc>tn1i=Y) z#`D$X#$h32rb%V^b#s5T3_Q7d4!b7hw(RE=*O_609b2#7xS@ZTqn~#eQ`Omc)N$#w z&6OX<;u6~pGaFr5C4`mv*v=9bm^C%+E%1l%|pRkl{95B4y zJ(EDw-S^28y37N|X*3AE7nUq5v<-JFNSIv9xnmC(%RalY@oA)vKQYX(mB&7Z1yOsl zfQO?O$k+y`owj&%30~Nko8wrku-k1@@X2{}C&7!&h^2s4N}F~YH!%_&x^3g!&Aw(w zw=Fs%X!NYhQfCBhYqD(uqn{Y7#X?uKR^pHnHpp0ka2Re<|M3N7N_u>9)6zJEmTjrEashpDL7RW;$6z=6paLa8d<- z9!R$iI3Wt}*2_5Sd!>2{8!HDZc>{5G+^XHIVtK)69l2S1W3m0Biki-A-N0+P`KVR% zfmiAZ^R7m%S9!@tq_pc~jq~}%c;`b^@*D~uPoS% z^lYXXH`%yZx|O47kA9fQ!eV+Wj-?TGoi7&(b#=2=g$mR`c%39<1zUU5F@3Kg6~m?Y zzN!IPp~bF=9ihsG9>V&Kc+~jlTs0Ir2AxB0XLBD%Uest49tlW4{dT_+_07$!D zKwCbuH>ZoqHo9fRKqRVms$*`**tTG$FY{2K^1zT7qODf{9^GfQJfJBHSo4H}6aPcO ztp`$05G#BOzSA`!ywLMVefNVVJ@SeJ6dPSHH~Mm=yF?&zQX?coilrLcH)2U@%~DY9 za{^sV_nQJjyU|iFp?ptbMhG)7Khhn%;>U*BlZqUNnA?|+ekw=LW^76|uylw>m;?k?J{s<^BC?ue z!jd;EZ#-;2Fys3f&0NWa-k}S%gd_wXaWM_%!a9PTF(oR;tNI5~a?U09B%sOF$||iR z_V3CQEDHP$_!CDU99>J!tmxcAW+3O$2zFGujPBvV3_)C}_Y>yucI`VEv&qaWX>KH3 zMa%Tz7=0yk)~x%x35aF|a~ov6%;a^SSx)%_um1Ji5>eRv4~zrU&hPQ4%E&dN&4DEC zZXaa0vmkiGYNp`Q$&G;J6tq2343`gdXep>zfaBc8KB%AO5^zXAmJ$;lV>ROhzp4R0 ztG=AR#>WT00fsYor7+g>xF&W5Ge)+>b#`T-#}@Z}`#!C8(R&^E#F1tyK&7DI|Nbj; zIyP|<|-#zwO8GWn6c4CwshHklQX4ZS_Br+rrKY{zTih84kwJlY*>?V}8 zhBN%3{`>3o$QZ(~DdP(KqRNs)#^K)2-kkG2*|H+-DM@b^!KnKC!W{7k#Cf6{=?Yq_sVrXKo_<|@Ktsp;l34Ayfbdj0c-YFkLJCrg^3y(-gewdVIrK;avrr>V?rTYpcr-U^SS% znBHya_>S2}gfi91NH%sm%R-iQTNPD zqx8Padzu~PaXZKgD}5o=w~h;5sRvZ@z3zP>@a69%Xg-T7n_lsE33ajgTW`slyoVk-X z9@CXQG zJwt5CvKVqBpnt(~Wmn-_Vz6?E#(Wf;u^%y=XnFY*X>H`^vI&*?EPiZcqoW%BUh0B< zDUBFoO}nxrp9|KsP%9*?cCFm|!KwasL@w;%=0Rjzb=9lOOUD6Yd=3D7clw4xn#qY^ z*phI9*7M9ufXUllqrEGT1)DP?^6pQ`_gdtTo^ufp&Z&X{rAly+1l$s9J^mHSD!j$O z;SwyrSnWu#-s5k5cbC*K(Fdk$uCqIyvTpQ|g%4xRa)cgtlPVkoN+e#d6MknqK!9A1 zs)|%FLu5T^aZw7u;}`TecH8=+@s-lN?28GOBs9wlq}>M7G z`DV~G`D|hUUb#&y{*XK#K~xG@aZ00E9j5DMLtv>LQhc+_vm|Gv%LiVFPRMwhl}Ee= z)Y(Ydj7&Q1%TyIVdIW_t4T9H={cl;`cDb*5LnBC@3o*9Q?)IW$&f6v*=ow_Rzl8u4 z@81D*+kIoG_N`XrQ1vGq~B7q^9b$ULyWstT~e}<_k4#m7YbSOF5)m8~a(Whqfh0U%Omp?q>^c5HL2R zO>;MQ=Huz;M-Z?y#_zdQzc_H(J;SL^SV!Lmr1o-5WDV@LBOvUnKx;fUC&f<_-y&P- z7xvwRNMkP8nxO@v2oU^cU&#gZ)I!SrD#86WKNl$hFx`Qbzj6CPe3-O3YvJChXBkqr zY&P!$raw!)S^D(D)&m2a^u_U%l|_>zrpxb1GHwKJqIncM!a7v5sx;A9g)5q6%;27V zLY<`silFdOlg;{Gc;K&`3$wtSQO_$M{P7Q8)382K)T`caUdLoA@4|lwCNTOq@)6^wp7gr zky}&)x{s?}={Z~~fDx6$TFSN#!7CG7l-pIzmZ!p2gbdoIo}~_7=k&yliTj%^l?+NN zkr-0KW{!5dYHdAE zo$QS`|996Tgtz!D-ZLV(D(uay?Htuuqh4~E}$zls&+jgQd=n|YEI#@nh?d4cH5&ZRR5oyI-FlPe#YOv(F01FS&vAZJoT8SB z%C)j=uw18zyuzUN9w3VfSVwtsPw=H6VQ57r0HvvguYz(=+X;8{sacp$A;VUPUsF&p ztd5o0A(E|uw85}&x2f2|gEpGzJfu=9`e|dNyQH&YT)5<#tIH{bC!_4UJQ9G|-+5n>16J`C z*p<#C$3fy$@XIP@r~FM>2yO_0>Zjg17sT#NF@oTuwOWlcmJ{?scVb zY5$$<%7+Xb->Lz}dj+~N{?6C5E$e87=fVb!Rrwh7>W0c${d zHup0rX&YIA+9^UAbMaVQ@+F1(y+sl-Edugf@;L;N5@zovL?^MHicVp~!dH^xkgXL_048+QL#Y%b(Y4Qb2+whcHTJf#>M_JCU zfofN0!yjt0T&;R(KqN~bK_;(wfzlmtR)$;viZMQ$+ayI(ZM-VFiM3HmtSc}k^3q+; zJD24xs7OiZ;kCO8_^PT0&v|xudXb;<_$k2Wt44*)RvyN4)AOKBnD0dZk#p)eD1dV5 z8OOZYR7Jpd>->E9*ovy4$b6cd<36vZ(cM!5tIsact6+jv{M@?cj%jn50-;1+7kGf~ zgx8!eoG;Sk`i#s%r4{asQ~Som0n(t0s+qzK>yPt22lXh>fht4A1yXHA4Y;@B$q=>F z`#<+l$B*~VcvXO1-ZM4y00W57WzSi>+bkGUE% z^=Fwr#icMmyf!m?MEB)WCngQ13KT7AT!H@b2Urf`I?$>wRvQNqh1C%cV z_?=I<`r|ZZZG|FDX`Qe#RF|*Wy~kRtE&M0LC57;%mpF+zw-WUMQ$e%>k*T%Gm}V#= zl1gBSRhW8FY)$npb)@V2XZQnRPN?#=Yh1jXf-#YFUAegz_DEQ&9tay+;mtq<7*T73 zUKIp4qe7MMO6#1F2vrLk%HG9p_#t>@pNK;^OXFzgRrUr|G_gIksl~|MTdBb9DipxR z3tjyaODt0dW7xL|q4@fpVvbCu7v-rZlv3Qj$x$}XCxm|6+d)|$bw0I8p#?54n|3T8 z1V9Zq%b(gQQy`5H?w)1}?Lq=PPe1jX#|n)vPp zWdJj>Tb8cCYtb-o{AJ z_b;<=nVz!EKbIxN3`JnKF`ZF*{)^(&mx^qucKXO6#pu^9$(XA=jC)_|xj7Aa+2`9Y zPAUVtIW9IpEtf_+&Y#B9knRYN+2D;cA8QxS_im1(8A+PCm0v`3YBLI3Z-{r;bZ1)sL~A3ug?v3t(&oQbIyM(eYWIaeBP2&~dG*0SJS1&*e-H#VK)}hYDog}JldIY0 zAH7RhSB`==$Hl)^_=jAm6is!&V#7QO4|HIKX{ejxn2`9J07xzkQu!bm5`Z87#7`e7 z@e0j=NxTtoF+ZXVJvvfV)bA7Qfwwfm*kHe&5F|}_=z*4fMm25qsuK@=F3og59Ls45 zZQgCO_a3B?>hOt=PV!mB$fPMduWnwiP(2kJO6^6#5A13pAOK(XYGB-Ot#3+AlOxXs zuvf&Bes7eg0*<0>CmT6qi<%7xLYBup_=i6(%sm;@kYf%m z9JSX~gI2NiP*k-m_B@ z?z&BNA`(B*6|h?l>yX8@;nC5SWl}XTd7*Cx4jw}A#F?|TxI4Qe8dqg$tomG0qeICg3*==yKT zKQ$1d9zL5)`1+Qi*0nM+z!{m^b?L137LdR%C^u;=MBEVzRQ8%x>TdIQW|{8D>pJl6 z?vV6x`#g_ppF+$lr{&MdF>1zu=#1LFk4sZr**UFG>VKyvY zcKR(71=W}e0NdRJV2rBuV;&ug8|}%F&Q8RHESZbVT`Sw{2W%Lg>d1#%->`>V`7cOl z2w2OV^-j_8@xk2MQ5Y_T;mIocWDF{Y_NUR)Lnij#?m{JrPRm|t8P?_fz&k$(f53~9 zrSHtEwX8o`K7()nSalzkA!iwQ<6QkRBOB|BnJ$J0cs5D)G@D``QW-%?GosHoD0D`N zP&jo$XnSHDMZ$A8lHp69W^cQ)4#P+l0UEOrG=ue!P8s@7xJ$ zQUk0@>q%kG}ntk223`5ha$((m~(8Chi4NV)k1Kt%P`s~us}Zo;T7fuj-19);y}4$p~Y)5#Mh zqJzZd+A7};m5l*RqOW*Boip5(OiVkdiHl-6$mGI&ee=Vb5b)7a|M+6n;8CTj?7r+_ z@T+vUUU+Q=KQTx8Hn^au-}`ZZS#lct4ki~Wb(yKhHVKH3m87QA{SYh=*(TE_clG1r zX+EIR_Uc1a%Fa{bOBs6H@P@Mn`u8k|MLJ<`_=<}JuwU1s2MS@X`G*wV=YZZuQz4K{ zS)aqb2YmuQI=HHg($uqRJvna5>`hK!DrVLU(aLj33@PAY*VS3y4OCO+eI+jr#G7PN zyg5zWyzp^^vUFYvCPcK2UUvWDzvm>#BZ=lbmWm%fe|18^N>Td zU(8;iubwlvl!;l`w0bYpxX*ejLtx=+z3eekGz;7qH5j&S2W>=m|@?gcF+M4xp2kluZL#$Y9fN@?4b@un;iB%UyAq zO&F^{icLP+RwoVRvj9|^H6O7g>Gr)*xI^&yfQAE4N9Aj+{HL^|d#wX)q<{%DG5GGo zIxmyU#d(Jmw|_L`z08<%_mfYR&Sd}RXV-ofZ|4E+pnIo1*5pdbKIAOjs$%tA$>VO8 zUU3m|AA6s%vAN)lvSc3_rZN*fan*tYU;{(0z z+D#q=bQw3-WSS>@vj6$U)uAAey2-EHS!Av4nc?JC@w9<#^Y_55w<$5^|L%XVHl6xh7{G@TrEmqyg+)l(TN{;>TQKLyBaeC;14LFAI5sofH5DP zp#GduGmP_(Dx06nc+&6kVFT7Nk)daU2Mb`onLW8ow7n&vM+&zJfH*IY#l3J81Yu0b z3L@lC7ULRvMfknAwdLv+Jx$minAmn+s&ap%+WK(ZWG{7_wwHJs32Q0;`GO-4u-kC$ ze(luj!Z1HvcMdbn-Wa8FxnKDh$1%^|DOBE8M4OOI?q>eIwBOP{nqMO`}p} z4S?VcpqRoM89L`~DkS&P(V$rh_u?b!ux0Sd-K|8*DSxaArVWy&JLc6M`n(iKKvl{> z!iw0-Eo=b);9)xGNf6JVA*1Qh&Hnhk71_MhR`Nos=!pYDwNBkBh~=)82F7yuDV!8E zsBSQ=()+-sZ=Rkt38@6{`i6yjuir2IW-DrsG82s2)2XS3c{K0Z2PU2Ey&K&oVat5m zY5fs?>%4D0sWolVbfzt6wDPN{_;wKI_Cilo>0}jFYRff3RdEW1T41$OCCOkn-DdTy!~&fxlM6+fh!NBciQOJsetR8vIF(z54Y zdk^&AxL6|!jF}cz7x#lmq4X3av%?rzuR~g9B6~!jGz?+gI$r}KjeTRa(}$hwklPMK zR;`sMtd7p=;BAbx*vP#TB!MRX9LCpqhi$-RI3uN%zH}0l@uxW;hA@iL$($c5ZpAvJ zDoozxiYEAFYGNcF6J?FXFG&8}tGx`EX^7pJLU)Tr=GcTrM(^~);#Ad3GwO1c*bVQ? ztvkslatT`oPfGl zKX@*qTKD3#>3#H|*|wQf_AG`ba_xNZXVNP@7t{fxyc3*nYO`Z@)pW0u^PQ=Ha)HE7 z@GKoVr^^))!(My+#dL%E0Le!Db;an1fQ^)R;+i&MtTwiKPMCpXRRA#tQ*jRE^NZ>eN_$+f^$FR&;#1~a}_6mIsd+#OVXnr z&?D7*s7Fou_wTFd0NNGRF8=+1A`hrb^RDMT`~7s1DTe?Pjr7c)tB}8M(+3F9zo7qX zb^7O7@<4_6uNP!Vx1m>_7m<;jcu4xa0M`Iwu7zLw^J*Ay38W&n*L)=|NmOk)X_2BnHrJ8 UY;H5)H}jCGDQPJdDOf!DKSc&#FaQ7m literal 0 HcmV?d00001