From 111279713858fe81cf08b72a6c54377bbff955b1 Mon Sep 17 00:00:00 2001 From: D4rkst3r Date: Thu, 30 Jul 2026 09:52:45 +0200 Subject: [PATCH] Tree Generator v1.22.0: Phototropismus (Attraction Up) Aeste kruemmen sich zur Spitze hin zur Senkrechten - als echte Rotation um den Astansatz, nicht als Z-Versatz. Die Astlaenge bleibt dabei erhalten (gemessen: +0.08 m Hoehe statt +0.93 m beim alten Droop-Hack). Pro Preset abgestimmt. Idee aus UE 5.8 Procedural Vegetation / Weber-Penn. Co-Authored-By: Claude Opus 4.8 --- blender_manifest_tree.toml | 2 +- dist/index.json | 8 +-- dist/stylized_tree_generator-1.21.0.zip | Bin 18435 -> 0 bytes dist/stylized_tree_generator-1.22.0.zip | Bin 0 -> 19331 bytes stylized_tree_generator.py | 65 ++++++++++++++++++++++-- tests/test_tree_addon.py | 2 +- 6 files changed, 67 insertions(+), 10 deletions(-) delete mode 100644 dist/stylized_tree_generator-1.21.0.zip create mode 100644 dist/stylized_tree_generator-1.22.0.zip diff --git a/blender_manifest_tree.toml b/blender_manifest_tree.toml index cf7de5f..7e62cf4 100644 --- a/blender_manifest_tree.toml +++ b/blender_manifest_tree.toml @@ -1,7 +1,7 @@ schema_version = "1.0.0" id = "stylized_tree_generator" -version = "1.21.0" +version = "1.22.0" name = "Stylized Tree Generator" tagline = "Parametrische Baeume, Palmen, Bueschen mit Wachstums-Stufen" maintainer = "D4rkst3r" diff --git a/dist/index.json b/dist/index.json index 45bf113..74ed23f 100644 --- a/dist/index.json +++ b/dist/index.json @@ -32,7 +32,7 @@ "id": "stylized_tree_generator", "name": "Stylized Tree Generator", "tagline": "Parametrische Baeume, Palmen, Bueschen mit Wachstums-Stufen", - "version": "1.21.0", + "version": "1.22.0", "type": "add-on", "maintainer": "D4rkst3r", "license": [ @@ -48,9 +48,9 @@ "Mesh", "Modeling" ], - "archive_url": "./stylized_tree_generator-1.21.0.zip", - "archive_size": 18435, - "archive_hash": "sha256:eb093c862dc7192728e86ef07d45fc1a9f4381044c2f8560b399f2a85911ec94" + "archive_url": "./stylized_tree_generator-1.22.0.zip", + "archive_size": 19331, + "archive_hash": "sha256:5e5e3b5e0b73aabe416f93c27bbef4772b561122762dd52daf836f10c0e45b35" } ] } \ No newline at end of file diff --git a/dist/stylized_tree_generator-1.21.0.zip b/dist/stylized_tree_generator-1.21.0.zip deleted file mode 100644 index ee00ac4da72138eb29113122aa1a0ba99c5cdfaf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18435 zcmV(>K-j-fO9KQH0000807XCkTtD0uLm>eG0L=ja02KfL0Ag%qZe(S0Uu|J-X=Y_} zbS`vnZERIg!D_=W6uSrV560&>Nz<}JVV6?qWn+O3HYg*w@mu0Gw#)O&M)&n|ytcFl zV=N?Dl5cx3viSz|+FAC<_$)8;lBY?UXf?e(od*32sv!huINWoSTMgtkEOY&F7!TV^z|H`(@{M&ren#!s-p z$VhD|9KgwIy}*N~dHmsYjP_C~;cTq(1ADJ2qCL^kFN>nnl&iBSS5RCGic4XEu04p` z!ZExLCOiJJ|ALly#`rV%KHg42DAw_hiMSuYD!|LIjnQ$ZMP8l99drxUPlZl{u(huFv2fBPo;Bzryp5+FfJow+l+p2=-V1i*uX zgM;&paWL}3StO3c?_Yl<;I9#S3)wgnjjQx?;6KZ$xQ?Y1Co+_=mqu};t=f63^bWp4 z%eOo6eUfhHj~-;4_)!SYn*FvIz<<4#el`wdIF;D1xdYG4M?p04QtsEd_2uLCTk(Uq z@~3j_#qdePk-cUrlS%9^b(fD`44|j6pG@v#EM9x7Md$mEUa*j1=lj#x54>Kjpb zv&LKpK@eV$2>r4Sy{vN*ua-+Gnpdf}Scvb$u}o6g>f%tZ15c)@jKBXejzTFG08uIc zU*dd~KEpqW48}<+I%4X}L?!~Di9!+hawcPF=;6CO7!C)+@!p@Fe;S@%9g4R&2E4s< zyqb-@l~{$T422J40fNI6K_?sxC(#K^Mx;>`B;Tvm8l`~y(OibzqoWopU zstYlUpXCZifN9}BUJyueDdz!9!CQzA(bS*$@VRkvK0=~shz<_uF9cG}59Q=gO1N%lEPu+hoo#m&dj`SFJ#Y!-aA zUS#r_e|2=zJc!ba$)%=Oe;mO(XQZ(PnnYRj3Aji7qUw`#>`0n`T?E1>swpUV4 zfjoPfWZz4FewV^8yWQ-!Ygn0kap_I{Rf281y_ao#Aikl^b((f=Wqjw!APxQGP&NGi zeFV4^e?sg2HV;(&2c&_c9^jgby>4$uEPyIr!_I5kitgGO94OBz$>}HU9 zOX3l|?t%X4b?k+(Y;Pis!lN94;k3a{_{$$cmj-Y|XGFyG(` zbl$?xQp7SKN_k$Xg$EY6(3=Sv&wAMAasi{ukXEU;-=Td*`-drs_tTN+_dESP@uIta zL_p*~Ji?hdjbJ(faKjbgY;rF;KZtn@D+;(x;Fx)q-NIb6UALRjHLTnt5(1p*zpZF9 z;4qiK6Jnt6)Js$GBXH^9`?pc7SM_Q&&i3h`ZNUbQI=nZ4lHYr)W$M8ZM1<_+6ov!j zn`~#dZIVUerO#s-Bb5<%qE+ZntX;V(c;#3TOo64O|VE|2uIP-N8|c?QfO< z$cZ*TngrKOD|49Vu;PPQ?0k{#aAm8u43R!(wDe{I`B3LGS0#S77XuA)i5`= z;%edrl2~`oTD?mjgp3e(;9V+TiJRL5#sJJbMsYCh06Y_rtrmI$8S~%`yl+eZSRs)0 z9S#?(wP2PKGDXstHc=pavzg$VIC>0?9kab_a@c#^60=Cg3x5s+2-t3`06zkM9fRN& zs%O?9A=aGRWYzzRb+o90EJKr&vc zt-Xf``$jxM`$s%%jgB#JC!ltK>=tz4j76iT!X6Yqi(gfU$$xk<3sU zKEyqMI|;XdSi!*`i|5X3W{MK!_*4d)<7|P_KW{-4!a?1NY4{jV&8Cd!Al%G=HlS62 zTz40w8EbJfVYA=u=QPKHBkV*VThLU9_L5gfAABCeIRc*_We7}RJ*Yfmr4md5K!My4 zVP*zGxJa~!B2&)~tfMTO@;&GQlGGPcE0ACU*`f0)fxQO2vGaO0oy)YtI!96d3}Azq zBkMB>cMu-4aB{#(nNUT;avvUiJ7Z1sBgg52i$naV-h4;mqaO0 zD?LDYA1{YjLreVum39F`{{Dv|dQ{3mqJ`td%XaG}D#5+okeJ%W>jtV_Y{MM@9?;{CoWzO&+~Db z#IZvZh-c})fyCYKiz{FVc>3bh`@20lp1XOMPZAEM&eiql@NCE@-955R0131L$s#hG zQ3oJ8?)N~=BI5wax`a9EOm+lKA2=kjYi#xU?D+b+^Tvy(iD+IeVHJ_{NwM9fd6H@b zoA+Y;o4ij!mHU9yl9^HR0ks8!R6M=iQ|sLISm#Kp9$7KU42r zT5`YNE^EjzkNvi-9p`$sThBdc7Zg|bYcuq3J09lBC@exri5xh36m+jWSCedMcXrLk zmMBDT%n=<(k{m_OuXC-TEU*ycbBYVZ5LuZ3vAI$dFNumcURmNZI+*%Xub^4v`{>Br zKSpo+>@$be`h`Ihxm?c;|H$mLXfUnXgCMW8E6hpx7Nl*OO?tnMN_U)8deAPKaC)^w z+TU$gn^&A$74{f52Lx;B5rsIiR z6ClO7R&SS>a%uGjJ8jE6YcAf)y2b1F9E(SGk}o=Uw%6@wd*wQc!isBG%LERp){Z7` zuHAOc+U>W?`gg^-QRcONe4no=YFS=*-zKwEtdxs33+T#(;@*GG73>|@Vv)7|26Zdw z-hMkJrrfVx!5tS<-mlwyea8Y0YFBW-a`*MWUf8^*KL3EvvlCxc)ilbtLK^9yI;KX299;xsgVQwCO5Ds zbOZ6vUewZB9+Y?EptzQ41Y+7qD~@y`hEW`&mF^xjL|)T2T54f?q7Ozc7MWSNsFXN2 zU*8aj`UUp6U$=^T&b_z$FW{baJ8%2Tjy;PR6c%g$3y!_r@?w$fXsKSk{gQ~pwuM7= zwy9Oqeu`9|c5P*0636j^4nj7moDWZquTO7>AM|Lvb#tc|yTQ;paOKTcUL19<{NOHH zp>z+5@Q=ifGk1noUGE8|D!F;vt-B7az237od%sS<+e}0vF{GAIdSy!4*{fr@y_${P z=^K90+?R^@&#_8~M$<@!-`1-Q73Jp@y0Mak41i=R!jVZtjy3YvQ4SE=w;R;#8j2V^)VIA-Y3N+LE0pecFkkh@CSYv%J&qmWerr-GxfuZX-6 zF!|>dn+U2EMyJMEINIzJwZ@`Qq4^fJ=Z;&`+$(FEbU-Pi;sHZu+XN4cjsC~F(1|bn zLtEq5UrpsqjFM<_-wY!ZpTEVJr$k%(8jZ#~vJLkS#T7J?$`yX@A>H0Z0h;R22zwj= z(S%6dGVDSx?hdM%2vPc`K@W4R_%ro8ytC_v%T;PV#lKjltJrGrOZY1{i9J7oGe~|O z#&Hxk8w#)&i82(yxG$21cp;kf+BOd|4o3bIe`vLgnMbSCIq}UPhu&*IS1oeb9nX5d z<^YXXelQ)umR>EJ8kQ)S0?QaLKX<2I>UFU%w@A8knKtua9A!%f5TT0!l(TCr7tw=k zLQB<+%qY&Lp?oyn0#vGFxG;!{;(F8&=WTHYgM@SHP959$E%3v8`lbOywv|2D^70_*bB7N1+jWPrGAM+HI+EycHj4GTz+Acw+16ee)WP_);x4Aa;P z3}vC@+Bjr0t(*g8r_bJ9AmCrL0T9#r5t${hpa{k$kBMc=%sjYF@+SYOhe4odufxBC zR=zLrZ?Osh@^c{HJCKKCMCAt$_I>LWKI-ZKKxoq>6!6c{60Obr`__k>v+L83XaCr; zM%CM;_iJ~`F;t@mFIXYMXF=pKUR!yWv*ztD+9vaB+Z>_)tI=%nR0-~r4XyYNE%yrM zrvk{wKb?NK`Cvl)l)tV7@OHOn0!kRjc1_#p+cQB`n{4r95fzZ%$O}I=zs)#7QlKkl zb%R48<0REFg4dsyZ8}9M$`IH*h4rC>3*$P)y$r+DURmTFV}DBFe%Y%EJOVb)Vflzx zfS)&^d&_<-pC)iDh#~z0FLv~vL}BWOD_KIsc@$>*i}oIFMPmBEKC;c+XamH^5RbMl zZmvJxTyKHAPi;o&=cPQ_LUb^%)m^q)CWgJ~bmWJ`bWu})K8QG4P*|$)2*JQLqYozP z(bZUji-*w=ot~EgqE{GbN=oFTzFXXTfsvlTfKx(C0gXu)_IK8O5!yYU>U(-mdC!dW z6jC@Qu`LWFo`xw*NPF^r;TAyDuyYRJuVwdFaPZ!h!BNwEP;E? zXjWSqv)6Cqo-B+>lJJ_bs11+d8iM7sb?{IlJxIR{hp7i)=O`G=$MQ+itX3+RJ7Ga@(~?9B#0rdCRrKZA2nQQ$64y8&GSdQ&2~= z#wrrfJmKK>LPJNTh-OlSC}tp2uJkZX9lq2d?Sd5w^pHQIdsqi^6yRrlZnFt++nQA~ z^{+KUnoWOgbNJVO#imA;WuqO94H?0^HA|MOb(>8)Z@9@$yg=9;mxcG(d-D4!cjKwrl$GBKWP z(1X%2rZr^ESY}fs1hTop|2RivBk4vXa#J3$=Yr9&&a4^GXsMTB$2}ZJFl;g$x6C%= zpn5!IsM&N-)x25;GQ$Tq8PpW^aI32HkMi&p>`w6Xy^uxEDGRHi9(hpTyS z@Ap~`C}K1`Hdx?j<=xTVr~p)NEp*@?Gq^FMpbYrc630-fmcX6?bZqE=y_2am%gBKN zBFm5DqK!fv23olmw=J76a;W< z=dCghX{)r4R=@_Ikgbx6kAYnpy9j)FCG-fla)LR#EtAHy&TY5+WGq0KfXq;sE03hj zU)aK)?91Y0v4v#@ySjOOeR=%mdP{Y$wtzKBk=Or|!Or;8lLa~pBI4QRXk-)9Jb-Om zyNBXuia@`Z%`n7REHO6O3W=S;FZC0~7WRa9_w5N&3%99Kb+4IlU!54lSMv!I4vob% zhjGkw=TOa&+!MTEI`2U5i((!2&VkC9zM%tGIjeyO8iN`-t1@}gL)W5bDBu=#=2{{^ zt?Y91qA~NVN!vPG=64>EaIt+qpMC^$u3tTDVM9)bNGIoV)WRm$H^*ng3~XLqV=1UZ z8Fqz&(uTz5`Hs$6olKoP>PlK1iksOp7?jvF@>z?c>X&nO!-ruo1fF;a-mD7~lmYTL z$~bl?NU>It@ZSOriw;Z9@MT7erq9Mol1gWeJq6@MPu9{=CZ?w*6}_sVpmbI;^ZVgL z6?E{ZKr{ml9zJq2w`|lJmqcG%_~AIWiN)xbLHG@)r3M{NXF6m|&;EV8_3ywPaXWMP zUt7#6OmpGMB*B0O>ej^wK!L#u3q9QPN_o7)?-R_i1)iWXrJA#U-*1UD_GdFr54c=~ zQ;apH%!JM$PnXHEEPw=3NuKyeKb}$|?2p5f;aOL_rr4+NRKlWacqCNb8o{PV!31#* zvsow-YGP_t%kVv6g!P>ta%uz22J{~c;HFp)fUs*gJ)n~$5*V?Uv*=A*K31*x^3mmk zf?ut*{&?|ec)4Ycx4Abb1ItC8`9PLyC#eEAsrEr7wdBdh`wa+G$rz6oktR-GS)5jZ z8K)&UN%sBB&uVcS*BzTc{uXX6DC4xwPZp;+KQqXPQZ{(IiId@n;pzF+@dr3~=9o7` z1trkzimtLO4U4n*hzsfg7XYLWr|&ZzxLxtdkMC0zjZ0qIN2F-nQ{HOEQQh>)c9u*6 zO)14W&Bn~*nso9}8b|3fLh$H^&;DHepa1xuMyer2CM9X-iV|8e-b{cJG?u;|aJ!E` z5cF+M+o8-KOot_Q!TGS}zM_coCa|bcihEQ!t=hOrrP^xfX3c)b?NiP{%yxkCjZH}R zJ^~3Qu^eRoHNN6A2mF@*n9h%EMz-hmzu8N?#`pV5or0!S&U7rB93-A72c6;CW5f#& z)7|u%)HwSbX^x`VP?nR{A<-=6x6?6zS(%hj$ONWNsJJ*H9viAALoxvd9|RaHi$@xc zmgi7rd9@j<`1GEIFu1 zYM=~sb){oC{$t>)Q%qXFM+X=#dU3FffVyG;k`k~`6n9v%F{l`s@SwAufm$SlWz7*Z zFpnT!D+H`SUVGd6h7GC75># z6y@14AHRKD+!x-L?F+<$3Aa}bccl_CnN`EhV9z#0HL`RQnxa~Q^LIWkLCXw#GBf0s zO6jTu{oX(eR~sCM)`=Y#^{9Aa%T#X3Pl;4oqDt}j#Pq~W5C>KJ0LgbS$UWOe1s^WR zgVnt-QG(K61CKJZF-tgeYagm|1sIH!7Q<@4A%TqaoSa33XfZ)Ek9dorYC%^FNxH$L zW(*h)=!~-EGPV0tkl-rSR(R&n3_JTh{cyeRYM$EErF^iPervNyhWr%dgG#!fhXs?t zUZ!5t!+I!5$2At8``BR8QdhS!AoZSVAccoT3v3Q4KCF?H00^Fp1q5~~fJ*C9)u?Y; z)68NihdH6)0ipyMRYT5OkSVPz-czbpc6h-t1?QI@4oi_>dL;(fVbVU3A{~Nb2_pP# zh8lvBM(#;s!FWn82EdZOqR4nwDUrY<7d_&3(LS;-ifgnx<$$S3XzM8P2ZSu!m2}Fe=*~J*-Ef+V|#u$!O$Xpnjp*pHgD39He{fHaXgtOc7e*>%-x*eqOxytD7J3OfwI zhM^b6u)J_;0chqf!!WnkV6>b*S2R7`#K|)L-~S6U%E`_FCv!9=7lhj*o5ud4JZ<2H zi_BSxP3)CIv0{5rp07124Lo))P1RLXPRScoI`l~C9;idcas^@%mzFuA3POnh1>>1g z#9v^*mKDD4>*!joU&}V3IZk4EW{3QVc<5I)`5$aCnDO(#aFfIiQ?6JqnG5b6M zZd?^MFm}fcj0=GS1lwkD1LI=g08z_MDQp0Xd(h;OE4e_Zi5eKY!v@CgxB)KAX;^a) z1$s&tN#s`emiig^_X(Gs<4L-E%fd6H2U<@FBVX^TS?_~MKxPZ^YylL{4p!}4A@>K zeTMuyt%v`mJX+HI9y(&k>KMzE68?D zW#G^cdmhCLFHp4@QQ%pUOBMteq@4uqCz(U`EzmQ!mjcNbzN&#FRTGXeW<)ek!>N1{ z--?qcn4(EVeDcG48MHD}Yo-EcsR_VBV=wUMG%SoUAcvPW28;fev67~~Q1TWbWOL*SDP()%cir+(<6A$l&cXkjQ( zPtSM)1DASOT9&pmP8W`bajHCFq4+1}h9j#uPEyk^Ho3$6)u|shmxO!e3tKHMPnhZ3 z@++d!2%i*sQ1&oEzj6da&vMr%mQX zBe<6EtZ9(CibsXER=86}S<`9#l%PRrM!P+=+&evcs5*DTS@XfRA7Fd?#ABSeo4738 z@Yu<*(ff~_(&XG+sK3OhflHvAWbh2qRc;HpZzM49?&a~P$TD$~Sw?T;-71{m%n^mh z`1Ded{&l2?78an?Xt)YwoVCc4=Xrd$_m`eoi*k^ISDoC;-H@B(;{0qZ&6>R4Tqopp zM4UNJQySlnakaU*$C4YLn{Q9w{5XW4mLA7PG)_b0_7f>!N=gM5X#a;};hhYo$j)0hi+pu?098@d2W^8mxR$Z<8YCPVf>BW3N_Y#~=0HbqS6tjt1yohXoT2BN z7qq-cL$!DmqqvA3O_iYKiYOk1rf|VGa-d{_Dc>HW&aS1?%0#os#iM1>z;s|otuJZ& zRmM}%(}Etns|Ls(Tbuap>Fw#;JnnK?v_h#q72c9u!nNCFyLp))ODe;=yhKJvFjET~ z=0P!3UqfyJ#{IH`1CPsw{o3r|b%Y+LhAX0JdzZ`RP*o2yE#0GdJLcG3c8gVx={+@S zG$hqw5`ZF4g|1i9$C^v-mhd3+@qM;a>$=pi;|=*s~qL`AbgEw-1!Jp z%*7^vDF#$FP2WO-)r*lrm8hFnDdzIw*^MgRxGUbm7J<_U!STrlh}A2ys!T?;W+RVF z{2+ShkjV>N8kH>t;K8heDVo<Nnla=4KzBIt_jFTpmZ`lF<5nf0aB@TJ%CV=mZCYtf{_Y_$@6l9dSm!t(7 z`nG|-bOY~JAxjeb6apQd?YIG>MUKNXsRq!dpZ>0a!?ZrM6`yZpEuxuPFeVOLQMs1t zAs*7rr4MRvs;4rpp2|3J;kr+u0{E~F+4#IJvbev~-#y5QqJZkvpg%6xe_I&AD!wJ^X7s=*5i-c^I&OoF=L z4t!h}|J}>-;3maTut`uN!f#a2cC4&UBqN8ND^874cN2^$;UE*TW`5-{gwJe4e!rK? zw)n6f@k$=Egh=dFKz_lLXf`pt#y<-?YajM|bDm7Qq1pVqptxAAkq zN^09f3w<;&MlZ%vNwrfQZ1ceyE%l5Q!s^kqer#pPdV$N;<>Bp(8r+1lWWB&~u9uKj zm?|b`JDlz~S}`4~!bhoWoZ|fW&3kg8E9e{|_;rk0Ayu%X%JBp$+aV6c9p0EpS3ZHv ztff7jWWYCxfuh{ePYg>d4Dl%afG$adp=8oU^DwHCXd}k7*!=oY++RA*7h{=13@^`j z(>I_FKs(G-c!*+aI(KyMsk-cw(TDeNWtWq}TcUeZ-QJ)jH%p6XQsxm%8TD=Xcu}9e?uQ*O9-HnDQK3Rt|FpgpD$RQhP_Lt*WJUD6Z5Mf2w+W=^9ini3R*s z{Bz|^WA;4p9i|c9R77PltuZ_F(_tR}S-J+*92pDy%R4eBP^eLy*#s4}P0rAS+BZb)(sGOuk!#cLsg*-@DM@`Lc`oNhFoHYrKCZ~T*IgWm_hwC->>l0b zGvC;DD`WhG!eS!vN+_3=_KH~_hhygApOTf}7rv603JG(Rlu<*D?4L^3s|q{d2zHh1 z4dA^6rXreQ)sdD)F%R;#|TZL8feVldv94SCj*WJ}178s5v=)Jv_TPKM~E` zGA9h)hiifvHsdVz(kPH7N$Bet8sX;toSi zDxy%WI*Vr0LIi5^B{8H)DTb8E{AH$yBx|EclVTJpGq9JvUJ?8}hBT>)Ax+#dq=_Sj zG}$bMG%3Z9(!%C5%%VsS+Ct6V9YvbdM3E-$DAJ@ViZtV`hf0^UDorGvvuN(~)ebqg z6iqX%5;y^8^tZBzDixxH?2|UHO5!KA9Avtbcry8O$f=dFcZz8WG3bi-v*weV7s)Ee zn-Y=_dU-A$USWuA!nov}@|!RR>FUkH_m?h>Radt&KSMt^!C)0J(X+ktg3A0&dRW*e7(fW*(#sxyaa1gKGv!6= zm%iI~tM_Gf0B=$Z;2msl8^ErQ;8pW6>v7ltyp*_EC9Nl};N7GqcsD5q?+(aXm{U(u z7rdKn9K4$pgLe~G@NQBUDVvlcWe2;O()H6Xj+9Lbk+Pb;l~kZZgx?NtuFp=jxryT^}%CFDS9k% zMUUlpsBD>oyf%I;DceC|%@o)MJ1EAFC3W#*$;RQ;IL$K-(pg7E^haC zU8;HF@+~H{&c(#-TuiFHi%HpXWcMjK7?XMrV^ZZ}Ok6%jr3h{6VoXXtMy8uG?lyBW zCUsuMT*1&GrDI>tRq6u=+@b7Y3N9R^ik`nvTuts`KTUJPwU3;TrH#oQs10-2m7s## z28$DvXWA&>tXML!^DIo~$`~KU_hg1T#tlK-a+KVy%=WZ;n0nYEtr0vHsRQ{MaC}+^IJc-R`+PUUzt7vyW#s@Irg1+Tt3U9&(M06u`JPSwvND{i9N@ieXGI|x2SP-Dhjlq!7i@V zA(S~b60|QJV+ls#tS>2ytqPgMJI>Rl(z!uHxSbnn@(zf(OTBZ0oeCJ*ER(yo_;`6C zhOdX`LsjC5syC^UwcctLL^8n$nXK4ACW{$AYuy88Zs8jv=UW zK}v@$`F*Dz`J;2^!fYkyX;)k=(MY%e&BcG<3PE}>49=kw@WGc@%a`X9W)mWpi&@MU zV|oY=5(_h8fNPei{ljZF5={)HxxP{yYSN&8g`%mh!1@tG{DT!xM(Z%k-2(9;$m^8wN}4W(4KE~cRffzB zAe0srR=Sh1QekCL#sP6pY_c|cGpzF}?{x?J+x>mJa_-W_`i*hy61wBc=#_DG*+Pat z9&b>SjwWe(amQsvQ{QS5kDVENlS;L65>=P`V;Cm|t@6!<5$>#IORL{3C`l@YsM zxxV9`jVN!i0iq_h3h6DJc*-wr@!WMCm(fPIWK^&1ww0JUU6Zvs4XamRdxs+@?8%>B zTz)t{JN?;Sgk@BSh;S}KG+TE!Kna?c88oyM(QIAf>@+Og4NzDIZ{fTWz?mVNY;bm$ z3u+&5LG4mD@5G@n7tZWgbPIs%ur8d`M%~_r(F)#7p-n2A3)A^Q_9`>Z!G@f3P%)}LZJ9%l6z3#S$Khc zW$+}~h%zRLv)Z!7agvA4N#dcZB)2)7iy|I2qKInL=G5`9hB_YVspG+-j!9BO91m{d zSZ{ugr%p*`-@^Li=2(BMx&pu)&V}{I&GzAgdmlco!SrK2reh1!v9liDqlIGQP>t#2 zsgkCVhWnbq?e=S30y?Tgwds(Vd!3Pw3>-RvplFGK040f!-BZ@ve2YnE_%BOtUon;%e}Atdk2`)`1sq&YxD5%Ero}Y}gvlY7=FH*aEGmG1oTswS`@7 z7gx8lbdOass)Rckl>pzjwIpn^9`cnfeq*PSo@8D~Yc#N6eW-@@p$=9K2Y=WIR>s~# z5ql5oV1B58dG$~qA-F235ocf`G7HdY{M2Bm9;%!C!zyl+EH)P&%Ji#_ zPHQ|vdU$hjc|N?{qORrbHE>96$ad*yb;}WpHFCtFW}n{Ne(;u-AhB|lv!OAn1^I<$ z_8?rzCm-ajIV<|>sFN%IjcT)mo#XKgguO#DfUm7`uRy)4 zVxhA;3%*@06vQSNcvctaL2%ktJ)lR~7G~cdoj1ui=B&~iH?xh{yIc}TL04PWW42*c z51gZk`?8;|`T~GL{r}x<6L^jwLZOx`qi7LZ!iCTc9`q1Ua(jJUK% zX{n@f&5F@8MFnfEBQ9@h!(T{|QA(zvxjD7W{JA@*X6BBmvAPx9b@Xh^F<^$WSW1jF zE6^6S#@yORgK_9xu67nX5(TVGZJf~k4OYUgIw8kxD+xKfHJ7g^)x~P^!_0_~RqyH1DcMK0mZDsZ znl!un+kAOwixYeJW*BU)t`MMP9`hnFj?QTd6(HNtS-K$&jRzd*$y{wm|t4}WdH{z2@-xh)0x1qn4?H}>& z*ra%U1CdaHx~L7NJfx$27!4uc#27U=?P=Cu9}zvg4SqE-bH zi5+yUU19ny7X&=Mp1PJ}E^~;PeHMUT+pEmSD>@}9nP_RAxT(>Mh}(87`AQlt=rvV^ zYVb+~)&xEvJL(Xxa~ky`B5@CNM~?H?_my)5dpHP!?T}<=MKZ(ZS*9A&L#51 zJJBRRKk(?=C|E5hFjIX}!H_Moy`@zCcdBxSGoFXnFHd7XRABS{%OTzEDs>zPs5W;IYJKK;j;iR>Ce;bK9`&~dqGzBLGxoo9IO$S z&0s6$l>x2VGrH~eqKk%rB}k*Z*c8NxN^0zS8s?0U-9 z(#i*@KN1%6N^285a-g5enc<^#q5!tp;HbGQt9ZU;J?t`A|&PVm0{Ge0kEcSQn7d+?EbC6Zx zLHYhvc1(qI`h5M>H{z3r7NgZ7>0G6FZQ7xD2QqL3%>H|<`Y8DzBe7jHVPek#911Pb z?Sg3Cef&sXeQaUs_nS+z5?crSu9l`+gh1Oq(&ZoHid?trkwe zr)*P9GgV_zqZZb6rOExf7lb0z#v7_8ntdvYW`p|7yvRSI}V>4`O~Bcv&o5# zgl3FLji&w#wovCs0Ij)o#m%?3Ks|rAVkr>_BKiL6KK9|94d*#|F=hPzN513gtURJV>0($YVn6A!O#wl# zp8UeQm!oL>n*`#;y~5Oe)EEPILLLZ%9bw9HTkTHuB?10PA2q(PA-t6SfoWd6{`=_s z_`^`4A;93!@$xe%@LhggLc58AShG}VXlTr-)FGCO=s`B272cCGT7|H`@6C!F1Vh#h zC3Xo2k&pBmEN#IOoPuiX0!p`rJ*!8>Hn^+gQ`$`?GL&7c1tQ6^k@Z7Rn$cJTf)kF$ zSTl?kfX8i|oR2VT3=q3@e(`pAwUssRVs!5aaJ)i?XPBv9K$W|C5Cd@#6U8`uu)76q%D6=DNGOJOH0 zroX_Czuf%-e+}lFq;G4~ILRPNT4M zbNVkI`s=S|akQX0FXL#LU@RTHL}XXbwd06o1Nz5%Iy!(q)qj-`JAl1(Xe~k0 zi1VZYiz2cyIO!5bd84UJCUizc;Zb9#Oc@v`En~?-YM4vWC`4OQ6A75Ac-=zqJb3KP z>g3I3;+phv`0U*Uq6FX$&wjwO-&f;!F()@17O1T>_2W1-25U4brrN}Y9Xif4yBC&K zj)7f0cVBnK)@u~Qx4IzuQVC^VUFy*l4QF{MlzR~m-l6y#jQ+#uZ&V&1DD;QX)!%5M zKY*HJ;pc%{*a#}lNe^R8tj}2LYZ|Fq(KEVP8dN?#1{#`3y$QuJZhe~Os0Rb7PXnyd z*D5aK(wq3`w6xfQUdb`tXKJotSJQA;QSksiX?Y9UMvIZRKuNARVsYwMScwWGN^^U3 zw+n-#6kWBHKd)w<3<7_?r3!hVviKmes45^O?Fv*8C~!fpls?$5UTV}J z9`MWutu366vB0hDQlz3Hl{a^wncSmdlGWR0OKXt^NZtyhH(Rr-M`zGR`CGg&z)A!g zZtP~`OwRen1X3|kNezImfd^l}Nq3)$zae4&KyRQueR4KDee-_!LEOa2lCCVNM1+T) zBjn>)3^l;GM5?n$IHoJ!Kr4Xv-3(QMI5axzMD?(G*r`V*U6{w@9?M}emvQ257NhpP z4twvY)nCG25Ujf6W35Ebe|PgaAU}C_u}@!ds434{IR4x$TQH z)w*+YyD^>qOhu+a6fi;(xV zc1OSNXMmpy@q?DfFocmz{kchanLq-kQZq5s!@`;3CHfT|J{YRcg9SbSvZNbRMhZZI1f`=bo-|-lo-N;f0n&jv>MuIoYEFh_){13p9uCabE;ckI4Z={lkyhW1jFwp;Zgk$Co*W9`)OabRVEO_KKcnM> z5o)!izKQAz0)pOhnmYl`6+!UG7%Yg`*o@aYcKnawrD8Mu z`|FFJMsH7VkNSg+hx%}Qc>*9{uU>axml-z^D)6Szr-?D^XxWV=a?$4RTc3_E&ri=! zw*CM)!r+F7;ziOBFR)`qh(JeZ3!bWaLQIA|@x8bt)(5>rlXo77DCx7Rv?BdGyu34* zn+B629h$&Z(C7$*U!L*^24`Cg+*ZwF=Er&cK9ikbW1EpAtJ%zdGMLF33m?cSI!XdT zspItR@cjDp$`(9y#L9wY7j<%XwFZAuJb$w?aCAGsp^`mx0bO!Sx0PUmhWK|F#Cmm{ zdo&XaAIF*8#zUjIP4XbtdNOy-5S1;jnd_LjwWKEHepykAdldZb)lz3)HodCvR(et&$=@BGg1`}g;p-#H(8n(5?dVm99BkdTMI56vE7 zoKS=~Ste4MJIyMxA8$+$M&)u-Kx?}>hcPX2br3?AkuRe$#yT$+GnRE;4V^>Ud>mku zhV$+Q`Gi2i{eHGND|$oam6h`D8L5y2S+UJV+Z_JNc?s!-Ydy~;)E-O$X_XPG)U8Uw zBe9X{GzAa*r*?PEKnPjg=Ij`T(_f;jA!9bGQZlPlOf=RGLx4c>q?ZF0%B45E*fg`` z4|VX5@;K*ol6hU`84`QSgCw9Hzt~j;(CeMAHRy_b*Ao zZ99w!TlwQfqws0e>)wVWye*EzoI)40q<-DK*Z!md$fy5qrBEoYl@fk8vSX%(y&L`~ zJT3b4@;q39r_H1^;k+*qq|_o(V%8mG*BhFMb+6##wXGj6kgr}19Y_$Vx+c(Kvow1! zGjUrt^A^bA>lKRrIdVtZ5tbA~bEF@EQDmy1mYH5Kt&6in_DY-V zzZ1T_V`FfQ3&Eh>;T30&*_Q(~(N5Y!CYVKJzBR|9ww%!cXr?4BJ4`CS@g9$loK($3 zzQpL%i*y(9-%05ci8O#nZRM*WzAvk{$whFYt#jxW9O=u5rCGXxGk8&8Zgo9{Ai4xy zx5`2uS$*k|%nPdVllb!Pwq^cz-qFu&v(0CRPpxPuYWse2;ZZ0jo+jQBc91j#T#RY^ zlw6`bTjwgZk(s*T_B`NDZHO! zDoPqoXPNC1qqU{_^D*k}@~V*5WvC92n;zCz3s}Qr4qATsp`;|Q4P>QQ{}AdYmmeJV z51ihVIP3@%7JqZ}yXsmn<>2LSE8H>grBi8(@V$5UXKlmbGO>y@xmDPDL;J}l`7*RI zy9m|UYw_+gQ;c0&GGdp~+e?6Di}`NV%tjmLql}Lx9Ry?0uqRzrCvDJP&(wC_ zyM8?!1zTDXk4yrT6h`Ev1>DBjukB0? z31V}2&WqqXg^2quRO+bR_vDbp3y_c32*VKXZ!GWfkN#66>)$RQO0za?r7maaVPlxz z++R7Mjd8W7WiZ{?d#+3R&;D8X;;9xH4R8yT=+`)l9Sq8WBZ;&Xjd}gR#yg$np3R!# z)~M<)*pb9C4j)-Mxsj_CsQfjRlzP{{*5k@h?X^kYV&R#Y0j@0Z{R4mTpzCP`W{W#8 zJ=ICaO&QOv>Y3r&H3804i_^UdQ3JMrJsgja(`AZscrXj5m#x1ek3)`&wz)40M=RE$ z4*?^}5)GWzu|N31OfAt5l~%Wjx?s8jS$}tKI9t<`DE+o*Adqy=>)DAnnc&*KqwszkG< zSJA`{LoZZ>jl;)>0qL7lrn%Y&IO5WL5gzs8%P{OQO0h9w>%`gDnr5LWO^hmuio%bC z7+pH=)T}aG*ZHH<(M}j}K$Ol(K63h**)V|3hUnOEm=N8N$-bE18kurOG? zd0TDkN3qCD;ZTf{0C|=s(XMmH6Y74TE59nMdv-1T$NL3PO9KQH000080F6%mTq|X` zLUc(001*oT01E&B0AF8eZfSI1UoLQY&3)T)<3_UJyCeJ$b?E32X_GWBl3J2Sj*wbx zwZ>|xL$~&{*TVqGA_WTsIJih^IqcYv*w5Lw{geHY&CI%>3MhbV@0_!%bH*(JRfVjq ztgO7(BpCbQJYt9J_piTV@Y4vrC2t(C#&!BR@L%|h-Nc-;Qy%izOQX2amhHSOy@x-c z<;iyZkfg)>)gzA+KMLVpv)^WeL7Vkj>fI#Z;f!Oy<~F=DUj@BKbhY1m>qlBvh)21FIe)h^ZjuKPdj=Rta-{K zZ2XyBL@-W^E&Y^z^rrVonk|#gb(+nMF9BS95yhYJGe@%-d(V@5eEG-MUw!@6H>~hw zg}Dxbz`P(~>SG=HSm!j(Rx8e$*QvK$vhUatPg36M;!wwd$J3O@-~SXxA!kc~C}n^z zc9Eqo@K3^nNs_V-oB2H92?J=NkOe-U^B5X>_$?2H!@+R8cV`zLM`zau>;%VvuXm2J z`NYdu7N$I8K8ytj4pRi3a4?!ir!X0oMp2M_FIQ`v0`A8P9(Grsan$B4g0JDs-khIx z?!4IdLYx821e<3eG-VSXCc=F9h2tmKY94SLLPB)D;(%SiTw$t9 zHi}<(h9khV@Ewp*Zk|RPDXE!ZqIM7jct3)`3%Uj zr%3i4_ZRmmJlW~$XE(4i5A4dD`B{Q(yS>+Ke8Ik<&2^S`?s$Cf@gNQT%l0M$%7r(@=jS|Jr1$Wm-yIfS-LB+g1I!=$fIHfE>;*6dR2CxnMH3$W zz(T$NM)U|R02xTjGkZYTw{c3)4R;g*y$O4YkUYhv7DFdKY}ycU((SkGF-CIA`#S|_ zH8Nhyv0?C^;%vFR=deA0nn<57ntJLdmi&+Cxy^qo;jiZ&HEVBgp2+||)nFGWC zo5lQI?&Oy&UQd_TD_je9592_4cFn_wm;-YKh6Fqh{$*EDO2-e&mg|Q@hISMtUiz|v zJp~N;M}#UMa$&$V{YlDjF9oTdtJr-vzL=*)jYqHue!w2#+7&OEBywQ)OT{>l$*zZO!Iv;P4~ZgsdmZ8_#4E(E5xnD&_4}RvE_>Bo zKO!JZi< zfd9p?mw`G`_7j{)!S^RotXB0pn`oXiXxk*0O*(=Pz^;AgWvkQ!!lg~?<+}+7$QjD^ zPTM34B(MpOaYxZvM*E&4o54NM?RJep431(#0gYfQ0|&?D|Bl^9_aHW4``Z-&a_UVu zP}{;7M{`m_jq!qZ=%8!O5Djc9%#x#74r)HDK3lQYyKpW61K(4z3 zlAE=-TCnbS`#H@CAsKcekS%CsM0?2(NFU-nhI0gdf8rr9h4r9{8B6tN1^_bTh6uA@ zAcTuViDNwV{J=WO^pqb!=i#KPkqU(b6Yvh5R|)Jj;EkQ*Y_{NON9b2YSv!CYW{#}R zB-}xG%)-e5D~)Ti@L+9GSol$FmEtk?9-0(3yn-?p#eu=FyXct*01nWR&`9wx5o4lV zVS2yh!HX8EXjsul3_jGXi5`Lsfb@tfbD%||IsC)pHpuMoy_9Eq-dFx4alweF)B+H_UC>+nz7+}hP@yLwwQv3g{K2lGRVc=$3Qrv)`1#~No;R-heNh(OEnM~9{erT1)yeB3@KB(eH!c?WcJ9;?(;)JvyGdd6$nI4yMla&DrRDBu=^qWSamIXh2+u$Z$sOgXp-| z1C^2tAt37#=BP8-OcZ_Kki@RB)$#e!%}wWx7ta#byk5a7BIo05*rj=r8VH;Ba`GF0 zNI`9VkJO?~M)`os+Cu8ATEgoT&KWqN@%Ohr7giAV5TPc8hLZ6)_vW1us8byH^-HFB z3N8oki{Epukn8T-U64V_YC9}M+t8X{8_ciaIHhwM_QHAEmYkH1ZFMR;q=(m*93sq7 zQn4Wc+gjWfyS+HUxv%4GTE;_cG31h5%0j^By!#YHNT5~|C_`)NYg2~HBGB)*%hmvx z$6njE1mrdaw@$y`E-2~l&ua7!9WQgm8y2CYFb~WgWfgd!S(qSbR7-p!@PHGhP~vU_ z6@g-RoGa5cn%u4f#GFvJcg)w8U`6of%O<`L{8n@STn8zOKg33z!UwTep_+gYUMbj@ z1Wz2VEI%3@Ol_=J&{OhVd1&rNqqlvMn!_q>#UQan&>;5^b7zO>|x6@;fF?&|ijGbf<G~z`;|)@5|)b=cIdz; z(ZXQ6ZJEhUQg~fQ3jLmg6v&42MQ7r09e=Rtpd;zENC`Xjl#rVhMu^=5Wp&Z#-;8G| zX=Q83V84nC2#+Qi3~R_>uU$4XR2*pKL%@$8a`HfB(hDEjWPOXJ4%HTVh_n>B8H1A; zdi%EYXYqwW9Wl81!glGj=+_d%w(GRmtK$lN2Q3V0&zHT*jokl&72GLr@l*e?CHFWAsew1EVCXv)41LdBx4q2|`GIo}_ey)Xo|zAKzIYQ4 z9P74Sw}-`%qJ&pK?193gL~OOF+&7t$Mco_7v^GJM=wQFRlLtjQNF$Iv$4a-RV?K=H z7!8>Zs6>l-;CbZ1)<%~cUoN%fyr{Q1H*VjM^7;iXzE?*9yUu;P^KW3{b-Q->Z^?rm&cMUvN6_loyi(W=nhR?Um$0VV*gVN3dK~AV(Jsf*F+ z(aqW2=)D?Eu!Y=5D!is>V7c}dnHNW$Yd^S;GE`|=UG@{PdhHQX+W!N=RHZBo-Rl3q z;v+qqk@V|SZD?VZzNF-2B|LX*x3P2T(e zgR8*|pJVyd@)j|A1XXBQE1FE# z^b*}ct7Rdo8Z_uZjun3{pTjr1ez?j~^DX|wJk4UO!7t&jqDk!e37mBN^C*s^xY>|^ zy-K7q2IIa;8tfHo(r4RZkV!E1XZWDiGG-oSsdM6+K@PpwfG%6)ush!Me$4@zWPUIk z!P{Wo_*dYE5A>G;5dFi{&JTfZ@J~blzN1x{ z;{I(;yad+exy?SejL86T*&ZW=8d|b%nXt(qL4u?V$61)bSw$g+FFXY19vJFO$;Wgc z?B#p`l%2kK_W^@{(R@No>nCKEz=9$en_O3xQCYjvo8;F2Qw@Va(O!pt2d#Wx;LkD( z0P+hU-+PeQV?^b95B7cQ2Yl64QK!(RNhlDHqZOL{#q+KAx92x!AI|@=WsRz~OYhh2 zOa$(YAH5($gwKP>6L@XqUCx_#zbJFouWfUL{;x)}<#Q#t&o;E|J9ME)n4b$EAN_px z{`S2I@pJyU62QZ5&jge(pm$B%=-V?vm78q&Y!MZZ-`ER3H^0@KASuw5V0D87#^WSa zfvGp2S8X~)DYO;XJjIftrxAmR*#i&5)LvQS9TR^>F{b)c1s(yL=b(JVOTaIh(7k29 z=Fd|&7TAdXfe$-+PopsP!;F^@aS?@jf6?BBC*oWTCjW$4x4DoR5^7iJ#?adZw z71U;&eqQmzEkuXlwW`Zj%fzrZn~nXDm@eug&<7Dm3kpjW9wHdHX7r1Rdi430;1a_q zh|Vs`0MRE5G$keSk$+pkQp!vvi=%1{7`AB5}0AlIAVf4!04B7){lH13jS9ZD*j4D7}{@puZjn zm!sCEDEO9CAu`iyb-(k_HTfuRad=+;zGH3j&EKDXHfMBAEGGxe`ELz+#0 zZHqX(z0!cT>bhn~yD@@EHXHbllU1N1v=N`chGN-vY6u}$7B@p?-hP9zH(?@H+iJSa z)yR6Lt(yrh(jPd+*=T#_4eNp0U}LIg^#g6j*o>BX0d}0@t*1QMs%B>h#kd~h)C9&D z!v7B{_~H6ttd?T5{;q57Hh@Sslj9Vj%FP4oHj-|rmaf+=3IaMRcgQ-s9LKCBkAC=7Emb}JiKgDC~fQ# zWK%I9P8R69h(5H=t-~9((Gp8}m*qyi^#c{wvqw8a47Z>tQBc8gh*LDpoT2iIDmc8d zbns4pyNA6cAPdl;3SBQrji$cv(&}vYy~9va7+&h#3K$A#kv}prGk+kO1n66!ubTEE zl4U-`{t_LR{2baK5ZJab1F|6udJ2v-S``ftZ=&S{`u+TmPdEfLD2y=d(Oy#{kf9?d zZ)`8E2aQjSUv(pVZW30!J(Fj#f+wp!{l~gLtUn#)OeF;MXf0LuL&Fdj`<4p#%1gR+d(g z0|P{sAILQwg*XhfaxHFWKx-q-j}cmR3oCrXpD*w^4nhrFzzj4rq6z(XJo7;rKoboD zxV3#EO-{E|tz#*`*+xBO@1f}E`|^xTSgp2L&+31bU;!aIBRgsFww04lrJOt>#k4C1T#gb9bn z;+n%aX1aYK=SWTuv0*xIL7R+XmDM2P&@nql#U+cR6*15Rl-qfgA(dXb7G0x2w5T%z z69Fm}S~M@3NY9(Jt@Sd$^@xOv?fd!kBbamj>R}5TaymphIhUgrHo3kzIv;7U#p)VM zK^@AlOB9qgBsR}?bk6E{>f}+^+~QE8nLUF+iA^J)wK%H!xae+pMhu1^CSHP9cM$|- zfc%X#xg9W4tYxCZw?M{6;*3yv{(^Hd*eyE|KbY5~E z_~By}bnvP`Gy?@5zH&1+J!*}kqp$o1aGcx3V)WAxej~DugO12nI}n(j|8v;-CvZpH z&LV=c%@!0lyYzUHU@!)C>tYZk!$69q8tx^Ne)RDB1XHMiC&)y&=KP;~Etbaqd@iy- zuCj23!QYg4(i!C0P&$bQ6S+D0_n-WDMtROZjZR1BU3N?{U*E}mRN3&5$+Sd*O^t%J z4n&C1Qj$;;Gv``{M+-yVF%O+GS70`v|6oKt#i0O%UBi_Eoj8%eSolthKDyOY)rzm4 zT%Ij>YOVE$%a5b0EpxoheMA~87kTCbSq`J53f!dHvz646r*H{uK%i2_c(RBzaeCn5 zvE4GR!6cU3?LWr@eeQtY@=DYBp=V_KbN`Ed&ucu&Kgd(iw91+8YLkP+Q|b0I9EJk% z%)@L(wI($#L`N1YYc{0iq;)_vi{%UG7{H`k$`=&`CQqoiI3gY!vgAfG1qL4k7$b~F z8jhBy$m;4DGL?71vE)QzMpns!GSFMNOfa5{$at2;)B6QFTc!_GumlTJblFc4JW1iK zI=dJl2S}4be)ZI^TGgpvqCPl~`y?2^yLF6L48AG%-Qd{B2eTHPzO$;F#HxZc^Qo-r zS+h(!cwS+K5RlB-=;Z3`l!@{!2UMWs&(}KEBxI{NA_Bp(0+=L9Vf~fEA$P>Jxe$_r zj35WfKnGenf#W|0zB15}d#DeF<8@u%~lF zZmE>6O3?2PlyJ4dacG^`aZ!(or?yPxmi(khr6j5pk59}O)q*&v+WSbpgF)^uHwrX~ zdP`WS4iiKuyE*VE@g9@FwX^&{R-?cWr?eQX`wa2EYYfHX`W; zbJj7KJ)kqnmdoVsPeFpKR9oSlLo@8`_0-Gtx~q9=QDFF~-G8PcnsQ@aiOI4%3 zX-zY0;T+_Ih6jigWMmOFZ%L-KE_+8QYWnbkV=Bya@dK;LGZxct3}frfl-9dHE2I=gVpcmj!aP(79Z{y=^BgcCm?(rfC7VbfD0y z2GBlhhbDNHhb+F@XrXC}7IfuvHJ#(^sttSiwhW`R?a|A6B+7kn?pM*Rh)A!dk+G{& zP|+))g?F}(abL3^e6^mN7eW!KSAqS=Nt>`5tqe#Lp2J$O36ot{enyyui;#ErTvlO+ z0oX9~!WfnpPA&k=++`RR?G+d;r_U8l54Ul$ivQRD#1wzBbHK?QO~?h|_QBoEB0o%t zo}iV5+`*oOTzg{Jc!?$h*b{FqZ!d1PthyoOkQ!Prx}w7ckjB#4OQa?aA9IlCT{%?N zYOWp86$C1g0rF)N&1*=ia6+G>#kp0Y&dHYq3`|N914O9X+EcbRUSLuR7}ymaE642f z2)IdA*ucacH!vv#4iIdc#SKh~fdfP>+oiApthPdvN3P@op(biz;tm^_xZ?&y-BrVy zd%)0BB9KIGg>QvlN)%VdFk6mEs8rxgm@RbPtI#y0GNLmVRbn4mm$06x-t?1=gBB*G zs0BhC#>8mi@G6BTd}kl4f-JUs>g9U(YazsxdO19qm2Oz0y%q;1HGZ^7(UG>jU6^pS zJ5Bc9NNf?)HwbLvcBj===LO1Gs)X8QCd$9*^*1v{HKic+SlOc(zwr7yta^ZB(HWv^ za41c;`Dd>?RMFfM$`Gr<9=^2Dx7$34+6}QYhExx5nvM;iW-*DyIqhdCQipX zb#@#~IB^%Nlg-zNPFWJ80Rv5wIe~(9d44mxy7=k#>TXmzoW2o3_$-Z>IL>vwy&J0X zhkn?LC|-JjEVZeNaH9Z&w3DFyL_1_pfSyHr&X9cJPdN~$V$m_ijIiceIOEUkTXq@+ zGc>8NkAC>TgO)b6Y86-~JOB%gy})14urS6*q~>DX;}7?rgCI)1XFn08@kCu@FH57P zN0%+=;l#c?_Br`}*DMOBWy5KgRCR z9V#qOg2rRn!Z{qs3H2?MK+9Oxqo*7^Qh$FwyB;51oa$H}V^dqp)e!WKoBL6lg;W6D zudOwmM|Y`+FIdGnzClI`YAz!(u{U`a=EvA_E2^1g!AU3Z9l;F_K7EO;%?%yaKmdS$42iz za!QkPi#sPuj2gHE%1H*#AYJ9IkWohh^UiJ_e~K&AjIju}Ii(EWf6%9=LcGUWcwqIpD6}>I! z!8>vQ{o2~ZCuetOCwbiEs%V9heJZ>qxrA%C)4O?HUEvn19MgMl)M!Yu!!!Uz zp6Zxq+{w<&nx7M3Dj{9b#olE+2p&+(Y&qmlEDlQ2mQ^40dl0@RJnnn|Di$Ry@(W+& zg*sTA8YxtYx_J?5Q5{}i4&+U`>;$$5oJI(aPd-4biJ>b-8O6AbJTCSl>!Cv?uQ+Oy z8fAb7voI-ZQaR0*d!$1-5>Ckr0vT_q7}cS;#6e%(fcFDoR9D4de>1@nWlsq#D(Zno z$I>kj`3RIwrX~if?k_!K6`+ItjQb6K02Sp6T zHEFwo7G<7cny&B*mM8qB97{cY2`fGJFQJ2{bcm*S`fX@E(}j5zOI(L4MPXb(L&#}jJ~uwxFjvu(1!;4(ha;@g)B+z zQwVf;vEv4e7C8>nq#8h*e)>BG4%7P3R(!vawTNbF!I(H~Mdfm|2Y5&~S3an{shY~9 zdMcB|h3h_r3gF8+WaIm~$m0HXe`h}@iUQ6jjy*N04r-hDE}Sbsi!S7|3u8-7lERmL z$CsR7W;VY@HfFGa;;WxZV zfc%0f(QINxt(Z6Kq1ca=H2g_Mk?ISq2Huq_jCvs}F$VZf4dPUbzGICm?&0N}4c1)n z6$p-adqoFS4T`Q6Wu{bdM)vp7$>_>T5TUrN1Z6+?F9imxD6Ei?mzb=0DBaPWQy88Z z(S=GpeZgg!>)U3&VRW5LLbg9tkd)Tjl5xM2AcAg7jPC?7(dW5e*4r!_)GKCMk@T{? zr_-iGy1A`rSOyi8W8J}-#x4y8jUA#&?o*`(Goe#bw9DBAIz7Z=FZHw?>+SjF(ard7 z^ycRBYRfWB3umYD;%e@?v)@=g;DH)-Q!KfYOAZwr!ro|t%alWn~r*8nEhdhC+-Jy`7E)MF8V6au7M5< z%+b!Tbw*~dg3blcLF;~;GrN!24%22Hqu83xJ>4fQFHsig!#n@h$c}5!>nRVdmbH0~ZF` zxdV>!nYoHrmUUDg0VJe3(K-nd$=>FI0>tNMrx61`y z)Ab^bAaV8A)#c66&DrGzt=|Xfbjp_MAUHzw;?V^Mim&Zsr^w#vDSBK!QAI=iOO%#x z<+m!CCWV=YSqJJ0S!L(CA8+iOmu(%J>$N@rpv{JL1*oB8tle#6EcbargO$${+1@ec zPOmWL+T%m)e%X4{!vLDcJg7I}i#86%Zp|B;)G2c3O^H8C_!0fe(F($Kq32>Ct=K6y z1>TRdH9hk(}{Nd{IybdUbiGnZykuTb`3UJtIL(@zsZi}C0BdZl}Ky#F((m6={kR- zXk|}^Okg(oLX-8*#;SF|-W4uJ>f$}u^|0KEqCKLvri0~MgqI1})-#TBQKcD==$9YwMGAnNorBa7EoxQWXpZj?1^+a6_;8aMI!A~)K!6}$D1 zc=IYZv0dgyEW)}XH*vAZjk1a5)2%CV6aS?mH*r;!o4BgV&2{Q=yj9m~DjQ|~qnHB<#(s8e~*$JL1?-n5(+;q>4YSFY^C z+bxo+w7yi=e2I(YcVf%qX3l`HQ6^Ao?-5U7b_W(@eE&9W&za@4E8IzatcLi zjW(L5W;MkIX2og)k_$*k*A*Qw_kk|GJ9CsAz$qIPG;>uOn1#Gj2E%tQikEQW+d4R@ zK{dDP7}n}pu`GevSMQ41BcIkw*Vw{kw>Iq<0&eqL*vXD?m-~5r8K}5a2TED;bFNS> z1ZB!JaoJ=WS5$%`Kr0&>mfIM!bJof+)XElP+(sXVw37297{e{c#1(a*R2N4XD6_(% zx}u3SU&Qs$pswR@Xe~<62J5tCTnpwWl7n*lk2IFRlXqUWO6h9LP{iyT6^+RoFO5A_ zL9im9QkEWqlaPz>ffQ><$h+#*z3{AwjoDj%AMjZ5uVjOiq@f;c;( z=Je=zbbfnr%9^=hh&2)rL}9JfZAP#t0i7SZ9u;Ow$7KJP7JIDLK^d-Sa-Xr6C$f@- zl-x8SuZxJGZO|!l%5hDr)1|Cp(>97KlBJBA(suhVNtF`8T}c<5aSwm`awoQpu9Kyse~^w>8*Nl&;=>ao$!^$lFr%Eu{jLuy!)K zy*WQaADs*zrX)30OeN=m5*7_|x9L4LP* zlcE_meS|(p48^9xEV<;;>-KhG+J6pr*sC_3c`3Pi@W!??O5+5jI7mZZ)xSvWL^M}4 z$gXT@7oZVYVgmd9JU1ST_6_p%w4|7xmWcGUq?DdEcrDk_nVx3krzNiZG{G-7%uY*6 z*=b@L)|o`7io5V@MSdDh-F0qNC#b26ssowrpwr=H7FY|TM5KtRR>6<$REI=lI^-8^ z$bgxik?4^8XJGVej8xcc`f z{Ae8let(Ei7SKocMri;^DGxxPWti_K+$J%f*Rn%+@51d~&usA5m?HMvD4(_1I_KuK zsSHUum0_?)C73A>H(8&`kd$&65?3xmj)%&YImm0X8IrOk6xK|FZLou4HbYXE&5&%I z&9GhBp*~e1sZLc$Hjgh#N&!a0{*FsEPh1gHNo{md;*Ks#s>6$tvhB$3Q;IN3>O+i@ zsu-ih6=Wn8p-p3ql2VY7pqn!8Hj6S!>cWh21w$n`O+1017#0Wa1kj}82S^k z>*;;$r)h4wrm#ODZA|Y$ZCJpr1QpyiSe&9f(?$U&6OxIY^=rCUCipUbAT!hv285HM zRE&aZ>(nbwImas%*z_Bp<<+-^mcex$xQ2bnQ}~e%I?_g|&1+30DIY#Q|`u}9D3sE+4Y{}9voA?lA(;6pYzq_lq-^A@j%m-QTM$Fsheni0W zI!7Wku_sMQy5^+oJc;7%7rPP_Cd7`@ghEkpREB-*y%W(ljW$h8G zhpC4x(;C5JnL3cK0LQm=fQuHjMaXs4BPoZ;?aR|AU^h=Zgl8fXlXzS{%c9rN`joLO z(R{v+z@Uje$L&3<-lk|#4H=e{mI+?E=q$=w>vYr?UQ#^@+%o3;alW1xv&GmJQQIiJ!D`ZW1&FfE?a2jMl z8Lb0dNdUx$Ag`JyR?>7SYlMN~)7h~(AaxIS+6D8;Os76@3JqhcPZ7DnK~5a!kPU8-AUy-tP3Z#af`&` zID;=!aFa{~z~WLMdzBgIU_;J1sF+iUfhO6;$zVxV=BK@#0;Zr*IUNiimZJH~rF#;0 z*hiAN#3DnD%4(wj5xEVUJLi_;M((FIhRPGd3iWf6ObJ+YvZv7)4*mP)6e&U$91_37 z_~Xzc>wE2~-)J-_+$~h%8S}%3pv#`3IGA-niI{SBdzW;P5Ga9(-Uf?K zHlmDa;=KFA;yB6U<|Of0bwP|doQonJH=>AY)aKOjxQ03&>#5_>qK;`&LmZE8;#hBf zj%Q9uX3xU<)8<%zs=AQM9L|OHr_J`^qkA7dt-yWEmWh6vp4T<*plDJ%wN*|U8y;gmnEPgi4sx3ZkXk|FBAJCd)DH7KQle?%W(iQKMJiH`F8Bt&~>gn>hmKML*y+ z87TUox2T)Y6TVtgAr70^gNVA4`5@=bdC^}-om?4kR4Fj*98KmR>>ZE+eC?e}64d)D z7CN_+>~}=jN@0S5cXfdt1gBkN4tkVrVR%PSUS}?EqB-Wg(i=Cojo3S)K&6DPw#eLk z!y0oqM-%sDKV9{8RE689c7`VI>Mx_(^e(Eo?KyMYKvjJKRpI`rogEW-HP=tgH@XNC zV6%&jIqsgCuc}veRan|x6M3s?U9~KHT^k>nZ><7^Q|G=q_sCOGWFH4?8YRv1Xu|Q{ zcR0|(LGyF_xdrTu!p6JZK3nknNSBqGdzIcBK{a(+NoGqZ*Gn*1{FK)AGD3U zw6N9eMn4xC<@Bs1tNBBUarsZ2>f|>&eOPQ*ccD4!)xXCRNL|-Bi;??^YcvX!g`C+iFSl3lqkRDJj9g(Jmy>J7zHA9 zwc$GBGLshswvRZwJUY7IPl=ds&Dzmw6ZNY%QQuzvJ$;ypmuu*ARbZyjqp*d-sH#Oy zp5CAuKHHqWv%h1)H(0xW`h~9#YW7d=UozSmP!6l19NPDQ^erq7*FrfcKsj7rrP^p@ z)$%JvTbsM2`SU+u%Y9PBoP`*)mSS+P6f@_~pX=2uXy9OId#3Q^V4BdWs9?Dmu+c16 zvgTpDtoM9j3kMV16X?g6wN5yI1wL#o0QM=JylZ1==EYE&-GRwW*M!jsKusv@AR0m% z(o#v|nir#IiVD_RM_k_2hQE*^Bb7`;b8~8$`FnRz&D*(DimKCqGvRF!t zHSa?xXpOnGj|LN=ce&bGi~-X528CfdJC^qO_UQb4bYKM4sLGcQ0bedtkxfa*+frN< z%)Kb|R(_{Pr(_@1 zT8eTtiqh@u4aHUVEs@wG?kU9P@MDQ(lLQGro~uk?Sj=%Gz4c}~2k@>H z-lR${RBTebOpJ;K>{O)RiXN8TMLAXJjkTFiuSQ2VqpR`FyQ7OOM~<;htCgMQ#vWL< zB- z$Tl>%Uc1xL<@?dim63rcXIVC3QFmmi@~aO12W=``=CUt3I1Fz5TcpYXo74I`Jk7`W zfm#(zBzDlXa)qg{ToUm3dFonG-p*j31)$gVD)aG*PDx58TAC+rYBVF_ww-WMQ&Cj( zoXJu(ctMxY1l}V%>JYDU8ucO~aW7ECC50rf?sm8vU0uI<_kMK#X>{Q*?A=ArJm_2@ zPrPSM^78|azKeovNr9R2HyI4sBHLR^MKWhHcUbd0ELS{>{ZN8^1=2U>H;zCdVo|(M zcU@e9#ybyC>ky!d0y-hPMOAnqiuLGZ>LcLnw-=|t+3#afD1m*5xu1xu!zI`p^n`4Y z=FBhTu)%JkRTM-EpBq<^A`2!hwq5905ItZgKuq<++?&BSVZIs6D^=MC%Ynl$hG@Tu#4?a1 zGI(^AqAA}?4AkZpJ_e7<1m1G8b+cI>naSP*Fb=Et*0uk_zpU^Aa5{l6BECF`L41-P zG8|RI_c(C)5ClqcKRGli)SnqR5u?6B2z6ozM#@{%;Yc+6FU669&BBqa+J_m!HRl4p zFBI#Oww6{tK>d-hTvS?{;FSaYRL~4xtrG>X%?3whju=FV(aB)V^tp1;K$u+RfmOL# zWUsfd>3Ok}Sc+<2lI&YJ<`Tr5Q{Nz*UN1q}R@Dw>+)4v!cz~loi>@ZMCFRO%T7hv z2~S10r#Kv@e;E*d21dSA>0<;hK!N;T{Jt&j8-_!2bbdS%H_Bo@8l6F>SC=1e-i`lp ziDi5a+3x}$>H-_GhV8bQeK)s21ZzHtQq}4({^U!8*b?a4rvMoEOJdlzUEsJwl>lG3 zhuZm0h>Y}VN4?5LNqpXG8!)OBVfP*!l@Z-BfSx^_DfsnQe~6{VP{KtVJ*D?zCnn8R z%t;MQRj6R2(a=GBV%>Axzl~zNPYUw~ff}0V#Z=!0wu6_vTeP5K2IpCT_Trg8O`9j9 zw@0_v8l&r?UPKt}ev!(akB$R-{+3e#l zX-k_hVnD{{Hv0^yTa3k())-u5QbN}Uib|T+rK5A~MyaHJNI(_>bfyuIaA*efq#iIa z1P5FH0=<9D-_h6Mm2C5^1&$G=08K>G?^si|?T9BWyh6tajm}c~gq(f94Pd6t7+TJn zkF8b6NlnUkFepBwwL zqzSXhiH(G2j7W`U{v5VY=O+NIxpgg?54S))f13#@5eOpr{`w*I;hYT@Ie7`n`2CN3 z$rD^P%7FkX1}t;2#B|S^y~4L5W)|Uk0S4HwAdl(z8`LHwhAkcs86~W7K+$U zy27S_pjS_R={@jqH2IAK@#0<))P2~P0Cz$j2!kDB%5q!oPWeXy{F8oF_`-(pQThj_ zd3pTz@x{^mkwim)!J(7YXHww1;&Tb@CJJKJsnXEUm{X}k%$Lz4Z$c})wQ-zbgz%o+p4Ze3iSjIOtI^DajBjseG1%skZU7f>axrA49|U1CWv zv%HX1E?8&$2PDX*ew!PH!H*j zfR@5eSk8Wdhrc}hilaX2+r*7^eDwL#IPgBh*{)U)>yF5^Eg`4oL6zQN-!1{FFI|Cxt)dShZrU06po;`LF5^Kj>2r2|8*Qi zLH^fuifXt1TMR~aRvsHqTgK;6z}KI@B;h=Y+w6k}8f%-WPNzuvIbRwJdKz1 ztV9J8rMW%2!@}SwMOQ8JM=TWr!ruei`jpK*9t8ekOBV7#W$}??QB^=n+GVIBP~Za3 zq(0cLUTV}J9`Vcvtu35Qu)rS(+HT?7I|Z?8{ghgODvu z%ve&kLX<>gUq+L7t;x=eEU)a#$i5UNOJPPCBuizIwQzOsFZX$$d(ZjdJm)#j^Zg6X z=aT{3eUYvG0$U{S&yMoJGhdzuH^W@(i32O+CI`;#7rM-t1pGI=7W0&QGms_NqNn@- zG?1e+CjHxa&qze~5x!IZ!NCcgyz}`45$WuG$n{66F+S^4n_O8Ijk{1Qltf`-}u6=%Vsdy&3_I9QSJat=WT50 z1GgM0I#h+)F50(pLsn4;Zgs7)w2A*lnvZB_$9jFxOl#1CCYAh%BC!ckF!X#ggYl@9 zBu&elu*(>QQHyxjXBhvAKV$Nho#6rxGplKNH#_(34O|3u44{`mV^O@)#c86w%`3HV zGm6Qw)C*e?AA6|}H7Tu0bF0wh4Lr0OzF@(ryPW;LPwq9*i#?;FM7}pEQ<9o>(FOpP zkP-6RsRAVb@ZDFse)XsCsGIsFhXz@YTzeh=QPaiGaq?ypt*7g3Ob5D-K%3^lg~Qx5BYmN|SwY z(Io~@Ihf7bTp`(pmu9kZIJ3$Cv`lq)cFDl?9+^+m(kM^B`h3pQgjAp4*V%gjiJA3V zs=T^Y4e@T-#0y-W$#w)mmb)#^*1R}>@7TMaa$n({N(En*Rhe8|enyz;4-~82vAb?H_`hj=r5FCkoHlygW)YNsg$$y2hA z9(9CKqtIRyBblBD>jmZgRmFC&&x6Lfq=1Lot*!7jIQ0Oy#QIo3xYhyrxT71F!x@De z=h05zj$z{4`LMf@?cmE|j5%`w-@Shi=FL1k}Ua?im@Y{7F(h+`JT*`1-O z?x_ys4-xijMPN@c;Mr2iROaFPy#)#u$G229g%}>U@UeR`aaeoCTG?u{^&golxgg$D zCG%W!{Mzn-Xgb}_Mt%Na+{xrUN}v?(@%n*QKcPr-c{4oY3t-e zGnme|cEDRG2R#bky9)MIQ7v;!h*_~ySOHV6JMO(MVlU<6`YfSQOlJ6e+-VVnIWFN2 zrK9M*#U*9}%BvUQJJC1qeK>G?kaArteZY#di7qfGmxA&ebYLuhb6{^GDin%2)7*<{ zsg3qLyFpFv)>B|9gt)56W*hT)24tYvZQDj^h5}$jvBHK!;8nye$HzIdf2q zm9|*$H6!^7Br4%_B%awOHWD6|ytETL4v@5mWuE`7$~0)0{7B*smuG%WD3N}gw>d%+ z;`$}gQ#9+b9neTXS;)TzvRzC$T8`2U(OugU}EJm}l%*HJ&Lk0teuf=2J$;K#G%Z%hoZ9RQkJQk(`%Fe+9pR@a#Npd8Yqy^@eSb zmrz}qSnY-um;dywaEzLN@gB%pB=Cvrsg;%b>?_O9pWHnx#~SCR1>S7!OB=%whp zu^OVGRoRwqEOD@&Azo~Ew;_nxn;zm&;xkkT#Qd1jwcFm>trvhpH=kV) zza6LLXZrgMpuk3v0+gF~maWM^c+ZYzgE^qKcHylFKTLz1n%aXb8@EkZ^ zFPupv7xOQoi$BtY19vlk?&D)C=LTq4MLy(Xk)zDFD7xw<VN6Z3~P!%-^_$PtpI_Mo{eeLsR8$2x0}c(Sz`4EEJjb1C6e<&^sSA&C`a_Ef5bc8M=31xZ||gg3JZDn%!ylcqnXu*zJG55cnuG_P*U z4g$tx?I;J!@0H6%f1%EePq0kV(VpMAt6NQocDr2Czg_qE7Tn|>UPkhbbN`xf3t4Dt z&94kKdG;=!JFZH@8OncVKt}NQ85u942iF7QFO`c3_k_FNp#i#d3@0m4I6A>2oHf2c z(Wx80ErY6n^mT=)y$Dyi5*v7UODezEV%`QR>^EL-EG9hvG-m1@at8rlW-{l6AhI=)zvsl;~!*G2d zJW3t5eYB$xsTO-*sc5gB4cRl9exq*J_N4@{B@ueLyKQfs-OjrQ%wO0o#k|@rB1L~) zfHu5#)>O-vVyu$X1uX=+!YSMa`p&V!P(EXZO!;$T;$bktY@zDSP9{3r)ID!TlG>^i z?*v#rcj+)AcWhshSUM@suNKt)0?JqUSAuwVX|7+zx~xV(IQ4r-DWSZ99L=w=^eAp8 zo#%rvCU3`ny{5V#=@!8yQ7|hmUqSZ0dy%+8o8_SR?JDlg7KS)Z?q(7ZN8eLO#thQf8FPoV?COGw@ z+U0*>gVj2MU+5<8GN9Je^XG`!{wt8ZD%5JzQ<{Jqh?CppGFr4CXnt^j9b3~kJgY5^sG<}j1a*8S6-bMn*LplQGdq&6kz=`;-7}6{{#R4 djZwBI91Kbne*x_a=wtu@ literal 0 HcmV?d00001 diff --git a/stylized_tree_generator.py b/stylized_tree_generator.py index ccf0db0..d9ab1eb 100644 --- a/stylized_tree_generator.py +++ b/stylized_tree_generator.py @@ -1,7 +1,7 @@ bl_info = { "name": "Stylized Tree Generator", "author": "D4rkst3r", - "version": (1, 21, 0), + "version": (1, 22, 0), "blender": (4, 2, 0), "location": "View3D > Sidebar > Tree Gen", "description": "Parametrischer Baum-/Palmen-/Busch-Generator (Geometry Nodes) mit Wachstums-Stufen", @@ -40,6 +40,9 @@ DEFAULTS = { "Branch Bend": 0.75, # Krummheit je Ast/Zweig (0 = gerade Staebe) "Branch Droop": 0.0, # >0 haengt nach unten (Palme), <0 kruemmt nach oben (Kaktus) "Droop Curve": 2.0, # 2 = weicher Bogen, 4+ = scharfer Ellbogen + "Attraction Up": 0.45, # Phototropismus in Radiant: Ast dreht sich zur + # Spitze hin zur Senkrechten. Echte Rotation um + # den Ansatzpunkt -> Astlaenge bleibt erhalten "Trunk Tip": 0.3, # Anteil von Tip Blunt fuer die Stammspitze; # klein = laeuft duenn aus, 1.0 = stumpfe Kuppe "Branch Thickness": 0.17, # Ast-Dicke relativ zum Stamm. Am TreeIt-Baum @@ -96,6 +99,7 @@ PRESETS = { "Branch Start": 0.9, "Branch End": 1.0, "Branch Bend": 0.3, "Branch Droop": 0.5, "Droop Curve": 2.2, + "Attraction Up": 0.2, # Wedel schwingen leicht hoch, dann Bogen "Branch Thickness": 0.16, "Branch Taper": 0.45, "Root Flare": 0.5, # leichte Verdickung ... @@ -119,6 +123,7 @@ PRESETS = { "Branch Count": 22, "Branch Length": 1.9, "Branch Up": -0.25, "Branch Start": 0.12, "Branch End": 0.97, "Crown Taper": 0.9, "Crown Bulge": 0.0, + "Attraction Up": 0.0, # Tannenaeste haengen, streben nicht hoch "Branch Bend": 0.3, "Branch Thickness": 0.12, "Sub Count": 1, "Sub Length": 0.4, "Root Flare": 0.7, }, @@ -127,6 +132,7 @@ PRESETS = { "Branch Count": 10, "Branch Length": 2.2, "Branch Up": 0.9, "Branch Start": 0.3, "Branch End": 0.95, "Crown Taper": -0.15, "Crown Bulge": 0.5, + "Attraction Up": 0.5, # Eiche: Aeste schwingen deutlich hoch "Branch Bend": 0.9, "Branch Thickness": 0.24, "Sub Count": 3, "Sub Length": 0.8, "Root Flare": 1.5, "Root Lobe Depth": 0.4, }, @@ -143,6 +149,7 @@ PRESETS = { "Branch Count": 12, "Branch Length": 2.0, "Branch Up": 0.5, "Branch Start": 0.35, "Branch End": 0.95, "Crown Taper": -0.2, "Crown Bulge": 0.4, + "Attraction Up": -0.25, # Weide: Zweige haengen "Branch Droop": 1.2, "Branch Bend": 0.7, "Branch Thickness": 0.16, "Sub Count": 3, "Sub Length": 0.9, "Root Flare": 1.2, }, @@ -151,6 +158,7 @@ PRESETS = { "Branch Count": 6, "Branch Length": 1.5, "Branch Up": 0.9, "Branch Start": 0.3, "Branch End": 0.9, "Crown Taper": 0.3, "Crown Bulge": 0.0, + "Attraction Up": 0.35, "Branch Bend": 1.4, "Branch Thickness": 0.18, "Sub Count": 1, "Sub Length": 0.5, "Root Flare": 1.4, "Tip Blunt": 0.08, }, @@ -161,6 +169,7 @@ PRESETS = { "Branch Count": 2, "Branch Length": 1.9, "Branch Up": 0.12, "Branch Start": 0.30, "Branch End": 0.46, "Branch Bend": 0.0, + "Attraction Up": 0.0, # Kaktus nutzt den Droop-Ellbogen "Branch Droop": -1.35, # negativ = Arme kruemmen nach OBEN (Saguaro); # zu gross und die Arme ueberragen den Stamm "Droop Curve": 4.5, # spaeter, dafuer scharfer Ellbogen @@ -244,6 +253,7 @@ def build_group(): # (= Kaktus-Arme statt Palmwedel). add_in("Branch Droop", 'NodeSocketFloat', DEFAULTS["Branch Droop"], -3.0, 3.0) add_in("Droop Curve", 'NodeSocketFloat', DEFAULTS["Droop Curve"], 1.0, 8.0) + add_in("Attraction Up", 'NodeSocketFloat', DEFAULTS["Attraction Up"], -1.5, 1.5) add_in("Trunk Tip", 'NodeSocketFloat', DEFAULTS["Trunk Tip"], 0.05, 1.0) add_in("Branch Thickness", 'NodeSocketFloat', DEFAULTS["Branch Thickness"], 0.05, 1.0) add_in("Branch Taper", 'NodeSocketFloat', DEFAULTS["Branch Taper"], 0.0, 1.0) @@ -546,8 +556,19 @@ def build_group(): pfin = N("ShaderNodeMath"); pfin.location = (2100, 120); pfin.operation = 'MULTIPLY' L(pscale.outputs[0], pfin.inputs[0]); L(ccl.outputs[0], pfin.inputs[1]) + # Ansatzpunkt als Attribut mitgeben. Punkt-Attribute ueberleben + # "Instance on Points" + "Realize" (geprueft) - dadurch kennt spaeter JEDER + # Punkt eines Astes seinen eigenen Ursprung. Das ist die Voraussetzung fuer + # echtes Biegen (Rotation) statt blossem Verschieben. + apos = N("GeometryNodeInputPosition"); apos.location = (900, 480) + anch = N("GeometryNodeStoreNamedAttribute"); anch.location = (1050, 320) + anch.domain = 'POINT'; anch.data_type = 'FLOAT_VECTOR' + L(_out(c2p, "Points"), _sock(anch, "Geometry")) + _sock(anch, "Name").default_value = "anchor" + L(apos.outputs[0], _sock(anch, "Value")) + inst = N("GeometryNodeInstanceOnPoints"); inst.location = (1400, 320) - L(_out(c2p, "Points"), _sock(inst, "Points")) + L(_out(anch, "Geometry"), _sock(inst, "Points")) L(_out(bsetr, "Curve"), _sock(inst, "Instance")) L(pfin.outputs[0], _sock(inst, "Scale")) if align is not None: @@ -561,6 +582,42 @@ def build_group(): # des jeweiligen Astes. Dieselbe Noise liefert damit pro Ast einen anderen # Wert — vor dem Realize haetten alle Instanzen identische lokale Coords # (und wuerden exakt gleich gebogen). + # ---------- Phototropismus (Lichtsuche) ---------- + # Idee aus UE 5.8 Procedural Vegetation ("light detection") bzw. Weber-Penn + # ("attraction up"): Aeste kruemmen sich zur Spitze hin zur Senkrechten. + # Umgesetzt als echte ROTATION des Punktes um seinen Astansatz - im + # Gegensatz zum Z-Versatz (Droop) bleibt die Astlaenge dabei erhalten. + ph_spar = N("GeometryNodeSplineParameter"); ph_spar.location = (1200, 780) + ph_pos = N("GeometryNodeInputPosition"); ph_pos.location = (1200, 640) + ph_anch = N("GeometryNodeInputNamedAttribute"); ph_anch.location = (1200, 500) + ph_anch.data_type = 'FLOAT_VECTOR' + _sock(ph_anch, "Name").default_value = "anchor" + ph_rel = N("ShaderNodeVectorMath"); ph_rel.location = (1400, 640) + ph_rel.operation = 'SUBTRACT' + L(ph_pos.outputs[0], ph_rel.inputs[0]) + L(_out(ph_anch, "Attribute"), ph_rel.inputs[1]) + ph_up = N("ShaderNodeCombineXYZ"); ph_up.location = (1400, 500) + ph_up.inputs["Z"].default_value = 1.0 + ph_ax = N("ShaderNodeVectorMath"); ph_ax.location = (1550, 570) + ph_ax.operation = 'CROSS_PRODUCT' + L(ph_rel.outputs[0], ph_ax.inputs[0]); L(ph_up.outputs[0], ph_ax.inputs[1]) + ph_ang = N("ShaderNodeMath"); ph_ang.location = (1400, 780) + ph_ang.operation = 'MULTIPLY' + L(V["Attraction Up"], ph_ang.inputs[0]) + L(ph_spar.outputs["Factor"], ph_ang.inputs[1]) + ph_rot = N("ShaderNodeVectorRotate"); ph_rot.location = (1750, 640) + ph_rot.rotation_type = 'AXIS_ANGLE' + L(ph_rel.outputs[0], ph_rot.inputs["Vector"]) + L(ph_ax.outputs[0], ph_rot.inputs["Axis"]) + L(ph_ang.outputs[0], ph_rot.inputs["Angle"]) + ph_new = N("ShaderNodeVectorMath"); ph_new.location = (1900, 640) + ph_new.operation = 'ADD' + L(_out(ph_anch, "Attribute"), ph_new.inputs[0]) + L(ph_rot.outputs[0], ph_new.inputs[1]) + ph_set = N("GeometryNodeSetPosition"); ph_set.location = (2050, 780) + L(_out(real, "Geometry"), _sock(ph_set, "Geometry")) + L(ph_new.outputs[0], _sock(ph_set, "Position")) + rspar = N("GeometryNodeSplineParameter"); rspar.location = (1200, 60) rpos = N("GeometryNodeInputPosition"); rpos.location = (1200, -100) rnoise = N("ShaderNodeTexNoise"); rnoise.location = (1350, -140) @@ -599,8 +656,8 @@ def build_group(): L(rscale.outputs[0], roffs.inputs[0]) L(dvec.outputs[0], roffs.inputs[1]) - rsetp = N("GeometryNodeSetPosition"); rsetp.location = (1950, 320) - L(_out(real, "Geometry"), _sock(rsetp, "Geometry")) + rsetp = N("GeometryNodeSetPosition"); rsetp.location = (2200, 320) + L(_out(ph_set, "Geometry"), _sock(rsetp, "Geometry")) L(roffs.outputs[0], _sock(rsetp, "Offset")) # ---------- Sub-Aeste (zweite Verzweigungsebene) ---------- diff --git a/tests/test_tree_addon.py b/tests/test_tree_addon.py index 53860fb..8cd043e 100644 --- a/tests/test_tree_addon.py +++ b/tests/test_tree_addon.py @@ -1,7 +1,7 @@ """Prueft das gebaute Tree-Addon: registrieren, Operator ausfuehren, Ergebnis messen.""" import bpy, sys, zipfile, os, tempfile, importlib.util, traceback -ZIP = r"A:\eco\stylized_rock_generator\dist\stylized_tree_generator-1.21.0.zip" +ZIP = r"A:\eco\stylized_rock_generator\dist\stylized_tree_generator-1.22.0.zip" fails = [] tmp = tempfile.mkdtemp()