From 7fa10b4cb9fd3badb17d8345bb6db8b1286897c1 Mon Sep 17 00:00:00 2001 From: Mateus Rodrigues Date: Tue, 26 May 2026 14:50:49 -0300 Subject: [PATCH] fix(ui/loading): memoiza steps quando widget em async load + draggable status - UIFrontEndFlowSubsystem: HandlePostLoadMap/HandlePlayerSpawned agora registram o StepId em PendingLoadingSteps_ quando ActiveLoadingScreen ainda eh null (race com RequestAsyncLoad do WBP_Loading). Lambda do callback async drena o set apos criar a tela, fechando o loading retroativamente. Servidor rapido (TryFinalizeEnterWorld) deixava o cliente preso em "entrando no mundo" quando o async load atrasava. - UIPlayerStatus_Window: herda de UIDraggableWindow_Base (drag + persist via UZMMOUISaveGame). Rename CloseBtn -> Button_Close, adiciona Background_Panel/Container_Header/Container_Stats, NativeOnKeyDown (Alt+A fecha), NativeGetDesiredFocusTarget=self. Remove bIsBackHandler pra parar o "Cannot create action binding" no log (projeto nao tem DefaultBackAction no CommonUISettings). - UIInGameFlowSubsystem.SetState: skip re-push do HUD quando voltando de StatusWindow/Inventory/Menu pro Playing (Old != None && != Playing) pra evitar Construct novo do HUD e o flicker dos textos HP/SP. - Novos: UIDraggableWindow_Base (drag generico + persistencia) e UIWindowSaveGame (TMap por WindowId). Co-Authored-By: Claude Opus 4.7 (1M context) --- Content/Editor/ZeusUMGForge/FontMap.uasset | Bin 1880 -> 2108 bytes .../UI_PlayerStatus_Window.uasset | Bin 158032 -> 158399 bytes .../T_Panel_Outline_Effect_Square_01.uasset | Bin 21420 -> 21568 bytes .../Outlines/T_Panel_Outline_Square_01.uasset | Bin 18923 -> 18923 bytes .../Game/UI/Common/UIDraggableWindow_Base.cpp | 131 ++++++++++++++++++ .../Game/UI/Common/UIDraggableWindow_Base.h | 90 ++++++++++++ .../ZMMO/Game/UI/Common/UIWindowSaveGame.cpp | 43 ++++++ Source/ZMMO/Game/UI/Common/UIWindowSaveGame.h | 46 ++++++ .../UI/FrontEnd/UIFrontEndFlowSubsystem.cpp | 26 +++- .../UI/FrontEnd/UIFrontEndFlowSubsystem.h | 9 ++ .../Game/UI/InGame/UIInGameFlowSubsystem.cpp | 14 +- .../Game/UI/Widgets/UIPlayerStatus_Window.cpp | 57 +++++++- .../Game/UI/Widgets/UIPlayerStatus_Window.h | 38 ++++- 13 files changed, 442 insertions(+), 12 deletions(-) create mode 100644 Source/ZMMO/Game/UI/Common/UIDraggableWindow_Base.cpp create mode 100644 Source/ZMMO/Game/UI/Common/UIDraggableWindow_Base.h create mode 100644 Source/ZMMO/Game/UI/Common/UIWindowSaveGame.cpp create mode 100644 Source/ZMMO/Game/UI/Common/UIWindowSaveGame.h diff --git a/Content/Editor/ZeusUMGForge/FontMap.uasset b/Content/Editor/ZeusUMGForge/FontMap.uasset index 7a0d51803d74f43d3faca4f05e5c3b702bd60c7b..9cdac7198972c2f760b4a3aa8be810181740f340 100644 GIT binary patch delta 896 zcmcb?w?|-tgs9ysyB(&?tJ7wb5`@!zLgfD9T{Y%D}(`q@RQ2fnYh152Hb9KzxwYY9M_Yh;L8)q0A^XS%xuK=^v2G z!2wYYBmV=zS~dm-5ugAM$K;8Ox{Q{S_cLmX4U_1eG~JF@(WTKDxUt8l%CwrDm&SW$=hEXXtG;= zUP-(&hLL{eQ{M^0q)|=1`#v+07bXQWcz0%b>E``R=8T5SKq(O5hEQM<6e=LV1);zs zD8xX3bMiwLVNrev2Tp=y`6gSl=(vhP#l)cWKVYy(LfIf^zyM601WW)(LnDHLck&t* zX)%y@K>*~!XsGpT*?`uIP5!{bGWk1;25&gbRUl=PRapI4&jVv-=HznLMfEVlKt?d| zfJp`hpez`G^a&xcL1701AaP`kUqFH&2e5+}Kp+UAz$DmEP%40hDlA0^0LAKI3gO1V ze2>j2u>GJwg~y!&I7uLzh+-hfq4*3Gj{_+O84FJ=3h)Go(^OEz!%PJxWiSAF1_r=> M0R;!|WJz{=0QVn(%K!iX delta 700 zcmdlZaD#7xgsAwr-|s%QTQBaoekj<~S8t}$?t9v*6Lll`Bp4VNW-~G{Fazmt%##nW zsM`Wr3`Q&r3_wwa?Le9dNT&m75Kw1D&>%G+K1i!Jkah;*;E6w!86_smFa|4?0l6yd z5alrPKM<(0F)#=L1vJAj-9JngNi{7nGQll98B~$&l;I z`dfOkIGgO`iA>&FJV0%3`FSPrQ1#~S_vi4z#Nc`s-iz?vtj%oBC<}5q2yj9uFbVP% z2yjeJWEB?Wg>c{`NS0^vZWbL^VW^l0l>P^Fx;T{04W&U8Or02#7$`(QfP1nItF)LX zgaZzz|4_Cn+vJ0+a+9lBRak$6geI?H^<#AhhM3^w|E!DZVFrLzb3ye$qW~N)0#GrK zdj*l$$QoyW#6dv-3~(^uhtePl>~T=Iz=I7IRloqPhbx5H$pG^*HnYHTAnnj-K{5%| cAdqWe1_AvF2B7$Z0kCaA7c&7v?k~GN0HTLgo&W#< diff --git a/Content/ZMMO/UI/Screens/PlayerStatus/UI_PlayerStatus_Window.uasset b/Content/ZMMO/UI/Screens/PlayerStatus/UI_PlayerStatus_Window.uasset index d06fac09485be3ca093a2ec1faf9530fb97055cb..c8760d26664e43bc8b2330235044b70ef5150d67 100644 GIT binary patch literal 158399 zcmeEv2VfM%_y2}or3ljH=uJo=A%vD52rU5uC@o%+OLB0@g}Vz7iWC(Q5DOrnNEIof zfP#Ripa^0?zKEz4L5fHhq)AKu?=w4d+1%|N341~P{TZFxw==WznfKuF{c-a@i)p+fs${)c|C_X4{{*F-^!sIP`Ir~$ZhU6X>Lp$8wkbnt!L~blCPb_a zKU(G0nO0q$YK>nZgCX7O9c$8O87zHldRwNI(&Lr)@%@eIN#>FCY%yt& zmn5|yX_ThBU+POzJ-UWR1hk24(>Bz{KeSCyfPau*XjDY&wqZd*ei4B_5dmRTL=Nrg z;WmMi6hOBZTgho9KF_`0Y9L9tr()7OdnM_8icL<)`S|@KZrO~1FAj;`7_hI(k)AEz zMLE=oMirMzQuCs=RVrGUQd_j>8yV1|x4~r4TMaD(S_QIvN&0ip{vzu6s2^eD-yOi4 zw3u+G4JA$$fwUn9UEP%MURLC36YKf1FD6wX6!e8L!{!}swix=xBn&kq+N8guTXw3T z$cs!*F{T@&$sx~2KcYzPW769UQuD~`tHGS8h^3-7$zMNuOgTkP-yWT%HiQ4tDN9pY zWRlTlwn(doME_o1Q5w1;B{f-c8tNS2<0A$8Eq?-Z8={BY?Vk-gkm!`MZ9gbWbg0SH z-7bScS{0A@lh7JXK%#hhWV*s`SP zwI_^tFif8~EX88ZOiz+J@4DKqQl6yvSbe&|BwbxJ{0&Gcfq=~;BdFJHMsvE9bNP{T zHIN)`(p#;)4Z|~y7K62?-ew$Oh%+V*lfJ2K9A1?bFsG#%(rsax2?-`ctT8>^kR%On z)u{VpPMQ6TRwI>>dNu6O0iBi*IVwY+o@7XhPLD8HjVb8{i!}SI_?TMA>!P>HeHxvX zVKM;0kQA#orrV?*{&!6^T@_(%>$WYWJGv|(+S*TVG3o*O%f;XOvWmMKQuK*gJq?DW zICE^KCB@KZn8DQBkZhG+es55F2s6x-X~?h;ROd`%lC-B}&A!!?seQ7nHbYuJgT)F# zO|+G6k>{bftPF!xuF`8qi=zc*vq@@IHt8&MB8+bAeN?g7+NqFVnAwtKu*8RspzgKA zWZF#7(HR5l9%H>FXNH^867;qRvrTGR_L*?>7JrJ8`WP~NrB`=7-`FYHPwH}U*o#n8 zQQD$U=|Tc0X}mJ#+~10vSc@@DZ^;5evtPPiWBka_eQXxz`D9DQ+?wRns8Q1M ztM3#o$jn38G}x6=NrQ+}vUgWgt{4ELL*4t8RRSvG^c<4*N# zxeZ<}oZLo=nd-jr%&Z-djY#NYw%Cm6DN>b6kADwL8DRCRh7?u`aG~i*F&X+qBiX9| zq_9D-XzF7qx%5qqPZnaR3Xka-5#Q5H%CP>1Uo)0sPPf`DndI3I>S7E>N-L}psL6jWnKHWVv2JIZXfk=;#fzU!O38C?u|QcUUY zvY5Jgv7(cxooMZqhWDDuk`PVA&}o%oOeemP zB|)}Ml33iM&2hmB-7_&N1ov}=Q5|69A z`+j;dYbo;d*oELT!jP=bG}$^^^ckr=%}FHX;3^1UU#pBBii#q8|-6W{Y2hWVrrpH*hSwvp&Yrh90Qo*PWk@aRHF25Uu3dPhm25R8U7o&3O}jT3fyPB9F=3DgXCCb6$X6oK?-Ps9lmg=#Gcu%T~wyY zB)gRh`(j$d1{Dov5afVZJwIf|g<+QKBA=={dNQq2aKy$rOchv*pisRtX|Sl& zzsumu8YwYXRwlnjNlW3 z!v|t7F^zSoqg}f`22-+A@ynmLwX*ia8AjRSEc$e7ve}XrYc?4Zv!o?ApNe@Luqv7D z+QpgsX3!i-I@tHahVVg=eWTel2!%6gvKM>s{pA>C9MaLh_KO=niGI&qbO#KACCRgsJ_Z}cH>=cXq3pk+Eaas4 z3`Y8*bwzKOm7K^|Kcxn5T_-0R4K)AAVqUH2j&I6Ba-9w2zsbCl*i=)RT#f$CZCl6WAbBN%?Z(ojaW5A`iB7uz3w%`>2*NN#d!+!ctKCv!RT#+S70c}fAqGv(H=x%J|C2W`ZERgo;>9otB~xI zwj(gVq*-XKPJ=q5L%Y*FQE!n4jVj^RD8>?{$(kK&us{oG^pXDjMJG2C`X2Io}H(M5JR2#g;347+0qm^E=C#_Aq=3oW~)tJ!_4U}n}sKgyVvnI`S* zc{CBs^f06)7%a>mOt1UlM^H04DOOL8)FwT1W?Tn2YB@32zdrNP=3p=@rul3EEcH&V z{4=CSvo0FAXbXd_SJ~Voqy98K1I+4dFsB)?DA-+jjRZiT+uJ?quTovX3+5DJPX2Vm z_$$zLq%lvkcXhFMMMA9E`jljex?q5-MG334Ir~i$x`hoISBvf_4?&paT?s?CIXTcW zK5Y_9_RvEgo`rm3l9R1i`@de~{rPAcUlGdv_Ijfy=AmnNVq|hMO*}ErUG&z0WH84w zko4uK%ySSNPqI7hi!0vf0scffCZZKP#(m4$lxfSzv|$f`O?Jzrz1E`+6^$j6BF*S- zPSl%>qe-OZbcoDK8fK6x+p?yh;j#LpB^?C1e-xDili2qH9tq!u;G>u z7Np6vik7;3*271Bgf=AN!)Vv3yI}-Pg-0G(_X-qFenj@9@+5iC=}}fRSk57bC_hl~ zc#&hnV=Y0c*)ZZshnY35E`Cmns_zL*b==+jwwDg#V8$HU2HWJoZVY9lB7G~uT8KQ zunm)}iJg0k0^t^;O$sx5%@PG@4JD0V7yMoB{V1vUH#5(R2ck>{gQRZ~(pwauDIV?D z{$5txN0a5BIz6+exbL1hOv>sP*hf^*Lr+aud2@CrdqNUHE^BdNk$8f3D5TZneS^e( zKSHQFVNV}mHm8NA(Jb92#Xt7a*U*AKiK&J(y_BeNy$bqsuH(u^gR!FrW^^D(CW=pFP~NCi<8Sz#pWvJ_min4bA`KX~7`2W3r3x zWrL}hTT6F3wH$+4Y@cqC-Q(4_l;gvt!~4z0(Yv_|2+5+`G7+0&xk^Z>s?n6hTGwd9)>ihqWOs8ZV%H?-9V>|mAY1(%pSJ7_HtqDncB)M}KJz4O98MV0b6EhbXUM;`KJT`0GN+q}q~KK+|2toa#+L}Rj% zCZud@=>2xD&SX7HYfv~R@&Y#L2x?!wq+{olRL8sZz1QmAB$ymXYgZA8U}40D0w2j+gg8%50u< z6dJ%XvB$(XI`XJ>Gg>OAVyEm$$v0$Tm>pJj)$%N;USF?6kOwPFo?80$`%ZW5b=qCG zaaijFbhaqQ96E1B`u+{U=xmmkXNq<3ghRWu29+TyTdIM! zZrA-VfyoW~*)wWq_GIFr8^s#Td+h!+CZ0UWz3FI#X5dFUelr$R>NwgfmUX4txRg-1 zoH*L*jWcFQ8_t&e3_JXB<_zgp{G1I;M6^MiOqKwPV)D%N`R*v7`_fD(1shVaG}>CF znhln)rG4LMoqVFCgHB~yb$qILXy8Y4FuzoH4^sWfyYFHzRy~`%hwt!K0SuPBZ5w~P z_=aQ*GNFI^$*ZU^GuzoMzjxJKMJiugO@3RN1Wn*&+1hHp?_ZBYwRsviuXm>XZ;%SD z&)tY9F}p#1B+27n9G%%o!?T2S^0YFdprdNr~L`5cY=PHAwGk4m@Rr5(SA(*V^&l9qvBjrhUl#ynv|+f zH+o0K3sRb7x^>>qsXUFQ20A4%S-pE;tfAF)5-rnh@ziy3X5RldZ`WVZ!RbkP3-KN& zpv>c8#q+_9K|i*?zdE4#sN%yHeC9TCu7W%h2^pG>Gp+a@dOD$@J?*Jr+&xn`Pl9d@I55mTG=c?7XAX^x zfWGAIubC?!eFOR;AIM0?3yEW(ner{hQ0e8Q*MDLq*g1sM;q1#2E5UAAiT!WXEd!ei z*QbxrTUqm^QpGyf#0*A}#>%b@uUZ2-EKgZ&BS*bT$IfDlJKpugqGQM9ee32esdlJ6 zB)-gbxELj%RH@_Tt=72nNI+VuI{^5B#0tjQZ| zgO_;?Mv_8(e|fqH+wzBk3+oB&d~`m1g?&|5r+?TONIrLO2Ai!v-n!lr9wSdGlTrD# zO(e*O?UYCrIz`UGh|z>HOP}nR?(`!o6UeNPn@KXAqx&*zww?by*25Rci3=7&L+%cra^J($a%ks6mmaw z!jXM9WH03CU~4p-)Qx|kBMw*{#~We(ROI<;)5}1Pjzze2Q;EjOHRCZsqitCdlX$5@ zyhQQC+{ZtKO7yiFEV8Oe<S_c|^DMNO#oIm?2-! z!(`hb-M#@SThEB^7D3lps7fy}AV4+>m1Sv?^cc_Ox9oCCdBbUu#wG}ugE*u^p>o%j z4w+y&&)Spci>9HixlL=O)aQ5~URKIaVc&uj_Jab0eGxIrBCtu9g%05GRtPekGKx|n zBq8wF)Py=(N7EC71rsLr?hBQWj#2b(-n>j{U2`3_y{$T1s?n+&$-GZ1olcC;I%B$y z#$|eCAxW2r_ZSS;Cv*v!Hl5xyQlDkj(SC-B9yRDP$f?tgzEQktpvN9ZE7Z?0LMUIK zrqlJX?;YuA6wz6+ilDm4Z_^mBqeBQ~JMuiK*kaY`X!c03wA)I!)TShz)ksGMI%=Se zk`ssFNpEQ-IHds1jLl4-Z2@n)WA)CpfL5teMaYxF*Axp=9A)lL4&tc-$$+T>lqMhQ z0DBYa5Ki4e64fV@&aketOZY?S-P0?=yW6nE)nptPbOeYV<`cy}o z!kHP|#TbkhuEnfa0^9G`Wyr4qaP1`T#Garo2L|m*v-hhQsO)Z1*s+_*ltl&fHk}ns zlAlSWnGclRBER)TT4+OC;IW?28Es8u$4S~pHCqe}P*2|1U^3;p%;wGehxYCn-LtcB z({RxEAMbY10k|%M<`aYsraOLdKk>GmoTK%5;>Ye}WlC zqCQ=hZbplfQG=e&&#YErEKA44O4Y(NShK9OY(Sf3i(>BHip~F2)X&&XG8?SvO>8>D zDBAQP_iKhJL-542+%e3MWn@@-qD60&JCXMrfEZY`ENa;)z=Ex`&&Z??FK?qRqux&t z@0JnQBxTlyL_OIralq>)_hT4AFRRFdkWTj$RRx}D0hq2cCnqy7<1njvPZPEUNyD#+(6+Nc_#Ehi4rtIi!cy;ja*ziQ8-<$j@Z9r97`Co1Qc&vLEvS@5K<6d&cIs@Tert&gzk7&o6>;kX80#ERFq>^?# zSNt_l;C;wphKem$p6BY~uK(8Xx*Yqjp#o3vSEpLx@z+R!cZ3`D%9`5o4)VGj`D?7e z8_WCng*w{tM!C?J5emFp9HwYJ?ReLD6-xf#uhi`QZhh@|YW5C1oq|81FO3>&$5XQh z;MG&$3433MiAO$yJ9|*Gci^endwVgFxCf>?JXidw+51;w0-*s<&ECPEn!S$}3p)*X zuJ}{4_Yz{ErU6gQ-oc-my`L0|Yz=s7_6|HXdw*Iis5RgTd%vX^lQ9>;+M51nDZ*Y3F2k>6!bt&MJRNwV%p*dXUEqjhcX%1RkR#q!o({bJoSx(Xygn}Qw()c&e+N8(=Ze42 z6?mdd53w=A^ITor$qd0Ds%~vr2pT&;xj`_*1ioCSu^# zz@M5ufIl^RnBxIFHG2S_nmru!0G{CQI(4!T6W(OQ*#iB~#=of`D0CGY_42LDUw8U4 znb)O;hovv{MZDAVqjHnhC7L9;!z1WPr+X+ zaZsTFPmMo;C*&!XeVxRChX%Z6D)Pj4a^Mg9wvgu)UjHz$vB~dUUEIm@PyUcno_H%v zO`b!J6of#>L7YKenC4g9J3mj+aynmriA0ip&x zHU0#ikf-o3nFF-TQ_UW**Q4fNmJHO6r)Ce>>rs>EZ2Y~re1wAf7lG#}&t-$P$;}E!+N?cPY2#w zP7l{>$6M_Jubl$#c}~|$(2h6J1s=X#LI8gY7)5_-(F1s5@5oV}Vjc{S%}Uz_B@;ScLSHUF~819)ow1$b)yWk8B{{w8v{Ddh<~ zHUDzd19)os2|P9bGA>m+e~Vr4r{-Vk8@1!9`4{k~=3id(0G^tE0iK$FDKS(#f3EsZ z&A+_u0X$dysri@c!?g3K=3gLBHUDDv0G{CQs$%}qiF6i64R}`x{!`4CPIv%M%$L;g z@PQ}rDsVB*H))q=Szd)2o>)%{{@zW~j^~cQ;+(%HI80Kyc0BP;qZ)rW=Y%{3-Ye$9 z!GrIFzKHehUv!V~Nrra3i*i+xlD`m2Q`67)hik`E>%UNrC)Q&^Us5cEi&vCz(SPFn zR%g|Y7f$sdDCH^mbF_yP58$cEGmP-jf8a*xUvxI@{HfuAXCT}kWqz$7wN#?0uE!!(vJ5AuR>`L0#Edxu=g@! zwBxDiXOshf0&jaE;lZD%*~8ee+WAw{7l9|_DePgzIPG|9_Rxj%=Qw}a_>6Wuwf+-$ zj`Np{@!Ij+@#pBT$4}6X=Z-(of5P6|PSlR4rY}OCj`NqKNri(K&Gp4`{_@JR+VRxp zFI`>e=cMPfRky5R5hi`wzj_!D@-9)vur zOe-9`7zh5u{3T?%c09HDi@+28C-n2kOWN_&>><{HKY=%AM&aP~a=;V)7yGhyJT-k0 zctW1S9>%_+9Z%T96~+Dw&X1lY9ubu5qiL^d#}obMi1(Zfmj^H6wZg-DUIp)NA>vI| z;H~2HM>Dna_YSYiQJya-@Ps`)Jxe>DTK{2xP)%QI%q~1UHGTP^5b@OXW!me7$Df+M zM9k5Sr=~CHKQ(>1=m9*TFWCzJ(vfsCk}$yy{L34dI8j(WS37@?V^F1_h9}0`J(w6$ z2z^UCUVArqfB}Cml>i#ON4VH?cz-G634i^X48ick`Q}^8wd0BXc}Ki?3OsRUP-%sB zJj@*s9Pz}t3*V9^8sjUru@ePmRARF8E7&w{ZA-(E)D)-6PaltsPH| zKY{1CpY@gp@YMQG;FTku(0}5!f`0F5=TE#Mq|_IIC-z^&eCd<-wd1+t4}Y;#X%Cre z3I}g0;i%bPtF?uT=V*U_cmPjLKc~6iFJ)cf@HgE7Zvx#T=swVnr^cVabF{xj9>7!6 zPl4xXe@}g=oj*1E6L^mHw{^XCJa_y#+TW-Rp2NGO82>Oo8!4*@v-iWC_WejZ-Y>i^ zN4%2?JTd1lzfn8h5*K)v6nNip`a=)k?Q(&4Sp{$WChh#W!V}++z+bQ9*xfd3$9vBO ze^(X!eaPuM9>80pf`|E_ntrbNSUZ1e`UyNW{hYQ%JD!?;0#8jpeLvBTr=~B!Q`678 zg@~u7pI?8foj*1G1b=G!Ir=m0ctSt_RQS)gNN4eB8fu6Ab>=$Ua;tW{a9)=Z5AP$Z z;n@laZ=nO;1m31C9>5dx2_=7vT;R3erd^(Dc#B=&Z7C!?_yA@9O`v;(_MaCHe@m%u zC7#gFEgryA)6chE;1&5oJAZ0;%N+0~&^tJjJ4Nk}XPdi>!UWFrn#T0nMd7IMqYR5}+ z!C!F&UK}rTWS@4tSQmID6nOJ_8NZ*j?j;H2dfT!kP_FdABr{-UP zr{-T?x}qIV_?Pb-<}Vf5C@jw>j&nNans&S+ye=gk_*26>cHMJ$-#hTPSHa&f4zvA+ zcDxi`g(Kb%3cM+tZgo>T-gCSzN4$LsydVzqkq7VsT=4g!0xyu4`SX@`{#v`h`$>T( z_-lMeJDw~4epcWaIZXUr?RW+k{2f%_ZRTZmWoyUV-~#WE0#C?uBKrpid4`({nU$Q?ozdso7tnqT2D)><@Tq_V=C#@Lb7L&Hhdm)6Soo z{eeF<`>RtzJDw~4)a~Cu+?RaYT2Rt?V8&yU-o{;Bmg^gl=>3`g$ zuznZsL$52V9j__Xjo^s4UruKG69Vtoa)pN{&assIm42k~@D8Z(7f_+_@D3~RnsZuT zQ9E8^UYBG4{i?td{Wr}6cxw6rdr;HQjg_?X=L%0vKTlLHJUli1tWc%!@YM9PebvIl zQ`66s$F$?A=_m9>O+R1t0G`knF(=|?Ac=clN+`#D-lx^H^H+-3b+TP3?FqcwLTo_?smNz!Q+W9l_x*YLls^IM`M7%jFcx`GI9)F7zcw+ARjtB6> zxZ^0##R|OLoE}|AJAYsEx|DeEXKMD|S$r(PpK*0@w?0y{ci^en`!x^XEpox1n!V4f zt6iRI_748k>^)Ma9Z${Pfv0BgKY9R9&EA2hX73U8wDac*PtD%f7b2d}Blv4!?+xo~ z=TFVvAWk>VUp;`Q)_?GqYW#(JYnP`Qe;5yx{B5RtgsC3D6W@0z`%mD38>PPv_bFWd zggpp-nOewr!hZ_9y@iY?>`&lT_bps`I@(`+A>);F(3f`#84tRt)Xxirgm;y2V1MHK zG0}hieudM20U26Z$fzknpZ?{dDx7 zM+zBF_)oE3Y2>fH|J3H6fmTFJ;dR3N;Hl}0;7^QyV!iT1p!WV#Td(}h<%y{`^hK;!?zYvAr?y@ZctStL ze7AW!?RaYQU4bY3i&(F`(q22B+ImIc345PFGDYz2s2xvjy>gT4R-4bS@c^Ehz2D+^ zLSIDxUH1TT~9Na6A)>_Lq0OA8rK z_)md%wvh3J{RuqZ(886c@Ye!wR3YP)bkLWrg^cGo-z^bVIP$#9?ay(&(xZ^^9M>ze z3K`FFy>h6K@f`cFet6;bpW}ScSjc#e>y@=0#QQ^WzC!9LRmI>(0Xq6@9Y#tw6nMzy zMdVDyy}R?&@w~1xROplf^D$l-WLgxChQesQ`~DO7?(kxHq0t}4Z~JZ%)e&Zn!W6Mu&d^kWpQoW{6S zjnnAwTAY4_uGKkRnXdIYU4yP@JL;)P5tyJ+$ETdeb6-)!7z{Zyr`Uobc)>j235qQ# z_N9ntTTvWB5qaJeeJJ*$h&;Tb)Q2MYPoRi2KZ*v5s2?)%rx-vHe4&mu6ay(5DWZH^ ziWZ8<3!>PL;!ujnYfmwSBI+MO5osMLW^o$wKpxUTk5kZ?t0BEM#g7&A7EZ&wKI8P` zbls+)Kj(B^x^CrkJ-U9u>H2hqk3s#QCn@OdoNhqZFBS9-PB*0ME>1V1>o*GeTTVBo z>(`uaO4siwLO#z?e4gTDiX|vQ_Hh)^SG_5sU+{e!+SQ*T-uVLkB*hX$qfefqIDq0n ziY0meAfmG=0s}UI{w_m#xQBi}O|dM$*AtyUu?T-Qk!XB#hO$W%(f4?74edkU!4A;Z z$rRDAkMrk-5#5N>CZb{YXkQw|bc$w*4S9YB(Y1&M2J8#^g7quztrTq(@je~yGbut> z>hfnt60PHTqlkv?U@Z!{bfO4ML8HF~jk*L49TGHj1#~dQ7dRb4SDf7-J(ME$Vg$WG zL7(Sz7+rC;gfij$Dro2>=m?6X74!v8N7D5Z1+C+B6kY$~bZ5Fk{-_6ZJx+I_E9M$V z2i;gfms8LU6f|@c<)bN1<#boN-r{sOy53OG8x{05PIss4O-}cqYgq-|kkdWsT3JC~ z=X4BRcPi*6oQ|dIZBF;1YXt=jn?ajTkgtAML9bTO?{WGED$`t%{=R}wOd z&%(b6to1~bYB4*-6}F1&WQx$I85Ccl2-`&Z%M{U1uTq>v@imGwDZWB+B}F{*I>p%( zVJ`?MKab*kif>SSlj2;8Ybc@}(8)y#`Xf$Hq3c_mevz&V6!dNdT}na!sh~@88anWf zg5E?l0C6D1u%~5wZb|zO2p5pf4d)q@ynz^K|rIJx)VbkQ2&4R>e8JkglUSy@;-3IK7yz zV>!KquFr6KDP18K)C1W(!s%sn9nWdVa{{NA({&=JSJ3rYiqs_LvvGwE;hN5`&=1u8 zJLzHzPM;+D2?gC!LFX#6dG@$4fCx{8AK zR?y8AbSnkzqoA>WD(b|y4T8o#uAqH6jqf6AD(Gqo8gqV>N0}N5y1IhKIz*Jgcannk zSJ3$8N~E_@(D;@|r27$#P>fb!&9+;oNzoPA!Z)9*9 za}5)xF_#!gG};cGK;NRT(f7~`=nQlM{fxGt?T|P62(m_>ppVcWXa}&)Qw*ahX!smK zU*Yrxx^_~~k(|Cr*C++OL_uHW^q+JMQP80ZI#@w3=JX}HhI9HdT_ZUC7hOAZ8twX@ zg5Iy7e^k)>6!cyNy+=X+prC)^G}?YrK_64lzbWVw3i`N$KFaB9bnUL7;fEnxq~GE6 zb-H#@&@r68LDyIX4gZX1k$#uc7~3#ELOSSf3OZUr!_TA4O^Q7@eT%L=IenY1y*Q0_ z{i2|MRnUhO^dSX(KtcbkpbskOBb-Lt&noCY6!a+teMUi_R?xo_EdtvAE%~V_bQNRh zZla<0r6>yB6M6)@sYQ`gpRM0E(-pc6eg1@^jw1BDF2$`BVaK&8eoS!-McDD<6t_|Q zoZ@1NV=0DG6t*Drv;?Kqqxc2IB@~~b2)%;NKtG^g$0+_r@i@f|6ooA+ZJ-XNe@1a3 z#nBXn?nCFH>(FuNHgp=g3>^-p_yWa`C@!KnhT;N>#VJ;!_$fuF;6*7U%fXfC@=MNd zQpK)O(NWC(dO=`0hsZ3;mMT@IRLQbsN|z~Lu59^AwJTSuP@z)&8a1obZq~3x^QH}( zG->G<64=tGqfe72ZMz3`43F#*-K9mFn7%!u;zBxii9{t{<;s_@RH0J6%9ZOywrbKU zvcMr{n^cKBy%!A!^`#<}yoy%x%J~v~=2hH_1;LtEk)p+lmnd1PbeXbLU_(V3Pl^^T zQmkn4;>D;Zy~a_#RIF0*%JqChOFY_3U$Xx2Dt;4RU0kX`*t*ZF_TGD`Ve16Tq|#*` zt5&^6%|?xzG;P-0KcG!u+n{#g5s^`yyF_>G6W6z2|0kaskeFmhPDwQmwc0XAj2x9U z`q}56pZvm<7pJ~9bJpzF=ggh=#*(FPFMDVCij}KA_;CG(k2Y@F{P7ptzud9&t6g7z z^TWO$_y6?sF9!}DJAUHi@2CDaedg@tzph-pcKycRH*bM2@F{}KnFC*yh_52WiWMzZ z5`1|T8A-8drDDbF`Ie|0+N-2~_@njxCYGua_UhtwpOxd^(O_PrQqfAJtjAK9OqH7cE8@IH=YQJv#E>Bsf;)8i>WXgf z@?Pz)){P9m`<^vN>K=UQ@!;&nGjI3)BYSR+^jnAVcY0KN`C5+jNWjb>ir)+h6Q&@4YqKE1+tH>l^mm^~sU8jmnY!ej|9p z`?(K|x{>|ar42p5{WC|J&;!W1b-a9G*qU2VUG^W+F-KbSNy|PT+@`iX+AB6k z8a87Re$X)N=*|nninDHc&UU!X=gAdH;vCP)(?wiBUmCP>IIY-*j zdwfcap!>b_&ca5AD@RwJT&izOhu=T$+hWR{H=nJcn{BGRyuo{>Gm$OkHvb@fN6qF( z=44fU>F8Tebjmo`KYjSm&)!OUCSXmIDgJ+CjQ_A&iT)!>)}B15(!QTdZ2o@Q{0mjL zl-QW?`nh616^ZCquJy}*`kt9?YrEq6cbAtsS@xaIpMDTKzs}oh{whE7>hh;IzZ99? zY0Wz|{5~E~Z2Q>dwd>BQed55@cFV_)PqUhTA9$$LaNRRf_UU5JBnH2v+q^KcQI&E7 znl)Wie93E5B|EVpW&hb<<36~(=jywe!xA1p7FnfF#a@wBBoX_zKl;hSuAAf5eD>G4 zW*sMQY>~WtV{nVRov*FBy7-$(Ugx^D`u@agAFtb+dh56`_HeTocKdyh5mPJ55?pau z^W$9>oS9zc+e+ryPoA6@cVpvwjjzlz*ui zXXqD$50=_BY|uw-O*1xqb>-BGUQabiOsTTF$|oNbOaE}s?wNbi4rCAN-SYRjudG|Y z>(^H{U)U1-?bJO>W+b(*gf!-=mJDZk36V@QqQ7f-Ekwc*L+eZ^O2RGoPv%hEZi zOy}c$WBzz5u6OgD%df98AAUMp_v^T|LpRL+vCWMb|Gm|24oq0Nv-;IN8{(F{nf792 z%Neiz`Q`rx4e%d+&@cMbi&ejUr0tpM&(!U@eaoh5k5=n@(D#4)M>iYv#Kvm=y?cf1 z*j?l8B@-C=*!j<{+$}z6Rlne@>`CwMZ~5XFQoin?kyT>7M2uV0<;c8Zm(TSd`cjT` zBxYHYwLhJdzWQ}w_N}_ddX}#+>ST`e*;jw}xsdqL%#jBTse3N{Hm2^`l7I9&xUaic z*CQJnygK8B;F$MHw<*7DahHx;M=i^dwk{=uUshq*ks4e7yhJuVw8YL68{6)w@%GA1 z=ck2r3%+?Q_-=OHJCWY=5_6>TMtX4k1fb1h45y!lR!v}f7T?Bd=zQmtiI*6+D_~Q=rL`^)+yQZ-ra3{CoOE_ z>YjevUS7WOr8Le`|^SXS0io@IN5RCTi;yz<<}2qZ2jYhm)hSQG&kXq zN3t$V9XLGWi!0~9fA{e{N76g49e?YZJNa$tG&V#RwL{_XOGLw~KzY`o#N-_15_ zYL)1sNu=4PyG3sPsZVww+D1u^>gyx4yTVr9G=^3{=^L* z%^3e^$do4<^;&)AyOy2Q>PXD`uh!1q)o1hYS1L4EW{a=f`&y%Y*#|m)a^T8{xq9E< z?ri@4sSgj%8d2-;Nz<>7wV3eJ&Xg8^`P3-=^TI1I({DcrKe=*egR93^8;_qp zG-TZTC10)0TJ~wsnOi>w9@mfYKG>!8aAJJcwl(CKr1fM-W&8W@%>4N7;pEN-Gra2l zw6gD~0fR4AZ&2*!BTv46zKpcsVpO2-oQZQ@-5E9JnfSY-M=bj5&5TA97XA8p+pE{# z{y6%lQ$B-ycb%TQr{}M?pNX4udDrW|tzUI+%cAaa-HwM3tYoCV%%;ASug`24Sc7%A z-7sOGaRC)RTiA8$Q@36?3d^kDBlz(?7khVZ`^6vg`}C@pyg9J4fA?z5r|mp3W8pV% zEl>G&tTg)4nBhOY);Mn1qO?!0xA<%Apy%3l$dSlljx9C!j_JJ->l%GKrJ-Mx@8tC5 zQztL~#4u*L;e}l#>u%ZUyCd|eni!gDjt*-uZ{x24o4#uFWVz|J?~ZvUv(3ut-C}#3 z+jHgpldWpKwLExE(N5RmyQWt8_WHEs`A=7@8fbm?tBvMw-uZFBkB3%F+J7SBn?V18 z79Z=)1xJ1?HFev;I`J{v*ZbZ)b1G=umZ)RjU;O2dH;!JuV*KuUlkT4ecDucM`-QYl zN4LyaJ$%74n^q5O)~M!BZ|ocR*rAN)>U+((IcMU`m!Tl>mD3HI=ft#ra?j9h(b?-4 zAMP~7t6%zp?Db369{Hm|>MQ<%<^3h_mqK4f8UujZn;$HZmQSMMGozWX&y7D!TgzLe!jNk(!sf%U+H<_*T9)OqDMBU zHTT%EyozS>?di%JxOJ@JN zx_$lVKVCbP{Cb}`rljoIRa;h>+^EX>*y3BthjlA*DxjbD-HTrpOS$HMdw0KXyCQm2 z))nv4;uk5T?#fkdmrQtK;E>&ES!T=I?GNqxK=({kXvu}U`c2+?eAu2!bIYI4Sp4jW zqs_W}e?BFs$^ZIwtl~8$rdrg&E9ZZItmCu0pJ;F0cWs6F%P+3SuYVXAWfF7A&hcID@*D=tp&VL5elr9y*H$EfB*d>H$6T5 z(UU<5Th_K+H9PsMZytR#=!@cKHciit^GZI`WZ>NGZ4+PJ>$~8sE!Xd?*g7L(WASDE z2me|mVd{5TZcY2H<|ik`s9ylEgyH|R^MBTm*2%@ zzbW}fnWjtT=9yyk+IsuU)pz$tG$E?cr_v2Rqf)J4UXygpUx-m6<= z(aO};ifHSXJE|{RGC{sgpxmxh%5nfjV(Gns@X3~t4N1?O&!s6ht#;4Z_gdo7nL|Z zz0bO+re2$tRyp5ms+8VzNBb%X6KYLmnPuC^BY1mn0`I!H-$(T>R_PV#n}^4^Pi}up zlcs*>E$eA$m`xzVqgwcVxnvGiQ+aytt zp-Xd@;^LLC=g;6D-rGMg^xOTb_L{;Eld2|=U?N8Du zB&W8nlCY3!FGs8rVo{Rt-&EyyELX};X61v|hJM)h!V4|?wditQ?n;|b+4^Q^SH`)>C7edCRo-}{|j_D!dR<*y(8HF);p1IOF4`=(C~3ZJ`@Wk&7H zK67W)uT?BB`1bkMd~xA7FSp$K@%ZK&BWo}IF7B^Gx0nC5lqJ8nx7)0ssSEIU9ILzU z$4!5K#G%%)_Gc0uU^+AOflFq@o^otj?Js?r4L(pT?#Etnv!A;L1cb`OyF~jEFw@2s5 zB%{r2Y2|>;-u?wdX__ ztPII$PFKk^S~Ex-sF`Ixs(ccu)(m~3ob`w@D^_nyb;n_z!f{y{26k!|7900eY-D^- zvn5S$VrR%qu2Cj^ij{4@`}zm@w{0EZ$MzYcjA0Ran_k*N{~!|Wz_9;H(CIg*HvC>r z^`eIbRh?6v>0Jdgz01&*e#7Z(UKmzTwirSy16ONJe6#62!Y_6o$ zbBpuZb6a$Oy)EmI7qt!jn?!9LN-acxXHbj0xQ@Bb7qZH2M_Jx7XHD}WS0p5xq2RSI zVP%k1fI6H?l;WkDk&MuaWO}d5i}u{*XLFJ6k7H2}>NYU0bL&>7iB_fWZ=#JJa)CF=G$Cy-dIL}9!Z}CyWA{AN=g<3+hYzIp5L?r`hf#D5p!X1i=r@Ay{pcOX zNcs(DG;*RSwk92HL-}Ep8bGxOkD!%T(Qc(z%gr9TY{%XAaxorn0L&>@_$j-bKz~zgtME3s=fsvOHDcCOkD{64RZb&Kud zvN;p-Gbo}iWt}G#>8KNVn5&9^eT5EYk=sg;cUoD~*D=BbKXt9dCz_uDafo;ia(7$Sdu7 z9^ymDp(|-%7_}X1O|;)tdVLS!3i$!I59?{H9k7Z`VtstC{06)o?&T-+JelS`SjTut z4f%7e^Av7}WeMcFi8(iR%rmaSqUXqFtt)-VCI+QA+EYfb*mpRIe4 z)|#krx({H#ovC~{+cj&JFFbcGZvOvCKMVa=?`K$761_v5J1*s>w8)o?MW04czo4Jm z*!!;y^;Ku;*&s@3Lp|wFy%$Dnp$L|O^=lwow?@#_kFcJ|7oPAdx$SJppL6yr!jttR zzgmw*`((0l_!8`ez|*$M7oylP%Daam=6b?g-|rkxv{AX^qnr)hE8izyJcv1l<18qS zd>-bO@;(tp0dEyK`MQ*F1)hWbX)!a&q#Bie8-0uaocpIZ&+%nzF)z}Qg7|E-7XIFg zG)sQYQ+*Lfvzm3i>B_sWCld4JYVXxsnwo_FpSf4gS7?iYX78<5X~ z?ib-%{;&5-UYqx4{zukF(JN{;k9m!3FaCB9=wARUbwmYLUR2C@g;x=NAi!=d0Zez` ziv#Q$l0V-dk0rSy%QzZc#?cXY1&R)@1>hqT#c{slL4MxSO}snPvAXww9z9~b`$pq2 zgCX7Ot$Zng($!v4Xr-PUAKrxhX@=;u43iIsW zP(z}v70YcR!~piFy-Ke5s}@bz-@WLWnbzBoVKOG-<%(E~Im2MF8L7E=al(hayb-H6 z8EiH~p7$EcQLbm(LZ9VG96l?IUIj6x)0+r#Bk&4CoH21&l*KSS(~zE+#Xj^2&9s@B z4j?PmVn{M3+VExtK7#6RG?|dh-rUHW-`k+KQYm~wC5zPkyClu2oDe0wAmU!5*vk^` zUKG*#GDcZyO%HQYru+tqyVpLTX>!Tl1`}5udQk+SGR1#Jn>?>I0mRGIoEzEkXR)h? zqX8c9IUB-V`NA@mDrkJ_CPEkpd>e~kkuU6*7n%^#geR(IuH~8VM+i#DKjb6^uY_d( zs24uVMNmF~PX`f@rFc^URI>s%*h&7Z2iVURo^6LHU4=x6`r7Iw~rf93np^IbB=x3}uC$6AuZ zjA&ahzFb96ebSAEZL{~lztF-`XY~v&a=AqC#j}lQJf2{0>O%{YI~!Wbm6jz`q~B7m zgyzP=7Cit98%%BUh=t)hb%fjUh5cfF!~S4UnAwtKu*650ZSk$yUsbUeD#)1i&=#H5 zs?N(bI&FHqc&GO}AM5zg7G<@9?YW&IxDwhwY>RQ!?n1LgHjZE}ookB^EiqSLl(WD4 zn|HcWs)wUuu9TfdMOQ-mhb^&pVOpZvsOXp17AMIf%QLfvcR+v)mDp&pm8 zmj9||fnTTd)3TgkQOnWMY)>AbxCa)DFWen0@9A23S( zVPZofb`4xEKvq#EzGp#rT)x6dMF^?zH*F8y7!;fxUp!beQJBYzjMKbZ zj6--DRK{r{#O5ZHF@+aW3aN{m2WdL6K0=zXDdIa`NI6$vDEPze54VEVCwvcJqv|#4 zmqHs;@U=9X2r7&&J~BC(ju!LUo+oE{Zl}q)|G2m61l!Hlaqeb!LF}A4l>!e&gSfE> zbItdp8wZ9iC*81Nmy>QyI*`oUtF~EL9(koHhU+a!(TQ|kD!5_~6{P3c0g#(>frp1{ z?4JpMTpxPWf6SxeR8f;PJv>}vD>BcX#6DaH-^ZE1E1~_v+la$GWnpULmD)P^;o%y_ z6bg=OgNIxCvRpz6|5cKI>6U&f3BV(xotiB^JX~YyrCe-#c2snwR0UqK43_QS|BHF2 zE1~_vqaqezg=UFrqvFHEHKz0vLd1gh!5yw)8SiqPkLI{s=Zm(orWa)K{qS%t|K~&x z-6vBoCNNAHMW{%`zx9p1QPj2v>OLPHt}*>M&6UG(Y4PxtZx@20BNd50;*^7M=i=&e zP{4a7g{I!H>xYMHq7NP(uF1L?B44BjusHsgo@l>85-2pIdw94O3I!|hTYnsnd+9j-lyw+|ou`@3%c+=IT>8ovP z=5D5B+HB_Z_;8b%zRb>}Dfw<$O?NFrt32JZg6QzQ_6!RBRSlPV0t*kJh~Q-YpHgC; z-uS=4Gps0tB7zgoUr}Nnp6{iB6;Vx5ip?lCr`Up`OB=z9DK0g!K)B_oCaDO;Cn&b0 z=n}IpWqJmaExE8j#SWiKJiI`6f2?@ZlRoaM?njv(X2sVXUY~s9xs*mizN@&GrrD+M z=dQ_kYr-=kvTHUD_53LYxWmP)&@;H@s3xY_ZRi?E(WPvSl<65vyKLLK!?RH4{b_a( zJxMRex@Ki4WqO#E_U`af@{Q+G`XlmPMZPt=gS#fPC`H z^DjxL*ZoOyvldBuT(f?2Cyzy;LZighrDoypQMr^yZOROxh~Q*tA5)^Jo|PzwrOm|? z1+lbyEy7Q`Rvt;xxiiBDBCIW1gynJN>EKQtu};e4Qa|btS0NM;ob=-}O1y9V@Hop4 zL)y!(2Ms2V^g9h4r}>VR>A6%F*8dl!Jv|alueR!P$Sf zw3oV6JOs~BaMF*hlz89z;c=Ed2?%UElJ`MQi zr_FAKwL^=rJgz*R8WS55S0NM;ob+QCCEmAwc%0=2GHq@|EQe4;aFWM2lz89r@VLGF z^V4Rx!unQ=usp6jo|-l{Cayv#A~@;C*OYkQ`r&bwJ>?>r5?3J<5u8~5juP{*{2Pi< za4JdLhB<5GJeNo76_HQ-tap~IL}-@bTpOP+>b;6+^>`&UPPaf*E?#!>7`u{T8=!?`>b@S;Xkr2+_! z3{>nUr|0=Ip7s~G!p-S6y^;P=`uOlvy`_hN{(1BQwby=#)1OdWwyzYmPpuiO&5(R< zGos99`djn&*@!3IHKIg8g{0EDE(SgQ)zgBt&aQ4xQR@a!9O$leKEp%euoT(`q#qKy$ z2rrc)4yy6~B2IZ-I;O|n;j4AD=N;!TckRP>eQM26aZQ>Wr^#I-8WdDWDy`GxIMb+g z=@iZGTG_Cmt@N);=?l9F9*^`bllUjxs zBwSiMj_y4p5xe6Y=?+gvc=y-2qo`WEd*PB5e4>;;Rwhw32tM+K%~vt8M4(EH>>n zJcoS1;=sv?Xfta;fgAo0^&=Kmc^Y1jehdSv^BKRYe?)0fh?_&a|6V8Kb%TepLU+UZ zCAa?JaVn5URwwWX1?9s0jGV+A8&=UGgo5~;-}&$>oJfL#RzAQyA!fx00@m{`Aed?o z0R#mnkN5&53TRg1!E@}=m4{G+5D}ajewh;gtqq4Jgiu6qYWPJ;%+qj}{JX7YgJU)S zqKG@LJ`49 zRwXF$zGd~F9HQNdqn@KU{zb;xh1wQE5y7b+%TuDZe*CX(ceoWtV@GlPSNgG>W5Ye^ zyZ(E7T5dbJ!9!V*1Q3eh$E~d3s`L1V2S1p5eorf!mhF|*^H@rKwErcS1Q^(z; z#5^76$wBA8H(~BU;s~LL;3TWElz88=`cF=n-HM~37IB0@!vClCw0aUlA>fLFlj>Ba z#5}6=;2oPM4O{D;mRng}{}0OQ|J0sV40S*VMFb~J-bsmhGzku%L72z~4IE0km!4Cze z(d#@pyk&Bpgpo`HHb7zmjUc)gjt>E^9x6jce2j;HuelI_k8jTqF!UD_#Tq@zzIuF$W6-5(<=iP3t>HPZX>db&5W ze3U%FXe*VlNGO{~-_GczG+wHeR7MJ=91Gox+Ra4iqztMnot~9xJu88yEtHNs9esO~ zNhK2L-b`1$WFjhw)oWmX%M_y;g0fG?%1KOyUYy3IBE?dFG)pO4@$2Wh%&4+?@2qdG zO%lC?0!8sd;W>(B;*0gX{bOqA)Q=yX@np=cb!uswS!wwv2Nx0`yL#au5Sg6$j$>k<%+iIA`DhzO1du2m}V#w zW;UA)`gF78Rfj*}k_DF;3aAo9C+ki0m#=dvkzF7@Nvq|c)Z#+$Oo1FmFz3=UVIqSt zO}?<-V)*?Z#fNU|A8=dVXKQD*y!d_RXp6I)A6NfIib0d1g z3w2IyF0o*iTABv8B{T@I`3(g!1+;hb-tljITVj0VoYyM$l3wZ4LM`pz?6w}1Ipece z1fdHBH|IrE!$Wia2h6$cVE-NaM{SLK$+W70zPs_X=t6WSbF_4wOtI&I;OM>k$8}!X z(tG}oEe?3ArD-r{p+SJnZzzyCqrGE)o4(7sr$yxRv(H*5OzoYlmiBKpXS8?0?9UAo zl4o~ccH-@IFP2&OtXkSCg#_)hkk4qY*MmO7)JdIbc5J3Ov4LjL7D_4Ol%kX5*|&w} zyf%uMFPEYJV(4ki!!zjq4>r@rJlIULVlfLx4oZvpI_B>q*-SZw;n7s_4sV^%w0(T4 zYHzg2uqWh$D6lTjyQOMCTZK?v;F2{GNxzV%&&`A-*k%{C3 zZsUkYNVE*C*Gyb$dMYKaV49M|ER>7YgO#sQZc(n0Nv;`_Z5-vNQ8}z-P!^KKx&$i~ zEB(r=9C_`7Ume4}#aaMtv;w~tR_7lKg{1v8=V7>lmpo*Cqzy;l)5?cA1YAWZkkq9M z{IN&))r+pm1#LN`V+t{Y;!70IQ$$b}Vm_%qCFbvI;d^1S6)YO^vd5~l|K)~PsmfUt zU!ypa;wuzgvb2&iJ;Rb+jIUFbv)y41^BAUGjB`9zrCp5ks7f5)zd`X$igPKt6yqAo z%%2!1QAq@$%}|0kmLe}_#o&h|#@;hLvmQ!PP(GL@C$V*~(}Okm17Gq&PU`#uWrVoO zTtpdbc_zEucf;=w|0B)#<9O>mFSsdGa|o~9NvdyAMj;ChM^-NJ7kCW6z=ErJFO75C z@ZF9LFUTn{+wy|BB3R@L`{ibFk5gb^Bd9*vM9x#o+-Co$Del`m9gZj_0jJe@9&gwhoIWaty=kIeezwckSKWi%J0 zh!BbhPWaeO&x7w$jj)Ihp@`sA&2&o4Uo~%2$q~l&r)I@{1dEP-nTjP@h>HJ z3gOSWcGh^u))P=!94aov<+y-zR8K(VgR688LFI!h9Bby`Dw`4zuxbz?KoIh)srBeK zpmm$5Hok!Y{yyPR{t-Um5donAZQFzfMMeZg2Ke~2k%~~EZtP#F$HRB=LjjeZWt8)| zU^LRN@l53d82S+Ku%cD+i@&L}dIlG{Tq5}5*+!itDfbU9TG=CckZY!Ku)beP;)|w1*b-M177AGekhACoxLyDa=bm@DT)ESsNiI zgnO!A8@U|)GPrs~`1!PM8x+cs3>K_r|A08AH8qhi@$Un$8%qJ)yfW7nGz25`S zzhCF11fOoD53aeSckun{-vlt|QvXhp{%Psxj8IHL5uB6}!-x<+{wWm%WnZSqNlfla zgK_H1R9?`fD!nmpo@-Tlf}Zw>Ds|({Q0_9ZFDWWeMx0@kEj~^3lpie|V*kB2Y8R;A47arM$ z{GyLgq;xS)T(X0{{-szU}89+xln--?B%vNeEFm116%jqj&7Wg70SxRLfI+WlovU>mh4}@B1+$e~M<)$5bj{Mqrt zxz#(l^u4>ko9^28>Zz*2)o>vp)^;^Vix&{(Pyk2k7wOy9*Eb^Ezje5OKp?qXpCDhK z(9pm(VG+LJLB4I-T;xf5*;5Y6sn$8328k+1wMIyHqX`-I8I#LN5iD125JHDZ-@`>=J(F%i4WLp}O{$G1n0v<)N zgqJ%!B1Q~E6fkltJlOl-+&Pma2MG`aK_QR`0YV@N0Yor>h#U_QkRT!iFvumBaws=) zD~EC@B8N{zMdb*{@t(-5n(Ya*$82_!$rAFmzVFXWYI=IAt81#etGj3MZ5KlROj>H6 zM1Q>BqLCJ-d!CINC|V=rML#%1{{7a%b4BZYfZd}OAci7sjaU}cr(1)A9xNfj+dKpR zP&%ESF9;Ynk_n-r_6fJWHIRktBy`fPYRD3oYJp<*{~@b@)f7c9arjY zN&{8vADb#tH=5$rG{e$HJ!PSF8k*Or)x1`1ri^Oncr(y_M!(&mBVG1;C|-E5(%+44 zsg$+3Yg@6SEc`;RQ*YU6de~h9+YN6O$cF}&GMUU~HOuSOMp|RksErVS&}k?}ucmkl zrLo5zOlm)vW?+PebyvLDgBo%u+5WFPn|%re4+A*atT4iJ{!WfN%Y6|u5XcA1HB$x) z1<^8W%Z(PwY+`AP7K~U2CkCxnE5zmE(o<3s(?|Njd;@($tia-#FLqJ=(~cViYr{VU zeZ#;c0BlaQlk-^e|6~#Xjlw_X7nlSn)`+C^_Ytvz6)`1u?QLKZATS94_9Yu4^*B9c zf;;`+MGQ;=_!PX&hDs`8kT5U_fW4TKweUhik7Z~Q;7QP?yGAGkO*AkGP_#8V*{Hn# z<4FKB6kn02 z0oA}HfHx~2vQc|QYh263GOt!p{F3eey0h89B!FZUQ(%DzzJo;zP_%(NmG2vFK!Jdy z3xZSZEMW=&w+@ShvuGj-9$^6aZ#_8{D-+q}R&PV@?%u3|)__jzJFs7R+OWY%z2XuF zJFohE2uk>F@k)4`s9(C91FNF^WBSFqyBlxDEbn#oWbpGN!i97`OeL~f#;nm(20d$` zcmqs+Yk7`kEU@~H(->j-vkI5~Q=Q{j)g2*g*Tv`MkLTy4&4^El`t-@rFlJaL?qOHm zluN8y_xTlFUR6GKmEp%ee}|^6gM|MfiKT_ZSWfv32??VtOUFb^JzD$cdM~IKW4e3z zN7j&Vv5z}Ls*QJ{H6_@3#SKavnVjA^Gcj{mMlYdg4nrxg%lU~XK^~D2L};Bt-3ihq zs$h*8Tvn+{tjZaqhGo^Tu#mMFc#YY>=ownWLxpp!POWCuLX|U}Y+bysa$LpZb(Oyc ziDfGgf5^?J3KRr&s6cm$>kiK>_Pb&>(iV-y%;;G?Y)+vyw1!c$T3FXaX+fQ4N*Hdk z9Pho}Fo@)}-oicU?Qt2s$=VyrS*Y3+aWPsNHe2ZQyk4(`l?q0)nPFLtfz}%sSmH}t zSi#=-XpZw|!4dJB=!o2=={X~g){(2#6lZ`YUC+XuELI$?qR74KMb&lnbzynu!oCf%~}Jig%zg;4)zr2 zIlF6#@yR7u@TKCgb0pi8h5D>G|M}!H*6nNQtEx+?+xMJ|AhJ#lor-_nl~Ud9YaydI zStk?d_6a+l)G~ULwKxB{m{Q&C`=^ZFWbG}`?JMGlyt#~~Wi2$&?JE`CzGgD@Ci{j2 zx_$QPW{uB^^U5c8$FaaSyYHU4Ix?L4*R6ZnPt4ca0?(&CrDltXV|0`j2IB^kfj4PQ zoSvcJn;VSIVt@@WLJ6n{o9dR3v*Xue1hWhZ8F28{vQ|-Jlm2SFCaQOiuM!y4CJSYP zZ~&(_87&&v>T9y78H(fJ+X^t=wU0(9`A#){Te#5vk|Mf-4?pNQor%};X4a@NP?UjT zOq_+*a$5L&1kn}Cbt^etX<%yy?3iQp9BiAjz#dJD4g#|lH4711t&z2Vn}?OxRhZv& zg*!=EEkt+>tXTseBj8Q&bq(HZ(QEX)iDvBE{A{sZN={cW5Y)0p*j5Ok5uL`uvRaeQ zprO=S9egIiV%7?yT${YEYWYo97QJ4h=4nc=VN4neN3%Kxws*tpr-fZSI-OB?2cr|B zN={cgt-+*$k+R+leKZ}VhcBGyjSQ`a_&=qF0koj2Xn9@XHwGQvLD?bj6V54byYVZE zysZ#_HNgjics<8!c_U}$EvyMV9Rs^eIhy0_-)rd#5v3CIY~W7~8Z8Bz^mVijpUl%n znxnKVujY9*XaA5vS9z`0^qa08{#L-`H(fpat$^Ndx_bCq0iEA;_3*a>MrU2gwgLv{ zlz~=2R##eQU3DNWrgZsN;ol?5e#0uN6?kSXC6b4j{$t#X)P=ifE2Q-?g5E}1txHGer|}nIq15OP=(`PCT(zLV#;9n zsRLX^kin!4>P2N{I&b$bOxj?~4r`-4NLkL4q`e`LPm&6H#=Ua)CAB3b56(=<9O>9| zD@?`$jaC5p@O%E1JjsbYIiKV#SUGoJPN_zHlNDE02%YE3AR`)T6+nZV8X*h)8Gpg^@W*;(pVv+K=i#pu%RaBKV$W*` zISK9tm)78^1cW1x_h~l^}bC!i7>>I%8KTFn|gZQAmyL;tf%J?@?7Z;IT!v4qVu(nnwh8 z=elSdQXsj#c*uUu{Y4KRF}L8e!^$h`3dm$7a=E-pc)>wg{=T1tB02$yS;~(;QmJ=e0~XVjEq#Y>S+&mI#iF(&oA_+)jXQVLg(kp7UL?U zv;vS^-em@u4#gH)yiu58Yt2VKyuMC3rq(s%Vv`gDXjn`muw<{ z>5z^8D@#^z>@->dNG^gO1*U`GMa$-dGT9tgCYxi*Wb>6W*&ILX%#5czm>`6oY&d>2`Q}rB$t|s2Bt%yeCeUln5Cya z@`DNtcr0?BbCLb;jeYKO6dD-tSmM8&ODyZgZ$e5d0LjHxB7x~(D@Dtuqu1Hof|OPO zl8ZEPz;uwNOjxeRA}@6=vi~i29M%Pp+J1PDfdP-I!XRIft>b}@JeBtkw?Q9PQfDr& z60R+AP?rDg%9oe-fme^L-}9(toZ~7(T7C!v10Jgf*GD;2kIye*p@9L9&;QW*`Lb4a z2U1!ANG|Vk3@{yvQHI~;5)BOCMtmy($wkYtz;w{EY-RlyQd$8>F4@Eb(;*xGSC*{c z*lDx^kX!`+7MKo#7cHAJ%4GAsGTEF~CYw{rWb=(O*?gx=HfO!g276vs0FsN{Tmq(d zcH=RdpOwkxqB7awB(eg9`bC*+aMs#E8eD*bw8(x?m51XBa*hYoG!iBgx>n?z+=iD_ z)+%J451W?|fu&NN>OB44G1bBjv%a`BX`Qy-Z>9EU3engbF4y6@Vt=Kwq4Mv9ne2my<_L+-d6gZrxfhO=_AkrxoE3 zwN0vAVca+L_;H<1RDZM4CR{UzG^$$YBeSR6<)+V@wAwVLXD_pzt(tcJk-4=;FSE_N zo3mc%T`tlhW_67^)v}_u?x@4^DM!j<1Q2O&vvHe8y?>SYaK?h2yY|;P_qCm^ z`gP2V*#lyJi&*mWybhm!-M$kB9+5H(W^SnI3j5KD_wLo~a%48fHIc4P`J)4sdYZ}^ zcDr3;{_I%{#vz6En78rbvfCY3$1RFaoH*$odIqFxmbf8%D<9-?-hQuM~=%iX?IOW9#`}?nAeX^zQk`t~XZ=i=O;WMzsF4wH$hVqyr7Ro|(|7O7zr> zCHtQKcHk4w*x9O1JreKyx~h51l6jB!?0GO}T|>ejzi>#<@%*Yx-g8;`AFA(sRiE&) zM@GMp-}O|?$K5muSJr=1DV*^4x0!YH#Q5$VHyxS$%Z8V4_IjG|2Q-@ycj?jhsRg&2 zudVc>IW>#$+cgMY@xqabQEN6w96GmVLQo^ZpWCBan`yIdMCPSvINQ;?-5L{qaLZ%;I+QTVHHBKP&9u^sR)SH*m?jAIC;n^9~=H8@0!j zvV-uG&)qvy`$Xl)EqiaKUV1H~-cG{L-Bj_N8~esa&-$DGyZfDlO4|s3bMBnWLm%zM ze-@N<%VZ2Y{5j$0sV?l%4!OYOv|M>6Y(mV)?S!AUaLvg^J$uK@ywvB+$9rZ5%_960 z)8A;@z4uGe^JmS?9$!2D)LVqVvVX$K;NB~#?9n5?%LC%i-Wuix46W>%x7?7HsPU(tVkVApKIk8c$g+#_}lH*@>)=r!9`wVXrv$5&3; zW*piq;*Ib-JI_s99X^rpHyP^;KYzf+FVdyN{&(3=v9A;UC-F(i?Izu0$91vJY1bpM z+XTY@{^BkzQ~N7+-J+Te2OQ1`9#8ngo9{k-t-7Ns|ZxH?mXTtkM)Fxs)TbMayi_%N2H~&UwKz4bK`yg-bNYf;R~*iqOZY<@ zot?g`rHa zF6(-*1+GU&D!+f_rmV<0wrvx}j?QU&tR}8eM|%0xk^|b5%G9=VPkh??d}%>Yu9i8nQ3RMnnab`ccR@a+hS|BCHz zd*BScU{&z73D>W-xkC8OK1yxdq1)r^rdlhu4f}j&4UFX@^-OA-n5d&VzO{3ub#DEv zJ=g4P)ybqrQ|Cm-+qU0b_P1#-6@pVwNFRUy!hw-vljwz9ee3Vpsyo-naN?Jdk_V|p~Mer(0%mV_TW=!Y5FiJ!&H ziTG*sg~Z!`Tp;{omdh2#B^_h8RGR$y7=}D7xSQ3V8j@bR z<*F*-**7=sBmd!M0g(hv)lpT=#;W^*a9va>%6pI`P?IBOlpr~mWNcsVWh57ulA~NL zHdg5ouFt0oPD&eI(Ea7z+$&f!^2M^t+F35S z8@DhZNzKHgojLoP(qm_}upBi2XlIW5RYZLU%nWrTkblff?EUy`X3pKEVw>4@rQBI< zR9{ViEj6)Uaxb!(h)u~#NlH#v1uRXlF8@0;u^;TSr8#$;OOK^JhN^r7kdoT3Ls}nO z-?YK7{Wf4>56HsAk(tjH<~)=uJr?!^sxlN{_hpgEiQvNmu1qkn2iG@yU3k8IdnulJ z-8XZNC6pdRD;NXV4ULD5=E><)-@dS2Kj6^p)$RW#Qw%Bj?9iNJP^HJtoE(~c6cBJ| zf`vUehZbVDaNmO(&XX|3HncC58U^40K==tammlp3^v{IaE-`neCB`I;%18q&*qsp~ zdIL#9{9FdoH2c9J!Y6H7bQE)D18ARn2X@B~PD(`7qLxK5rUa4-@hgsE_D8A*Cm zq@5+)gb78$8-m_!GH18ycIfVNgqtp2g`=3by%^saNiME)PGkXLgpn#-s3*B7oIXhy zQkgskeJ-6Fu(Im<6ZDqd^G<5I{JB_sypWGJ+2Zm<$UiR;_qnIaRn|I2GVpXG{cC36PmSELnvs-jNCkw|WRKLY)bZ6~n9dV~Hw^ z2#eC>;!}XUk_L@HJ}6gwVZL3{!5U!kpf6Hcm;i_!*Lno!6Ym)>CF_W_dthX7Ro=mBv`)(W@= zU;#KmgyCzHXf)tcz#jk(umunfXa{&2upNM&vJT)gz-9nShV9V~z)rwI05*RV0NZmO zkPnCeR0cc)*ag6*Y7F28;70(q&=&wd0L}yc4OkDrFL%&@s{jU29#9vs4X^-!vxnCK zM*$}Q#{tIxUjdE)z6P8Gvi0sjDu1AGp+3Frve3upp}1T+R500aXX0CofR0MPL@0^t1I z7l01|V*ycsTYxwK_9Ei}j{=$kz62}+Xh-qR~Bq!S1vq<{hvF3Bc2xa7j!B@j9&QbZAuDgsgjX@c}3 zMMXeSL_`q~1f>ho1Zm0l-t5d}bJ<-I_AcW8%jjfhXJ+R&@6CH}-ptM(`(JOf=s`|S z&Y+SUSD^&QJ%THSz?w}`PEK#$sLvZS_Po39TGGK1txq>C>A;nPvQGO4dOz;=N10o1 za9hRG{ zsl0Q)o;@R+W5b-I6O25cW^#_yYqNM`v{`G;FhPEt_&%<$E-le844y5;^>yI5w!n?@ za5t<8$2Ep)V34O*u$Pa&i-*6LucwEvn}0}wP>z2u$E@wlB~3Z6oWBHYu0iPQ(T6lviOrM6L%|7ACJWN8;#nmNTVU0H=47!unoWK@WB9W z!jNR6AtNo33q5qNL$y3vago|IUeDcIGIRlQDIS0g!-8Pc%{oIGmvj52>vb?YP_H$a zqWGa1IwNoDr8Vm^`50Zo5bo>xx}h~m1w(2opJoooh>zFvk-D@rK9L*h)I9vv=@r6C<^{ zG&9%J<8v!abLzl=MEn7FXmN+*$%Vg$L`|w5+GHSfJeA_$^#bl-P zT%~F=&y~g=7z}#OsbbbkQ%Qw2N}#B`b+l}jXbI6q1xwU(N@e1M-3>KJs zXC8crVoY0$H0n~d#w^5XeX{%Cgesu}(PpDz2+y@@^QN(CZhav)WH>i*?URyaNxs=^ zNab?2jaW`(CnA$K8g+?$TsK~qoML9T+=+XWf53jlvmCIJiRKh`$Lad6+J^nIl!s)b zB@nT!djH-2C|CiJY+ylhi0b25jIG(C5~0^p+LJeHQE`IP%*HJ4hdJrv%HY$+3{wi{ z^!Lk&WLUDyyk%G}^=iKlZCD@}g=7Of^I*(-2asl#5p6JQGb~zIgFKUF27w3R2u#r$krHm&^ifYy76T2IA|e{liHy`V&bQ9MY!sW^;t+$u z3|ck5&7rUJ7IfpaAa>l-6%mc{Vud9_Ke6kdXFmBDnVH)dl@AJ5vQG9!l)2pUC;;PL z=hw9sIKjGz6QhZX(Et9mzzNV~;KYYLy)H0P;GVEi#JHcU4DW<03?>*j5T#Aj>A0V6 zhwaBEa6o(TSzP748U2xUc;810O3MXb8MPSc4C0ft8G3W5QJbF9%a90MzHliM$C?%h zwX1%0&mG4)5sY3kP67`eFPM&f3Ig@#6Cj7o0)1dIF&N!~IR5_YJ&D;h)gK^w(*5VU`3<()1o?&T825whe)yK#~p-7lZBemuf?mPd*<8W5Ng0M7Vr+j|t z_yroV;BE$^ZUhRY-d_)foXC34iMNIjjBs5NOe(27ND4fPin_a0;vwWsa2nd?M3fMo z+uyv`ugC{FPj7Pwx`aj`7zZ#<#W%a2zFS|aq(cYbD`}D2xF-8Y0U;yRqTIcI{-7&P zJi%mKi4{Pm6OQz59B@w~UDlyPFN3At=Rcb3%hrp+xt321FbwB{KAifPuqGEPELEG# z6EI)rPM=#fVkzvz*DTk(X!}&zio(vP` z7qo3I5e3pC6sV{Sm>8?|?eyz?TzrEkbMEVoM4>!jcwP~g#gE2MI zpw}g2aZ4Y*8qpA8B?>!qh%v;bg9pT&irv%}8x%B)RBHG{um~{zasqg&7wTX?f z6~T)G!=J9xgUggk+$PZGM4d2|Ex!}hpltyvcIeO-MuPY?8DH(%j$Q>noKN6JU3*d& zC!i#~L2Kq5vpzV26LtvRSp@#^%Ck@Lfe=tluGMepOHqIEhPue>3?&bsLXa%M_lV}r zIKP>=E{g^G6=DPa&PdD|z7SipaT89_%-$ zcOr2lxi`zb5`&zxWV3nP#PyE+{2-ch!g=C)EuHX9CU&3P1V%neK?=JO3lkRz0|GY>6n4kT6B)O>??_~Tl>J({|F##F5zUOFKA0{O z{23!x=|soZkPM+rm}UJF5};39-5J9N<~}COvqAK+zgzApgER<_bvML^C4ea%p}Y$q~f{rwYuXh2s7$1@b*kxVEbO1k$`Zm$((n7FmaU{miS&M%Q9q`DO0E~ z(WUOveaMq=t*9(UX9gQntHjKoQ1S8?MZwzGuX)B9(SrgvVNQTm#-a^h^%LO~9E`&FEg z^FBz*uwBP1L5pxuX)#p_zr-usMMMd?0#RePk3WNoC_F&cb%R_!t%Q!}^COU+2- zzUp-@0g36!r^fR}qWaSsZQ6=rCS*lw!DgDdF;_=-LYpjP=9M^mkxc})**N~Ekq$CqA>gSYLzYzOImwLiD&S~CmJ`NSl3{FY{ zpA%i&B_I5fgv8MT%=&V8#&u*Q&9d0*o2wS|MEY1h`k+-i$9zNjlwnTKFyrE$__>u* zXZCCWRU<*gKvKdD30l2w1hCYQhAcCI#PM8pbJk?+c%(Kl5#`Tg@Ytb<8>xjY0yEFn zLtNX8y8Cfx$V^M;36N}99&_FH^mGv(ft`l90N73n=QF_z9`?(|cToU^M+D0%_{RgT z3^!qig%U83!UI(=B)XxHSh9(n)&KM9u-xV`i>z+BE)GFma(hGtTxh?|im_T8Gb)rF zuOFX=JQHq(8LIZLEBfOA!BhuBG(4Rq;{C);Qs(>=w>eN<+l%` z6htSa@TpoZXV+W9aCVAL(ZW_O(MZusboMFF2FO;Sl(zi(nf7&YjLC%jX|nru>@V}3 zxhGxPk3=sux<_z$ob-lpTp)Mmgy8}XVeSHfGir8?$E~g0ET+xOE1OdB+ZYrMQX?=$ zr%xnZXuf5ylcg=errZiTGy#Q+)I}Q5hs3^){qQu|B*J+J_aewvgDF&-&Ls}mxDaLAQbKmAsNZsY;=sW;q0+)UF4Dk@ zw=1Il=P3i(8O~*Yb>q0GNnvtk-cy@lr(MZ72|b~T%}S?D``VFoKb=p|CF#K7Bs(+f zJIt6xh7Z=5Xn{c0&D_qJS8t)c#aRzsFtVE9Q`5O}7jDlYLkR`M#w`6frviH%9t|+0 z!Ah#*)uq!2x1mPr{jKOGZZswL*8pV=M~aHvdv?u<-#p| zf+K=`;P(4=)nUi*hT76leO7u3SL(Iud+}jXkZVa_ZkiL1{K}ghC+u%j*fIAUN&qRu zJtRWW*&3!D76`%i3T{s0SclU{JE;z)m;2_sE>A7bTWqmzhOD40 zBfJvQpuA<6G}J{r-GA#`^ed$;1lQ!vZ=d2es&p|J5Z9qjo&*-Gs+Wg_eFM`6=yBNk z2n(eE1KE_Vd~EeRQ7&CRy}6v5fMQGQlI7Dv*EcrK>K^%N(#72fmtXP6CvFpIL&6xE>M>?0^FIJ z6+WKh{*0$kz+nr*Z{yun+*2<2-#@Q1(n+?)gq^Y1Rye$dSt8*)Ij98Lvq$k|y5SvqZXsF% z%i63#-++o54C&gG`Cdul76|vGq1E0GTO+pM{cv3eF8T#G z44)~mdlPqmL?$aRB>{Q^OnJ+O&Hs(%fN_CW6xmO^9z#A_X%b8pjp8PC#`mArvk6mf zs4}tEva>nc=tp+<|Ox^d`%!M-Z6iJf_1XB>W**YGnGiC7bF6hw`ye0_8#nP2EW zDe~m;%{Nb=HZa={d4w-XnLRdRzO|G_3_Ls^y=kj_%MPNTJ()+ApsbTn9nKhFK;DQ% zmgI3<4O&WX$>n$P4NbE=?0=rcpj9~vR_;pCs*v~&=$_EPx`utt?V6KVp5t5!Q`xmJ zmEBN)k$e_$4#hxRDkHo>!$TWbn6IEDWFj%n5HS$P0|r_H&IfNqcZeKK!J;kDh;y4Z z70PScXaco*c)_EI&(g#j%qbdh+ce2AOKaf0Ke>VJaCo`qq|uP$2PRDhG-=Y94H{!c zng%w1%rLEKVB;hsT?4NH@DZI+GfX%jfz{&49+@UxcuPhg5kq)FmqsvP=Y||EAfP54 zY~X8>$*#0sp9K}PW{nBEBs`MXbB^XSwX{AfhWTYp; zG>#mA-4+e#H^5|R48!0&g$7Er?KH5h3gBs)Gz0cH30u&@p0mjWgk=eAg=W!RA-yoc zl#6{%q7UkUk+?yYg6$Ks6Aip6t)*GR4~I3ASzsq&JkTr*j7FdvkyEu$}T zJ87VRC#bP$40zfZ!x=b<>_gM*g)H({s$SOu)H@CB1s0&*DX8aNfO;pPo^t`~xfHOT zYXR%I6|i3C0@mwNz-8yM zJxu}X{S5LPTY!2$LA~A*^>9gwVW@E7{(yQN3sCO@)a#&7FMyVvhkE`J^=K9s!V-Xw zUoT*gvK!)hEubDc5zngEvViTiDqy|V1+3Smfc4rIuwJ_Y)@xtDdbHXz`Nw4AS$sw} z1jDoH;hcowS@m#762r6V;napfs$M81@)wZ5P7-`!wDqKAze7DINL$O5b-iDqUJr@( zSYMcqp}u)a)MK(W)d#a`;73K>{>oY0J8PGuoClo`zOLylJ#fk231`pHljccp4FXOkS!qqn(ojqWMaAQu2a$jYW7&-`{5rg$g_=eMdYgeQ(Yj z1QmF4^hxRaMw|c(5R~{SrSC|el)it%7DUg$RKk;^PfFkWvWZp&o|L{LeNy`F>8qZf zQu>Z~Qu@A;IXWunWBUFGn9iC(Uj)~}XnJtIO`>G2VGB@JQRb>Ne(|&|F&@72Lp&@( zyinS1wXU=>y_dTv;RVu%#CR`3o)mqr*Z@z8K75BPMc*E_P?95z<`;y%hobRAHQPm> zMSc#a>C$YGM(^b=N_b2Tt?_o##t@Iy8Epf+blR>p-e)4bzBGN?26)jjczZ;6jJ|Gc zql%WvU6lAKN8er%9;>t426%eft~EdRN#M0(8$`5B?xIAW9NvBjyoGkcL;ESE50%)) zmK66lj2=S(k0#B9rDMz1_K73&V zJSq7^`u5TOqdjANa%Y7;@Nnsb^i`#GK42TcvPeRK5?&<*Jlvx}JhqR#jwMv!F_9C~haVM- z`N`;ez&4Il;7QTP@EAYYK44k4xupV+?Rkpn!{b#*A1>{YpLc2d9&AI2-pgH-#_uos zkQfh-%}MdICEE~_1ETp#cvAdic-H*%j-PcvAE+JjPFE&jS0Y$CJ`O z4W-Z8o~8F!k0&Lcjb-?mFhD(?6h9fBH9t+SsmGJzXA>EIE*YpEPl}(omnD`@X3u8D zsmGJDXSkOoWzXhm)#EYxo`8}93<)mKEZa)L`F01*e~WD{(0jRylD==D58)3AvgeUD zFM5M`8)!NxK|OtIXqdk_{|jIG5WeB+mF6k zB0RRA^{EZ;*!ta?pR+}HjK1j2>9{N!b^qPs+aVL)6nJWnU0a%D((!13bC$ld>FV*=**huv@I9ayFJY*C@X&Umys-83 z9k|CZ-KZY#rqC28rmqX+Ny+DUlX^U<@$;j2Z2iaNrGweNc9~(>tg$I*G_o;R(MSR)@G`wPfGt79@BSb&rS|gk0)i%0%YjBJX}4V z6nzYj=>y|ujS=?2LzzW=$JS9^7Eu_#k?Qdl&?dzC!0_1kF@67alzKcV`x0bDAH$n7 z+CF%}R(NduBF3o4lad#P$N0(gVdPl#cvAWhLg};iU#5;zk0&*L4A0ts2^_B;Pl-Nj zdmS}FJ)RPMZ2XwKRD4}Mo|L>Wep>r4-f!3k59e33FV_A`!bJ6WQvORf8TpK5FGrwU zDHLQsQf$w{pfRM6*=uHBUYewyJ}G%&c-H>QK^x#n`7aF5S|47TY#;i%Q+{IWV*ll! zo$z{C;W7OiH$^>tQu@d6n7%W6y_UTQg#IW6CHa)HXW`Ho$|vI|qi@$+_MwmAF@0co zm#5hWucsA#izrNuchuua`7aEQjUUtZjnmcRN$GnpEBYAT;CJnV7h#3R#;@rN^>|YH z!0;G9nLb3!RFB8>;cwCY3%)-Z2Q*?3+n0f})Z?-7v&I`Qz~#ZK^`8CkCP?6YZ%4e> zMR==eddh6|^nFCzvgYR-B0Q!K?sL@RNsS-w4~~<-`_qni<0bG`%(WkVQt~ozp8fEo z|Y9g5xJ8FZ*qP$K)kjWM4YM*mVU=qz3KFf>Od@j$o6Ca4Y*)X?|~rlPUx$ zJT~7RMaK|=<6`yv?5Kc;Fi79qWe|Y46qQ=^IYl662vhNbz%%4e+G+iFi`{Y`I1~eNy~H zJSl#TumK+9=UtI}P6Qs~(RHLo>`&ac0Uon2Qg~=q5N{kr44JS|8j#RgWj74^w35`_u+_Qsaj|OosYrtq(&ssi#i~&srav zZB~ybr4NigYkioyMLnJpeb)LAxYc%ecSQ38`Y#zUh8R#E&X5$xJ+T4aN!pe*-VK_M zct>dZGqj=JSllW`lRILp$+huyxbPqm-!$= zVStI$p#FtYnOeI?J$-?+EioRR5fkH$qjm1u0FTYLV!Zcd@JxHv(5C1s> z4A%6qkC9M5H_$q>kEq96D}zTScfdltp|no$QT2GKGI$QOX~c`6b+#T;j~6L}S3-oh zkk+a2qk6n~GI%9LcspsGkA6~*w^atOln9UcqJw@>kH_qmwS1Nq;TdV4B2THuOOv1v z?U|H)`TUG}JSqEvcvAMo|D1X}Df@zWQuby0dG&Zw_66~z?90$U)Zha#7ZCT?T6XE$%nAm^R<9W)^_k#$}o7Q>fp?W-&4Gh-w z{U~G;`DFARc%&Xrj=mEjJROC}eykpkm!XgC8=`#fpmma;s>fqn{MP*ZMMNLtrzS@| zo)kZEOr`YiRdS-2c0}OV1IwzX zPfGs~PfGu4l~<3)_<2;MGq}I>9c2;P7k1t>vVwX%cHYz)@3;issEYQ(`$+!;)dORulM0t^tPZt~DF?n$X3~}(F_pXpxiKYjtsO;Vq}>musuXTOxypXLvCneQQYy-XGZjZxwCJ zn!ZjnAMse7q&n*9W4yA)ds~E;PSY>dRgb5qZCT^JD}gu0j(G1$;N7$%9=^lHfaAw} z(Sh~U^OLO;toe!Wa4{g>w`Bq;&-eKC77!U24l)mTK08dKa5l>3r*ELX2-x3-6 zr1ZTvJ8Vy%k-I4Q^Guhm`6;FEPi=rFrSHg3DScnjNIgHL^d0e}^u4CWet1&)KGBYN zQu_Y44e+G&9r-Dx?}r%I}XLqTh z{b~a|_MTk|k9}{*eoyE7rt0Zq=i0=07b!onb)=8+^Ydov@uc|4@XA}^m2Ykzyi1fm zYk7&ZGoH1)%(VfYl)Nzd%20l`1>L|fwS{_qwxn%|<>fN8jrxa0C@<}4oh>cZ zI@^~%rVk9Szn$@z{bYDc?Tp9tkKtXlGoH2nxwzPO{K{I%%P>3Rp=^rfbB~?y@C*Rj zGxq%v8^6-7_TeYPt7JuAxSjDTTj9;JGoJPMow75YwLjR{&A#JT!HSiuE{rE|(S1=Ft9a|UMm(w2V@ud70hG#9GO+4*` zhdf65tmQ>#XFO|p*NE=5ZC!^-S45aKXk*CJl4xik)ElJCPlm6A7fCB!6JfbPp2mV#iW^JQ z4U_WY(ITNk^sf@$Ncw;n56{9dJd{y}_d#-gygWdKz(d&P5b@fdUZdzW60V3;1ELen zi>KEaaK*CYK-6@ac7*F|5V0*6dNt5%61^tE6`!jK(U<0B((639vNrK|wJ`lM#Gy2e z^A`FXn2+OKi>6lZX#9j*-_;+%?fwSd?XBK8gE^;QsDLyU%q?X-b703w#Ph1d>a z3`8tz53x5*BmIMD+8M415D^3EbcN^!5&MemxI^@Sm<$oy@r0NT5zD+F;+caKh*;(W zk*8_ohnc4FoWL-eMmmwFSRd0PMd^(+T^p{Siqe~Cx(-~o&~#n6ZWE=q({w$!Zl&q^ za78{N7OLD%nns?Y9l?A|j}xVL(R3rY?iQs#qiGFX_tJD@xb7FFKd0#?aNS4KP2q}T zidfAcehCqIHv!`75Z{1^s*YoWvWjDgvWnyO5F$Po3lW)y={^v%A(n#J7vd`rUxkQ= z+p)YK#QP8t19br9p#(gO_bAT;A>wyWcpnFG5X46i@mVdz#}KhB9%2GS{ALOJhvS+A z5#=BeB98gXP=?RxAU2@s!H}*8Y3$z+hr5bM+OG)SYJLk!d>l%+=Weki1k5H8^0SLeu{Aifv*VTb_QF^r~y@saoSyxg1T1Y!UoItOy)9V{>MR}SA@hym`n^^B{h@~OE191k#=@8$A zxC|oJp9OIyL>)v7Sa&wWc@XD7oC|RkMC9c}i0_Ni>uLH;xX!2PNpL+NN|zI*FN@M; zX&T3Si734R(ijkLD#Wiu>1v|%Em68EO(RW6FFuQ7@_?pSz!iCd`8X!{{V1k!9G*bL zG}8DUP2-q2(mFUM$RDhOW73f3<2clzX`~(L#ySfi4yS44RTfPzgzE^J{s69{XnGM` zkxqPeF~rd{y#%gfX!=9Aj-~0Pa2*d3poxveD~>r{_4JBkitSwn*=b4Bmmu9rlx{6b z$BEKyXd0hwFUoH#O1FbF;?)r4Iny*g=O)T`7o|N!X_F}JNz?eOk0{?ul=g-+V%8Mp zb)aed{u1RIX~s0lFQ)OkunO=HOXGK^EL~odt|&_5nPpa|tSDVZl*TjCtPbvJvUC$s zx`il>=dM|u=Av{nQM#!pjr*2ZAHQ2bU!SG%x6N7lB~iMXC|y;Qt}IGBi_-Yb18WEO zcUjs=l*WBnmfr@_7)n9JIUM!sABe9)L>ux5;zNi7Az~ezt5L6>LhK8%G{kI(sCPMV z#eqZ{gzcjb(2u5Z{_jK6IKOKlT^=Hi8}c8=1IGu)4#yS84aWleg7ySyM}8sQ$RFev z@&@~X{lfVj^|~g+RJg~!;~b9uf|1t2c^vh+F2o^_hkZxC0rehz1@tH8LLT-V{ev`` z)C>Y0DN*`on!W+o z?xOT!QTiTD--K(3DBY8$|AK2TQF^H;{WneHT-8mK4ilwAMd=S|8vU3aG<^rI;WT|0 zt`Rhi{rX;%J|Rl~C`um}rH_fyM@8u$MCqSs8vA}hls+d)pB1Igi_*V|(!WBQ1?>N~ zV9VZw>wJilARd5N7GgPwmm#9;F*zy^=~@s$^vODGBV19oQJyzLtPim?#2pY(-s?f! z3K8|WHpEXMZi0w9Ul-ywh}$8e?2dqlvdwgY$!i(NYXEU4MAVN_5K+ERc2G{vKt%aM zxk4FQ2a)NdSQqL*{uYP}AP$GfbO2@l2t<^1l<|WQQKnIrQNJcaTo3Vmh*=Qx1!M;B zFbkZZoRc}faaFsAgoO~3>VS;OISuToSgu@!a%C%4C|{v+rHYlS)vsQyN|kC&>eO|t z-?~}bHm#bqY}wwet9N^s&Mqxm`h@#-4h-%V)~&5qL~O5+n69DSg0T^YN|h^Dt5U6T z_3Dj-omx5t7dqtZgYCp#)sva25j74GwRr_ zX72IE3FRxiT&s4Sy3Jd(Y}LArho_gfk8g*-px}_uZeiV{V`BUCedX1D35k4Ca*A%S z$()fnYGGAU*KXgrd++c25B_=h2lBLQbT@EFNK`dFVRO!a9Wvcu4E~_0{qlw%2a*hErKHRv!d{g(RTQ%d2$11$s z%;S9X+ejLrtYCyqcrMB;gyqt8imL>ZafxartAVndPgy#ZYxP3J`OW|QXUQw1=Ge;K9q%;?4t%=Kl*5Jl-D>EU-D1|`sLR>&a=70*jeXLy*7Uz~xR;u({AF|w zcdPuBRb#iLjlDW4yX3(f?#p9O*JW6q`r!9-j~;)1qNDTPYzNPpRqk&&`qU+d+c!Li z`)7gQmi4(04S$fm=hl{9-~5%sjq8cXxou3pG31j+TFAeh!`=26*g1#$WOw`MPai{H zYV?lG;fB06_IQ;iWvAzGQEvDuWy6Olb#k#{CkNzkte4BPPwdD=?|wUb z@A=P<3;nzo)9BP(zk3I>pM+*RE~d$r|MVU{TQ@fD)`6*QeAZvwUOMs4E#HR;vDpF3 zmwoSf&9QedCyq6v?yf$u^W&@sbFYT|>A9odM-xuCt zN}Le8q5HyjwrpDAxPH*;!@C?)){J=Vk3QaG%o`qlp?ht|!GTq-&iLo2-HSBGKiHpr zWI&zQPS!WpNe_(}Q1@~NC)4IWf7bnVYX7x0UMXMg6_@Y)b|3u6_4^CUI;>yV^j)X< z4euWgNY9+P_mEe_40<_%rYAkQ_QBJqTfW^p+n{g! z<@kR}K3-Do;k0az371AYz8C45vV7^dm#21b$S$Nt4E&xX;#*ErhYrO z^>K~S-|U&%u6MWaV-Kfx{oUtgl{=-zcxs()luGnm-@m?B=zxTWcVk+uowae()TF5c zUoGMN>g7v^FK_)bhjVKE@|`2yUOAPRc4)x;Ul(6IkbErEy;hs%i-Ko%Jv6?|iP{a9 zR9gJy-F~(Dt##K;_{pcj;m5moH2t)6)7x!U-d(%8bvN+{v%5i4FHWj&{>rb)3hl3F zDo%N8^^MwB27l(b{^kB}Eoj|pN&Ka0KlJWe5t9`&&47ixVOl{IJd5=zwSW5GbjSC0pN z|7{L8b`lu3usx?YGp_vT7`6S?8ZS@UEHHJ&vOnJ@d|q{B>F*nj2kV{V-swE}M(+)e zkKS8zqDTC|^TCeMReJ|JaxBKy%i;Dc?*3VfXBD_aXxAO~xUa2ue%MRHk4B7WGJ2h{ z;mPkV4%essaxm`h)sPRe*N3~7E!*k-f%eT(@cTC&#_XKc@9F$e@ArNC^;Tz&-8i)W=%tY(qs@Wlx`t2JCfK33|Eus-Mi4UVi(|nZ~V_@Y&jZ-<8eb*6)m%Qpx+FLdE4M}jH{jheWH?ALjcyHDEUj|W?u+Q;LzIrWn+-}O#7+3AO~3-3K0T<^BaXLD~ftFs*_?>?yS(wS4aexO06 z*DOfr@aveH?oDs_aMQ2HtUkM7{ew!?CXAZYu5V^(E@D{Idh@>7_syZ-n|9vooc&qH z$gG~*tM7|U`)%Qfkx{QTyKbuORQnHec=F1$r+eG<_~(xv>HT6ee*L~ho94G0ubaFX z1~Z3)(ew}!d;6`Mb{5CnqMfLvtLsiW7qKF4?bE=&R)Ts~Yq5BG>j$lyF4UU7YrX2- zO#|MaQny9L*}=aLJs5GZ*YQmk_i&wuciw(ItVSEp@4e2BtoiU2r-1qm#~xiVU{9&= zFXq|MZJLN>2av_u3bhtbIFRYO5ucJ2$R&aKEe;mB2mrJ<{@9)_E z`{`{LqX)Miocg2x;M?2zdJEd`sO|gYs9|ua;6bS`eX{cWsoGEO-L1dp*JbIKhv`k< z8vc2>`O?T59}Rqe#nVgY?{8gf`1N2PpQC;Q`m}#<=G#Mh>ejuLx;>y8_sx@U_8kV# zW<3nKx7(R-R?c6Wyk$_c9IjvF%|_1L8t;g){d%7?m}YG5R=3`p3o@szezI!sS6LU9 z?tJBki$B$=G-I0fX!L;|Nmn)wD6`eQqw}GYhkAiQT-^Pg8?$e|HnUOlUapN+I)3RN z>=@~S3}55brSGEf%jIf)biw^$?BE?Axvx8R=XbX*$H$e+-ppMepL%)a?3Ulm_%7_; z^+(5sr-nB@)H3tt`-d+q-!(WYXaICjIVS2>iNjvMF zoYd>_U-#Dhy?Ev52ahUzzpl?$dYIh?<#8SYBOhOdD&(^Ke%&(@>P;Hw5^nn0W8=V{ z6^^XxTBDM8gVptWcfa{lgBi{49yYo6X#LGrx3S%)&Y2omeQLi}C4PPL!{*~nb=TC& zevmN1{n3Kam)11@qe+V?RZA?d`6s8T^5cp6y}Q2L{*$DwySMF#YH;I^SF8Fp)x3W6 zkG6qvw>>XUK2qksPvrhxhWC~yXSy$(b){{?soZBP-&&TMb>H|_!~K`$G}v+V(U0C2 zv?HBQb#qTlYkPb}hhsNp)|0Zh|xV>Yg z?yXanlv=Z3@UAm1A?5GX-w2LLZ1+tG7t2psc)rBFGa+N!aGT7t)*aCTy^g0y+^UvmW_Qdi+E-cj#0-VBj+u1+#Fe= zcaLDMMXMD{$4`O2mczcr$4`qo*0nsjb%oOAP|fY^;s@uh_FetOe=w z_;EEH=dFyN7Flv=Nb8f!9Jw>Sr)IV~z}bQ=F)?%A;`2CV5{ z^+APJOXp1xQ@DEI=!@Vwt;zK52b06s0J42q&H3@Ydq6YgLs}0FY31M=>;z2%snD5H zOXm{sc;OOtVOnH~_^AV+U*WyUWn=P##aH`WTesxmwG$~@8{Y&;buI1KyQ?Mk*?DbC z(wZ~x^g+L2YpVl(j`5p3>P&TwKvLtUMc)QQVDJ-YGKrLqD@bAa)Dc@=U48$HIcsVz z&lCm{wbOyc$nREc{jElH@31v*cdXfIYxdPAtL~hByzBZZZ7_Mdi%XQ z$F|uPT>rx(F{E%=!dP>5Y}!=cziV(6T6zxvJYzx18ROKq}JpB{hMn`HO7 zvf}Id2O`Mhr0vzeIvOWgwc5q<%tmV%g1+upXe*O-*ItUR?YREW32g?qTHXEg5h$K{ zsAAL=@wIFY?*CWAr@p$xWZoR0&*0OIx->J{xQY#ni_~kgcw@9#YtAsm_0^>% z8isLoU=yfe{zpRjG~TE+^NE3at;s~*&Pq2B7sxGwy|;?EPYwZlfZJr!mANKRK`44jTokD_rzlaFr*ceII!{hC z1VqNX8W|kd%V12^>dAXx!q*VJHrYhB$yF8zR?zB$N~C>HeEz(EMTPrR}gh5)F?-5wFVwxFOuMFmILg=3(w{vJs-ua9c-H?ROhxW&SSk` z+EhZMS*$D^PI$3rq(*FzWt1J@OqkG8?szta{rgbRMg#DjahyrT7^uy(iOHH=T?cs2 zz0B;AANbAzFhZcFz^MfK?c_mPF9&96-36t3^^v~ zFZR{}&Y1`}LXF0fb=X+3s{_3G5S}WWO=2(i{RD z%(a|iyg~3*(j96sSyf9DvmM<)4o481o@+bAdCbl!_rDhHe{SEAlEI)|>7ZxMqIqEu zjG8yRadY5Ui)txh9Leo<4B(Ccx{_cXL*38ino=D$2CQFVy<+w&SEj`D<>EQO8683T z)l$WzD!0dIxl#!~bM3QqsUz)!G9}KmR%9$sq{liRpJi=eUBt$Ftk23YKN(^sL~H}=U^%vh_gF6#BIaQ~@t*Mp z`-}fE>%d0wdFM{16KH$U%RpZ<*A6plFD`8?DrfVxvP>|0E$=NbFGDRgtRKu5iUi&d z25$vdIJq7`uAO{Vy}Fd!tX*mQ#kk-?e0=63yTCcHUZC;LaLw;KIlzezVI;T^k z31|iDWdcYKdK(V#oe`5);rhS2c4Qudl>O@{xgyM6t>MZ(?~1Zjfw;{i*oUlQg1}1- zAZr*;Snc2){^t(%&4a9aFwY%QfpG6h{)R&RK(cGrx=WSp7&OOG>ZS0bG2 z&z+ZYbJ`Y&$81c4U|evVye#AA1!ENoBkKz}UNDj#FnR&7778LcxPJ8}>((H+x&cclH1Sr^tt?Yg;}y*U{@Q%Y@Y-=j!Wzb zN9+wftK6kPG%z2-+6#&Sn}@!ouup`ufU^XjTxB_2g_hv{H1kX{phdCW#<9i!@{dnx zTH;F9Vh$i9LQN*K(laxY0PHQ=dk2s#;W=B4MGSa52_UBeXYzX%a^;={>VNKRg{xb{ zaDY?DP2elkCZG@f;cLZqkaDGWSmH*~O@Kd5NSOz{_oVk;#)T*dxiJ%-~7dd%`z`>vqjERSKhSuk+lO2BZlP~m35aI;{zSuorv zMqX-g4~4bE@Z7+H2zl-nJa-G8JH<wQ@onUu>`lI1q%-h`7+$@yB)9eJEp1sYr}qf!(j??J{1 z`}V&+^7+Tb!y=jTXnfi#i#3a33#|7 z(r8HMjbhyZdCSStlEsx^0Ca8sM>Tr0TE@1B8MfE4vMHfj8PGK)63yUFLxRAfJ(zvcIX{Kc1 zdRmC~2!j|Bzkb7jjf)}4KU9UEtcuzny6Gx0k|4B`jyTR05(0Bw)lG?y?5* zSeLs(8bep|S9Eoy8R749qJO_eR<~v^I!F2OvA5~F-Qmj*A+iq#31JA zKp`t1V+f6Lw2-yVu2*UP271K{8IIldhydqqPeT=7REGkXYcws%kG(k+j6aB143)j{De&-9SiIKnnyJ@1-tmu|k7sm<%VDV>BLeV;4u$ETh z=Z+N0$gdG$k~zXyc?d0&d=P))2!kzsV#S4}@JlBMDd7_fKNl)n$h`O$&?m+|iv#Ow zu}>^;1;vbt8p$9&@pG&?$NAZ8)rr6GgW)CNLb|tsrtv})3;T@wO0r8-)HM942}48S zV)8Dg1u7*)W6`)`WSb8-ENBgLuew$d-=hlk6#=369WKfO%7kr?!O00#u_hwF1&;q$G!YkJcGEpyKn#c9^B*mSM%Sv|xZG{bf0(Dd=fY zoIlQlE*I%6UHlH0Xk_sREbx7e&5jbu&MfonDc-maE`Ep0wuOt|;i5Pce>Eoj^Tc+W zQ;Of=`lFN;+ShvScepPDnyh^t3WfIZ+>7WP?z7%aDZb#f#aZg2KWhFt$`6DM!iD@L zM_=$uPW-?hL%u>h62VM8sUh1;c_@}`2GuuDGykch7BA3Xy`;qDFRZyNJ6P3~n!)qb zc?RoQ2S12MR1%(Q4zUG9{KQt)c;M*}S>sVCTs%leK1^-}*VYhaF{7c-Hkg*<>1~wo z@D$tgk4a!l=ez^y={-@q=Yxf_IS=pc(_+&8-7~Uzy+Fgh3KY)ixaGE za4l+pKT+YKgqdtJOp6+LD&eI=;q$417d+{$)N~3I+J=1=Qhb!~c-!OQ{->Lw|yWzcI0q-iaSrLi6we;)T$Aa=7jrdV}J_f~Ate z&o|@>8#(R=kBT8#9zx<|#X=Y+KBRZz2kK)@2za4Ma*ujWgofj8(c{{;EWgIU#Jw4P zVlsI|_(N#80@$+iGWtofP87DtnkNkwW+cd`inbhyRRIbku_}OdlwD={u@FvPKOaAk zB-VVP`LP9`C=5T8mkb@xo%dHb6S~S@R;CYV&iE^EvQ@!3iQ@HqoJ2l6Hz#c_S-&aq zV~IcOD7(r^Rv9IJ)P_P?P5V?0KZsTqMzZ1nP3gyOuE+}y$7z(*ut=D-Ne#1XExb8 zj0e{LSw};rZupfN3wg%1)|^?rVMM zhO7|ax_~uLy8EvhOp@0E82zYokiUG zLI+-f_^MJba|+u_M|gnzpg=AUqs>~gsc@aNjAK8g&fQn)T%qLLa!#Q?G&w*CvjoVF z?65r_CjRWqKqbtQN|;iDOsofP>j?r97nTMpRk#tba3l_z8Kl%Zv_!Vyh-K8ZN_dZ< z@c9@W4^Jj2HC;-H(S^da7*0H#kpwXrVj{#8h_Z$We|uM!l~Mz3d&8+y>L31_B~smx zFiolq=U}By)GI8LBzmXHa1Mdq=^>^n^%D2U3pJEBHk@fnovWeLxkAag#Z2H&j-)GL z;`w`7hCCnUP{1=PVQQ2xr3BfQhSLN+!=qAHA!67dT*zPI9M)3mU7H#e4 zGwDI0JN_??V@d0d7iJs-kkt8vUddleThjG^YLL-s$ur2syppvKb**`Io{EXsK3t-C zXdiGD&4NEBF3>wCdc{hEL}~E@#1d+0AsZswn}E)MAWQK?C}hy2C+BH@ijHDgQ;waM z?Kn<|FKWmAlsb;$lc(dd^eZ-l8&G+gd4UE_vEzTdz#Z=jeUp{AE7l#ir6C=s^bZW? z{`&-O0na3tTIo>i(Um~IUWRkljS(RNy^i4TWa!uZ;B39;#Ci8VX^E8~d!vd=w^=p`umi2uDkEyY1@RLmyFFPuh`5d z*3A^Xs6JoEZ@j=A@2)g(x2-$=|Jz~ip~S0-YIyaZbeI*{p;5z*XZb4y+%+k*Z)d;# zzi=hdscy}yqBm@|RO|wdj;t+J>lsJCZy5qLg9`HF(G~Fj$F*^-HH!yB1_trmi1QEzoa#!Dl<)^PT)Aa5Bj4XY3VsHLp@wkD|G^&l zFaZkl!J^J!5F259kxSo3$1 zHbD&|hjkO+dl@Z!Xd%>c;wo_dP-298*17>w8u;=+2T!xKmejzfjgXIb8u$h$18O9| zy#cOT_<%zP$k;AVj+CPwVGxh$2qBB`(1E7$QWavk%dL|uRz3Viw|5+O9DDEUzbCL! z!U`qv4}=L2E5w!R_4vmW|EW7`yz@%Lqm5E|+emHUPYzyyf#m8COiRSA(=3id>0v@* z$t*yEG|lQEVPfJ~KD%On+qV1RvulCbPSi+V8q#P}k~CnMYyo{x z>QZPLwma^gA9*-7;{Ej=jtvgSuSOcI^QMT9EHvP$=rEHeh&Sny(=;)2|9LgCeU z3A9kG&i{fs`@H6H;KcB~!EftVH`RvguCO6Ql_G`~u5Uo>^^0HFu@j?1m$i3Z_+#5& zoTc(qs56rwge_<&lsaR7NBuVKkm+dK;EA)ZnZ`|xN|MTZk<}UdyJ+@)eq7S*@D;x= z-#Deh;@73}R*5)h@j~{1uh)~y;xt?+c&rBSiFxp#jgV6zUyg~#FIRy7 zBH(HC!_(pZGV!$04>o{T%)D?c!P?AUNB?~o@syJZ9=M7RY44b%ouIC&rPHjyl2L#} zp=IGf(~=dde{rMdR&GeW-@>v>A|I{uCW(M8d|U(F4TBYch6@6U^uQmaHU?-!j#l78 zAWz_$7HSDAm{!0sBb4Im!9>?6kDydXIMA@+;cRGf9>h5i=R%ZaA)35`v2ZNZ z#NZ@c$kJ8u`|(kfwI(+-ReSH)9Cd;__ zsyqJNBaT1FfI*hyIHSmR`~Vc@;do)*zLGv8=@`<53;9b7CdWPF?dv!63CSm0$`|gl z{NpgsEuMweD|K8(bCrk7|CNqk{;zht?7!FXXa0o8Wayi$LN2jc$7KzIB0kOu>O|Fk zCU}Yx;})szxcyA>&6O2VVPSVS{iXe~A}WN2bHi&}-QR1TOizP>_6Jlb|4v zqgCj&_A?hy3zYDO+aDjd$zDQ$zc?$l>n#Wh5 zFb}EE36({mV!Fyg;aetKKox*0y^Wv>Ko!3D$wSp+$iPs>LAc^yPfLuMjU+ zZ%+@Gzz~lhm%t!Te@`DTf8XFB-(XJ{7ccT+t_SBvpA?V$WtxX=iFXRfynILE0kqi| z@Bz{Raz~Fvro7k7uf**#emAc*2fLp8b96&#B{A|9nrDqn>KJKZzFF}yyusZf(V9u7 zwIs+dx0M!7rdPZWViEgOnknwva}imEvg2dgAYRJhp9=T~!g=8$u{7syS$=*E=OhgI z*6**x&i0elhnDaJ{>C;2R6`6UAjXrFFjA#y8ZS)d3&D^6O!x=W+{o>%_H zA%U{;cM0TA%|NI7FTnO8aXTWP53TCith+AN=7uZD?*AV|8Z_i*?PZu8_9}h2Y zUoZavZ(;;|eSM2SGEo}me(mhnp#G@mwv6L|r00}OqT}%Nd29kgKI;NmFT7;7hK|=J z-Iq8yVmFbkgNV4~&MUHUeYE-v{@H>XOgl_xOB73AZ!b5053rA(o&mmr0l{7&!9D>V zzAhea0dC#_o?cvasN}CtH0lyGQQAyCEy2i}%taui|FZckPg$iPq)X(56s-y~pTE(T z#B+K9d|dhz$8|j?(LjNmf-&#>)p^sr+FfLA@3%*$$=lvIfVHoLGY%2@qzvr<3lj=q zXu+(y_;~udd3d|Jhqwf}f>A~r8|(w77loSa(gqq*q8#Xbij27glKiY5ESC&+R0rQMqt~F;UYaO_!YVzadk&vQgt%M!xVe)gDHzXk_ZSyhZ;Imw>>a051=J z-vD>lfDl&~mk>7>AAc_w@Gk?wOGKx;dqlwh{zP1W1?!9NEw;6lv`MXF$SW8;3Ss3G zTD{Senqb-Tyih9{e{XLeAD5sI4;QZhS1(r=FIZ>0yZQ%uxcG*gsgvD?9u_I2~5WVRl5xE4e!nI#Ju>mSRIlH9)7011U~4c+|RJ;9v1 zdIb4+gWQG$g?PIK;Bp5HtGj1N0NJK`g)7VsVRP(*!XlxoWi#!n(B1rR@^ByGnVt#z zjhaGfs*k^?uRm;pq3`15>+j2cY6bS<`^4_H5+y1BqIhq=cyAx%>-k(_4|uZZ zUE<=s{X#k3<6w}Ub5pcDJ_

ZT}zN+cyFA_LcBwE@+DP_K6IR!@vKJ_x5p>Q8W%^ z@!me!H0J*I_x62?Os0zW_F)SaxNScR_TsN&aG`1w3nsOWDc;*JKBR>D^?VB%Z+Oza zZl09P7VqujhzXM|>hCjM;o`l0!Z16}BvoJdGYK7l4K|rc@<`lffw_5(Vkgr)JmpfB zrt#t=N|R%nDKz8%+Pf0)D2nC3hQmZ6MhrxJfRRg|Anbi$fXubYk^=$+5qO3`0tN_y zT!1JfAOebr5C~v66%^z~Q!e%eP*9pDDZ2a7@xA-^O-;!dm=M11jtb&TT)g6YpXHqH>kXF< zx~;chHNDkP(3_&Yp`2x^O%oRbD=a9z$?PXE(if|jW`P3(>3%$$`rTFo@<5^)&p28J?#vB5E8bo`UYp5WIqLV|X;+<>do*wo!RnVKF zlc^l`;h0b)!U3GwW_1`0ddlX|GZe?cn-E~WE6heHv5az{Wqu%)#zI2W&NUm>@9g(6bPsHCkEW zO**Wyu5bgVcXWjtVp$_Zcr2{l0Iv>k+TdLnPP@ZwFgtBDBkWdmMR&e?x`K(Ik+s6^ zNC=IX3=Wnx+DsM$r8k=3r3MbWk)P$dlyz0pYr1ln%?7=brpyM$W^iycYhqxRI$VB6 z*qmcBS@~-)GB)Dw>B?lZ*bFdJHrrv0W}?jSJ`%H)q0JEgr}Qv^=5-aRtgFZ6x>B41 z2gqwG#%3$(*&zOEgV*~w&79Ndv~qT*gSCODV_>r^M{}I;c9kv=QMzlM4g9IaV5Hz( z118#pXLiz7nxl-YQ}1-@IXkb_F3MVc)N8uB|L+1Vy{4=C|1QwnYr4As?*h%drmOq^ zF3>`*E5*CO3-X$kcL7CRJulZ)I2nomm*h~cEBoz1S#O2%^|y`+4I@A7N^)Ge5lN1b z8BS)z)IvOfoL~MCMF{IjE`3DLSLSPBC@MB8jDHhKY+7O}lbRTxo|vG+R}tg)V380+ z*fbz{QHIaxFqJ4MHhw)TRMOQXIf^e0y9Xd01Niuu<{IESKvC5=OQ;RNBtLI}OQ08f zUtE2pVT6cD8JHfQG!S00kE;mMn3Mr=RC>C6*Lqpf;=^BlP=H-~1E47BD^Tc>q`aP= zfM4B_)RmApFg+=KSn(M_Suz%B6u0321GouLl=CGh^hnO4m4bKVlxoy7S#ebbKX|?c zIliW!4@^O>DDNas!T(cKG;;$rAJpq(fO*Vov(}b z=c}rAzIe^f*BChQ-U`>;po79E&G=j&*OK6ZAY2=P591W=0Nn&1kA%F0Cs6DJ7oHaq z{#s1DAH&DFkx6Ok!aK&mGvF7`Y@{ACtPa2#6vjMoc7StKoYUj{OR+6@fojv1A}504 zlb1x4t1(4RxP9w;Zf?zJA)D?-{l8 zWoUN3BDajs#PMkYJ_*9-ZuqPhAK2rwOAMAP>bf=*YU9c@cgr}X!5{<<*KyK_lWd$2 zDYgYKP;J^$N+%$52@M*>kGRNJ z9gPQgo5D0m$oNnGyl@oyEFqR!D4tjQe}zzO@=TCPJT))gPee#*lTQ;GHcmQaqLBVG zDQrP;g{m6)!F<8#fr8Pq756yZ8q2miqf!h zHV=g5sy2C+yvaWS0h9ME7guv*lA3-;fyDnMgLvg5i8uY>q)>a4S5?(taN1%f?}>Hb zQdr##B6w-8i&k@b^w(;?RPl&&i{2fly|R7>nG`Q2EGVWd@7vXV)jf({SXIkyA1p1a z{xP^NROKSbYO8V)-1*}ck1qloKw>Ii_q2vz7P|;MK7X12d8TR}dGhlsHscJ`RJ@ic zIhzOgTHZ>jSecGiv9dd^R#D41wpY|LE!VOl8w|NBvf<=xyx&=hg5#i3QSjYz!OO>H zpEhj1(S{8gQ!x)vzDDiQhRrT**zDDY&3?Dp;K)nSZhq8;&2eqme6J0g6WXx(K^r#5 z+-CDP)Ku)Lc5*hJjL>NK@jV$BP;K%Yd6T{GjXfT7lo=RMZ85Hna?j(PgPMxA;?#ys zl-q31t4R|rXY)W;wO5t*4dEc(?tL{-8 zFsf?V^ucjz85{iRAapxj_}&&~P3Y$4jzx!FjT>-_ z(C60JKf1%y``S$$9K`nhr`^jp3H?x&T>rd)<*r33A>X9s1TGCB^xB=4f0TA`XV}7R zpPXwHGN%`Y?lD>X9E%ff=WtVPBLY5JTtBsyK-R^aOB_CSo2~tf`gL9z|6JO1JE0GD zjjvv1)G>PWsE$W!j%%_OSCL{GUL)|)Y46Rj)>7OcWpbOW5ASVv2%lM=h>y7esH^X=L6I562)}koxj^r$tS4XjO%Th zI!~TNw}vUGd)}JUi>|j{-eG=B{Mhlg(Q9J5=;$zLXZ5{Y?)x7!s6IKbGsd|vwI95= z@Lbm)!dB&;H1v;urtr8x)^UekKXv+xhuF72snzS+_rX{mNd|etB{BH@h&>g=xmA$1gS4WkkL`H7(M7BJ?2)q+#0AxJ&++CJ#qWNL#q; z>F@hL`HVo;b?hF0HXLMLumIkC>RH1k$MFZ_PvfgEm!bJKrX&dv)6 z*2_0yt8FCo4RfcT8~j+DbG>iEHJdeP|2C1o?$@u3gMMXlTQ12D8WS~a6QQTfTXD2W zkDgIe&i2Y*{nZrT_X+*Tq_y2SQWCl!G zI+4(OPk!k}pWOb;=O@>0O8KGbn8}3x=8di6GMhZdu6p^>Yv%9vY@b5tF|C69yGKvw zrfgXpxnlFOmQxA+@RISHt%I9|y%l_8TfxNT!EX}!T5G)_r}ns<^G!+7|F`J3=xjp& zEG8kb&G_5wsLr9&+jNibI*QPLJiXn>)cuxSHNSS_e*1I%vj}}i^BpHHHu}q%olb|Y zePOI|G@*Z#AKW*h@O(tpnAjTWxvveKM(8m$xn=b(Wku%cPc#~K)-UTlLSME0!{new zbD0erQs=z>>Hc(F*@$UylarISw=~gfqR%y&*6*?bS4v~rH~4f^K=Md>!tfc%EgB5p z`Hw)>T^Jg$Ij-P!dcn@-N4i7}&cK!9nBIwg?y)B`o^rkGyLi*0E_++x3U5q4yO*rZ z44>}WJSO{%+}4L`z<8xXxEW8Ij#>wvmB{sLO!t(di|?=UmX;FlzC^L-dWJ>;@j^My3h8eL&n%@ zhfQf1IX7_Zk&j;_^wtHBX1w@nVEEWI*5ge(EPg+S&=W(;>l5tSI-hRN_;Onr6yoqZ6-nJ#7GaF`pbxt7bjwUpjFg-HH zwdLlbTeh84zy(5I{bRR1!?F|Td0fNLzdl&s8)KiCu01>GRz9B;( z>xK>pJrR1UQ}mk76B|6zIox%g&`;cSHQZEfYUpQu7CZlXAH~dpEd9k?zp<>`1GXAL>;ar#k4}m_|K~NX@r6=39&@s8Thx~f04p*B*%>Z zB@O~`6*{JxLdKholnXB>*1--RN-9Y!OGggPButRGnA$!8N5~1+N@9`@J@_+->cth$ zn50}^6G*&hq?o4!z^AXgKX55BCMknxfy6VAiiMA4eV3EMWhDO_G)4}EOe`oylzqu0 z-=!TGgfwh;DXTeKlKRq3SAK*hY;O6Ae8WZcV&XMbPv@6~YT zog~K+#=`O~Gbvm^@|u#$Qgt?$(532(M>=w)NQDxjiOr@-1*y7tD@C2jU!VF?(!hk2 zAw`30wv^xU){Jzq?TU6LUfv$tncN@TJ9btF8(s^5c2<02im2~OGeaHm$vbBDCOMnO zW+orzRM^a}Xywl8Vv}kET*>i$6XVFPAvP&9DIqacS7~W{k9*&tiQ`v~Elob)y>~3_ zaa84_fTZNU?NWNVdZ!G84Y-vS_CK<)QT%y@&1iTi9SW!p&E!+Cd&k0_#C8M%1YZ`O z7!N+I(v_iBgpEFsd*791^XD&zp~+(a_l}_z%>e{MbHa}D#8j$xZ`iP3>ClAk_P(8E zmDkSXv7>v(&SVZvm<3ciG`^$%cau#FP+;mB! z0;xny4kIyqnCeGTLHZ+HJBkUJ7KLo!7=Pe9?%C-(bk_rS)vUL!P=2_dEcIPg7N&~J&~=SS#`JMxYiI$!xvJUw42 zm{czzg9!>S9)n3PL%>dfUZDrE7}?{Mj2|c{Cb`eZ;;A~F{HB#n=<-36ILw!i+QkW` ze7-1#IOGuvF~TMfn28ZydB9exQ;b%lc-Ssct>W(<(gpJ!R0Yanuo9$dfb`UiL>;bR z$5ckRRVBQLor$Lv!>e~63jlgd zoFJ?MtOlTjcq?23SPRGl;BBxi;52{*;8sQsP#sVoupWTE?{xq^$~^%%2KW(h9PmBh z2f$LmuYgd%82|Wv!_5gMPa2wlxKx@Dl0IK~1z%X(Q znUECKKOV~6RzFt8o6OsQodC2*G_(tVa6lm-5`f;k0pJlp7GMM593Tp?8PEuTef=fC z31|q|3h)O!4cG|S1VG343}72zJ76AQB)|nY4~Pa_0^qppF+gL$4#0dsHsA{2CqO>n zXFvhqB;XWaIpA+VJHSN%ninb}7_bE}2k-{qGTR>jedT1?$rfZEneL5tq&0Ei3KFjJZX=qx_8UJ_2fI&|9?4%`l|o{ diff --git a/Content/ZMMO/UI/Themes/Default/Panel/Outlines/Effects/T_Panel_Outline_Effect_Square_01.uasset b/Content/ZMMO/UI/Themes/Default/Panel/Outlines/Effects/T_Panel_Outline_Effect_Square_01.uasset index 20754b69303be8a1c2253d7cf4cd3c8583e05469..57fd79bd8960f222e3eb121cf42247069638b050 100644 GIT binary patch delta 4663 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 delta 4524 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 QMs;n`Uq$9oqDJ=r0bHqF>;M1& diff --git a/Content/ZMMO/UI/Themes/Default/Panel/Outlines/T_Panel_Outline_Square_01.uasset b/Content/ZMMO/UI/Themes/Default/Panel/Outlines/T_Panel_Outline_Square_01.uasset index ae63fe178a7c54a04b81ce70fe0c2785cbd54d88..cd9c9262070541b3a4cc549e46a4884653c7d079 100644 GIT binary patch delta 69 zcmV-L0J{I{lL70K0gxCJHiD`>8B-H(it2@MjepKC#=;aru`FjU0W-6dE?ofuIJ5FE b4-OE}`gtH0EGt2mA_ex#+Kb4u5kA@r(PJC$ delta 69 zcmV-L0J{I{lL70K0gxCJDmYE8DnXKP+iuUlcZ_eAxrEXgu`FjU0Wq_bE?ofuGPCk8 b4-OEVIfiHQE^$tuJbw~^$FL!@5kA@r`R5!$ diff --git a/Source/ZMMO/Game/UI/Common/UIDraggableWindow_Base.cpp b/Source/ZMMO/Game/UI/Common/UIDraggableWindow_Base.cpp new file mode 100644 index 0000000..a74fe50 --- /dev/null +++ b/Source/ZMMO/Game/UI/Common/UIDraggableWindow_Base.cpp @@ -0,0 +1,131 @@ +#include "UIDraggableWindow_Base.h" + +#include "Components/Border.h" +#include "Engine/Engine.h" +#include "Engine/GameViewportClient.h" +#include "Input/Reply.h" +#include "UIWindowSaveGame.h" + +void UUIDraggableWindow_Base::NativeOnActivated() +{ + Super::NativeOnActivated(); + ApplySavedPosition(); + // Validacao usa translation + viewport size, ambos disponiveis ja' aqui + // (sem precisar do CachedGeometry/layout pass). + ValidatePositionInViewport(); +} + +void UUIDraggableWindow_Base::ApplySavedPosition() +{ + const FName Id = GetWindowId(); + if (Id.IsNone()) return; + + UZMMOUISaveGame* Save = UZMMOUISaveGame::LoadOrCreate(); + FVector2D Pos; + if (Save && Save->TryGetWindowPosition(Id, Pos)) + { + SetRenderTranslation(Pos); + } +} + +void UUIDraggableWindow_Base::PersistCurrentPosition() +{ + const FName Id = GetWindowId(); + if (Id.IsNone()) return; + + UZMMOUISaveGame* Save = UZMMOUISaveGame::LoadOrCreate(); + if (!Save) return; + Save->SetWindowPosition(Id, GetRenderTransform().Translation); + UZMMOUISaveGame::SaveNow(Save); +} + +bool UUIDraggableWindow_Base::IsDragHandleHit(const FPointerEvent& MouseEvent) const +{ + if (!Border_DragHandle) return false; + const FGeometry HandleGeom = Border_DragHandle->GetCachedGeometry(); + return HandleGeom.IsUnderLocation(MouseEvent.GetScreenSpacePosition()); +} + +FReply UUIDraggableWindow_Base::NativeOnMouseButtonDown(const FGeometry& InGeometry, + const FPointerEvent& InMouseEvent) +{ + if (InMouseEvent.GetEffectingButton() == EKeys::LeftMouseButton && IsDragHandleHit(InMouseEvent)) + { + bMaybeDragging = true; + bDragging = false; + DragStartScreenPos = InMouseEvent.GetScreenSpacePosition(); + WidgetStartTranslation = GetRenderTransform().Translation; + return FReply::Handled().CaptureMouse(TakeWidget()); + } + return Super::NativeOnMouseButtonDown(InGeometry, InMouseEvent); +} + +FReply UUIDraggableWindow_Base::NativeOnMouseMove(const FGeometry& InGeometry, + const FPointerEvent& InMouseEvent) +{ + if (!bMaybeDragging && !bDragging) + { + return Super::NativeOnMouseMove(InGeometry, InMouseEvent); + } + + const FVector2D Delta = InMouseEvent.GetScreenSpacePosition() - DragStartScreenPos; + if (!bDragging && Delta.SizeSquared() < DragStartThresholdPx * DragStartThresholdPx) + { + return FReply::Handled(); + } + bDragging = true; + SetRenderTranslation(WidgetStartTranslation + Delta); + return FReply::Handled(); +} + +FReply UUIDraggableWindow_Base::NativeOnMouseButtonUp(const FGeometry& InGeometry, + const FPointerEvent& InMouseEvent) +{ + if (InMouseEvent.GetEffectingButton() == EKeys::LeftMouseButton && (bMaybeDragging || bDragging)) + { + const bool bWasRealDrag = bDragging; + bMaybeDragging = false; + bDragging = false; + if (bWasRealDrag) + { + PersistCurrentPosition(); + } + return FReply::Handled().ReleaseMouseCapture(); + } + return Super::NativeOnMouseButtonUp(InGeometry, InMouseEvent); +} + +void UUIDraggableWindow_Base::NativeOnMouseLeave(const FPointerEvent& InMouseEvent) +{ + Super::NativeOnMouseLeave(InMouseEvent); +} + +void UUIDraggableWindow_Base::ValidatePositionInViewport() +{ + if (!GEngine || !GEngine->GameViewport) return; + FVector2D ViewportSize; + GEngine->GameViewport->GetViewportSize(ViewportSize); + if (ViewportSize.IsNearlyZero()) return; + + // RenderTransform.Translation esta em coordenadas de viewport (pixels), + // independente de DPI/offset do editor — comparacao direta funciona em + // PIE e em build standalone. Assume slot centralizado (default UMG + // stack); meio-viewport e' o quanto a translation pode crescer antes + // da janela sair completamente. + const FVector2D Tr = GetRenderTransform().Translation; + const float HalfX = ViewportSize.X * 0.5f; + const float HalfY = ViewportSize.Y * 0.5f; + + const bool bOutOfBounds = + FMath::Abs(Tr.X) > HalfX - MinVisiblePixels || + FMath::Abs(Tr.Y) > HalfY - MinVisiblePixels; + + UE_LOG(LogTemp, Verbose, TEXT("DraggableWindow::Validate translation=(%.0f,%.0f) viewport=(%.0f,%.0f) outOfBounds=%d"), + Tr.X, Tr.Y, ViewportSize.X, ViewportSize.Y, bOutOfBounds ? 1 : 0); + + if (bOutOfBounds) + { + SetRenderTranslation(FVector2D::ZeroVector); + PersistCurrentPosition(); + } +} diff --git a/Source/ZMMO/Game/UI/Common/UIDraggableWindow_Base.h b/Source/ZMMO/Game/UI/Common/UIDraggableWindow_Base.h new file mode 100644 index 0000000..a24db37 --- /dev/null +++ b/Source/ZMMO/Game/UI/Common/UIDraggableWindow_Base.h @@ -0,0 +1,90 @@ +#pragma once + +#include "CoreMinimal.h" +#include "CommonActivatableWidget.h" +#include "UIDraggableWindow_Base.generated.h" + +class UBorder; +class UZMMOUISaveGame; + +/** + * Base de janelas in-game movel + persistente. Subclasse define WindowId + * (FName estavel) via override de GetWindowId(); a Base cuida do drag + * (RenderTransform.Translation) e da persistencia (UZMMOUISaveGame). + * + * Convencao do WBP: + * - Bind opcional `Border_DragHandle` cobrindo a area arrastavel (header). + * Sem ele, a janela nao captura drag (vira static). + * - `Border_DragHandle->Visibility = Visible` (precisa receber HitTest). + * + * Por que RenderTransform e nao Slot.Position? + * - Funciona em qualquer layout slot (Overlay, VBox, Canvas), nao so + * CanvasPanelSlot. + * - Nao polui o asset (translation e' transient/visual, nao layout-layout). + * + * Persistencia: na primeira ativacao, carrega a posicao salva do WindowId; + * ao soltar o drag, grava e salva o slot. + */ +UCLASS(Abstract, Blueprintable) +class ZMMO_API UUIDraggableWindow_Base : public UCommonActivatableWidget +{ + GENERATED_BODY() + +public: + /** + * Identificador estavel da janela (chave no save). Subclasse OBRIGADA + * a sobrescrever — default NAME_None desativa persistencia. + */ + virtual FName GetWindowId() const { return NAME_None; } + +protected: + virtual void NativeOnActivated() override; + virtual FReply NativeOnMouseButtonDown(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent) override; + virtual FReply NativeOnMouseMove(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent) override; + virtual FReply NativeOnMouseButtonUp(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent) override; + virtual void NativeOnMouseLeave(const FPointerEvent& InMouseEvent) override; + + /** + * Define se o ponto sob o cursor pertence a area de drag. Default: usa + * Border_DragHandle (se bindado). Subclass pode override pra usar outro + * widget (ex.: Container_Header ja' existente) sem precisar adicionar + * um Border dedicado no WBP. + */ + virtual bool IsDragHandleHit(const FPointerEvent& MouseEvent) const; + + /** Aplica a posicao salva (se houver) como RenderTransform.Translation. */ + void ApplySavedPosition(); + + /** Grava a posicao atual no save e persiste no slot. */ + void PersistCurrentPosition(); + + /** + * Se a janela ficou fora do viewport (ex.: usuario arrastou pra borda e + * depois a resolucao mudou ou ele fechou e reabriu), reseta translation + * pra (0,0). Chamado no proximo tick apos Activated — cached geometry + * so' tem valor depois do primeiro layout pass. + */ + UFUNCTION() + void ValidatePositionInViewport(); + + /** Quanto da janela precisa ficar visivel pra contar como "no viewport". */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Drag") + float MinVisiblePixels = 50.f; + + /** + * Bind opcional do WBP. Apenas drags iniciados com o cursor SOBRE + * este border sao aceitos — bloqueia drag por clicar nos rows/botoes. + */ + UPROPERTY(BlueprintReadOnly, meta = (BindWidgetOptional), Category = "Drag") + TObjectPtr Border_DragHandle; + + /** Distancia minima do mouse pra confirmar "drag iniciado" (anti-jitter). */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Drag") + float DragStartThresholdPx = 4.f; + +private: + bool bMaybeDragging = false; ///< pressed mas ainda nao passou do threshold + bool bDragging = false; ///< drag confirmado + FVector2D DragStartScreenPos = FVector2D::ZeroVector; + FVector2D WidgetStartTranslation = FVector2D::ZeroVector; +}; diff --git a/Source/ZMMO/Game/UI/Common/UIWindowSaveGame.cpp b/Source/ZMMO/Game/UI/Common/UIWindowSaveGame.cpp new file mode 100644 index 0000000..717778d --- /dev/null +++ b/Source/ZMMO/Game/UI/Common/UIWindowSaveGame.cpp @@ -0,0 +1,43 @@ +#include "UIWindowSaveGame.h" + +#include "Kismet/GameplayStatics.h" + +const FString UZMMOUISaveGame::SlotName = TEXT("UIPrefs"); + +UZMMOUISaveGame* UZMMOUISaveGame::LoadOrCreate() +{ + if (UGameplayStatics::DoesSaveGameExist(SlotName, UserIndex)) + { + if (UZMMOUISaveGame* Loaded = Cast( + UGameplayStatics::LoadGameFromSlot(SlotName, UserIndex))) + { + return Loaded; + } + } + return Cast( + UGameplayStatics::CreateSaveGameObject(UZMMOUISaveGame::StaticClass())); +} + +void UZMMOUISaveGame::SaveNow(UZMMOUISaveGame* Save) +{ + if (Save) + { + UGameplayStatics::SaveGameToSlot(Save, SlotName, UserIndex); + } +} + +bool UZMMOUISaveGame::TryGetWindowPosition(FName WindowId, FVector2D& OutPos) const +{ + if (const FVector2D* Found = WindowPositions.Find(WindowId)) + { + OutPos = *Found; + return true; + } + OutPos = FVector2D::ZeroVector; + return false; +} + +void UZMMOUISaveGame::SetWindowPosition(FName WindowId, FVector2D Pos) +{ + WindowPositions.Add(WindowId, Pos); +} diff --git a/Source/ZMMO/Game/UI/Common/UIWindowSaveGame.h b/Source/ZMMO/Game/UI/Common/UIWindowSaveGame.h new file mode 100644 index 0000000..76e6f35 --- /dev/null +++ b/Source/ZMMO/Game/UI/Common/UIWindowSaveGame.h @@ -0,0 +1,46 @@ +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/SaveGame.h" +#include "UIWindowSaveGame.generated.h" + +/** + * Persistencia de prefs de UI por janela (posicao, e futuramente tamanho, + * estado expandido, etc). Usado por UUIDraggableWindow_Base — toda janela + * movel registra uma chave (FName WindowId) e grava aqui ao soltar o drag. + * + * Arquivo: [Project]/Saved/SaveGames/UIPrefs_0.sav (binary blob via + * UE serializer). Mesmo padrao do [[ZMMOLoginSaveGame]]. + * + * Helpers static abaixo encapsulam load-or-create do slot e Get/Set/Save + * pra que a Base nao precise repetir a cerimonia. + */ +UCLASS() +class ZMMO_API UZMMOUISaveGame : public USaveGame +{ + GENERATED_BODY() + +public: + /** Posicao normalizada (translation absoluta em pixels da viewport) por janela. */ + UPROPERTY() + TMap WindowPositions; + + static const FString SlotName; + static constexpr int32 UserIndex = 0; + + /** + * Carrega o save existente ou cria um novo (nao salva ainda). + * Sempre retorna instancia valida. + */ + static UZMMOUISaveGame* LoadOrCreate(); + + /** Salva o slot atual (sincrono — chamado on-mouse-up, custo baixo). */ + static void SaveNow(UZMMOUISaveGame* Save); + + /** Get com default — se WindowId nao foi gravado retorna FVector2D::ZeroVector. */ + UFUNCTION(BlueprintCallable, Category = "UI|Prefs") + bool TryGetWindowPosition(FName WindowId, FVector2D& OutPos) const; + + UFUNCTION(BlueprintCallable, Category = "UI|Prefs") + void SetWindowPosition(FName WindowId, FVector2D Pos); +}; diff --git a/Source/ZMMO/Game/UI/FrontEnd/UIFrontEndFlowSubsystem.cpp b/Source/ZMMO/Game/UI/FrontEnd/UIFrontEndFlowSubsystem.cpp index 31ba12b..5aaf239 100644 --- a/Source/ZMMO/Game/UI/FrontEnd/UIFrontEndFlowSubsystem.cpp +++ b/Source/ZMMO/Game/UI/FrontEnd/UIFrontEndFlowSubsystem.cpp @@ -233,6 +233,16 @@ void UUIFrontEndFlowSubsystem::ResolveAndPushScreen(EZMMOFrontEndState State) GetLoadingProfiles(), GetLoadingTips()); Loading->OnLoadingComplete.AddDynamic(this, &UUIFrontEndFlowSubsystem::HandleLoadingComplete); Loading->MarkStepDone(TEXT("Travel")); + + // Drena steps que dispararam ANTES do widget existir + // (HandlePostLoadMap/HandlePlayerSpawned podem ter + // rodado durante o RequestAsyncLoad). Sem isso o + // loading fica eterno se o servidor for rápido demais. + for (const FName StepId : PendingLoadingSteps_) + { + Loading->MarkStepDone(StepId); + } + PendingLoadingSteps_.Reset(); } } } @@ -423,8 +433,10 @@ void UUIFrontEndFlowSubsystem::HandlePostLoadMap(UWorld* /*LoadedWorld*/) return; } - bTravelingToWorld = false; - SetState(EZMMOFrontEndState::InWorld); + // Race fix: widget ainda em RequestAsyncLoad; memoiza pra drenar quando + // a tela for criada (ver lambda em ResolveAndPushScreen). Não fallback + // pra InWorld — esperamos a tela existir e o Spawn chegar. + PendingLoadingSteps_.Add(TEXT("MapLoaded")); } void UUIFrontEndFlowSubsystem::HandlePlayerSpawned(int32 /*EntityId*/, bool bIsLocal, @@ -435,6 +447,15 @@ void UUIFrontEndFlowSubsystem::HandlePlayerSpawned(int32 /*EntityId*/, bool bIsL if (UUILoadingScreen_Base* Loading = ActiveLoadingScreen.Get()) { Loading->MarkStepDone(TEXT("Spawn")); + return; + } + + // Race fix: spawn pode chegar ANTES do widget existir se o servidor for + // rápido (TryFinalizeEnterWorld) e o RequestAsyncLoad lento. Memoiza + // pra drenar no callback do async load. + if (bTravelingToWorld) + { + PendingLoadingSteps_.Add(TEXT("Spawn")); } } @@ -445,6 +466,7 @@ void UUIFrontEndFlowSubsystem::HandleLoadingComplete() Loading->OnLoadingComplete.RemoveDynamic(this, &UUIFrontEndFlowSubsystem::HandleLoadingComplete); } ActiveLoadingScreen.Reset(); + PendingLoadingSteps_.Reset(); bTravelingToWorld = false; SetState(EZMMOFrontEndState::InWorld); } diff --git a/Source/ZMMO/Game/UI/FrontEnd/UIFrontEndFlowSubsystem.h b/Source/ZMMO/Game/UI/FrontEnd/UIFrontEndFlowSubsystem.h index d1168de..18339f6 100644 --- a/Source/ZMMO/Game/UI/FrontEnd/UIFrontEndFlowSubsystem.h +++ b/Source/ZMMO/Game/UI/FrontEnd/UIFrontEndFlowSubsystem.h @@ -249,6 +249,15 @@ private: */ TWeakObjectPtr ActiveLoadingScreen; + /** + * Race fix: o widget de loading é criado via RequestAsyncLoad (assíncrono). + * Se o servidor for rápido (TryFinalizeEnterWorld), HandlePostLoadMap e/ou + * HandlePlayerSpawned podem disparar ANTES de ActiveLoadingScreen existir + * — nesse caso o MarkStepDone vira no-op e o loading fica eterno. + * Memoizamos os StepIds aqui e drenamos quando a tela for criada. + */ + TSet PendingLoadingSteps_; + bool bNetBound = false; bool bTravelingToWorld = false; FDelegateHandle PostLoadMapHandle; diff --git a/Source/ZMMO/Game/UI/InGame/UIInGameFlowSubsystem.cpp b/Source/ZMMO/Game/UI/InGame/UIInGameFlowSubsystem.cpp index cb16f33..bd4a318 100644 --- a/Source/ZMMO/Game/UI/InGame/UIInGameFlowSubsystem.cpp +++ b/Source/ZMMO/Game/UI/InGame/UIInGameFlowSubsystem.cpp @@ -81,16 +81,26 @@ void UUIInGameFlowSubsystem::SetState(EZMMOInGameUIState NewState) // (Status/Inventory/Menu) limpando o Layer.GameMenu — HUD em Layer.Game // permanece. Para qualquer outro estado, mantemos HUD e empilhamos no // layer correspondente. + const bool bGoingToPlaying = (NewState == EZMMOInGameUIState::Playing); if (UUIManagerSubsystem* Mgr = GetUIManager()) { - const bool bGoingToPlaying = (NewState == EZMMOInGameUIState::Playing); if (bGoingToPlaying) { Mgr->ClearLayer(ZMMOUITags::UI_Layer_GameMenu.GetTag()); } } - ResolveAndPushScreen(NewState); + // Skip re-push do HUD quando ja' estavamos in-game (Old != None significa + // que StartInGame ja' rodou e o HUD esta no Layer.Game). Senao, cada vez + // que o usuario fechar StatusWindow/Inventory/etc, o HUD seria recriado + // — flicker em todos os textos (HP/SP/etc) por causa do Construct novo. + const bool bSkipRepush = bGoingToPlaying + && OldState != EZMMOInGameUIState::None + && OldState != EZMMOInGameUIState::Playing; + if (!bSkipRepush) + { + ResolveAndPushScreen(NewState); + } OnStateChanged.Broadcast(NewState); } diff --git a/Source/ZMMO/Game/UI/Widgets/UIPlayerStatus_Window.cpp b/Source/ZMMO/Game/UI/Widgets/UIPlayerStatus_Window.cpp index dca2771..5a6bad1 100644 --- a/Source/ZMMO/Game/UI/Widgets/UIPlayerStatus_Window.cpp +++ b/Source/ZMMO/Game/UI/Widgets/UIPlayerStatus_Window.cpp @@ -2,7 +2,9 @@ #include "CommonInputTypeEnum.h" #include "Components/Button.h" +#include "Components/HorizontalBox.h" #include "Components/TextBlock.h" +#include "InputCoreTypes.h" #include "Engine/World.h" #include "GameFramework/PlayerController.h" #include "GameFramework/PlayerState.h" @@ -20,8 +22,18 @@ UUIPlayerStatus_Window::UUIPlayerStatus_Window(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer) { - bIsBackHandler = true; + // bIsBackHandler exige DefaultBackAction configurada no CommonUISettings; + // projeto ainda não tem DT de input actions, então registrar o handler + // poluía o log com "Cannot create action binding". Fechamento da janela + // vai por Alt+A (NativeOnKeyDown) e Button_Close. bAutoActivate = true; + // Focusable + DesiredFocusTarget=self → recebe NativeOnKeyDown (Alt+A). + SetIsFocusable(true); +} + +UWidget* UUIPlayerStatus_Window::NativeGetDesiredFocusTarget() const +{ + return const_cast(this); } TOptional UUIPlayerStatus_Window::GetDesiredInputConfig() const @@ -51,7 +63,14 @@ void UUIPlayerStatus_Window::NativeOnActivated() if (TitleText) TitleText->SetText(FText::FromString(TEXT("Status"))); - if (CloseBtn) CloseBtn->OnClicked.AddDynamic(this, &UUIPlayerStatus_Window::OnCloseClicked); + if (Button_Close) Button_Close->OnClicked.AddDynamic(this, &UUIPlayerStatus_Window::HandleCloseClicked); + + // Background_Panel default é SELF_HIT_TEST_INVISIBLE; precisa Visible + // pra capturar clicks em areas vazias do modal e bubbla pra Window. + if (Background_Panel) + { + Background_Panel->SetVisibility(ESlateVisibility::Visible); + } BindToLocalPlayer(); @@ -69,7 +88,7 @@ void UUIPlayerStatus_Window::NativeOnDeactivated() UnbindRow(Row_Str); UnbindRow(Row_Agi); UnbindRow(Row_Vit); UnbindRow(Row_Int); UnbindRow(Row_Dex); UnbindRow(Row_Luk); - if (CloseBtn) CloseBtn->OnClicked.RemoveDynamic(this, &UUIPlayerStatus_Window::OnCloseClicked); + if (Button_Close) Button_Close->OnClicked.RemoveDynamic(this, &UUIPlayerStatus_Window::HandleCloseClicked); Super::NativeOnDeactivated(); } @@ -219,7 +238,7 @@ void UUIPlayerStatus_Window::RefreshFromSnapshot(const FZMMOAttributesSnapshot& SetAllPrimaryRowsPlusEnabled(bCanAlloc); } -void UUIPlayerStatus_Window::OnCloseClicked() +void UUIPlayerStatus_Window::HandleCloseClicked() { if (UGameInstance* GI = GetGameInstance()) { @@ -229,3 +248,33 @@ void UUIPlayerStatus_Window::OnCloseClicked() } } } + +FReply UUIPlayerStatus_Window::NativeOnKeyDown(const FGeometry& Geom, const FKeyEvent& KeyEvent) +{ + // Alt+A em modo Menu — PlayerController nao recebe (CommonUI absorve). + // Handle aqui pra completar o toggle. + if (KeyEvent.GetKey() == EKeys::A && KeyEvent.IsAltDown()) + { + if (UGameInstance* GI = GetGameInstance()) + { + if (UUIInGameFlowSubsystem* Flow = GI->GetSubsystem()) + { + Flow->SetState(EZMMOInGameUIState::Playing); + return FReply::Handled(); + } + } + } + return Super::NativeOnKeyDown(Geom, KeyEvent); +} + +bool UUIPlayerStatus_Window::IsDragHandleHit(const FPointerEvent& MouseEvent) const +{ + // Drag em qualquer parte do modal EXCETO Container_Stats (rows + botões +STR). + // Botão close consome o evento antes (UButton.OnClicked) e não bubbla aqui. + const FVector2D Pos = MouseEvent.GetScreenSpacePosition(); + if (Container_Stats && Container_Stats->GetCachedGeometry().IsUnderLocation(Pos)) + { + return false; + } + return true; +} diff --git a/Source/ZMMO/Game/UI/Widgets/UIPlayerStatus_Window.h b/Source/ZMMO/Game/UI/Widgets/UIPlayerStatus_Window.h index 6440ed9..b1541ff 100644 --- a/Source/ZMMO/Game/UI/Widgets/UIPlayerStatus_Window.h +++ b/Source/ZMMO/Game/UI/Widgets/UIPlayerStatus_Window.h @@ -1,12 +1,13 @@ #pragma once #include "CoreMinimal.h" -#include "CommonActivatableWidget.h" +#include "UI/Common/UIDraggableWindow_Base.h" #include "ZMMOAttributeTypes.h" #include "UIPlayerStatus_Window.generated.h" class UButton; class UTextBlock; +class UHorizontalBox; class UUIPlayerStatus_BonusRow; class UUIPlayerStatus_StatRow; class UZMMOAttributeComponent; @@ -22,18 +23,46 @@ class UZMMOAttributeComponent; * pra suportar variantes (ex.: HUD compacto sem CRIT/ASPD). */ UCLASS(Abstract, Blueprintable, BlueprintType) -class ZMMO_API UUIPlayerStatus_Window : public UCommonActivatableWidget +class ZMMO_API UUIPlayerStatus_Window : public UUIDraggableWindow_Base { GENERATED_BODY() public: UUIPlayerStatus_Window(const FObjectInitializer& ObjectInitializer); + /** Chave de persistencia no UZMMOUISaveGame. Estavel — nao renomear. */ + virtual FName GetWindowId() const override { return TEXT("PlayerStatus"); } + protected: virtual void NativeOnActivated() override; virtual void NativeOnDeactivated() override; virtual TOptional GetDesiredInputConfig() const override; + /** Diz ao stack pra mover foco pra ca' (precisa pra NativeOnKeyDown ser chamado). */ + virtual UWidget* NativeGetDesiredFocusTarget() const override; + + /** Atalho Alt+A — fecha a janela em modo Menu (PC controller nao recebe). */ + virtual FReply NativeOnKeyDown(const FGeometry& Geom, const FKeyEvent& KeyEvent) override; + + /** Drag area = Container_Header (header inteiro). Header_DragHandle no WBP nao necessario. */ + virtual bool IsDragHandleHit(const FPointerEvent& MouseEvent) const override; + + /** Header do WBP (HorizontalBox raiz da identidade) — usado como drag area. */ + UPROPERTY(BlueprintReadOnly, meta = (BindWidgetOptional), Category = "Zeus|Status|Header") TObjectPtr Container_Header; + + /** + * Zona EXCLUÍDA do drag — é onde ficam os rows interativos (+STR etc.). + * Clicar aqui não deve iniciar drag mesmo em area "vazia" entre rows. + */ + UPROPERTY(BlueprintReadOnly, meta = (BindWidgetOptional), Category = "Zeus|Status") TObjectPtr Container_Stats; + + /** + * Panel de fundo (UIPanel_Base). Setado pra Visible em NativeOnActivated + * pra capturar clicks em areas vazias do modal — sem isso, drag só funciona + * onde algum filho é Visible (header/footer). + */ + UPROPERTY(BlueprintReadOnly, meta = (BindWidgetOptional), Category = "Zeus|Status") TObjectPtr Background_Panel; + UPROPERTY(BlueprintReadOnly, meta = (BindWidgetOptional), Category = "Zeus|Status") TObjectPtr TitleText; UPROPERTY(BlueprintReadOnly, meta = (BindWidgetOptional), Category = "Zeus|Status") TObjectPtr StatusPointText; @@ -59,7 +88,8 @@ protected: UPROPERTY(BlueprintReadOnly, meta = (BindWidgetOptional), Category = "Zeus|Status|Derived") TObjectPtr Row_Crit; UPROPERTY(BlueprintReadOnly, meta = (BindWidgetOptional), Category = "Zeus|Status|Derived") TObjectPtr Row_Aspd; - UPROPERTY(BlueprintReadOnly, meta = (BindWidgetOptional), Category = "Zeus|Status") TObjectPtr CloseBtn; + /** Botao de fechar na header — UButton simples (placeholder, estilizar depois). */ + UPROPERTY(BlueprintReadOnly, meta = (BindWidgetOptional), Category = "Zeus|Status") TObjectPtr Button_Close; private: void BindToLocalPlayer(); @@ -71,7 +101,7 @@ private: UFUNCTION() void HandleAttributesChanged(const FZMMOAttributesSnapshot& Snapshot); UFUNCTION() void HandleStatAllocReply(bool bAccepted, int32 Reason); UFUNCTION() void HandleRowPlusClicked(int32 StatId); - UFUNCTION() void OnCloseClicked(); + UFUNCTION() void HandleCloseClicked(); UPROPERTY(Transient) TWeakObjectPtr BoundComponent;