From e6a79f84a545d40efc8f1b18a5785fbf6a9a5ca3 Mon Sep 17 00:00:00 2001 From: Michael Herzog Date: Fri, 17 Jan 2025 14:55:45 +0100 Subject: [PATCH] WebGPURenderer: Add `XRManager`. (#30346) * WebGPURenderer: Add `XRManager`. * Renderer: Fix projection matrix computation in XR. * WebGLBackend: Use `gl.STATIC_DRAW` for camera index buffers. * Renderer: Clean up. * WebGLBackend: Don't cache `cameraIndex`. * XRManager: Add documentation. * E2E: Update screenshot. * Renderer: Fix `xr` usage. --- examples/files.json | 3 +- examples/jsm/webxr/XRButtonGPU.js | 224 ++++ examples/screenshots/webgpu_xr_cubes.jpg | Bin 0 -> 115806 bytes examples/webgpu_xr_cubes.html | 273 +++++ src/Three.Core.js | 1 + src/renderers/common/Animation.js | 22 + src/renderers/common/Renderer.js | 48 +- src/renderers/common/XRManager.js | 1075 ++++++++++++++++++ src/renderers/webgl-fallback/WebGLBackend.js | 49 +- 9 files changed, 1684 insertions(+), 11 deletions(-) create mode 100644 examples/jsm/webxr/XRButtonGPU.js create mode 100644 examples/screenshots/webgpu_xr_cubes.jpg create mode 100644 examples/webgpu_xr_cubes.html create mode 100644 src/renderers/common/XRManager.js diff --git a/examples/files.json b/examples/files.json index 474be30f7c4ef2..a886b7144cc241 100644 --- a/examples/files.json +++ b/examples/files.json @@ -448,7 +448,8 @@ "webgpu_video_panorama", "webgpu_volume_cloud", "webgpu_volume_perlin", - "webgpu_water" + "webgpu_water", + "webgpu_xr_cubes" ], "webaudio": [ "webaudio_orientation", diff --git a/examples/jsm/webxr/XRButtonGPU.js b/examples/jsm/webxr/XRButtonGPU.js new file mode 100644 index 00000000000000..2abb10925a5bcb --- /dev/null +++ b/examples/jsm/webxr/XRButtonGPU.js @@ -0,0 +1,224 @@ +// temporary version of XRButton until WebGPURenderer fully support layers + +class XRButton { + + static createButton( renderer, sessionInit = {} ) { + + const button = document.createElement( 'button' ); + + function showStartXR( mode ) { + + let currentSession = null; + + async function onSessionStarted( session ) { + + session.addEventListener( 'end', onSessionEnded ); + + await renderer.xr.setSession( session ); + + button.textContent = 'STOP XR'; + + currentSession = session; + + } + + function onSessionEnded( /*event*/ ) { + + currentSession.removeEventListener( 'end', onSessionEnded ); + + button.textContent = 'START XR'; + + currentSession = null; + + } + + // + + button.style.display = ''; + + button.style.cursor = 'pointer'; + button.style.left = 'calc(50% - 50px)'; + button.style.width = '100px'; + + button.textContent = 'START XR'; + + const sessionOptions = { + ...sessionInit, + optionalFeatures: [ + 'local-floor', + 'bounded-floor', + ...( sessionInit.optionalFeatures || [] ) + ], + }; + + button.onmouseenter = function () { + + button.style.opacity = '1.0'; + + }; + + button.onmouseleave = function () { + + button.style.opacity = '0.5'; + + }; + + button.onclick = function () { + + if ( currentSession === null ) { + + navigator.xr.requestSession( mode, sessionOptions ) + .then( onSessionStarted ); + + } else { + + currentSession.end(); + + if ( navigator.xr.offerSession !== undefined ) { + + navigator.xr.offerSession( mode, sessionOptions ) + .then( onSessionStarted ) + .catch( ( err ) => { + + console.warn( err ); + + } ); + + } + + } + + }; + + if ( navigator.xr.offerSession !== undefined ) { + + navigator.xr.offerSession( mode, sessionOptions ) + .then( onSessionStarted ) + .catch( ( err ) => { + + console.warn( err ); + + } ); + + } + + } + + function disableButton() { + + button.style.display = ''; + + button.style.cursor = 'auto'; + button.style.left = 'calc(50% - 75px)'; + button.style.width = '150px'; + + button.onmouseenter = null; + button.onmouseleave = null; + + button.onclick = null; + + } + + function showXRNotSupported() { + + disableButton(); + + button.textContent = 'XR NOT SUPPORTED'; + + } + + function showXRNotAllowed( exception ) { + + disableButton(); + + console.warn( 'Exception when trying to call xr.isSessionSupported', exception ); + + button.textContent = 'XR NOT ALLOWED'; + + } + + function stylizeElement( element ) { + + element.style.position = 'absolute'; + element.style.bottom = '20px'; + element.style.padding = '12px 6px'; + element.style.border = '1px solid #fff'; + element.style.borderRadius = '4px'; + element.style.background = 'rgba(0,0,0,0.1)'; + element.style.color = '#fff'; + element.style.font = 'normal 13px sans-serif'; + element.style.textAlign = 'center'; + element.style.opacity = '0.5'; + element.style.outline = 'none'; + element.style.zIndex = '999'; + + } + + if ( 'xr' in navigator ) { + + button.id = 'XRButton'; + button.style.display = 'none'; + + stylizeElement( button ); + + navigator.xr.isSessionSupported( 'immersive-ar' ) + .then( function ( supported ) { + + if ( supported ) { + + showStartXR( 'immersive-ar' ); + + } else { + + navigator.xr.isSessionSupported( 'immersive-vr' ) + .then( function ( supported ) { + + if ( supported ) { + + showStartXR( 'immersive-vr' ); + + } else { + + showXRNotSupported(); + + } + + } ).catch( showXRNotAllowed ); + + } + + } ).catch( showXRNotAllowed ); + + return button; + + } else { + + const message = document.createElement( 'a' ); + + if ( window.isSecureContext === false ) { + + message.href = document.location.href.replace( /^http:/, 'https:' ); + message.innerHTML = 'WEBXR NEEDS HTTPS'; // TODO Improve message + + } else { + + message.href = 'https://immersiveweb.dev/'; + message.innerHTML = 'WEBXR NOT AVAILABLE'; + + } + + message.style.left = 'calc(50% - 90px)'; + message.style.width = '180px'; + message.style.textDecoration = 'none'; + + stylizeElement( message ); + + return message; + + } + + } + +} + +export { XRButton }; diff --git a/examples/screenshots/webgpu_xr_cubes.jpg b/examples/screenshots/webgpu_xr_cubes.jpg new file mode 100644 index 0000000000000000000000000000000000000000..fae83571b60f895456612c221b05548dc2d6715b GIT binary patch literal 115806 zcmc$_cT`i|*De}GMFB;cbWnOndJ#cUT95z<9RvX>p?5;J(4@YUfbwhp-E4uk$Uqx=Z-V(J>U1o8TX&Ncakx(_TI^!YtOajoX_*Dt6x`3fcrpA9ZkTs zYXHDC@(#F~14NR){r|jOeFxCp2Ap2|hvFI?;5ywk3c71oUDv*l@A2mUyfeW6y*^aCo0>bZUEMvs zKl=K|#wRAHrhm=M;_%BWt843jHa3a-2Zu+;C#1ip*8mj%tE2y?LH`eX$cA6Le&Ytk z4a)!6bM1N{`AtE0ilptnRqOD+4Al+4+o8J>ZkY@e}`J z(*LmN|IDBd|DP=SUk3dzd#+{yG!)m!4~&8ipa%Hs+7nT0gQcY`9~G!+{9PQ$7&-J0C84=QbY?XmnEX|0FYz1)4A=6y0@ zBi%t#J2P>%mLke7J|I5GWR6m+-8BxC3E{s2%wj5bx#=phN{0!S{Ft3#UU_Mei|jQ= zSLxAtcEiBF&P(2A?x0yc5% zQmIexbxTs>doTBgN-^xO=dJ$yS~J7B%&l9aA95Ff1}(?cp80e@1cDa2ecC>2^Xl7F z`8h9QV|-&Mgn#&}zk9L1Sk>li*Ax-@6VvvoS;{`huiaHDQMdwPIw|2HhN;zks=hoD z6_MSRV>Vm$9p;}|I_~Ff)+X39kp@04tGJ$|rJi8R&wmqSFzDJGXONy-sMBL$m|bwl z{qyV&2)6jNw@H7_wyO0>WF#c{s~@q>H+#}S7QeF2>TqZ*k7OzBFH3h^rKF8U#A&}x zWi5g^MlA~4!P%5}Qssq+KawbTi>_BBP>5c?eS^;CJLL)8%(?CrAT@dU3UJ2RYJ3Gi z&Yc4A&J^|SG zYEyMy*DrqJM|-|ZE@nUWB%um7Mqy~Zakq0DPX~@bwzd=;YsHa112iDbVn}>ws5eHi zx_Z)M`;e6SqRd5EuMJTG)d1_M@6R$PnViq@6C*x+6&rfPpM-%=`HO%HO% zCX9+WRFxIu8Z{vISMnc3^VHF3@*E?8#ta`W{fV?{I5j4c!Y9RBN%pz|g9k46lk^kt zd{s(D2P*B4v33O7Gp)N~ZbH3uvDop*H)Gw?g(k(qwyrw;@k@tKO@7-<)rQ>~5{Nsn zoRq!bnbL*7tWR18w?q$9Ho}Utjo$NTS(qfTzBR)#CTU*N-%_(c&PMn}{N?=%x#Vl_ z=04^2qP^r)jK2aD+N~$3idw@maqS<&IbKRU8ao%oOES2Y*YMnE33I$F?zi8&!%QPE zj$pgIq3e1r-Uz&*(oy`%b=uhecDEc$lY(EJ$JETXx}B!8%+bm}Lx}{Zc+y!CER88; z&HM`RV3k8DWy$sJuUsr0O}j*Y*_zyevJY(VtH>1~1!4X+wLn(NH@^ST_U6yXRbaS% z$yV@i!dP1}+9gGTF`+YrE0AH;}67O;4 zMbRaP1*cj^0ZXfU(MGqqX12dn=|<`BkA3|I1!#>hr@JeIaZcajZnWg2i0!hzKfeMf z67)NBPdzG}zW)`ss6f{GdmV1A9$D6=#?%dgpU&&+C z@(@=5gkWX<`o!K9;HKC`MW|dcOd^1|7+=|kfq_D{uoWc1&d7_3xgJ%~Q84Vc*4SZ? zLVZEejMl@fHLaAlpDS}j4^SlwAy&VO2)f_l=mwOXszlGynF$^6RZ~JIJ`Rh8oosffKvW3NE zlWC>2OeO_P_dP1J-o^my_MQClS7v5jU%tmzj=4$_w4%L(Kvc3a9*Tp)%I8WMMmZVG zB2gYN<6)ULolb;GTaI-bQtOW4~GFtQDQ6)2FeAki`%qpDf+bemQo3VxQop#QBofX^+ z(P*{_(Xs3)Ibq{S5p`X&e&ItU)I^@hKWGq$Nf;z2JS;I5iQ^XnN){!gLQk}CSAZQs zg2>rYZ^B#o`}zv+Tc1Deo{l=YMYH9i5cCxmylI+`w+}+_ec~`>7OO;=N4DsVi?5hm z0k&gC4|;OB<8uY|>|G6udV-iZRM|g0mhz6Qmdu!kEA!CV_93043Bj>091-Q(3zbgO*Y+93OQdBZj)?F+&@pBd{<_&Mo9u9F0 z$<$$_j;af4J$&y}D=z(VZHdpFv7Hj{M70*`-eEpM<6xe|F50zLg$3t}G5|3^Pg-5( z7YsJ{5SmsKTmp=6@s{;0mJT3fN%dUDL;>9`U$~d!rSV5)~4TNpyS_Kua?- z%d7{lUl>m~)s7vuXk?s#TkF0?L&sPCjG|*vRI<>1giakxr^rqN@{4YHj$zznEqrA3 zVDLl`SB_@QTc1f{7U{2Ibh2Si>@hOhfJ7EX6GXFd^X9#UeagNIh^I%J0&*xqXJ5SMNAK&EOx5dHQNUI1w{ z{2Mcx*1_Q!HQ_7Ppq!4&^Oj^9u2&O3?XCa5+T>xG&~00D%2+jDg~hT$Zi+M}gf0Vf zHw_bYbnPpp%rr8 zs3sQ+hmpl`Z5c{K<<%&0#hvLmC3-^EP>QZ+k@a>jneU^%M2Nl#Q z?v`Iyd<1b?3lfSQOKnL$P0S#ws!>K2#=w=CHb!IkI5iB74H7364|+mds}hTtw)gr| zJ#`EAkT*%I-Jwb;4na??xJw-gj6)dfdBr%ISUyem?PJZ zA4hU(E)VYM6RB|mO|)tFi1*g_nt4VsQ+Q69XH8k5t8?DRS~)N3o5x?!zx}jRX#p#6 z6>GD*m`}Az<-0i=aroaxRTDHc;ymqH8Wn{O#~HZQ zY!CbKPWT+i&&M3{ zk|KXfPaN>>492}VOy%e-d4iK0lB{`Ad?arDTJq)8^ea;0GWFqDt4>J=`cL3j3!5#- z92Ny_P>kNEt>x2SX<|(=K;2_ZUR5jBuJ|Ndetn&);c%YP_6OVp3^!RhA zV+b54^|fPJDE#a$*o=)7=Y!EhK@duPinCjPNG`I7yd@?VBQykpRsgl~g40)No|=zC zBEQW@LRspVi=d)1C+q(SxENd|8_Z{8ozR9r!lv~<$aoj=5l0FaWK;j@213i>mY*>* z&$D$c6V-Me>}nMITJz)_UjYi-PC5pA1qX#o9bv(L<%0SkJ&Hhg zjmKM0c&ao#D8Dj8$`E-ED&qCQoukebRNGXtHzUr=G$VP?5@xAJu9jW){<2F(YzIuW zADM?TRvs_^$+`jvU3}+0@sHSY?~1{3*k1woxyT5)=)973`Z)!<5Y{JuMy_+KSH7>9iK40~eVJb)C7+<`kJc@G-$qO2h7*?^NaF``5iE=OrqGgU~UZU;QA+mQY8 z)stS12JPM07t$!|KBj0ORvCnsz^NyZ8WC97TZAnF@iq!W{t#JVi{1 zj6OfDu#02_%;_Xw=nC*Dx+b?9N39#3yq(tD7vG~CNmH|t;~>m59pl#&f#XrNF0w~0 zl9Vs0%_|#g3M=Zf<(Ds!|PKo2!AmK>JBHSjW9!e%jH0|^^p*oF=`4-LH7sIk6> zSGf>gopA`Voo$~MouiKQZWs02n)Zqce1H+My{OaPUCKcIJPDU1hPUJP?)?cDpUkw1 zpsD}T>`^5B<1}W*pK;u{d{6SN`^lEetWS<>7M?l8F-0)@t=R+a@1f>IPddCi7yI{# zPW+=7T#%C}Wn!;M)T;oAB+rZVZ}|d@6NR+s2#4-YeY#I5wQ?XmY5;im5{HY4I#hXr z?qcbO#W8ewbNFP&cfQ#Gv53i8Ri5b`;MNU$Ag8^@>FM}V+l}5|>V_oFsawX;N2&AY+!fn5)@IS#3d`wglc4}Ff@kQYb1 z4wnwE^$fNCDS0@;4VyFYZ#3hLRC-zCK0%J3l!8|PYDv7>1??p{*mR;_UjbH50ctphb1ibw ze+B6IO)_?EKQDO3nU~z<8LNfcixW^)A!cQ(v6AlbrIU&*rTKiF3+VFAMu(19bu3sc zUfvL`m3nZaClX*mvRxiw+Ei60Y;*CF;CM^D2Tw-*gZ*tDxODccZ>O{#A1hG%mQn}t zv^8ss^T+wFs!0Ffd}~Fnz902ACiK#FD$Vs*HI_T7w%vmPWeHv=WkR%Y8B4-TCZYZ> zFgMvPllaJ>CL9y(@=BY0qjV_CDzSedSVby+UN@x%% zXdFw;Y{rkd04>asMWAEop9m(OgAk0ca7ZiWHSp9N*&JetIw02- zP4LKftjV>&mS4|2n`D}B#B-M#96al3%M}fw}7@DUdzJ;I+u6SfrJRD>ZN(^o1 zCO_x_Qt}nx#T6j2olrI%@mICoOU;p%WFA3x1^5#|Y`A2yAmb2%Kd=3F-m!gdNMy$| z1`A>{^|@d}Y@WAlbY%qN&$Le3_fkNnCIXqoN0dbkuZY zk@7vcOIPKkSL3nYDirvB9B?ewPSzplmnY4rNd)Q{ zawLdz+G!!k;2jZ5?YAvR=^aFdZr=zeg=qYkT$9+2zmVVA+{|nLwQ4rrUkh^aFOX%M zU>8a8)pUgi22G95YEg>4e-f7qZW8wBi51=*byX_dSeR#}os5bjG?koRQ;P-A-YDY8 z&QLA!+$k-$>#`HkzovVm>X+4P3mB?#6luBaTY2r=;D@xz+^4S~R?Pb!HF4AovE6pn zO>R;WY2CJjsp!`EwlAKe3F<9%sn*DBUkDZY1<8)EGYFOC>`937r z(zozZig5>tBCO-@aMNd#mk^v2j#SM+uQ0Akld9C zdzK#IesFrWVVqw57;t?>VMpo=;=-jiwM00@!xzNgoyMYdaRUi_$~c0%oNPHWmg^1N-(`Mz>6RwHzU&BU<1EQ z(WHBkxsDsYq6elq39q3V`&w{F)L8mvXv=@&+m|(}hufDNhsCWO(XrkQE|NeVc=0)>p zZ%n8TE|C&%isf|eyaEuS&J9R5_+L>M)3JwlpJPCU-u`&%_FC7ed_jd~_lmEDq?*oS zR=)-7&Ys;)QMm?rLt~(kH=~n!IWHKl-8h_Er}s1rqHoq`-lGE)*Aa~nBSu5I{;JWd z{B?wFx2PgMM>wy9YJ5Nmb>>;ntrmjd0t>9RP~2u1gelYR5t!-mI7+>t0Rfpcy6C+E zeDDhIYp-$oP8)?@mYf;b$(NW?@$}@+jJp(swOP7W#s*5wZPITFFD=+DPCgu05y@t^ zGM`)glYKKf4_f{$I<3M*64Sg9T!KhR2TsNr4rMW}*6|ugJRTc*(>1$0In;sEQML z(|_a$B2%-KNuG}iw7w>d3^m3)t0HntCzgC$i;^QlVb&}wjJ_&UB~G87T zjKrj@vgGQqeQq63-0W9OsC=AZey6{=ztJU6;d7WLGZl-QW*|fa@g8;sC|zf)vKg3; z4GqHEaGWbool}-?S}e?`&duo}7qR6Fmb0&i>?0f^ZWes<>+A(hnV4f#{v1II+2#X3 zd5WE68mQB&O*S5|VjC6TG{(zgC67{*1ZktbudzVSR5YK^f~~RKG~=`^Kt&R+=9E;f zA?5~Gar5@-z-`%!7@#;*+UF!WeSgy^zF@|xig|mOvXIi=4STVI^zv8XZIz$b|C%U` zh~j~vdKqIyVAgY=aMrr$EB2aB1*tFTuJ02Vu=b?i*p3zFMW>~8#(!Yk6yfs{mhIANW@roZMzT?rR zF6q$m!pK2UT($p2ahWISQ}ek|wYvSN5oykqmP#D` z{^pLB3AgC=usDC{)CUx>Sfpb?cs$pM(#Z*`QM-K@{O3^ZMaOcLQXqzIhCBtK1z)Y~tuoE1%8oqhUQ>&}*j5NRc`lj3ihs+0@5*a7H?Q3w z9rk7O^pcW!OzV;Mm!#Q#-Rsda*{<=W>-#+CnMsXE_Q*j8_!2*rYG;(7b+gqZ97sHF z{pZ`Vo(LEr;lLI0ZLIpzB22b1(TPj=jn8ePwZhKOCm*nrh>)_N3~%AJ#;m#Rvscaa zpeBp<-M>xQ=|X%~}yXvvSFm9`f!y!?m9k*NAPeBVPMNW z4F#;Nx`@{#Y`21iRsK_=Ty3`dNUR)mo3CEa-tdmcvCl$X%d z_I(${^~)}}+TjJo)Q|QR&&(^pua^-5VQ_-7SMz1HYi&l3)&X|KR-Cj|} zp0&Rfszr#812x-nZjLexhU&)rY>L76^UU`lk((1PDzzKx{*KEa`qW*FMG{x~)-)QF z$mW{u@1moA-xRo?o(8*g%QFmK_dNXY`nf;#4_?2-kvYD6GrPvdJj%0(CGMN+`CKHOP7dC#bi%~f z^0EwX2&dMa*d&QWR>#m6IgW?Um%LYipI3lo&vTKw-0@xvxLJZbkq#HdeVf6aes%Oozwc#`fs)b3W_~f_@H;#jb z0BhguwE(}Moc}J~ITZ*GoIbqsx60rexmXXgJ$nFCUhd|urG4kmAQzRNh0~{pMVPm@ zP3)S?jyhyo)Krh}*s{NE{5Ii~joWoQ+`28{iA?I;U41A&73kAVSbVrfO^Ka!7MQf^ zsS^`(Z$`3)1djz*`gdm5WbB=w^;Wt6#g)rcW@)0W*B<0%w3;uYXL#!YQoheXCU%a%K9$yM#OXPk90=V{4I5x;hpXfLEfb^pC5@b2l8 z&IsmKcO12_Ukm4Rxw{hDk%k+yKk|=fhnU}qQO$Qe&2{i8xh<&cI6wSG`u;LbF%6r< zjCUb+;|X<-%~lnZKW}43JMmHymKU!1Q7(#E&KMI6t7#lis;p?YfT4?v+iRL`DoKdr2xh zue@%V*(Pz?zxu%P#nkByic$NHqu5@vCVyUH7}xXEH>5z}&bK6HuvsXdlM6i8!2$!U zb0Ys_YJxqp@B~UAH7!-{qe|c71e>p`Vyxsr(Z6U`?=Ibk=U^)mtVoKa(`WN|CwMXkQTpQsnr~(;}n&` z0@BkjdXjl2Row9lj-rZklJ{K#ADo7vXUr`zSj)M&*}hV1m&zMnmO)ZM5wpxEna>!X z@Z}x58B+^?g(sF&FhZ6~+yapNkP3 z2+k9kT$z9?+yUkZslHt`(HT2GsN7yYeEjddIUMplJpw=;%4L6?-5flJd?Fq#1#c`oh^tbF4jgIp(&Z)Cecgp=Cbxbekje{ss5`heM_qA#SL zJ}06A_Pw-RL9A?xxUS(C*QscI#8+r=Vn!iy)9_C-R?`!IN5pDl+QMOBC~r7-b0Lg& z9rTa@kr_cx56ly4OMixvIChIuU1TC?CpXT3`)R;Q!oFegDkIKXt+_lr^xTKkPEO8d zsqvYKZDOR$mDgLBa#J4u!Wgj5O4VrX#iB_HZh_OoAsgoBNeiu>-B5nzGbG+=KGS)^ zFyc3ErBhGMoiI>sRNcs-XC)z$(1e;QQef3;wb2>RZgqiV!VB!_h>AnKIf(0G5 zQ#-F1E|p_hQ|6xqTp4c5AcM{0 zQwNE;vxYR)d3?~B8SJnfU^;I8yYpm#X`%SfZuOmi{T9V{d0+6uJNKgTkI(p^UmCTq z0B^dzY+_X+^eM9@l1%wyIt`0B)TSRrqcn!;@_==OUCEj0Zk-Tdl6({%^<2YnC3yi> zu&jR{mY22qc~`6plJ}}ev?#+?_)S$C_Vy}E$8z;$zl`5yQx@L#D8UF-=Jy3o#V8EM z{w%tE9PE);`bS=k(Qg5~fY~i1fbzYxomUgvcu5p*3EHaWwrP~EDBMThs1#1-{lSw* zLyDf#mFep&=C( zD47;-*`w>vKdB~Ak?lE{N3S8w!x#IjUpWTy;dX!3!=-ncS~n;rOyM8|5MnG0@>^%$ zAI{AspB#{G;j&S?eWZuUT8Jb^8pfArkKN$4W3ya-m(QUZsxV;gMV^avl(z49 z?#4idZZ>`T>t%t@u_>k6qrBukW8_Il1u;FN;7j#V;>$0IgNqpFpiF#GN|xFFeCrBt zQ(KGY0(AHTzv#GqWRCA%CX&g8Z4+MBIP}1dw_@|86iZz0KZ%MVz)6I1+6wYEBw4mV zjF$ziDJ(d_u^zF!)l{x344XQgFU=q5z2t3q*Su>e*B)CbkWh04ppVh$KVfBBcVe|> zQ0bR>mBv-3OOfmFYrB%24dS;saObma8BU5S?`00sa1_wMY<+T{J2#AXl>!LL@2 zn%fd3Zj5a*-ya?W)@VRIk+VOlUR)&NwBB(rFAeMWr5YsJ=T9PTW)n4SHPa8=!gOTI zAcg!~R+Zx5v}4u)y2dhZ zPM7@^7fEv&YPj9`prp<7e^*n&Pn#%HVeMV@ZFGcPWaaB?g1?ro0GbWrRSS!QouW?+ zo;hAOU${|Gy2f(jYr4aysPOkV&zQf-aU6lzbLLEt5tnOxn;Hk|%xpDF^8tO=T2=yn z{*kb4m0ww_92?vj%bb|Oext0jM1ZEh&R8?I?5SJr>y<;@z270CEzY3`yk~51Ww$%m zZ){)T?8aB~&5YCH=64gt@@*E+gB<^P+A`~@uD9{IUxM%N8~3V})rfYXuv?1Bd|i&L z?J+@Xyz%QX{ngZTsg5jS_l)C>mbZzbn@zc2<)XWnz5T1Iu}cJo4%^u~#liO|!xx{k*?KS3Fh0$!`s504c zm;Q&kob15XsmhWCM*5b>@ofqIM4lwAEVzB5dEWC&&2H~qtq+(_SUc33krWIFFSUE@ zU&SP3SBe(`8g1gr#ws>|iNXH1A`qnIOtU{jB1ki@6-MZB5{1U-%q{v?q=tq4s-J$% z5HKV4n=rgcrcC}tMzs?Z$UeKuA9MvEGWc+x-WVbydYZIXfSjTBNtNEqh&Sy7hloo@ z@9TJbKkp1 zCGAk$Sv-vXfT~T{Hq{y{SZVls(bzlvPjRy>PQ4|qU9)KOST^SNMBsX_x+s$W4(Jj! ziS+z-%C&wbA1dEK3L#Q-#>q+UxPF85hSNyD&f&FRotxb<`M~ZUxoG|IlVHA9%4?dO zQFGeV=r-;+SV<-QM5jX3DV&2(q;&N73ShR5Ht)?ZDyS+vhK?uLElXJHph9-IE)COP zh$K4fd~4kT-W{1ad!l}4ze8)*XiHdr+_YIQq;$G6{pq{^Hi4kc5Pp=Z?U;zmW`-f+ zjGR~Ew0{-#@+i_IB~Ud#rYXPu@V*8hAcCGuc@>ea0GGXr& zb5JRP-%uIO;uUWGEJea9vzlmEbdXSr*@>wXB>L}5kvo1$sOMLT6urm@OD`oBI|RMu`#Qo zqvEw^H&Q`>l}Sx$GQO_~&L!u){}Dx})!MV58w6%`_yZ0#)EUr<5ab;r6qu}k^oq}2 zS0YQa=;D0R5d!41<>zz+X7)W}j{>Is(L36^bVCwzZ|x!iU8!RKwW3$APJEeq^Y5z> z-g{=#N0PJ-hJ8Mv53HJA17(}48FWHO*){&I{TqTpWvN~z3$uvZTFylmH<#KtW2gwj z#;FzNCRhXC9-}xDbW#_{EWzq;D#$z0B^99wZiQ3%6^3Z=4_Pgesky8`e|MM9f?P+o**1pUJs<@E6^Mq>#k$<*fS;TW1h>USBR9@1rTR6r2ORHFO!%v2z(OqNRt>~H0aZNgSXUZKmUX!JjvuiDeLJ8^#LC&ihygis%vUs@ndsB(~I zPAK>*-)+0`8-6gD3DqXtkP_~EIAAG8?{(+;GuDNVQkOoJ;O$K5IyTS(YghZR+JgE-&rcV^xg%tqpsFj^rrW6wlR%N_7?|O&o51>H?ALRKB9b ze37II;by(gJY|pj##^hj!=3M*ct#iO8=jMyL;HrPh{H46|KW}R14?&%<=<=nams3e zE3!V{L@oIb#k5LYL z3QmUy`?*5U%J)2|YN10qP7$)VMO zu-A?DM{F`%JYD#r-MK&KmXV!^7S$~KIj_Z!*rr|ccs$=BnZmOx)$7eBO&;T3?e|}> zvjt@s#>15~FkgO06$rezUd9ix)j)szFpvU_lhELaQw%sM3%ykv?TGQ0U>odzA6T(tyYx{1V z^|^BR49>dAA3VW|y(8s|tzQ8we|UZ7=*i$_PQb*k4-n}KZ`(aiL2R$aqksth8-?H; zL=0L7NtHjv#Lo#E1tC=cKmmPoGNI*X|Dz=K6T5GFI&ZoA!-7$;va?~)g7ER?LlE=8r=HZj=fpIZNa2OKgE{^0koR$Ap ziQ3Noy&XeDJ|8{O^VkB8R=E2ms_ucCqp=nrHjj47{|(7Wu9=OU+;uXu4@g?%am;%c zcO%tFdv5<#@~tdgf=-(&+On>}^Uw+Yc}ZlMpYqOloPl@f zuIc3BhEVOLJ6F^4NTNx;7-6jtH>Y=fZN{Gt+IGBl$@5dLq|i0=`fRrw-u7YrexJhQ zbjcRio!L3lp0bHmJ&0@e;z7n#YR1&mas8k5?<)tLcwxMtwY1;go!cE}^AoFg->zUh zT+bzr7i{!p|4aI}p1*=-Gl!qL1dY^D`BGeMW>~8W>uc=O9axngc^lPks=nD!D%nz0QY7IC2Re@65*wj z84tdxXfo5jCI^;)?lP&O*tpcfSgfseT;)BJS?Gbrmg@}0)Y$QS8Z^>($$kEis1{S% z-4Ht*6@+9jsDFA4_xIaV@mkWd^@j#Ixoo}_x%Y?7EQ8hQ)^m|ZITyFOFMoQlbixdK zv$UvIRdnE__?$Ofw9ztRAljQTMIXBz4G{0U)*#(D85I|VWelOtJ1AdYL8IKnL6`Og zT_i%?AKk8SChbut3^IfZwG1n`w~&D|)2=b_4*Sgfnc8>meNJ+ZRSV*6F44(Mrhnx_ z1XPo8a|_l=l{EFu*2ykgOuOIED)py&<-;vw6S_3a3JS9c)iL>;yui8%xuBiGrj`$# zx|X`ALcn2&doWgu4)arUc+TyoDi8?gF+g)YexUG-dN`)OF!e{f4Gz)l-mM4uLc zlDtNViM&Q>Cko)5qQN(&MI+TZ{%V8K@MR)jY9H?n?d6v@^A=)_G;U_a0_dOpd#_WH z&3aLbvmkC~y!-g}ryKfcJ)!BtUraBxnQJY?UkL*%a&v7di-if@c-4otw@%^EeCsbBb*ZmaoWZpTznK#GvPO zc`VGFPj*Y30Q*n1UQN`7^wsXz=(mj>QAbGbJYY*KK34cAXq1l_G}R#0tzzv)-zyt3 z8raRF-J}J6CQP2@|2GW!4>?J>H%m^hbb6!6GD0%Qd-=JI&EVF(WHKVnmnN4Rdpzx2 zwW;hruM>!H$=IA5`wbpnr*#iV(TR^YO;I_c{;@P6CQ#R2U*8-{F%cS6N}|&9=+Pay zLxM}ZB{*TT_>;AXn5c}bJ88JRsD(FGbra`I6`PM|zb906Hp~tq0}LtjLsX)2-+32! zlDw|~>Xl^GOZ(6Ezq1C{$cbkR_n`=Bjw}YapuPg+Apjl=q)MDx%q1%3V3F3inZU1sHvqHrX)E>`xT_`WlhM43JYv8vcS$K3&+c@Osl#Jhn% zWu&s5GNU{TS;lPBhPo~z1WTK!3t4qw7rosDAH6?3B6xO%WX!=umn-jSaBZj5W$VY-X*{G! ztyb({;ai~{^J=5@e(I{CDJb00TaW>S#T}LH!GlO7lq=Y*C?SAtCAn|0v>2X3Yb zDpHzTw9!M=sVi&o(Ogk%R@1JjzL>Z~v)W9VbZ4W);_|sQ!=1y65L`IY>E;nKTE&%* znJxxG?j?$6^O4EfO4rZj-_-QX=r9PnqF5D&!o9N{J`d(_#|?NN=81tGl%s|$fDAfk zaFmj!grBJTq|n4F&~KHMuhRZ76fM)St`yEJ{oUBu>sPZOiW1h;QMWf*Rw!I*TJ&Tb zqo1{Jlu#7tns)`j=Iq5F@yzeKRGEpnzTB)NtC#zvgO}N||7-<3;?hpT4T_71zG-!p z72BlxWY4E~F!F3!^*3SpGRlTM0vAyjaZvm3JyE>cIj=>*dlhqgoH#>|vePH0pL@}X zf!_EX2Ge&oT67stf@&v75pPbsZEg=Gq#)++(JwViIZ!R;>%}Kg%6+$6XY)y<(Nnr4 zTFWl%upI~c;#MYuLl^gIkz8+={VsNy2cfGRFVfbGp`*EvKc6yLR-_>{t>&w`XU-~0 zsC<$nlAq#sN+IhYX8nDxz3zOzZ#05ap7m`zeK*=2G->2(YAj+63ON`>zozZ)yPmLR zMayIU66M_X{8>X}_loo&t9n5ei&{qrw`JK%e+Xx6Z6$2HpgJCG0_{oWv$8moU)_Jq zxu^x@3rP93n)mB#^^v2Uj_S%ZuZLcf{M=;y?r(JP*I{zPzDnMAR|V!gTRcrJG{@++ zZKx!NFHCiv_?V(E8Akx9v!~WdJFR%3i=tJ@&HWJkQYK1(gvs)6wTo@wB&G!&#NNS|nrT_NYCZTJ@Qs zr;c#xKB8pDo(pkK@V(sDz|FXRcEQGM%RJ+pzD8BOn&D3l=SR!jOm7+^n7foN-=HT4 z_QfRFC(%_@M6>nsRrE+pM(0L=mU+VuQYEN zO-Aw!;K%V61;VOS!*9kCs*F7vqJoNB3+jsWevitn`Ir_^)VcBn@sV_wXNpXJv5nx7 z?<-&LYn$qZ*ia1kRxLltzBzmQ;5wJ+=HoU+l4U|JbR1tMixl#$iyQFG<>P&ulYqwi zY{J6*Lww4{)}Z^o;vlMA@dAim>y6^HhTSb(nZjBT)mUEZU*qOqfzhE1p125h5~ab^ zCDXa#Xn8TQH_Cl!a~jnP9Vgf6jIWQK=gv=kt;_c8Y5RYV#7dMR#SU4Xp!Ua@EHPw0WxfJD z0RsNZa2@Gp{!Od-iLlZhb?(?7${K2WXL*Q@P4NnVvxN~D;mO#n8^ezDjVbg@bgkYj z@h`_;UF!*J$Ms%NwaJqoA$f+s0<1%yQO;d*MEpdPxo*ir$;*KBYcnM4Gu+0gDla3U zJz-Moqu8sC^Pn$JbhyvOB(J?oc}((UiR$VRlvaLKBAfc?KGekdnN+Coa+u(EGO3c8 z(8`V2I(>V|Ia&0rJsv{jjINo5f0DumA)oUXM60MB3+>g;$Z@I?en`^%Tuc_4V=)^# z4?M&mv{XA+IfP9N4KVPv#wMg`mS(*~1y_m+*4SBDbth<#+DC*zz6HZ_eIl;9F9gvQDm}>AGXpWtmuCk3QIo4W*0cO+V^Gd}D|6a6v zd5E56@j2!n30gw}WAMUZMmPgebiQ|K zBz8=Lt8&?rdO_Nr8~dB_$@2);5}2s^gkxPEQ(=~yf1dOwlMxvy)^-<*NWw@x9rG|1ZG) z&hh_rwEyeYY&KChq;A+62^kl=*n?^{9x04iqKq{IeHBxvMg&t}PRz9f>o2HNz|~Ce zv|HoDRG!?N0k(gC@R-6=I7O>^8Ji z;%q9NA7GlZ*gCo2_3j4VhJf751~>?vMY*SMw+__K-;C!3>wHYb{wjxm>ECIH_9dNv ztPZXUic?M1X%i`gMp)>(64DUNM{W%0u>9S*JUS|=58%u}9;dk$|S_$~HMVy1`x^1l$o z0MGhRzN6wn!j8s2H-rSK%(}#8*AzRE#L9vC+E9OIn+5`ZeUg*i-zADsUb5)}H|#IX z#>M4X@fHcsruYQPjDdrev!g~*sMT%R;po?S^8Ahj)x))AhZz+fit;POkez4Ih>KW^ z=yMh~05bsSgOo&408iQjbT)uA5c_vxmvv$N=f)3j%r!PIBJaFHj`x3yYa5Cz3Ji`N z4}wVGAr~(v(Kb_ZT&tS*c4%`SH#8@Cmctj|!M%IDBbL;UZr^QY`T1e{l3` zOCJ}9ig%12EZL~@4^o$M_vAhUg_SyiD27Gi&azDF&Qi_H`*^Nm74z_K>MLwA8nvA! zF?}=fk4<57kK*$CQ#OkGctB=r3y)KOx2qGKR`m$_X(zD07c*j$ui7Z8jekE<>keit z(t7z;)%~Fx^@aK^^{AV{2CgTrwQ`cR<$@=JGHU4E97B0Fa~^gy(UHAvcD4odspBy6 z!P-6__CifNSO+Vyh4wC1_ti>qYU#xnu3Zt|uX96|wpRqBWF&IR=7{c2Rz1OcEm8S3 zH6e$*u?4N4Yn1u)KQY(|y@3uiW>{fJQF9zgY!Oh4Tw-zZx^J$D5LD)RT_q@J zE~Yr4(*p*+CMft(&gp$Ud$(~_$ig#>RInIrPDi@{luM4JG*#h_3_k?M*cbx}or1tB=} z`oVsb`IB*c;y_hXlT3SB0@a10?$D%b4_V7@O-_Z_!T96fPGs2;H4>8-FxhPa<+duh!6ah!Oun){f5*TcOsFr?>Fx^K$k-o4P4$8taARDHxuwXqvhIZDtzRGB$+&+a-LooK zIPWYpUo>c*lV8P(h0?`%{UFaZu@5FQn)T*oSd`OV2?W45DP5$g$zlN%mr+8M@c-?gF=q_*e=0Gi3~-DbYi5 zt2lb%$ol0{PC2}2%lVnc>Jm5FRYhJO3Oyf}mA$u`z}@L?7#73v8u46nfZ0CjYuC4u z4|gx*?-i*CK{S*=Jj3qAoZpfm(5%!=UVb}3?e=kZsvp@%|2;op5co*lyw8YZEm{3* zfBtRGNoZ z5_Ko!NUYx)_G(3Zi>>Ifv%NanWv1BR&+Xl`)yGt3h*QV#ZNC%7s8C0}EfrnKL3C z_24xb;-qOjx@ml+3RrD-6c>q%VVr`2ez>0#YWJ5`u}+#HS_YcU!Jr@)Qc(K$J@yAG z_t--2$%RnfVo5u{#YI{buI3T1=EcS^QB1Yp1^ zi7TWx@B>y{^7rm`xC>Dd{bmT8<81srI`}w*c+ooaW_%wm1k?U1jqxYB{<8`;${~6V zZgc`FDh?$*>0YYOvIo)~L-TtcO%7FlPxwZpzu|X75wJMGQZQa4F3NXbG`ZMoE-P<` zmsHX&`WgDUVIh!5smwbDCn;HB*~|qCCh-X*vVHA)9oW5VfK2OC1#|~Ma{+$E#NL&E z$p5x@I{ve;25@+8_e|`MQ`Vu=M(YpLgX?@Bo&8M*#~Z!L52%V~AMK&9Vp@+@_!D*i z0T#ETo5pQ`1XZPkZ5MY>#-+_e=r$mIf3_|}H-+RZyT0T)#Px|>v-b)6PFn!^)1GyJ zFlRn`BOwyTt6Qp6adYmEP01&S>dO2RUdlcj_Z4**p`~ zJ_N7yMFCT|YRS$&H)cgf#Eeyc@-sMn`up@h1u@EZ#FrP`mtf);ITg{`fEb91{cso? z=+mRmQ=)8JpJdiuWNL5BXS~#MI|uWoK1nXq@khgpX*~DS_zji>Rz57A+J@4GhQn(_ z&myh&i-MuY5LeBqOW?S1-k>>KAb%^@!3gVTn=f@z9TL4ZpJP7rnaL$a2t&d=$Q5KN zZqj`~e%{n`H?65>BasoU)Yq-9#pq%V2gstZdZ`YIUtq(ED9AkC0^pK>8Q|w0zVb?8 zdGvpQNq)WYa?rA^B?V$6s#A{6?^U}z!D(=grP2;oW?y3lE;oC@ap;g4Cn-^%i7>|U z%@|jyo7s}7BrnZqg-DwU-IZO3OPZg3YXX=_CM`v=Pv#Y+WkemwZzqAWJ)l%*TZ&%Y zpQ%)l%6Ft4eBAPCp614Tc-D(4Pr=A`N)5HeN3xX+moL(XPsV?bK*!PdCSDO8m}?xG zd%n2&A|1gl62DAP)vb*tCO=R$jlyP~V!|JM<8OE`DgJZg(_Z9Nv?7J#u_;{t|2Un% zKWwraz7nYB08E=g!D!FF4n`6bZE|?Ka|PQ7ce3zoxHd^Wuhz*wErI-%Ygt;!D+5L9 zPGXtyb>7uWdCTGU&TRE90%P-acciS(cPVKNy53rb7r(%RpytCgW)`+>sX8ax*?Q8_ z7ZS;f(#k48@y*Cu^#adJI>126W!pI@xk9R`CDsK^Yg`y9K?-!`zd2osXs4v5#IBp= zVU}lSI$0^bVl^KcFT!Mc8tj-u=2mqxM|RU|hR9EjG+=fxyT8CJ46}bVHMZDCQIM&0 z$GX}wD<=$ck5F=JBb1yxRFd=Ll2hLyc>3L&A&Ry_&E5_h5T^XkTUJ}vW_U*wsO55rYe1}<5_9o?p@1R8Pn#rZ`%(YjfVzlfpW3o zh_S_PAD8^^85VPl9G!^7@bzAWK;x&g>NB5eCr~k0W=q4Fc;kRjrei$0IN4QUiC*UP z&d{*XysDq`sgrw)$p*ok+fE#sKzH{;7wQDb_%o*ZG{v+gP0h2NWzKxig@JTkYm%*TaFeu&Dwj`iPPZG13P0~YL=dBs6w{|nxwSp#=%!U1 z9u8Xi1?EvJK=n7-NOSI=p6({mj1qdIoxgdjTdtgy33UB{4oMpSj`Ve*P70Cx*{~fi zOpyk*3@5ZcW$n)cFE}DPjU?`fgOmzIqwV!vLzBZzC8+oZ+sZ(7}QnwcLs!UqZVdJqz7Y!8*Q9rJ5Rf$VE7WztAsm2mLOm0ielkkRUwSeVrQMa4`t8WCLmxNT zkKD*R@dgQ}ie=jwXKzm=`@}cd>4>;PwmI=xHNivZ;L6CODy`eU>`6e~VB04uA0C0_ z?#m>59Ddwern$u7JEC%D@kC9IqP8$&WcKRzq~^SuTy3sJWRA3gu~za4{Hz|S<5nE% z7SBBm2=cw{vhb$k$ix*0b2&|TsIF9`I6`0K9Q$omrve&QtmdQ=E-h%2sp|wmzn&Uc zuvVf^i}@qZt3fNAkpeUQapzFz6>Mezdc6Jv7j^T~*Sw9nsWwE-IGKy0}bA+NEu3b<)k`_qfNx9N!}P5q+9uV6Y^IG=Kx;sS1b!wgK^(G>hQF zJr4*~w#X?1&~IiWugqg3E?Ji!i6Wi#q_$?YQ@^dOA*}&H$y!w9joLZkEC6>L@GYx3 zG5?z5AGmKuSvIL9KbIPoPw)?2YJVBm$jh~w-9njR_o#ae72e&;@bck@T$Xf!9A&j~ z2B@AJ{d-;cctbtsaz(rS{v3uywQS>}zRpFH&4w+Nr&=!tTs?+mgJ{k+n7-d9$5?S& zS$`&QfGvONR5E(G`RW!!bWw~kG|y`6o1iK2C>rht+HshNrjx?hMc!HR%x@L0|K{xc zi=O~g3Kt9DW>wDvvP!icE~YN~J%yaryl`Pi{C6Ygr$nvI+VS($z>H z7OhmJRXGO&nZ&Cc8yn*-^fQxxuEucbPPUf)}lyFVAJ&e{BA!0>-v@U8yR zBk=QmDG5EAi+i$X3c>dZ0V&N7jbNhzd7zZ+&q*f--XFxWu|In9p!38QzNXc;7KIo7 zwCXOL=yG9_Wh~hG%P- z2JzCEn@)l7CHnBp#u79~n~{NYU5P|y@&2N?$I_+S!T$H4n+Gac3P@yu1=aCB>E%nI zny@4aS$|dKDn7; zx!t4}Z`gxqtz>)BT;UTE@Qa-xW8FokY80A{xBuUo2 z+>CmdWbz}2K^LZPc5rYH!S8lbJ5q7We?|A=i>-x6^N*X}S|{81CfrG5q}g6ayDsO7 zpEF!n=H}pX?&{41u@F1O<~`wi0d@!HCIj;=E%Ksj6RUw#cvClUF^n;%J2$NmiJf0cP|krVpyS0XU7yf{PtJF;wQv5L7G36vt>Itp9PzbpCwbWrWgGN{Kg znJAK<3D&$8Z>d|Px#4L}Mu60o5if8Xd2$EF4iDj{T?Rs1e#$u&iQjs?SkSOrJ|l$= zqw~g#JFzgHS|`UV0rZzWT3P>cB{=^1R~Aj+sP$g{kNy6GJWSPrk6)~zF4LZ~wxJpZ ziz=}H{WN(=Do#|D&!15m@y-Cu2KuogviHP#+y0`im?My@*!S+y1$T<{V)=Q&PE>4jggm-!KfcvdoaxTPMF-<=CR-Nw1ESD@&-S>+kL{m|4qAum z)HR1Q8ra0qvVX7&M0C!bUIxvNtn6uDYx^KyNR;AYqx04hOcq7_5oPvTB$RXFOl_R2 zSnjHQ4YsaodOSMyW-Vd!BU(M)xd$e1(3v3-zcLc}Y-vODF;P|x_W55&bXEN$3O2Wt zRyJF(^Ud(S324h3B|vofx%l!K05NJ_ zGj~L?UQTJ<^+5zk5yVeFw!SR<*@sh~zgT95-{$9kfBgi0XU8O3C6>S_9`f{VbOD7M z+h7RU`?FK}Po2!ME-K@B$_sVT}#FD3K z?4+P!CA!%TT_pV;*{PQFu;*bDqYV+A5d=Djb__jK4IJk+9-)!fZ<|+NxXI}0$7Bwn?S)w-aj{P z0ba_$zh3x|-VN4+53r7-e{QVgT}lVvS3E2EdVi#w<>vJAE28_ii_Q<2m4U5=4y;RL zb+I*ptT#E7sw0NRR->j!r0ZSWYxc0lOa|>6QX~KKnHlY<8R-;^%oQcBt^^9Mo1KEO;cqgX+P{1yR-^rS&8+b1fuIZXi9K=IA=2qX4YdjI zWX0ErVW%SK37XoEeeH^-?yNp(Ec`2hMpuS?Q}CcLt=$P3l%eR=VedlZpu_BkFOw;7 zUQe@DQTF8Bg6DmwWub1LacLzZh<4AJ%|v*%1hN>4KUSe&!@EuXXYzU; zaydZBSV_T9@~AX2O-eU8=k+je>Zy=ntM_Yyc+Hk2Qoo#zj{F^HINO&R#SpYp&fs1Q zlO4c8##IlGErIa59zi0uNFjc;GNc*0yzP^jkXHf5?b8oAKKecEUvx{~JHuGN^2Q-& z0ykI6h1CwvWmARIqR#7l%^kjp6P~r%4Ws){4`#Mm`OFQnRz%81B8uE7BS$M=(q*h3 z5am>-tC?S<5g?C;)43@1>t%0k9Za%vypgzHEf z%~+3CF+`88kDUKK^)8Ns(M!5IQBNjm`^^>A!R8(X0+#9hr9=a{O?zUDjFSm(J+Yt) zqO)K#Uc?IU6})OA*v5NB?-fL-g7?ZdJ}zJhkHQnrtg(5o_8&C*hz`~G{k%-tkd{z< zn6_GTX-a5h_973u(^~Zo{)trM zL?uMrQYRCspISVbD9_VlK2DWtcbB%qyKLPlL-@}>H)7l60u%`-j36bPt4o1r+?t?q z8r4p{4MUp2J33E%@BpAGBB48bDZeLZ(H%`=iULu z9V}cPWTHe-QSb(?K`H--p`BK|fzGY2lW9C-KZrqcyP)t4Mh~eoyk6l;M_55NCi4bc9)iSSFIERPey}7ULHc(YSmL_^^P8 z*(!%^-Hh&DzG#@ElIKQhzEnR|?3{M8TeA1`kVImnoMC|30S3=^G9xqDaGEKBa40q& zVU2o1xE+yi#~pL{Qvq4Hyu%oH-qv!JaPg!0v$AW3ehvL*#OsN(*k~y`iVQ2l*{g#; z`AXWEm|^PTE=>v}NtFU-t8yu>{<$$d6vyZ_|LT46P8<5mi6^;_;^p}Ab)?i%x1cDl z5Ug^mxUqZOvo@sIneD25$)6I{cY(l=4AVDf8}l6U(F{ECLuO05u7!-9#a{ei@BJI* z`?3@G$jPglPbxQe%^3?RsVvBhjFF_tD1qS-u;A}uiBt>2x{=3I;EtgY*?GPy? zhTU5?zV*ZK_AeiY!%ce(efv|>AJNCq&v|%RJ7}lzIa878h=w6_Ol$HP+^4f`)`WIM zdq1qHA!@I7{iQa!rb1^H}e%lbtba_za4ei-`k3j7J))Ge)AgGeaWl<&l( z3(%je#_LYa>mD&WOr?P(%T1l+JZft6(QSFSiZ32`P0C9x7+L%y+R!dWr@FopViv}a zsjLS6&yDX5q)IU3`rN&{8Dxp*TNhHFd!5J0qQ6C7^6AsUjf#eP)WD7Xl2ZcPyT^0; zlh@I>`$FH{BJNZO-hKHnyfh+5#;{C+Eg6!dmgF9b(s|?vys`R}5aB%F9`Ho02C&Nf z=W$U1{q^$t0fo9Zcc9y!&m!sE;>Kj5b|Q!wFQBr zrRoRGam&WvuWbphJd{=*u<&TJ$JZppeE;zOdqA-ZT#WpZE;_SPdV=IWr4X2K zTXAL0T$nVi6jthc?_4cC*kA9lgRFeDY3<*9U_QyfSx`IB-Pst?I(Xu3A)uUrm&7>G zzCOJpobt~N60Icano`L$_V;QPCLc}V3-?)B)qmot&vcu<;w0%vW-C0=VFf7;9$gNc zyJ$s40uu&cl+@WGUUcgokyzSWDYS%CX4p!_(FEL=*Dj8XkVzBUc?)#w=<*sM)GyR; zCLq-4V-`}aLCGn=thGwF*IRf!%px3$DPGBu?a6y6)*>tKI6Vo^QfocXsLOB#3#0`G z77>H?p?SIz4cr-`Ti(#QmNIpUo@(2X&|^7@6}$6It|+YAWAY9jJuV26R5$I-PEFxV zT{x+iwCiZ$$}S<{hkX2f&PXzAo*}E9Uak;4NQ_G#WE8|w zIc<|Zj11t-=E%}TXlQ4*E#%gmW~^=Y?9TL~z} z>Nkl{XN~UeqA#`VNo{xC?Gk!suDTq)4w6ue)M(3*7y|nIDc!+ybD*!a?MC6)9!~1o)RMKp#qySBAIB0;(B-gW~OK2m^bpoLx zRtz+vT3{o85t)_!Qck?s3!6+@%>Ovql%-Xmr?*>xrko()L`pQBxn_n(dpW82XZZ^< z!KodlN!ifjb#;xS?QFgT2S(*@FOb_pZ{CLW-N|x*k=4B(VgTK{q(0UZ_^)}F|GF$$ zjUSGm&}0t7QIR+9M1LgfU9@5D`R=7kItqbI|p1E9M``-GA@mIp4G^&Lmr| za6UC?AYo8{IJY?e;|8bn-sbC#@b6DjlW3}5^ok#;o-cUi0shec|ENuVVUBMZocDV( zBnQ}gD4=-Oc+X!Ij zYXc_ec1!UJr5QGj#*Kr{Y(Fg>^s&@Fn5j@@qyP37#)NYmu#q=xcVwLKOr4OeoUoJ&(Q9>R- zi%=%_cgEEU*y#3X_L*Y&^W!kqLd2p8*w4wh1>bU+PgA-m`rb@6XyN+pL7+o?eDg;h z#r+_*07bS>0Zurjd;9;~pqeMWuFw$6bSSLIoDw^6I8ii|%6v=x{}S4X{z?%~hGm?I z@S^u}x~ttZA%0KFB-ZYxpNpzJS2U*6%ZW`T!o=kBdPA0Dw3X|PlDPG|LwE2qdS?pp zzVc)!9nS(3VAq-%EZf$@lszXjOBAXmf*m@TcRKD}3lT*aoW+bTU#<*sPGEifBoN~5 zN%+Sk0d6>T=|6kW=jqbl(zoZejGnYzSgSfTAMJXlkDIEp%ZqjodoD2Rq>K#(3+iU5 z{LxsNZmwz1nG$78(oHhEXb0z4JHVP)tRm#^Na5DpeCFd z=cZ0DRer?vct8IJg?=~NOJCu$XZ7`MbwXb_Kb5I_z`W!K`%l3wS8C@>fzPDucn*4H zae@!wDSsvD99);V8A;e=Sp{bHxc+uAZnIzitb0|+#hTb(D}_g>lBtLb(}-MR1iIb| z)gm*d*De(kr0i%+BrvP)gZyt^4t~R#r_nE`P$>yR%If1~yo%kWA^I`Jkb)fznQDMm zCkar*E0V$4G)7w?C-MH){G;{iCXvk&Csh5;mguIORJH|^A#v<;le%=mJb$b9>rSa_ zwsSSNhQEo?`02nN7S?e9QkHIK6@>3JMchxfV0Ly3#gyIW75Z-ZR9YVy+Jme5$@dBw zA5QKS;7MqV(;#&(sXT4v|1c;rm_->fhy+g~K_6TitPTo@eOX+S!fQy)}*5G%hg4}~<-GOn-pFTz~>?f%}$RBn~b za6B@WKolFjC>*RT(PSo=Qwpa#tNe501w17rK&JQLPH_5x-JP{FPr@0+8*gZ~#+9{1 zDfG5lu1AIr;>(6eX*{M^s5}f2R#al$1e(BdL^;a+xVjMTYxHY>nTUCJra*cB*9wOP zSzK^ycfYPRvn`7d7SCJ?HH;n$XYepsPj&SFJ)=4}bsfn1Ay=8;-}S3>OVy-4);s?j zPrB0A^elDutb!-5LH)1W$a^1R9*=4nYg>@?`ht4bD}@nc_`|KHq0*&7(!H5jlc4pE zG9JZ<2W835b{i~Q2fH3}IU7VjpI)1XULYydkbyu8{ImGCV11Wgjym4q+*Z`kG^Nws z#Z^N*db*XZ*zA_Nvdq$_n&1&yOO{e6CaM9xa+t^MI>+(X6BcTB9+sZ@M>YB|W!Xww z^;eB!twl)>1{P(49m~-9`Yw*1`L_*z(Z?i+73m-uCR5*LXAmUm4ic>MY|lVH4xrr| z3>BQ|P>@)9O{Kgmx}+l_?Ve7&OSx4^qc%nhL7IkQbW6=hyYwaOCwL}CeKIrJIn_Vs znc!a^^PFIm$o?cs@3PwTF?4=$X~@g@NW&eo=Y3#m@{+u|m-&8hWq{bqF5S&F7)iv5 zm*^WP3M$j948HQ9($JVd-S;f0`uuvTSe@j)p#uoLes3D9?{YF{PP2YV5rVOy|2*Dn zEewC7AjtYfNi?)Ht}fp=ow0VksH)Mp#0@jyR=BRFRcannYK%x#AS3n)wE57+mpW9N z>=@j`kDm_!9R?_;rE(ob;yAJ08lk2WKPObp*MQw4U*;>5=v3i{&3@ zy8{uc;bGNMe&adx;(I*07OinM0=hVt@txzPQ+o{S3mvWr@6_}PY4Ucw4wfN9gr%Y z=H>u5^iS6V+M{i&V$8sq<0N*xq7uJ5rgWHpcPhX8KYX?AMG zQuAWl@BM2RC>!2j_xOS-KsUNKuEWM9?0kJ8p0T~0HLQ-393K8PW^QMkJ~2j4*b->e zf5u%=AZ!%u5SY%>npLOQT#HUuR29Gv3-xE71DC-3d0XkI(=&s`{a$BiIR4i{Im?P^ zy~-0c9d+vQ&{Tu(+6dzCFlBEq4(>lb>nU#SS#wts?=OKuf{=)RZgeXAbK{+2Bp{$F z2nUUtlLMf{H7h(riB@JP;tPTZ5HDDBrZ&Re=u72%qVqj*6G6J|>nBsonr+iwl?@B= ziY626=*H%>ubGcU?s;wjxa`3Nc35;6kfMLolB-yJ9_yJbXFUG()&W;7j8KYTW6<|R zhUC&wGA1FFyGY@VNdRz$-;vb5@O5@dsEk2G7K6OlwENU_LgFT^88qrva7;x#{RCM5 zdESs-um-C>5CpdX_$R4@N&tTX_>T!XjM~4qbrD2Q1}5!Vukz(AT%Pqr7Z?)tyJivh zD-QZ_@mzX>!gg=RW8)#7`terUq)IL1F^Axb;M*@}U9U+CI5=d|-1M^AvhA4ljKQ4+ znKekd7Doezxjx^N~pwPEM>-{k*GoYtA~afbHytt~N9|2JBGNpnRU^dEMFU-$!8UKL48Z z$~)*@hNgX#?BX%Mze*#RrhUsW1Ds^a0#3V!GwuMI!)p?h({X2JI~!wV$T1MToG!ER z(jhzwJ)gGh>AgO1isqQh={Vp4H1Yatu3e4)Cx>0Rner0=!~RP|Pwd}G=wJfqR{Nm1 z>wQppo%f#mX3khoHD|tyOTKEbTk%3;%-oDd1T3o*wH_us_dOZx4k0-VbAR`@+9y!H zbmx&0M6lT#kVnkl5Nd~6`lK>$$~7qTANW>~`ULedsEEsFXEvbop=yneeF4Cm0cp%? zYyY!`FcMSd^kkv~ou@rsuEmiXk0&!>rP}g-MO6=bOo{cLD@?KRVysK*_J!HeENE$Z z-SS|UG!P!(s`2S~h+ZaL3{WDh`OSoky#s6m?!`cyncu~WwzkIW`F5ki$!F6}mu3ji zo7vCCTbUA(w;oj+(#k3)OaW^CuI8QP%Q?IF;2Q7CiO$u>H}&dzzYMxL%$Pq)?6H_r zw3~lsw%|w`#4_ykuC6|Bq$%e6U&)sWgpgkL6F<>k^`mTkUcNY!A;s ztj%gd(~Vvvs?s(@C5l0h{4M&1;(x)bSfXjJrqfnB{&q|k7+c!zcqr!(Z1?PH>v!3o zya+nl->s})Y~tx%eIHYJu2j>wejelmg=|ztU`Mgq@mU+CDrF$3zH!SikCEd!i{is~ zjSzO+?m3~Rb`vt>hjNCHO-+*ep}QGl^Us9RJn=>Rn&*Eh zk{o*bY4nGn;fUGvOyR!vK*9(vLmg%=Ud+k!Wy=EqB<%Cp^-2x68YB3;GvmUsBtGEF2wki$)HxJub3L3Zte+!((H((^ z&WC(Um2cT7*a`Mo%eKx~t@>=ZA-?t2L$Fi}{!<)eC|G_W#b+?ZJC&L-l@{b;c^o}a zvDMh`ssq&~vgx2Z#@CzCEfc@XkC`;K1#*0-jLZslnjUC89>-4q#uh2KSB&~ROz23! z7vqI0&@!JLOR1E>a^lLnpo>=(#eMo~C+^PuM{0eGc_w?*#m%YZ#sp{PltjMeSEwKp zN#y>!pf5o~d3XL$MzsG`L)ga-DZZ#9^wb%cHBYuG)232}{K0J~Bo%BoryWL&oAJH! zODMC>Wf(@vRhhPiLO#x1HV|sN$&V666QD%Zj`FnAa zL#ypT>pY6^&G^@vlo|%%$k@{0F)3?yRA?u(cSD!Eb>P924`>v{^|3I^lY2Bf#WOR! zL~lJgrIfR9ZM!hg?4Sc*+2ule`J&+7`kW^zSk;BE`V`PKN$_`cBId@v5<7 z6010{H-FjwMpGs|qrGMNlJr{QLEPyRJb4FquB8DlcC4$fE5~ts4GMfK4dTY6!A1xM zS?Ff5icnl3f=9)fmTtIef% znqQ*j>vFf#!Or2h7kY|~AW=8Q-W(t*Qlp79`)R0N^lL64kAFJvTUM+G3(5vHLb=VV z?1TMT32ZM2_7gAnIA@l6!Pu&wpQm$guYK|4datLaR1T^mqyin{^lvI3k{IX83Zc{= zGBz?2`^Du1#J;b8ZY`bLpl;g1?U>x;?(6ziY22@+V=|uobdMM62cg!@=(s0N)Sy7O zHDVuh)6w@oE0*qY|L**L#g6?COGwA`padC7Xrcfeg;GeZ<}5UheIIrN762MJnVKY) zLA#0l4r2&q<1{HK;2h|gbQsNxM=t-|IJPGK--R;=m6spd0T}mZ3g8QtvVN!j-}RRb|FKkk zB@1Glva6PHM!m-g{K;zZkFpR5k>2H0kM&+;Du``(_r{1lzOzq7=`YqLa|$=EnMNv( z9!MRVMI;i+kJZaM@hk#nn0|3rXQ-D8J#>KUW13om?w)`T%{}hgQwZf?V7+Qc*+$x% zwpMwtTILzpen$}a<{IG5{S6y?9 z@IhhSgXF@MwUXw~ey%6FTSxt+Zt?U({XExCv7gIoIlAp=epwaaY6kC1KBl(ZCwX{Qa$?G> z+)b^6-`^U%B^om3xF@-4s^N0VxYL$|5z}#JetbH~8=rKiK*W;6T+ZgE>C;|Q`5t0` z+541-(7Cs6RQa);Ryb0rIofQ5T5C~Px%~h|jFtyxIvlK`o(c51`FYt-5U*)g-4I_Rfy>z3rQKKQn&RK~^K#{Ap~EkJm?5wi&rDrkS!VHxHqHL9YI%MM z>mk>i2ECK(z(k&uL;~sW+DfjOrJ9Lv>gr3^i4+IPIMc!~*ql+}+r@w$HPg|;?H8oj`0Jq{8Nk7m)$o0EAQ%5Vo9 zZ4*oXDd{{TG}Y1|p^7T!tm>y+Kbluo!1wKr<+8|5TaI6*Pwkf988dXyp`rDuzWP*W zuSM#Y%P;nG8XIk;4s!z8Rp{$de-}&J2D%5v&u8d#%7jUrfvYl>ZV6yKlYbN;l3^Dt z!tRc|-n-2%8zaqerkOE|Edp6*wa2jUinXkmeF`FH@O@$)c;Zs83?|$w&{DRb^s35? z&$$|dn-6((1a7E4LcVq`&s{n>&ISMO?`7B5UqZ|AOJUN%5FKK{#XmQ^ekcD%2l@*d z=h9|d4zQzm0(1ZuxA_$8W8B`BG1Bok*rwwVT(Bz$a0kQgLS|Y`5UjMY1`&so6Zf55 zwh0tLIU~I8N@BL`&%jHLJ)gU|H#8I#`XDM;fb%O#3+2g&FQ^* zV_t0v`)X5l13#JGPy0pW1X9zb8)!8Q@V5;L4=}lIQMfOimuvTN_djyWwqa2IUmiIO z0U1){3}Co;dHus057b>NvclD|WJqFzc1WKW1+S4oit-fugy%(|#MDY_gKG1*-33if zod8AKaoq@Gle)eyGPn`9By`=686P0PeGEt-&=W8FS%ZR-$uy&4B@LA_-%V*jzeh3N zt-wm4hdFAHY5~t}@9vf#&ics3u1N0Etx_^M9;p&^t~LMOs%PYiMXOHyDUFxZCvYMZ zBLZa0U~cmmIS~u{Ij6LROuLLL1bb$7kHj5*;ngn!&_8c_yZKrK2DU6~j4kF2m)}(y zw}M7Hwc6I2RyoukMrF1_k++pVd#y^TkEPvS{sr{9mz=Q$re)`i=w{@$=V*>n{uLm4 zpo)>_@l3q4C6TGC{JgofvvJCcN0Ls|(KvfUeV|8RaIBZT!>(Tc@cl|d!)u&o&r#fk z#7H$IRi-t_iX(V&yn~Y^1f6Pci34h0lL3!KUZtsI*uy>LPw_ZPO|B0At+{Rf*u~)d zeOaRWf5r{GRx<&h?tgNA3;@eRFXlGli%jlbUr~6hFsZD4IkQ5Yb z1_3d1KD(dhP-!s_#+$K04lg@z$E`IO`iZ*4dqhgC0zE;m zeBoRYYe5HNbSf;)H#7d_;ALHSDV`}UDAwfUwM^RTJ(FHFJiU*nP+9ujwKFjkUcst0 z!51`-87%Rwq_uHSmN5#{%fw6PlO}0>AEx2qnaFF>p>cDeP;pI8HFa#@hVXQs8BKY; z6u>%8mUiRvZSng?QvKrz)sA^}$qt3tdYRsKTa=g)B9Cf9UDEA5Y~`J;C4u@^!u6G3 z-&`|JM~mFOP@XC+%tu(r6cWQ|z2~TH0#FW;y66sF>f*M2 z?m5qOCp`pX;N#zUl565MYC0|X`nt=9Lms_j^6YIUd1ryY4(3n#h&Kr$uix(myv?PV zw)1*jr}$WzE>d94mysKnK%u0bl}Bl|Fe3Jip05nu61)9QfBwBT!dC%x7i*+1Uex=b zNY}YPmj@)`gHFy$L2%C3#5qb!v@;oXaJHMo=6i2nyskv6FPr=5L&5weZt8=Vz-$nb z58vqlvi}ws3sMJ-_cKAX2W8jK+9&zH#b-LSf{XIUodg5|wrL4szswkp$>_}|U&2^A z-1rRWSmz`kngF6qAm(TK}T1sA<(U>Ox8hK^40Zra4NGU4k8*# zI6!=|K?{H3RH#j`xXKIJC|9eShuw_H4=d=H6IiY;Wpt!(TyoVeDH%gu6p~3qh-ATI zlEVGmt~Tp(5bSlEafR0`JEw`rtTlm4-$J<6wjflerDjsBSm&I#luf>TC~VqU;AvX~ z5nW>fc4D`JS6DZxgd>dfX6zja+i+j(=ivYeLB51XIfngdYQ9{IFSyV5*(Eva!0iqhEgaQcj+yA6#B8eIaAeK3%-|^N$66&`j_nMMn+6 zt|VfXYC>;U?wyH>_hKUtn9@V`d;N~PN791v4u1@HaSb6H6MOGHi72Yi?X!1~Ue>pp z9ZxfZvMw|~wo|OP)AmLYe%g@|+u5;}1v@hCnty%lQgKc<3d;dcW*-2#g7PTrbg83G z(Rw&$$}sW+%Ir)!H z*CuVKQ~MW~!e)>WND$g);NI0?AREoJ=C@;~f-KXYt!CsjBzR$}H56qwitC{3;Y6l; zeeAT3BM8Acn85YjNfp-{b;*w)?&DlyFU743RW0$a6e(Nz3ymf6oD@Rl?lslLVrersBRMbF z&&7gR#{XQjiTu(`2;|a33(YUgtV^p{WcLb1u-yfX^^6zu9O*#XRL(N<&{GqhJ6s&l zxxOAp4T!)V>(h^28xOlx%1Lw$qcr*t+Q8}tBO{f(VJ8`~j^K+Q*PPlKMi;V zgTG=i|Cuz!h^tWV-@7HLB(;)!E7@Wz57BXt7}#y9HN)JhB9i-eJ?lf}96h)xjVV(K zO3qmV$pIp^ij&*C;gEySW*=0AGb|NUyJ7u7teO~lz6OTae{O`|cZ|u-=TN##T@bVb z?(0m&F*NdYN^#KbOBWkUGn(P*8d%yOJO_Ld~My#jKqTN~Hx+^8OHg->FHy@Ce(96H03;lGMr6OWXdx zNPDlSruM%3m%S}W6Omp7r4zbz2(SfdK?sD-Q~l&QA-BCigh$C-$*V)4{$Js$wBU`P3q0 zPLfV_bA=Ymz-JJG6{(Pm=kpQ0bpM8fv?xAa)X}-=iffloK z)#s~>DNjpWE{*v)DU|a7UaDPSF>n7GRY#y_M1{W0;)x04C+Q5>@mFied82N!fAJI< z+{jQZ%XcuBCp?ljh#&i^C2ZS%}c%MyS4ZgD`HE2TbqZUUVFP=z_sV%)Kg_+0pTI=QP~99R9LrDG#0h|=1W~G z`26ek`l(h*?+_{$k0qNAe;Ut|uhmk9qk;T^7a4AZiXmV3LbW6gREVEHK4qXuJ|Yyz zyiUHn>oe>3C?!QLIYJrbHISpt-7NwiA_oj97E%$Qm4*e>uzy>VyLFyhg!MC3fOSso zJYMzpQ)&2?#!Sjs8r8zou|0J~`*`9HC}}tv%#0sPunjVvJ&gLC81{%`X4|ymhQM4Piq_00`!Uw(L`Z{~#0Y`a?%%VW!RXMlYpW{|wAE9jeUcpp&aQ{{ zpIKGz`>qJ8i;nwVT$Pr{uPQZXkM194P4qSeL3}+cFbAf>u#$Y%L;3@TbJYvwUl=vk zJ$34Cft_QUuRo4;-t8!()A_BYqQdkMUIEv$3E_WlJxmql-bFYp07Wclt27pK6Vg~Kh@E7{!X|<78{_tA3Mo2{kfg8uu~DVKwV#{4o%Dcc+ufMG z1{hbwykyUjW2(35lxeyIf0!hTuKQeju}j!9a-+-2V_yAsI)8kLg}(4x$`GAT0;$a; zv0Cq@R#iB=-W*)HY|@fTQ&`esw4t6hBw$+u(&k5B>< zJ}Pzb%l=B-Ut`}e%`^kH+9zdeU-g(D%{1k#*kFd3wYLA{oUOV1w0mXR9+#J6x)suuOg?X`O%y|9q?ss(8mbWsjw(`mAsyQo#e&iMAJFW!@&vw!>|;YpnlT;x3LyT~Tny@)$?Z?Z-?!MKbv)maB&o;5dlTx54gLMDx%#8;7w39Ox}0zY|5<&ItNkpUm$wf6Y~ zaiHt6kLu<`9nzgvk}8I+TQXrXZdrvqM1`cMl6*PiCC;r`UW^uU75ulgNrQpTSuDv+ zt-pFc#4~2!-ujfWzW;T@R9H{`Y=y*jL8q%&>D&4a?=GUikMpii^Y!_8^G*V)9XB)G z-`f2n6XFrpH5?uq*7N3z?%fv;uHJgkd)4;_-|Giokw44MuNLuUPpZlaDa z))0kH&7`JKgXML%!9KlMO%+i+-}f>eowz$2k-{`xAayzZhV+?!f@g-{uY=5=H9J2J z+rOtRROfRvK<$vfGTK{kM;`o3-@Xo&?P|e#RBa?R{a}U1xo-f!QR`n;)CHhnL$aoeJAlUeGqhUeqg%WW-g`m&~9K4Yvm42(F zwX*C8e$$W6ovrg>2KeQon>*dSxSsbCa_S6Zvyr2z*!`MG%v;MTp0VkkW_PY>%#j?+ zS>xBddh{CSdC0m?M${&wENm*24lwbDSb=?O_(YXug5oS zZr+i&VTYWQ6PjG1|7MmfE^TROdq)hW<=3hPQ!RSA1x5_8r^q@dqLg7~{@x5I=dRC3 zaC98vYrbs|OJ-X@CO|%}QT%B}ULFQjQ?Hmxu#Z)0XB!1W|a z_jm@YUE>3L^>q-JDOj;^+I@vkdllu{->xt~gY02NG`BmDpMU9S{Wig9Fx!+AGDOu_ z6sM1T+?=-T)_n&VTWGSSaVgYnjik}fc0qn`#Cb)!;qynf+9W8M6@+YIa3Ao)&=Jsz1G*srkM~<94B6xwB@UB@|;jAD}ZU(9+U1yV=zfCGmkWaZD^-j~}OdVj$C5 zKPK9krq7>fyOFw*6%;5?@F~lMKTS{Y8T_|dwi_olh=d1bgL-64o^lDmls z+KL)-k?Ej#gwE?`OO)VYzWGQ?crL!f2AFG_dEPgGNUS>Iq~0!++t9?O8UNZ)v;L)f zmYVYZhI;KTJ2a8K;2KBpkbTT>uP9iX1xgv$bu^_YXHIX7Mjhj#*{w6%Y}F#KF!aNP zf*mRi(=QzkE_Q2E%UK!f(bnBU?O&!U9c%S_KI-3q7C@pQ% z$kS+xSh>-bM0r7JrJx6Sc^cPzKwO0DcX;cGdzCiZ*s07P;N#~xBk2r0o(kyOA3(2? zWvn`q**yi@kBf}vWogdO;QBtIps@hn!Or0ux|s}-xvepZl|`S#u56jo z=$N+X(hhTswv@?cqq9jNLITO-_o82iGO9EtDeo04IITrar)sl)dZfeN&RTF45YqHT z{;{9N0PfSJus`lovrdzDW2A_v;;=`=o0UO?Uo;QfTBpOz@uD>BvcM#Z7`-R%q)#f? zDn>>W(l>uBojcfU|LBh`NietGXbcTj8@kIHRI;AcO+yn`pxpGe4-L_KXK*5-r8-Bz zA?t%6hw~lXa#G*iM`f@E5F-O^tMc@nQghqdP}`-2ppP-b%7dNK*2_B)*IwM<(|!Dc zCt97ZB%009D0PqtftS-=PhvJ^U;+tKzooe5U-lmWu|-k0M*WA`8c;Iy`{y$v;GgA$ z0{+=i+?5aC?PG@t%m=szH{!(G)zuvZE6+^)!IggBogY#*dQ8*qELJxQ$_M3ov#9>I zolK8oX7|9jnYfYjXS#W71l{X5qm&@BZ@aHC?JtEt+0V~gaDI}ee?oi0oG`F1#0Bw= zVxPrmWZ3QuNoR{9b|zqEhQ0`WXSYFZVA~ko39Uex7%69Ev^!0bf^X(F$Cd1zmaEH) zv?drkAcqsS z`6#XkA<4=E?~@j}Oo*?|>~62h@ucKdMka>ovsmWpFSME>88eh3zEvEIKL|Y6JC}dy zr`GVr>&oszv*Xav4ANF{ZI_#)5OJ@$uA|A#*x8Ms_b`$_fmia=Ca!RqEPmT-PM$R9(Jw!RFc4-%||F zst;5%^57&US9X&DhltUqq~l=Z+jU{+fR+U*IF&Z{TqK_H>PN?hR9c8`OWXWe2qP9fO1D z#DL$x+vPWf0c)0bA&=mf{j_GuScDedpMFs^CYnP+%D_`p5zCxcA^xg7^9I4 zCX}!GXZs!M#9cBf=H5m;w@?0+Of4%VD*%3E&O6`;gBKeJA2%7w_*EJUDOwrk^RBaB zo+&VX<%Dt~S>&^tjV#Cy-Zr#E&$G0V!@r2`r89RTnOq2`Kl;sCv(q#Fac=J@49$yE z&z4i7Hwz1dU{lKB zzoVI#m4EMQNsmgUS-|dWwVBNv5=hEUt51>L)tmHfgvEE}1;*<=O|!c5IqD*~x;u`< zo|N+PubAGf`*)!+>hw;qVZaVe;DtkJD#r7i9eLmAvAx!jdLS#U?86RNpM`!NU64_L z%8L#IIG>%}uB=`%huL+$>|?O9cl&4ub*&`7kZiQJvEK2P_1#lwNgcdd;95?jA}pTv z)oOX!vP}Ntaxas2|83z1m%U`sK~t$UW}?LHa>nIONxDs0C-Xh-iP552H~0&mQ^uBt zBrSu`Nz#kZm0#)nLyFFdHx&JR@or^j)fj#&T;@S&Sc(o%Fbw{tfE`@|+urjBgVwUM~mi=y8Yji3=y#J4tSw=66Vr$7yrA5Bw{`J^@(asi_xY9zlGU#B$ z>oXmCGWyGKtPS5_n<|%?Wh}l5CtYlo@ujZK6PfXN&qc`&k+o2*(dqqZpGA`1(0}(_ zWXKaMHn-#&?748sqFE%onU?mq0*twLRn@2?_+_OWM&3^ zLz*Nco>^ts>`Xuk^!n@%XNs{>H=OoR3KUAcRcJxD+wwVA6Cb_lLcUPYz z@7{vM6+d3HUCmFdv;7Bh813KE_VSw~9awMbLXrRhKS-UF!%j-~yDXXpE8=Csx+Z0? zQB^bPrB)JZII2VpyJ_D7#HQ&Tlp(ry*O|RpNN8}FF~(i52J-F60rj_? z4OkaM{xrZ;L{3B-ayw#A-K&thMy(kd1K>_BX9n;)+P9mOu;v9E?ztHNo}of(-lxM; zI&ERK?V>93zs}E|!jxT;)$W^NPuqzHDT$mG)3SL5>W^?@-*-}CzCr29?wc1=x5z>L z5xOma2lxKyPO98+$8Fo_%%t{Ze&X;we{zi&o^`;t*e*-X!H3P=1Y^i75(<%nmu(|} zfUKQvWGE>~pC7oA<@OWOC!Xr#Q8^`{t1||65DeV zaddlEd49YRUkPC`2NnZqdS&~oDb&rBj2egVm6GmN^$7XHgCnirQBji4Vax^N;nG#I z9-(6}P7CN_8Jai|9P8i!JmWgi{DVxM{hcs-vh9}+bZe+~Gs$&;o{H=n(2;aC z&FW1+lGWq`@6`9Hc+oA;txb*B$d{C_w{sGMk1z7%hcz>yd6d~s(#9K}qc*d`6TU4a znfq(mZMXUfpvswItCFT8YLncS$UsR=qUI&_=X0|Q6>^Mv@6ojj9@6Jmot|qfJ>(bw zs%5CgICG(cDBX3wkS-&;$^D2AQwVmY`NsIWXI=6?AEn42nqM_98Gi*`hJgXMZ#3?Y+xLFsUpwtB zL(sTvb^5S7V%?%06D{#!&gIKm%;nkFs+)^2h{7vfb@eR`FNRcfJ*r)2k6sxK|2@=v zLZezf$#yqsqCFnuF`|iw!fSgz&-Dn@D`VHC;U(*ajbF;r0-N@0y+T$-7rst!FMMVK zTVq!^t94Q4M(vN8YrML-FVs6)ov*&Xj!dD|yZ2X4?6tZqA*`H;K)wFQKEDDzKY0GG z-jT@2sC`(Tv-*D)W_R~5DAzyVYHkbP)WKI$rS}#wl)w0)OVoMcZws42sd1A_+$5gL zdGPhmTNM@sT&*j6y=t+#yz+3DLkT{Ekj3ehSK;Ple;5P`8Yiv`8%pO3v9fFHLGCAJ zqS>`pA@>c+a}gL9Z!16?H{>Wu!Y5iPzR5$1zytVngwcFuou-n6I z1h^xk?R7_k!luuccH)qEG%J;M!40#b`hkT4T#StWnN1fOc?_A^co~nV{91eIW&Bgv zmCaLV(mPDGU&)R}xZefUl(pS9DPovU^lV(a33s*MTdY;-n~Sd^ezG)9(uHFVfZ(~~ z9pg9Moa8E&$uKYC#kV1Kf+k5UG&OFCZkqP zc!;A_W2L#FYihstMyK*PSYbqZ(M4UUe=9|5SV!7lsuj{GMds2k=8_9A?6R6Elu(S9 zl}ehlu;DA;Q9Onl==sbY@KhE2m!j=|BcuFp%^eUr^bUrJX0i#Z@1@&A3V<83O4-o<%L2n;>NXD-F35|yMKFE82+VtE%5REiwI;warP#P z%f&fmV5Fb!`3Hwez={(0Zq$=W>JtiHZ3bb;SU~^=&->|S25%gFES@q`zo~K&jAo?K z2AS3==FWaKLbJ@mE6gf|OfF}xHF+3XNu#5R39tv#_=7G(2n&WBqXcP$!NZdAEo@ZncXJH2MD~w z6>PML7|v`Cb)i1SXQT%O>IH-z)!WbIEF!vT>gPHck%SJFz39SlCU*nG=76JhtfP47 z(;BtFTN6wqZSOm$5~g~0Bkp9Pj@~#acKp>(UP<}uRqwiAJUenwlQFiy9Zm{Z*P%1T zYBQ~_LJZ4t6Zu$0Ect`KorpjhMMm=hFN5~QL}S^0k=C5eNyTNBs?+cVl!!DYvBp+? z{~WEYDnp>VEWXwm;*+K*Tg$p;ug_e?5mwBd=jbMej_%M9+Pr0B}_n7O_Kxsz{!%N><{fff(@4 z|D7>LKTAJLZ>|86R{x^Blmw3>XD3I1Tnd@Jx2$uX1k-Wfn*d5tMGiKwozN~y*#f{~ zH<3^kpHdK1e!Ue;@1~Ls(7&(t}7inr!|^Al)nu<`5rV`flGKknc8GCrkS} zAt+dWOZUXxd`rw#;41PbG_H^v<7!A2Su(jPmDfY@TebvsFa)pKZ^$4nG32>*5E!Tj(5+8cfdIY#-J|*1OOgJr)-6 z7FA=MxwB=vONt@8Y_WZCz7a04GYoCn(aTV#9EhbwHY;`-5ZKmj(wq2Zo#8fhV%~3Q z>-fL(=UxsFldSs-8T6fBZ;FJ~uiU%rBwOaJ`_$(cjPH!<1wJw9`jV@vW>i z0-dXVE={Ze%Jqd??ORlNv|G-Tc#8tl^(=Ywq}lsYkLe;j*5w7e>3e@uFxR2n(@Nv| z$R5KM`KlJnxtSqclDVd6n1X?yMwyd<|J*#bbc;M%w&NYcY>E-$$Y}KfW2r>#WTGwO zGoI821n?JPYqr1rI%m6FoR4ICx_`+Trq|j0o{V+yXfT*98f|JI{VJ%^DkQ8j@ylNd zwM22)LLbG!M9FCe=8z-@>%BWNmv-crF`Lf-*|=`o=7J%X71jZ3Nvb8;SkA0<(t z|A?8K{4e45%x=49QjmNS;`Yj*T!W3hd*A5js;6VxDyC4bfL3eJ$Gh3|SKC0_O{1NP z_v3zH*I61l^BsxbePq|;d^43a${c9b8}l~}eclzbe3?y?!td8x&WC0=OPgPQ9QS@> z*%iKIitLlCP%~%u#g$IMY^wFMBs15BiF=fTM?8p;s=>F&g+h*)0p**uc-uf#>d*wn zDwL~T6H?su!R!VjI6K!2>%M0CJ)`;D^hXl?w#1$wm+^$pR0o-C$7`Mk$hw zrDotJ5knKd^jGU;GYI{rM)gkb3%N|A0*?ApF#{`R#6l_fVH+SMg>7NXZoPQLv@>R* zz(V-m^&LFf$@f|1PbmJsGz9x!aq>Jr>n{HKgD(h}AYB>&JsX()RzD-Uc_d z#DkgSR95NDNnC&q#f|tZ_m%eANNMg8P3CL&+nEhY)^BEq#RnTJM($DZ{=N5uou2w} z!_%HU#r(N1mGk*o+}yo}8TSnRFiK|m+lDe3+dP2`SZJDbN2ZPn>@thk@nMo{y_?x` z(r@@aeq~Im+Dgfe-8r@PWk3EsDpC7p)6?)UZ9W<(gE>QNd4ZTJmm&S`H-yq?ji5y~ zEvsgz(mXmzk*QWB=WFHL1E&21VMm)e z4sx(TWv}2m5CUYwzb+tr+%{Ob6l5S7Mbhu><|Ebw2Ry=YX1Xl8c!8!rxL6ukoy0U2 zvl+sD;66;kqfx=QcNI7|(1pWt)02V}CmD7nfy9h_AX|O-4~JqW0gn#bIb$FA_!lrF zf2O{n5(zxXp#wd?%(+2-#0&ppO!$8*EB_DR7B~h3cs}p|d|PvXecAlSZ$PP4N!A?9 zy;g6BTw^7%#JP&?dEA+=EpfN=qiGkT=%W`uoYx3k5pRS5|545xPtKScev)+ilajc-boh8a~J#$_A z=ON`6Pa)vgC)$YjSvuQH$q$`C)5J~s9}^qfBI;7crA?Z|xG8DTJV?8$v;ZM}dTlu$ z)2~LAcpskIPgaC72r^Ya*lD>b>BqQT@^=?%RnEmESQ5Qp-GY?~8|bSCY?IYG)Up+` zF*Dp($bgFM{wIUuHDvZJv7n{6s}&nZp-AS(9Gs7rP2W5hA4%eWBh1jxdM@xqVfu44 zn04%4ViSN$kS25Z%XIVRTVo6$o=r9#d}uQeN~~Gt)VtF7onwQN!&ib&d~OmgH!GQD zV2atV=vG}?@zEDWKbp8qn+}l#h>5$}BwOdGx2IyFQ;KXc=V&re8$n*?1t1sJflLIJ zDU+riQpqlrE7sBq=q23LN>Qnnc2*Y4gHG;+;bT$F?eR;Z)}nGJW^3^1wP{B^_9wOf zcBdCSyC=6d2_)~znMy?JWXXoHR$bz8ETHC1wy z@-N$t$^U8;O?OdN#daOWZgJfVcH^=3gR9;TxLzpo_KZ@`A|3XC&xi=T*e*(Mx>lo6 z0Mf)UTZV^aTKO3lC}(W5Yk23wi}~02bKNdiF|YzF?@EX_7KpWg6+nCeVL|>(h7i?Y z>m*|WEU{z>kbdG=8pOJ4c7}f7)#J;fXIJbj$=mqz54>@9J0;ng_x(GFR< z{Us{a1BcLz7u~D_V(H8U8`R0y0j?IYbwwVODQsz25`m*LlkT*gb%+f>bGsq*^Kx3> zL9^K*rfy51}XN}nWqk@N?b1YgoeNkrUX_g}X3VhB(*A0W9Moa&!# zwP!KEZ~XXOKPDh8c(k?c@dOB4$Yi|vn?hZ)S507|0p;Q|I4poQtl_9_8gy{7lihR3 zPy%W2SZ-A<)JMG~lF%Xo>?1--lJZL7mU{YmspSPLp6S+}hd}BUXAqD5f@|x4f11G; z7K`HR?xL>la+J@kx`-{W>{Q?T+-*j_Ee!pK-_(c7k1c?%#rt|Ts7Eeau6n{b)C+m! z#T)E2F*U{=>U(18=X>PoaS-ki%7V=R?82x@faE}@zOUEw2jsB+6L1Ry%BU2rnX2!1 zIENKjrQ$qgBWV_Qt&jkDaetv6wa~}$Fx?|*T5uKP-g0_rvnQrGb@I>=Rh*^XOjCJHYd8tYTz5hI8*<6b&U`9|8v6 zSItL`TVdEdyq{Q)%qZTjXYL(XizB_yQMKCa3~pwfG~9|E(wl?N#Ak~EGWjFf2^ziG z?{~CM*XW+tNc@%lBLRtI7ingUNi$E=GgHKy2ip>of^>IZ?gC4ucszj{nPv2^RO{{= zaC?E3^v@yg0+CKL1;!hu0}2qdm+MO`B$__0T+lzCqjCz8nU{TbJ{WPGT#)T^)1aS( zA9ryzkt?*1?%QHF<6(^-L993Ey{i(Gkq4v;j8x_{qigrkA+P(5(U4|Ax$S7Q^0q$l z+$_Q7BYFnD$y4#dpEUIi!pTE}zWw4kRaM_yB| zX?*|5RohgqF<-zdK&9!%g%s3HxF+VD4j)Og@TG{JZ1RevxS8X4pSFlD+iYlv5o6c| z5jhEEgJ*1WFfE^2phiwWQW#YKmlQwyvLY1IUv+r$nn92boShF=|2pycv6c^4J-03o zh)-TQ|MB0tl*jhmq}HdDFVw^r24_#<6)3+UMPdCkv_8R4Eana%W;({b+URPQVb(}d zffT4C4nUIy!jnE{YT#Z?pcOXrNeeQN-N#K=vtI_wmgPUmDCM6mnLz-<7^rscG^SK% z9vFcCI5<;J>2dhX9>zbDNFBXMKD^w5-7J18vD$6tsds+Y+LmJ1wfle%^@dw?X# zo}OI(d4xmt7)g9{6^R`ww+xM7BtHBcYazB3#SR5_$K-uy!w^q@Z}Mm>;tR3yj^2=w z-}WHbjKL2?Lg`J|8U^r7qwM?qia7ByR&ZxsemXmn@v`F#8ezA z|NfR~>34*I{i0IOho6^2>Xm=c+5bbe7GzJab_bPBh>1M_i{N#up3DbO>U*fE>KirB zR7-qU$sa`TXc~99?R$91C43e&e4lO9+JH;j^-nkId0(fW@Nd}7dxWQ$XsJe0PLoyR zS9s;fd9KU=JV|lMlyoymc6T(IBk#27R|d#*vk?KSG&90TtlYf9_{P-Vdm6BoMn*sw zd_y#-eH-Ds`l~TAiC$G`HjF@Zc^C`1w1T{DMnWnpTV+&KUSONiKg$*5^+P*c?YKMAcU{Q0A}8B&wgHkBNS@|r9e}i>xs&KxT3r`V$BoC^Z)8Y<= z6mmzozqV<1_lkWkMqK8qR_2t0eWHfJL8+I-}} z%loYitL?_Nl9K9)3750T@=jTjWVCM~_gHJFLUrs|ouUY#q%J_%u$j7j$cd!bDra)D zVy*=LJ<71OR-38R*<{(bts-I(A16WivQruv%=OxCX~!(d?lrv3V62bQR2OCe?3dPqx? zj0}6H3e-#egx+rMX{$ixf}*%i`wE+7F`0)uC%kg`vQl1p#9ua7*e)U-xG;NpWnG;GrShynOx|RGEk6Jp zD0+oYpTCS|z$rGC!-pIs$AdJ#Fo0Ju(Z*4sd!OD{tLuG09d)W$e%S}(?5M#;5-j7z62J8PC#w{ZIC4KhtG2G z-@xeqF^xh}ml%^EckbHxF-(#m?l~#4w4`6n_i(mJ)a?+axEUH$IJxAO<{$6YDl z0#{v|QN74rCjTTqtB(?PClBW33~nD=aQu0VQ3uZRNpmn?=D}L1QgP;&V25b!xHm&H zTAZ2U9IyY{?P2KV3)2Ads8jC63>V5ovxT`5VoTyBnUFriOg?)-|E3Pbg)uWQU3+N6 z45y%=pr%+?$2*co?a!$8c!+5pzbTA?YAU%1jat|b1|}cB0HY_BM{?7zoYO>|)1H06 z_8H#rZ_~Mb!KuEN@So7?|K8_Q1V%D++CKeFajO&6-trR6UJa#ByfD71;QMKJ>1vz@ zcS{)G3w^I^NIMo>&8p3a=q~HLf>q;zNb93l}o>3C5Rri-KOPmWe@MEOKYaBk!^ABf6*kQdL-o9Z~+OU9)$%jbaT}L$rI6 z99wxB#3a8MAXh{tzqb%Gbcn-5_2B|Qvk|GUOxr5pnMDGMcE{<*i6-fZ_S={NuehJU za$^FFFqJ$ zsml(*;j?&yP)J%(ld@j(yXjY6ptOwHV0guR?kgDPBg#pK7*&(%nR^8M?>w*#5ZvNU z_pO-#TeaEX8eV-{jiaHTauXj=5B&_b5c6Y9$9l9#khX;DZwiSp_&Qfn61k$;FKv@y zObT!ca9hNu!bywO5THT!7@k4H%DD?nSvi<8xb~Epu$@}LJ+3rsIC zNuozyt#yC@X#_VQhw38z!!1n8c}1T3;JiYne|TH$*{8J2Vb2@b&Q z&CY}lxD7}M-hZ3K?JQm9o1+Q&*az@g|LbZg|Kk_>YZ2u*h9`WDWEce`MOx~3+WM0v z=-+NWZ%TM>b>8S*Hzu(U)NaMTF72e|4Hh`jfB1fM#-j|NR`NG_bfwu^Us)G7`%Pg) zifEM$SMg~$e^R$t8m!;VW(WPYSIUIzW3$F)uE!Hl=@~C9KUJkg!icA)F=O>rECyK` zHcd*>7AudwPDX_VN_g9RN;Cjf&lYnqeQrQUWuz4|;S#Eq(~G_;hWNiHTUmfX5mT#` zR%LJTCXBYjR+)UFqtsNb8kq-I^AMA;^q(F0=E7X_=xoEJrH2hYoiE278vivK?$&7Y z==kjCL96kykuh=MR3YYD=1tZQumlg20H>gi#-<4Kkmd5>o+z6}-j*hS@!M0|sQmXc zW%@srVt?6hiiMBADL!)dQ2vBQjyxwpFGoTE21|Oh8tcH++1*ym1r|X3X=gY^Vk3=CAp>Fo+eDQnmjewlKm6&%(*>l zYpO3qqSpODG9}FSM4)<)eEC7o)yo&RY;hL&ap2TwdHlU)j@9V$&zQT>H`%qXJ@(G< zwup30>o<;16fsTku4S#v*ghy#3(4fHh6NS4?6wuvYl`(f**jOcqLIZz6CKuwn0fIk zn5T=qLv#|Y1!P$9Z-UY@Fd`EpBgg8G|LDXt&69eF&p!5?Z7#gG`0tzZPEpi;1a}f6 zK?=%*n#dsEA9!T{A%s^Jcx7K7k)8f_O6&|({y48DXD5g+Sm1V6oWq+dX#lv1+jhlz zX^_yve%2y0=*61zMV)?-Cr37c!z=Yt5Tu>=#xv;gyZht+T%A{p|JZL-9gCgXCw_A` z!;VnFiv)xrz8jdU+e*iS#{eF~a5~bLiAPC+878xqG^flDejQxEZRSkogP*IO6+;gvY98Ak15rMubWJ z0aw)Sr`^3wLy2U1+NBKdPi}3By-hc;ja%C=SQ0?$uzDao{4KFoGMXg=p<}HUGRKT7 z(D5*9(SKNyHDVvQ{L3_E`0^S#F91J4-g&DTK%l42gkHa}ofZeDu%qlJ#uWmWQXBua zb$T%Cfi9$T9FK)wVW;!O#%xA)o zb#4W(5X?nC=#;o0G1El_@=SkM2V!=G$(2HnxjJ6>fGKIUp<)4#h9wIHEvhP+VYgz` zII2O0Rl$!pu!d|!NRAAyyu|F58O1k)VfKKCo#&ezY8lALpriRsQD_@6A9C-%zDe;I zRoj;vo|zI2w#Iunt`Eq!{Jd;H?{YxnWp99i;2^qXl#|goD@R}t;nR`B>^h0+h3gLsC0M6@-}&6Y~Q8_l{tL;WwGkY0XBTps`*c86z> zxLK*}8K0rEb!gt03>agwam5lKM+< zfDgvKy#`B|xV}p#ucGIl$3u%yJ}BtiQypj+xmoP9Za{}&l#Ra)-5+yJTT=0p^)cwa z;R+tdZoR26#fl8&OA*V9Rk>Uzl%^i80MR=WJn_;=-_2}`v?Z@M0NP|8CH%^1vvty> zjD+}jgL_W2b@23n^JkN>_v}yj0Nx5)tqb;X1tE)*ffMhexB^GCX?vm#&HwWhBSF8O zG!XC9_J0cK*l}D4bH&O=(2^6k`k+)_b9vXad+5WATv|BV$y4^q$g!K> z>NV+?tP~FdD&-ZDT*38Y2oFEZ=Vv}e#7sB)Zw7zFHO~PZ6TsH$0eCFzyI*Hj>oz!a!@&-v>|rWKx1fV!R&bn!?OFWUbz(o z3a z$t8?ndrjL8G(P{mF#6x+{!2hFr8gWExgSUZzIxNmVMJL-Eha3Cq_$O;3Xuo+ugK zF0{`em};5Gj!M1G^M2dah^LKU$>&0tB)Mmh;BK&D4Yv3&USm_FfIIx%SUDm$y5XG_BE+_AVJYg{*tO~^ns&V> zPYX9dyut{9EN$K5IBrW@ULBvaN&D<|KO0X@iLv){K5tf>EvEbNUx#zikhG57StqtZ zrCF>3hd*{G0A$F77m;l5$L|sLX8IifqHqY#2xCZnoKf^8%^W}|m)^jL$T2N_%d36C z!z9jJ7D=NI65XdmV%>f`J>$P_A^x38LY~W2ociFZ7d5K3Yk;gt5M;TZPxh_W)eghr z>lW=munq)7*3GHHd?T=HRbVuCdozURf%!{va++_JwUU;KT^1jWY4?OiK`^{w?T~u) z>4Q)_Fb1%@Lefg^D!1JUf}w`--$?xd-2MFG#TSo^`JdA8)oeNoupKyqKJhV=a)z|> zpRm1gkjd|0&UOUBOtCWqIPU-v2rM2;S>?(N3?x*bLneeFu(3`8 zNk@EUhM5*~sZ!1MFe@Nm~SY)F|_0m`OmLJj< zmJc6a%T=)Cx3)%FK3h6oH4xPp&^wJvyw9@_UjB;dTlD(dmFc}ww9Nf=WefY7#|@nk zphD~Cs7^7PwZ99mEQ_%)UU?(1?`$qLur7*6LYU{(nD~@om)|EZqrj{gWMq-iSi_@! z`SqWQLMdad3HOI!qrQty-aeT+S+KG2_ObU$o^IK5+txCJTWtAvf^h@G_c1Y1klQCy z|B?4*|3T>N1@O#B9E~3zXNI%5IR0JnJZ;>Nf`T>;btV0uJU#g(J;7zq5rImNuG{*7 zVb3crP$b*K9zWN&f~nV2Zx#nI=WmT74ka4N=w;@Ku@xIx_hU`=OcpkezMM|X38Zp? zwoYa%tOAVfa9c)p%wEudN&1Rtd$!}vXPB3zR$XBJHSPcqK?Hkjgf*S5SPw3%uqsdv zOU;9AZ^G2traNsz*Lkj?{{DFmWDB8j7fSCC`rzq$%RMA(64)|Su(phqqPys{@;phL zICCRFT++DtgzJMr04xuCO|a^_o#Co^_HG2GH~3O04i!n2OCa``*1}BPW;c842B7rn z&R|3CA8DnqGFNUr`JK5aD;u1VNyhi$?+*Xm!9>m310GFA<2hTN52v87AMV$;40uso zH#2!X`r$R;o%BXw*dg~}2|gKrP~Wqq{D-+nIBrg^BIK>%QZ>h%+()wC(B)MU<+FgV zVAn5kl7+K2RnPC9cpiSk7H!Bk6rb3g=(U<`+t=uT*u@nW?( zyqiFlskGlKyn<`;fUSB2(Cj6&)!wz(h=Q$$l;t^OB0m&&=DtitBEV-!@Cv;kSox(`h=G;vy`LIkUQ-z-Zo(Jsy4 z>9@f4K=%p32x)SjVaE*kK^4Lrr{@!Zac7l>`iOR>C|m0~MtdB^JjuG2to!2{ue@=S zPh(^<^H;E3NNZr)shkiUbGmVQV;W9RGB{Xf8!>y@h&K*z#fI3rcSAJ~YM-kK&vu%A z5vS~*!M5e~*4vWp^nR zqm#~+q%2uSV@KSV*VMZeSJWFSddo$FHQ0#4K!vR?KH z#?x{3aTL9jouYOBD8?$YYBlIX;JJZ%aROgx+>k%Eb2DB+NQ$GYH@9*^-wiA{J-qyf zJN(&)f@E>bESS#_x?L3vuS-Pi(Xu1lVD(kiw5;p3-p%vUJXQImG5mTLI5T zEe>Yh(zu^C^i&SJMhQR;v?haMIbIt+dw2D-s2^HEK0Q9oP&7wR5N8nKcR6ogzc3KF zNV%>MdwJ_Zt0~LLLDU|lKbUGUY7?iwe_yD zz{EI!l!5%FnC)gmW%gf!h*|c7mUOzk=JBPu&c4;ut)1zz7`9F`>%>i?Y&j)46FNIM zR?OvQIS;#GzQ{tN`N)=1cvu57SS}zGX;@;Q(WF3}jXLU{F%L@zh69y_>i@}$75ygj zjPM+!DFPaOV0QJz4W+9L|K2^mvB6;=BE-&*GmxG8vlOp=93jcI9&y=uL=m3b^ONsLX{p%A}v5zDS}H zm;#u+R#u|e7L*~>POnm&$yKQ2{Cba|TK>i0FHE+dulygh(L2UIrYlF=FeCy(?0r|zbXNIQZ-E%g5E zIwZ@kN)D>=%zD)%!rC7=J69~(+8WgJ2Rk2EuLpx$`O*+lEW)dc@CzLVa_WZ_5sm~f z!KQ)EuIPT&^(3!a7n^A;NJ4#)%p5zU^JBU|NIAp7kTD91Py_{Vd1K>>_17zz78aqo zw%u%N);o2{?P8bK4gWsxtFxG8S@{RAf2UXv?9CQ>GQ4h4i>3r7O2{u#N`cTEvoYkl zRHO9Sq#BxwNeUH`xlXGMioTvbzvqb8PS}Q2+c4{&L>$_rCfOLS1Bqg_FhGeMC}!|I_z1yc8!Q2)ZUaBmtDJd6GiQWBIfmdUGLxT zpWplYIluG$p5r(UapFYIbKD>I`|WP98Sg+Y*TN?_Saw*kJ#8wLqHS$uo19=f6;wVe5pEbr%wuK7&-T;!!Zo*l#AuV-Ot<66zxnT|he)M%s{xiKl$xy$q> zWGROgd^bZfwGxJIZ|t=0i#mmh{aWwgpn(L=-Eah>*B-t{Mve&D*B~l~S#2U1-!xZp zzA%Q=B5m4JDiV8e=^(j8NSH~n?)NF|`0-M8RBdH`$@UM=rF0Zjdff!6HG>}Jj!U2R zn7`130iw9W!vuKt*qqg&wNeY zHHq0wbiESmSEea2BxiuyyQ!%WiS_TQGTaEmY?eCGvu-!jrn5iNtBfi2GWON5>_1a}pv(77FJOt|@phz3MjQyMhQ z492bJ%QRAdS$X>4c80bfFWnC}Tj6$OlWOcLC63x7atKkbJTsOk#2JaO>SAVXzThx& z{nn?NW2&Wah<$2+K7fL^CQ&R4_3PYWUq?>KQ@lz->QQQ}pKx51!u>tPNi)Qcy*Oh1 zmXFrZgo}g1mi}E%bw{dkQMQ zF+-+kvTy$nP)P!ea`pKz{n8L5#`K&fsa-dnjU_X0v$p!vl}+*2bzdaYn)#Fmjab>Y zs2KtwEsebw4^ssjDQ(T<8rdFm$8<_SBe|JHAL7mNKDOmEf&RLxda03*jBM|9ML@_ICfnh027_)_uX{sheaa>T`78u;n@{AW( zJSk%9J}%t%C@?AyS9HGhtNIk^E>uzMN5E1Y9-4&zMB_FIATzjL?_@(RTc4nfL6RxR zBzqDLwC{9PY!P5Kv?SfqMXIL`glqh)=nW^c(1)Zm#eszzlFy%}XlzePNeuGNJ+m)n zWUSTV_R07m;AkF7DS{Q!`-*eH!G5KtxlF|?m7Ezsks82te8regP-gM<`c_^y;H>;_ zDwL1LWEHprI{u;&RJ%OHbHu&>Ebmo1F}~7;wedaWN7_)QKU%*aEIuviaEJ&A8fPa- zk?c6vW!G6s_u4|YXNprf<56#WO#5bZdg3`+9Eea$4ceo$Y*WBp_U3Vj*AKCG*Zf4K z*@{w<%+RE^5MyI|ifct>W6!t8uR?_@D(#n$F&NB{?@&xSW^ZQ+s2)Wt>5I4#LG z5+Mb`?S@!&+aJ!vpk%3dD-3;6u@wd%j2)iH?xGm*(-vMS+UbvvaR-cuFyTRQMDSs! zq#S9w??PSs?)KEre`^?MQ36^v3}21~Cfkcja$g^mAT9e>?*+R8LRB9dO=PfE;qqTV z5W=^EU7g6+xY$K$y$YY=rB(HlOUm<5YA>~|pSL#0mPNa*w>8x@*SQA8T)kM`;^__) zv2~97yLrecw*_YZ%kfN_(9jh6bF-IWlNH9lyJLtn8P1tMY~Vj`QHco#=c^igReW7; zxN-6cUjOAcQF@J4pgb|PPZngb5tm>lk6qPED>jDE62(YR--5H#>9B**Ccwcu2Sk17 zt#PYYJnZDsr zK5MI{G_vXL_b_T|g`aCjNsQMYbA|dZ>2o}*v{Q-qgf-lbsbAZ`v_-J`*egw$;W|ba zJ1LGHKcEjP9oBZi?aZ%pO@vtGySw$uz3{)&$dtgLnr`cSFk`gFa-lH2?M9K#-ul5> zc(1dOZ~=4(tWeGP#T@VHVoyxZk>m627jamnUhk_EIoyYk+&XabB7;Ql>aTxpbR_(t zvmyHQ8jQ|-Sw5TbsEUgbG@hAlxRDYZqahn!vh}Md6I*T)Fnxx=yY^7zf`-IRYZFqf z#tv4rbNpA%l`2EV2`XRn@5XZfx!rhTp_5-xiU0-fNxOy4cCND$q*I}7$(FCK&!n(^~u34)}vu2_|ubUr$4O-sYD%&*X$A}dPg zmTZ`348PvjAvzn(R<}#p{fN@B88Dx!=ASx#-e9R!#3Ts|keO8T&a^*#?zXE_PZ(83 ziFDLc+m7g8Ch3Cuh%zeVJ@Zb~tdUO?3T8~00ApwzQf|l?8Es$?4hV4+=|rhqM+!5z zAAHoiPilYL7#Ut@${L-?$42YzQ4s(E2~{E=7yg;IE>n~=(v@h-uINl$8!*k6A|}>U z!qxRFeT8&vjhbhW6Tcmsvp1gbwY4a}n$q_2Qd-{|zH!Q&N!K+@hh+%+MHUr&GZo>3 z{S=%eSQuseYAt$HqTZ8;9hMm3;33EJ=|F78(jKx*VD${ViZy6$jSRf#f{@U z_BH0-3hujbTbfF6T*WB6Q3I1_AFucF_8aSPVD^NZcR7Wxx-{0b)Wt6@S;*xttbBvK zcBl<>=S$r*jXKlt>6KHQqD-Cb-DGgKr2BFf!a8HNT@Rb?9j1@zofhvgD57KEy29C8p;#EtXiwt zq>o!-y((OT?3KxbYq|{W-aKTQnsZ`V)~s44CI+nLS^$IT!Q3Q7G8{?Xub0caCNL;B zBpFvU{<&w50kd@2U-Qyk1uuX3N7K z?(+i8(}}EUzwpgbG@l$EY%;$ed~^h#$dergJj~yn2xf1-r2b47hKeRY9R%GoC0{gN|S2t_{j&zU0@)V=adV#EsPGouqyU{#Gn7_XC~XVGPppPuC3i=f>Oq z*_{)hH@HMb=F7_x!R9dbdwT^|jh?y}a-45(#a^;Uw;L00#WKPJo9Lay$gMkr@7yWz zUb=-E9i@=MzT}CDc;mZ}BsSa8z8LOo;8WHz2818gEzvXS1@lR5?EY|>*5fvjxlNRu z9$CTM#r=?Xi^1B!$J&%eO}@{=Y8b|A}_Y35>NbQ# z7?Avkn%0DwpDWaax#-Cwy)S9M-Yk$zEoP*m8)G4Gq?PVwY`yw{F-RNPCQQKA$>vbJZr^23|hp2fs3}X-P>%10IiSir|C1 zhAZq9X4PxcA~tx<=H?5>_>=Rv%H26-=NrS{^HkomxMk!}e3|$WeTZ2o`Qxg9De=%CL~Xk6uvAQmW=NNtcyP zLh?ZRdL?VOozUvRqU1rpvkf9ER`k7}xKgs`LC>e4b!OSy=Ns&nUP_}4xm>RggtizMjYx_{e!6l&n}UILx#CX`7!9f-$M#M88S$1`_Io7-46`gNt_n~2-I3Ax*8^v48RS{%AXh&XH~uaQf?3I{bXPhAmPZ^ z>I_w;m4gwJai_>e%>1E4cT^TkMIZnOj#7osH~(vcN!y6QhXkHZikH^?vM0^8Ce-A)3t1e!5d+DycQ> zFSTxW4s#8Ds`Z#a3|z#n4)i^?fs3v&B|e`m{0j;GZQ~TA>btt1qnBNl?(ox14Hp*s zyJ9gxML)I2U$(J|F355x&cUrI0S0k(@u~4Cu;Q~giD6Otir>f+XELIOB{c8( z0uuDaJ+Ny|3y#_;o7arP*SsDzosmtf4f|Cow$=W1Anj^ z5dwMzF6pE#bGnoi9ZQ4NNkAvu;u2(#UJK8u6l^ZEZIWy${JiOn5iHDu@w3Sk*cB*L zw!b2aY98M%mwT}w>YD?R+xGIVpf1>xo>?|4TRcshYk(*pD@^62T#m;y)9iR>$Ue@F zaFrGAtW0wmLz?sh4VtZn!|bwx)tAUZ<<17*LQhmfObj6U{^>}j0^!v7AAos8Buvb= z8bGBfN?e#CRGt%l0`Wn9Y!i_$BMSX%<=F1#=^pC6G3*0U8=e#^geOV{obflF3_*4EgVS$9;{QeG5@sQoU05A zA8>Gt82JMJ^8IgvM0&Dltm%ngDh7git>odR>c?YvqHvbsWBR^)t)|M%D#S(A*VWF^ z@Sf#&Q2n-HwV1O&t6>F{-aA2-1(LRg=z|)~?QG-_+Hm;^w-$iw7xg72(o#zZdUEa& z?n}wS<^OyQmd|djEU;jbD3DwNvMTXHKhggS7}oo6(_Lzg?hMf90E-5@)2B}c33u(K zxIp7x4LDV)yyp`MR#0Wk^T`BA13w!aLgB~HTP-hp2DX}##PEUU6BQ~`)(tA+dW}+I z-O5m)gpwThMeC+%67x01Ekf<&8n)}+@hTN8lt+|Xi zrG0c@iRIFAzcgjBGdyKfBI01ftVf;4^z?N1d=1z!@Vaz}Fu5^_EaVFlt&h$u&o{D4 z`B`I&sfxLiy6tVKBS9VJAo`4;NVA1{d>Tme7DeK*AnKeyN^W6B!aSd?0XE}P7*$Q< zYGRmX%$6=VoFbKaYCFp_Halvl>l;iPggapV1$a#<8{F8<2@x5^r6kqU;oM+N5+Zga z6ey<9Orj&@st39X8{S13A7M&HW+zj5eKZQTGCa~8=TEF-hw7|E6m7_ub?0Y`4G$t9 zJ|=mf>C$uv7~MRLG?2*UElE|e!s3O1EPe-I>w>lQYZGk3!8mfck&6C4aPjN}(BzCFsYHm<#MzpS)aEVA|F;|8p(t@vHodv5x*1xLbU zZ`6p0aO*)7&wIXDR_7G$xTu*~N*5D3tE?*CSdoiI)Q%avVNIBi8{gl!V_q;qpI<_A zw@gy3mjtHK%0>;|>+7*I^+{s%J;CbX#h~Nbq0TXG`eIX>m|RnH1vB_e`5|vk+L^q4 zL+bO%|J$`N?7`X8|MC7uO=CrRhZp<6^|=21!f;P(+cq0yY3b}uX%?PkcExhA@LA)m zBDfMTvsio7rHm+!y?c)*QkD zlfA}3jVW6U4mO)-;f)sPu2d^6HrCz#-BGZ4>880;+k@k?=}^!w-MLV30|C_s0vbMX zaVIIU@hLhNF-=@Hfj)0MBCZt>^mv;>SfOh^MO(w1*o#4@KNh!728J|~Kf=EZ*p*o( z)je}gAB|n?f%TQEG79==J`L|fpG(o2{hsY7n z3Ev+m!})UGX_$>c=omAJ!uKdX9a42mssa-0x9ashh`S@7+6$cOdL4yYW<4GqN z{fjg2^zCsS;k1WHd2q*Fmz8v=s@v-kRU}#a3)mY~Uj*wtOzw^tN#?2lh>lr*W?m?H z1F)&Rb?rL(=f;nMOZhNrm9z5Cx32Hs3%Cxu1dMA@V*gU1z(zOcNi<(=9_qMX45eaC zk5oP=^Qhm>NM1|&bH^fY=?KV5JrlPygDL1nd-y4-Zo^(Z$2HW}H#et$7xt3)Oig|C z)kc2G&8c%5*gZxSdgc{}D|Qa3U6~p)CjPjY5foE7DNy`pd|hk&N2wGc&=eY)V3Aff zOl!hW4$Zqe#;|Tt@^YO*BF|hSm(M`!DYT^cZi|h#zD~^UZguJMWy7~Nr^wZ3UEjVB zDCHx|T^4!|-F(xmTpF|2^U9y?h<1DMDnDqGiquG65ps$(OMj&m7D>w4lJ959!h2>h zX=f7VgtsUBypr=_*|^QyY(e&dxG&Nbh81kJd7v}@hw81q*`Y%vJ0w3Jg|Y4X2}(1| zn|!B8hJz3eTlef_%WkssvSg*6gn{h=;V^pJ56+j)eZhvjqz}iD(**3jjFnLk z1K5y}r_qwQuT`!?03@9KXT^Q}MOQCc@Jx2U`uU~M&zOph7w-YFNZ`h2iY`Kx zq6hP68Oi?w`;Ck4v=8I)V^7BX4W^Q|yS9qd#pV z;B{80|La!#bq~R<;4=I&-~@1}Uuj-GTw$5<^AK`AAK&99X*&_f=1=#Nb_?eJxv{X~ zK3v^!^3J7q9)af1qA>^xU z+vCr->PQLIB%9%Xb4T?AuDr4jK;My4-*~LwD(&h@PW4{fdYXkwB$(!o+2YoK{orj( ze?dqHL$#;lOqE>_LIkKgB0=5v{<#rQLJH_s(D}3u#D{SACxX=))lPq2PZE($F~|KY zp21mQ)5bWKruU4z_o>G&@Z5=yNI|%O8lpx`QU8h*@u%uAHb4iL2V%ibD0BQ>v*>co zeLXUXxj(8jIvwNcOfec55Evv7)Yg`Tym3gmxU&q|54zGg+|lc7^${7}+v{yI4WPS! zGbJcyMXS{N#_gZ}uWv~8-S8=>*TvqG!c(J)p_yVuh=S(?XRM&FE}eyD>-IMkcAP@{ z#5F?eVNi}taI5AfZ$@2#^76FOh^)$IL>QjS=PPT8#3zb$_>XlH#)=YlPoxklWc zE%dunEHcx8X-UC9e=R!y$TPf}s5=!FdGz|=ZL>Ce`pcTY@Y)rTb09SMzQOdeuzj4iiQtbYfzA z97)1Z$p!`aM(s~Qihj;fCgkuH^|Brx+GRXteZG{m-c_`E z&-siw!HPR!v^LkBl6=o6TeJfrYP4oZ-?Q{I;&Zuz&D4B<>7x!dP{|prJl&2}OP+_c z_RFKkN*mktT=dTosme_8uP-|q!=f@CW5}UtAUsJnhJf(XpE$`M0(+UoGB847rPD2@ z*91}Eu)hob+gZ0WalHXV7K6mFVINvg6GbPr9;A$GC(P~1O7SN5$E8zqUaM{1_Dy;6 ze0<@tT5}E}EL7PQjHfU&2AP?%H8lFs8-&Y{0t|ytVv!;tO^E96a{N6b{(cIG-R(Rp zE?YkVoFnUG@0`tH=zOO+?sEZeF{Q%s=S7xitW^y zlkvMD&uKz4hZ2YZJ&+**m?`n;`_nvsraf8@l*9a7Dp`O0^8(cSTQ?~T9&!t-;y4-n z%wwb&xq9Gzu+)FQ51~s^O?m4$?K9k z>rY=u!?#?HWYWt;aEyXJe9~!w^Osj^p~fi}RMhT7Bk{8XY4PE^*(WWDcaA!=48!@r z!n}Kf(G?)ykX%%hcb;v9p|W6glS(f2Vow*q@XGv`;S~iSynt$Q`oC`92pZr0=LXSq zpn#^`57!~pbN>6}jb`+vPSMsve}WeSTVygKJF(co0X#9~QJg<3^7J8XbTuyVNyqG%S_{d1MW$8?9&mQ071sw(}7wdu+tBEVkN} z@H+gxK0=ZC+8>JH;_!V|iy;534OdlGi;Y_ky{U-w8)8RYlZO1)D+HgoFVIT#7)F>= z4sx=AP8!e~>NsmQ^3qSV1GR7GX&~=jr0AeVd%yeH^7c*IY_FqOkgqz<`eQAnQ;bFH z{c9%&wnqV7nIQ<*9&p>Y>jq-waLPUze7QiK<7t(Yr-SJ%Ebph)rNHmSB|`WCrxxcg z#LZqhR4_C!)u18(p%*Dj3ti@}N2}d?ylT9gV$D0=w}x$w3;G^Qei92ZuKJC-jCrXRCA zP_?l<6`io1D^RngsLQ7$YD*pADqHX^Nwq&Ji#o|<(6);`UI>Nya&^NuJ;nlqU|BJLo5}lA=_`s0#Xq?j z!~Ukkp{`;KnUEP`hUb^_4GOBAS zljH(`hRO<{6_UBYhXd%j-0#2lY+4R%7P;?PJkbJfdl{Nf@^xw2+B{{YE)5A%5?=v3 zt?mt)r?zqUMMR}`P`kR*m9>^k7}$xqb;@n4^eRcJ%IBlNAFO*n zTH^bB{*{|GxwOW)(e(UtgGtdA zP4ey+p|ck1>lCa1(lljcX|}Ma6;!_Edb=Sdscxa~c5eR@mp!^a-c&0*q5E{QVje_VAcRWuF zZQzDjQDZr%QL!Kh%)yIfRB&rP^ih{rRjf%dNr4S20(po35aS1V54HGHw6+~fgiNPhpHfTX;?QhD;9#|rV*Yl);-)6tbU|4%cqh0Z^NZ`6>m_*HU} z#isF$Z*rAdPzV~%l=01)FCwBeD+o=_L>5Pz)gEUlx6xcMBrB``N4ewk0pMW8O*+aU z_&fAU6Ix7kle!({s>|%`Oc1SR+0CC!iX$tx@jSNkI;u^xuYOJSsOp6qg_K;Sl^b2r z@ckH(fkk~CD&=QXZG2qNScXSKa$(J5CGszEBRNrZ_3H*&O`*mkX(0h?V!OB2R3btd zh%|}5z*8a|fbKa$f1W4`9nz#b6a1t~>reX$8MCb~V$rW3XQ8rv7nK`a-m}m$lI=E|P})IM{>|JX~zz-riCp*O~k zoB!N+2*j=~=t6z9qIclCy5SRY*`iwES*iz8+YmIB>L{zM$pk&o@&0BxV1gO>}o;?BY{y_CGh| z+JkX?J=YH$c5t}COd^21*Qz0_JPpsinB&KWD35`PzXwO z?GmQb7>1_CHw zn5OD6_g!rpf=KSnqeAmD35vqp7E@6FDY$RT^72VeZIL1 zSIUez{^te*X;U+*ci|vn)2z~04bX!`>f#1m^&5Thx|E= z4WnIk%Cv>Ll-2{Z7M+3ysl~uR*^dXtHwYVEZF=0m2GLpA0$=WBT&W`oy7rBH;~1ZwSqw+txNuLu9JdEYPw22<0=%xfCp)ty@3m6czz|95 z3i9M%-rL{)SO5?aSpWbcg#Kc^rYAVZUItWje&Ne=-i*0wY z+nT|M)#>Cb2lle^-+KvnGCzTR82Vx~)e-FIGG&-%n2OTKZ}4Kw*6B~UYlKm$yEDXg z{h@+nX*F{xi>D;7AN6@U?I8{Hi02k&jO%^L+pEGX;{zY24rj|4XRz|VH}3s1$O}ze zZZUynZU(yFk{hZqBDT20K48}fEUgd-OZ;O{nyX#~%XBEmaY&o!ycL}7y_~3xNUkWM|`v1Km z%mprZJpghH@2Q`1+}Bj4!Mwmxe92Szm;mwP5iml@p?f^Dy@0_2KdXkmyJUQ-j!ZTz z*&t70dJ|Il&?Maqk_SAH6_6FYymI-;`Tqmx1;!Rd3$W5Z|6Q7)T8b&U2D+I0;ex6R zTRqZSQ}K2{lS1KLRdNmSaQieM1trig@t-B1VQZ=w%79j7KpTX^rch9c2nAmpBMUH* z(GP#fQ2g%$1$k36=T_@H-YcpgNdrALAW{@+VFe}yU$9D^Umo_MvT(~y?I*fUjXEoJ z^qR^@vAaR%?LP(TE!0|TdNxTe@c-_Luwhz9WJ}kDg1=%}!$$=t66rNW*B`4nS)=s>Y_4BMqAB3NKEhxVRi=wx&i%b!1dfX7LCC+!rZ~O;Syd z$;_Io5!Sfaf)T|`k;X$&lgR%+SdF+z?*eM{}VaxpbH) zpX-&g>U42qT{e3jH7odHcy`L8f!VjMcE*qV!0q$2UE-{lbLq0Sm*Y8q^glN=^0`M2 zseGHM^IjJ#qCkjT8H!Ga*xr{Czkf}p!PoN_*)1Ag^Af$iDs&l5X%)PBRi)vra*!#s z+Q|#u54l3`(q9ZjdH-{x!pX?ZkX(~7ws%cD*{c*MV2~)&;0~E#KS|rM=QlU3%oMBr zuz|v>{CVl+itnP*EneE9!~yYSuDy1NwJ!4ZdoZ6OM3in|WmUGeR@kIn?8!#|Ub6d( zRIHyzh@Dd3XkYx%;I+%fnUj>jh*w~!a>Q#HG4hyRJ1=R8`@TCkq8z-o7#K!`r+8LJ zRgfE0+)0fucFGuNNOiD_!zw^iuy}&^d8aJp@GuCBLufU31!{PQ?~MiuYIvq01>{v6 ztHqDUZgo|H2``*5Yoy>qB)u z2+3O_WQEB}ZuCQPQ}Ynb6)%egjOx>NplN}Ow&QNDmNS5j)oS~E{i+{{wyw?E-#3#^ zs!`R5WdLb1xRfWW(edg(3Qu7Ci}9S1g28jTSR+Di5_#LDM@T)u|DtiFN~duJ(-)UP11rr_5CNCNrc7WbfGp&Pe(4}kKNWE&J3vQ40#;fN z!x&oTkK&WKTsm1yVofjHi)*rkMe<}H-dew~8t}H@;RsnzaYMa%`Y85Pa3WnNl;t?} z>dCc@lldxxV++W4lRu{4yNQF3RrJ-~{>7W@{&362Z9jQiX_yXMHqGv-TjeDck*TJH zU3;7har(mAX>8+3sZ28L(6yC2dW~>$oT$&&Tl4E3wZYQD4ztE=;0vY{9Z8_M^L_76 zM$k*qqZq9<^lZAuTJ*-Onbwv-AA}m39d0)m{WC#ph{8Mb$8ovBO!+KKeFm+NAd;G! zn{5L*QBm3#*%#jDuWx(rYFS~9Y-(w2j``8t)ckHi@N+(^@vBIeS0;&OCB}$lb56BC zga}(bz9jYSZukCj;_7IF_gmr~tWig>u?{ru`w_EeNZS3nC7L6vCSptiQ&pVubJU<$lW& z*#LEhwC5ClqS9th6#6>WY#P}dn*d=wd79?*dt3Tv9aR@)Oo6n0A!|Rz!n*=m@*vI5 zAa~7xR!c*Rv-!n<_}4*QvV=Z6M^5H1)dtyh0kD2a{WMFr=0UlpR^|MtHJUwV;_6rB zha{gSYoHrW>BW}GLi!|08wwNVoA47-3SC%k*ReyH-EPa@m>hx?&v>}+Z@%X<`-3+n z^O9d~NIB7liU>9Coo@`lE|K@Lz!8-;WMX|pu*+N@?g+xNRE}s3R*CJmC;D^?jI*ld zy{4wiphz%-N(N7-Bz2g^$Ysh7@2od$53@&Lc8le;@2NwTdyoo5NQZ*&0l(bS!I`v8 zzPXivS(3*EXRy!pO!k4{ZF*+r-ENorP-0gzzi$V!JY6cIDp~6^T;hr_9N)LUkSd}P47yfGu6d1`>?@SI* zPk#rz50=%G8k0Edm!;9B4Id(`nifJE1Y*R7eDah{O6R9>P-noo6QgZ-r^$-ybX+(i)O*9ehbjt?1v|TrjtKW*!@_%`ij> zXcDFpUyO$~cYma)(Z8$z=Z3JeiaOV=exLEjqs?)AWveYvWH1*jJlx1BbHBpQlhk75 z^zl0iB9^TjMc(iViMf|B_5RKWn@s_IkII~{&O+TW3g;rx{&MD z+OCW&o%OuMvi9Akl#La^g_{pE2aojR;{SGt^AUK-va82(U-AY&Ni({3L{z81nN@>^ zQ+WJd`i9v^YlefcWcQWd%ZhOt;TPf)y=#mhV-(b|DF0DO9zVHmig&u)^}SCx^vfF3 z2q)VCqc&v>CMuC{(kP^>1`TpAFDak>8NSZ+BTq|~j9JuV$@Ev$ZWmGL`o71)RKLRQ zy(N|aq>)L1 z1LTUK3^L~E_+sW=Lg$1@QmwBScfIks*0l_`5((JtN=dAQUph?HYZzJMY5ZT}|HTEc{t&fX|n0${4%iBoz0 z$V^Rd-3mqGM!CXV!M|LTDJKrX8P4O_Zk?5!E8I(J1#l{gj9TK9d4ENQjh50 z@k5DOe@dF0o)o*LKjEugW_LZ2Xl?Q=8*w`?{IrqK(2oQUFKnF{j^C>{RC9i9{^+S~ z+GZ-&j`(RwQ(FAH`gm;G4uoNA0y(%R1TD$!$OC!8OLDyRP`881Fe*z)H;y>QP#-QI zQuB@o;E$~0gz~ksoj8t8=p(faN|`Aw5V_9;rYqOd4Z7Q*QnYucG3F*1>!A{q>}gkc znEi!YnBHW&7E#KmHIad^`azf`Tsrc;?nwe=j|EqZe|BR{=Brrk4h3(K`tOq-b@fm` z_Q3d$nwL^|vdNkrv-l?LZmVoON{h(kb$3iwr*CGs_HU?On#X~DuS5Beq%D`t)Qiiy zMCFvFl!#IA{fjxuj_%i(5z&luJXn3#y!Q*{9nNnhE zp^JsnyHfQ&OlN`nm*Qp-RzlrrYWOOAPyVBD77!q`f{8W=QBFQe_sP?dl%Fj>ryYX@XB4#Vg-&ra!PD?T}!=SxZV>*6co zFrY++s&$arn>Pm730-3~8VcW{s>0hohdb94Dk>j%Ne9kkQG12D43;EKKrs$KIb3+& zV+A+JVpnbIXfmVI-3zk4mms56&71G#Rbu_isq%eX;=aWCLzn_avjXU7h-(;nm z4-26498_k87#;XQ2s7`>9wbF#N%1jgzM@Zqfd`s{N+|whoLVqzD%NlEU%<_-3YsmR zn9tOwIAmga8KO&TuJ8I4!Q14E=zM zBoiD#42WQz8D`*6mh5ILrDw>fUWYRMbhtE8!VB(OeAl>w&D$%%V!CXypgw$Eqk4f9 z@?qF($?z?9!_yenJco`dl+I)O-YT7Ep;yh6oepL(D*L?TV1Q9D+8if`r0ag!xlp{W zP_YOlCk<$Dp`jT~e<-qOs|(0N+*rk)ur zuk3`3bercz{s?3E=LYQY^j^+0lAp+OUc+cJ^9oNkYo#CeO7!aA6KkTGOpm3-?)B~U z!U8tx;&_`5?K=w2R0MDhWE>g}EJIpo!=7abWr!CWST+a@73t&cC{AC8sw5Cs<0gB1 zstkLK;S)$X1w`dehOZZ$M|!hk=x?}Qtkv{p9Qy98w>QFUQV$h_KH7{kFL*|Jy+5*l zO*ze)731XO0Z1G7DS;TGll{LEkUaQA&{Dm~g143XEd;7Fq%&mTZjhGauG7}IIMaCS zwmpyi_Av69;d^Yrsiw$kQGCs>pdh1`{wITC`Zu*e^f3AJRjZ>RZDz->M3h!cV91aHsX-`3lryIG1bwVD;SXG`c& z^xyG8!%qAsJ$W)x(V77S8 z#XBt$CrKG6#x@*q)A!=n72hi; z{3wI+(SS*@pum`~pi!a$PF=vBqcAQ)(I^Z-xD^+yh#p{hO%|60)i#Xis`c@3&6>dy zop@M}&om@~lAgL(i1T_!KGqp*kL|nx3c}H_R2YxaW~AvWzgAIx09bvf|F=4)DXqp7 zoyOginZ^^XfLq#Fi|cBfj+kD})B)SbHb8s#6`65p)kstkky%=phK_ufD|s(#BiSuOu^v29 zBSA~v2MZxU=Mq43n@FY^z*;lRyZ*SOB`X2kTUR66`!hvDmp3=1_i!}ddtQDV6T+Sv zs$H`t1B|y81KhS3gBs5pLwqj8E**e9!owgAw;5gK|4U(XA>og0!^16w(P^Yk&g+QW z1y`v-w#XFY$g$&R5hhQD(Z#2SF9yDk+6if0fNE{}I?&UpB>yfEjX6sVi-pP5=ija{ z%H)BPR>3BO4%9v>MPf}yd0zZcdYU?O%%d2M367DPZcN}y*@ah8hKQe1+nM^8+%by$ zLz}&UA!7apv7;`Awp7{ciOLcd-h*XW#^LHGi4XgZ@StbPWYzs||L>FmpqEAEdDo8u z8}UQ1Ei37f^G&fmk%q;;cK>2#q6^8wzZX{xOzjR(oTE#FaXk_8m3*YeCVQrNp^i}S ztxF_di-kZlq;5w4T|+LYol!+mUqg-28uC8z^d%x7MgoQjAb3<UlVLA#h;pkfJF9 zt}@K0|3=GV#X~coq9J3DyNGSPw>qkmo93!vEsSDoEOysz-)|Z0!J%<&^%e&YM;Qz!l~fiejPEG?#&oq!<3CAC1)M|_g*vdV}cm>pncE8 z!`NdO_pQ)*TP9`dOI1>cYY`%>PY-@A@~vIV5e*|)m~AH)Hlm~05 z?w9-9I6?i>OZa-)o;I!Q@rY3B^pPP$Pxf_}V`q&3`;Ag7vW6j9*4Qa5Y$ zF_!&9&xV|$jcr0P6_k=Qvid_GZrggQI-<`2XpLfvkzN8#=Hi5;&tC0L5WOK<{Saab z3^fCG>U1HhFkU_+ZMTYLt zcyur~x<|hL@N%|Fh#6Y4sn|rXN|DIT8R_lyAtBwom9T+g`|Y6MgEX0o-!eif6v$dq zg6P-t7Q(19CT%xbD}G&8u1b_H1nZMNly7Bowl9>_?PNz}q`PuVmL{NdyvnQ=7c67m z$2~EL8gq$L$$X&JG0p6}{QHbM!hB4mC(xOEF5DVPWg-)c)mXUrO*AjrYSEYs@O9?r zZK2Bq#WvfyYU7Z6n|#Bhp}8}wY6rsPwE;?hTI7E*_g+y=t^M0BiVXx&dJ|N7uaOqv zwE&ACK|=2W0tTdm1PMfuUYAtq3n4)0y(5xP1O$Z8dlKozgc_=QuJP@Iy}$Q=u=g1I zU>`9?2sLxg{O0rA_jPUG-Zhy~YE5R^$=-HjPQptFen2RDwAz+As$X9jU#4?b>0y#C z*ji>_N%iF~tjTQ|{PQ{+YCf8OP}n z#U{MIt8Q=j9~xU#>vCeJ;4oWkqrah|iOG=y?&MH+sU!T@SH1SLuIz9L>|<6jsk#;m z%Qohp$L8={;=OBn-7p2BP#zf#g?jrQUc4s8dW`Zb{;0|Vr8p`oL(Ll;!aJq!4alEx z_1u&iP_KuWR{(&$YM&pntl}^FP2|5`tVJ<(yoAe#;CQ#q_ahSrGm801bH!9TjxUJX$&RYP9Y6=?+5~daC^DbO4OD+|kgUeh^78V@v6X}K zRF3H)xM`YD%dX5jw*aJUu;FRjFfPOYu&};pI%S>(S~GXKHEoMbtJpuiM0bbbKaD)u zTAY6u9rt$Ii2b24Y||jV+0C|fj76szbuK5y**Y3K1ti7O(!yeF&Q`-JBje>?6v0n< zLFPV&v5qkQbc&7Zc^vLIM^*k;IfG&`AtO!lYkibU7~Rv-6tOYmjQF?%glxF zQo4Osm*Ez`zREtj|=N zs>nGprHGgpqh}n&Hq@AIZpS%wftGge5X~a^*W0b5+s@>k7`rlRJ~YR!WW&G1rDMcR zvY%7{LXmJXD`|uT_dmj%R`%~r`2TiFTKImEN?5!~<+vX!VksSPC?_-+ zH8kgCR52DXCQrrYTr%{DTPn4qumMg!3JVl!LpT+kL2{vDGM=esuSQn-eK-CM<}cnH zdA-0t;y4*@AM-rzS;(n%hMS3^#+wm9rAB!0S4E}emV;LG;Y82I(ec2#m~D(0)%7!~ zGM(OQF1De;glIX?OcOrC-!zWc^Rh*0HQ(xz_v9`~eBLE#4l z8g8AkBs$rFo^LWUKoMD-J{_ip);?)KX~y-h*E-q&_sLUxy=83j|+ ze0=Odvogn)N&afB!Q_?ht`O#VC)GG@Sj;DtK5fhmTFA$oVVJevS7cH!w*erFjWIB^ zPQS-FZys*H$?|6Cch6&A?<{HSu>7ZV?_&cTo-%UI{0lo35zGR5!zmWE-asG~Bc?-| zqV8D&(rg2QWO743S4N`^rPC!B$Ug1oaXlY3-_FBKFEe?vTjl6flE!~p>km52lC2y?`z(NrhkibE z5Se~4_bR=|woB!qLGH40r2TH$p5!-YE+_GWQ9ZnphKslaeS^5NJ+?Aw}GCEuDf|0Wy!_-sg&v%ARU z==TSN@JGm(ySMVtTcmUdzM02n;qRwuuMaFNRNf?g!R5j5o^rv4Mg+ZWxpI z37kF1VKz3?%cMSGLUgW(6jY}h5r=b)ZqiU1xUV7 z@xnV5I!X-Bngg5%fEQ5>xHRQ%cI**=641k3pahgsxp(6a&7+~=Za(k?{u$L9+uIpB zxHPcNtAWdns1dcJ-0b~yiCH6T+D@-pOzw$5?Dton^D^Mp-z$*>wl z4SWEL2gD}i6cquPQbmL!N z4+vJXO8qs#0-eS`M$B_SumKbK)az_2*oX=BS}tYdqASEAPIb{U zK8k;5ldXL&eoV}bfTS)wMKsdu`j!iMM_nL}*R?WJBF#BdanPt^=rrD!zgfZWreiB z$2XU+#9GWm24f^7_?Jzi!Cu;3@v6g!iBui^h>k`VI|<|dVj?LX{iK2CQrNellCIvX zX{Q#SJ4(t-guQWE#&UkuY?kNC`2#>l9aRA+O(H^2UW3JUA^qt=ai1nmoWq9a~zAb!Q9p=$+Sm12+v zy|M%#Wyj|yO;#Je5B`~<{wo(?91=ezGH2EtDQPs-YD~9>WLqTlomqC<6_?mHZ^-;6!%tQ!VN^O4Y~Uu_rr3_Pe03fc^y0< z4ObBV%K}Q#^k-HI)0I^6y3!nG_4^LwL)A3fxyauu`wC}i5<^uZo_QHBJ*TDsZ# zB${g|^jBhR$&2D;t^9T%gNvelb;VD>k_X4N;*ezAg%8Dy_Gr^a zVYK2^!&DlT?I>dcx?B;li>moH^uY%su01vi<2y(d@*$lRSTf3gsdXi#9Lcy;$`dL8 zG_6Sd4sF%s^Y(@8U2KFZ^04c#SD*P+;o0YNpa45BR3EsLES{+e{`(Bv0ggL4FT4W@2XrdQVW^b+T(^}kTQ9X!m@J;st2#fxK+X)N$A4e z3QSMmRL@!Ux>e2`!z5E(&+{dYO*!m`r+O$tyc|qUAc{*0go=~|<^XFk9GB|A)QeC| z-Fb;mhFPR{pDM&y@Yw2@mQYF6KUh2_ll3on^dtDs`X~34ub+vW{63@p>!D&S!X;cd zzW%rAMjCYIkF)_tNg_E-WVonbK=NlQ)Ih~BL(8u(US)XP>{A^2&(-CW1sxvgogX@Y z3FyDR3jojz{h!2H{tMuVUSN>ymqc z?)+fYWrgOdbXf`Dke0f1+L61l(jL0B7Km6Ouxb6Te2a1sEgyp-SO&nrRV1mup4ZY5 z>yfuGEQKYxXU*}LxcQkjo1Bt{(1b7BWpEqj$<>Lv1Xf_5D;&wPG|SYm=yJh5Ubh(- zliAMyd<2LW^Xs;>HFivRDC)s_jT@?>CUvv@bl$-9Gl#0O?hp?3EfqV-lT0tgfBLR| zM2GZypMl;{`>jfuK&nP!6WI`-U+%5Bbur8CWkNyFG}3oOhf88Z>jo<&kI%5qkIQOOMw>&SB3abL>*4L(##g5c+% zt;xCqf1AHm`@ZO`X%v1#Fwuaq?!|2Qt0>oFiy}@612w#e#qft0tB=muit&Az&EN~e z*!&RRTp*bPxgCQYl8zno5VbYDh?dRO&ZT=z)e9xtvSGPQ?7mU0c=8XxQ1-M5bh;64 zJl`^Mo%H2vV>l6#*kxMIup5SOG7>jVtLYY93sPFr(Mc+s6yxL_T=;{I*R4W*kBPth)w4(G0f-)y9&)(7VC z8q%rs_2RqOwr7%60il>4X*7~oNXh0-Xl`vemzI%(F@)8N&6$25AP6q`kIsIp;3Cs@ z(|IP`^a|q>8lX(ON$zl&+=p5{#U^{Dl#~erDwk+ZgyZMvsp#8gZC5SWM4i|?<%^Stao=vWgxM-(F_9qD}SM7Yt7CUAG6H=3yD8RR zJ;ahlka4N@!W#S#5-nDKlKuP@nG&Wm6QLxSccOm1J6^R@gnv6MHVpmR0a)7EhCpSq zO^oa!-OPLBQs9OV*pW;>$&%=d%YFoi^zQO8LeAd+tq9k5LXqiih1pB^1It#k)uxmO zANYu7c`-wBI95%(ub0-Xk)zMKg|^%)kk~yNHbQj$y4DNWH+@j2-La#RLKE_6Q(YGY?x(-liYMcuuAsy(|3SSUBMN3)0xJe&Vta z%#OT2eWuk$R!;*a(1dF#Wrz~M62hXv3bD0mvSnH`&=GD7;ypCw77p_dDBI9+|N81M z1Kk)~$DX>P>(@NWSf5PZc+V>}9FNo#s_)4yvg#xZif_=p*-`AcInxQ$64!UNexkzx zbzPZ7TGT&{4FOVw%xZ^n*m%;|B(e?&U|izxlwV%}=nYIb4TN*^8o2b-Ft zy{!QVtgb#D4+gGww^8JE8OZ%ng0P-VL2vOE`I-><$|vFCK<-#LPEw2K4g}4h#n-NE z0!X!AtNOj3KpQ}^EsWv)|Hc{tUAA(cazpHbs&gHU2l7qjh;f90;WD!};Osi-2 z<9e2PHA9CysTKpYap8d|26kpQ(B`prub{}h{5n7b=QW+(l zmt>MH>Ol6vJ!z90OK!IO;bLzMnGXA_v!1(YV|*ns+UHla_JP7Ft4lB&u=nJ&7~UAn z@e}-r&|N!{hMO76B@EuwBcEd?z;coqtVf1Z>wl$oz{l>_d^8G3mdR-xQ2GR4;rR== zHQ_}h#5GlR4G9l7oyIhk#w$mFdWPjIyO0iD<{hlgpVypVh$Bg;S2ocrAYQ2F>w`MM z%}I<5oIBoFysxG9qMGo7&-z2ZEW)btQpkX3GQ7k9=mA4GB|%C$figZ!;bE#T+U(ey z?NiFXnCR|Zzqlzyo+nNQGa+pn^+p!gRU2_ZHhQ%Q_xCgV&h!agbIyTIr?5>MF*l5x zhiXuQ{BR%-?ry|k$IqKF4&cTF1an!lV|edNMB^nM{P{1hsdoYDZW7`KW$hmac8vo} zN};x9bz%UvGpXwWMRcMcubJzS(7|IuiVyJ9eUtw*dL6Y_2)r(A_Vd;g4OW{%^(j+K zfy*H>zCiD+I6yxS{NRj(0#;iFZ%Ubi1)s% zJ}FoIX_%nMi_wFM8=M-rOJqDU9toFVVsPSM2`yRWHY;JPIuL?drLaoiQ^Z<)Og%GV zGh-8v9G!oj>H=GwCio92d)Y8LQxDr^MnzLU*_vGWq20)X^Rbc`ev;{+2mA$`FXVOK)ijRSsTMVAF`}< zjN)aay7#bIcLf1^A1dFCBN5@4LI%B=DD;Y2(i!`n7gx!teaBQH1@gHq&)BH==a*Eb zo94@`0Kwu^vPQmKJjGGGUUnO4SBiLQQVn!*kZ(ZSsvhbS2X>9krvi!|EKWR4MfE8K z(b{oea_Ai7)I9XlUH6ycOG5znfJM&m9lbp*7r8Vcy#9PfvL(E3?8|s&i^jW?Z7U%& zBbyV4-njQp>W@&YvbjGKi{=_8ZgyoHMy4URJvbWoAu#D3tSV2$JvA0OUicNfmB z^WcL+O??044|;l$G!N!7xqu{Q6LU+3qpmY&hGjn=$zcv1eBpVv=($Bqmpz5WFhvr? z`PeYDWblc}s9cybwA@_uiI2I{#RCUDQ|lKN@?^sdmsxr4#PE4*T-x8f$3pG32VU_*`NKul{& zL$pr1y}7%P<8#rM|6Drb$XdDiaIh9Us%)Xm_L)RM{KgRGb$}fem$uCoMYIVlGfYX{ ztoc#ur&u?(Gmi`h6UTHXu2|2pD%ZQQUBrvh$3sS*e`w6gRVz}IV6e8kms5tpFOo_dq+!t>Ofvhi@^(puH!}LJ;di+R0h@swQ z13~_W%&;ds9;DWNV%;Rln@%(0xBgj?sQn)S^3474se)HcP1zQfW{bx+6Uc0`Q_HYQ zaLH(wy{F%Xk+*kdoQ@G%Nw|F#c2MG@61V{|(6i3nsQeJH!Y|vm8i5PsM!bPummaJ# zdq;n#NQ+JMDN{6>Q%g5dQR-vf7C}#3nz_iJyZG6D$1Dze-GXXdKrOjpu!H0vs`)pk zhqy;*Qs^1Qx3m_X4z^goL?BpMI%yxY_SfpNRq6Y8W{ub>C$Xds=@|}Iu^166;Y6~` zrea0&m>aJ|uUZonUiXE-Wz^AgE{$+o$>Cd`d#aV}XdAZIB424xypU>|)$K@)HxCpW zTgh>%aqKTO0Cew=FQqV6R+RJ^Fp%Aoi9#I;PN6n>$yZS?a#yCieqI7t-8lVY(F@?h zRSneQPlBrcxpBd7J-vP*JL1Q4I*#A=J$9GQSw|zDdkbY_XWt+?-FlV@R~Q_XcCWea z>9cuT^{NrV!u!efUQJC7Yepya!T`(1XmhmWJkuo^&4;KLE5(90n5}jJP7*pey3HBa z#zOS1l@=THoR&7Uz1K^aaEN*lDoV18?6j|{LWI%T!wpNf#IZ(ejr8L|AIqUO{cNJ= zNe&dg2gr7{-q+lZS2)YT&)KFf9c74CK3#si>b?Aq*K{{koYHXDOi=1 zlI)%B#!C5M@UfU}5POEYGBu`bu#!64^$y*Qn;(!mZg5R=^l!3$$XPeF0%yw|lGlD+ zzFMo8v^tcWez)|LA9q&24CcT!iD_bWrNf1dmWKzSX2)Z_{mJ>tSfhE7DBpQ$qvEDh z(FNHU6e(epHZrfk~oXnX#ePrUsuWai>^$7_iA>bQCY3Qr=n*0k#<)$l3l}N>+-}?fLILTX9W8Td@vYL+>1TR|_Q$ z7UBBSr?zk=$G+`Hm5M>RwaY7qSx3vimXDe%2L{Twt`6KZ8j}R;1+ab7BJV_9tFG;n z7h23EYA{hzfD&lxhZ?FecycA|v(hy3{m0?GykiD@tZb9(=m3e=(ao?_M3nH)#6&&X zc9c0(s-)zQ_U}YEYGxZ4v%HdR8Jm1Y+*}F&omhgEtUOT_k7}A^oFKG z#@SAeJXTE%Ix9+wAy06?%ObQ7;a1l%j&mWsa4>??`EKzW4x}LBkz(c z4hvAA&}7VH*NV+*!+-*VlreXyG!~LJzUKIO zMwiJX**We|K1a3OWnq|{(35zk*B*mgFPzsTauRgh*+=Qz-|W0JEYZo8%%BD2df<9>-Y2=@X_aog)&H1#DTw zeO<)qy)rK-Ll%8 z$impWET>CJ+Sr8!WL1sJQqH%@31`fkhwOtGqE)(n+nfeY1&fI-E0mq%katz4X^H7d$}5sp8`y@*urb!^f~<3QwgN^xSxqs z{qBiH4s}kKh)!G9Hih!_BUKCOoE#2n8sWGixUc9xpRk7ucXKTpRl{Qn7iNO8ISk1* z`RMxbFYAq|+-WBd)BLW_+j)I{?k76gNqkL&>j)QV6}V{IBrd!4=oDr-!ZnKkQxL?{ zJp8(R9xv2321gRr6D}caV9WeETBWs)g)>}UWWFg4QdU>-qn7(c74M^si zo(FM}aly)Zo#T_M4UcC1#GC5N>o)h>tHfjvQ8sHR(0_QmG`z%_n>v{ zov=>xav6o@k3YvGMYllXjhMospB);`Ke3d@zvo`OP)BxHon)-@>%4gL{GrBcPM+V!dqz^gkb>V^ z@E(_Xh*w8lwrKrnFLYqeX8(No7QFk3p=F4V@=I}2F@zJXvp8iKI_{E8Lcvw#{14+Z zb%CdCgZ_P*O}mGy&)W;@^135=uhUkc^C1S$IYT#0;UCQss zA9A0OY**cEe|rH_)rjI^JNiJK`>P0JSVUd7y{H{#^Y0kRpbE%PX_tzhqSvlw;*yJdOZA9{*k^`Rmx{)!!!@uM;yTzM^ug^*YFLDdZ zR|A^=e{j#O@^69ke-epanzj8y)2B?X1nzq@{=M(PL4frh+6D>$jfr@pv8D5`G^K=u zt-Ex(3ZQ{gsTqEiSE!4G<*}_%Gd-Z8{XD8b`^tP5_!03@r^3c9 ziYDzbei0Shq07hghsIQSqv1ieG(^6eNdAOuYrsw>4%VO%W7#URjB%B^=~@6W&$<3t z#-XAHaw*GyqGqbQbs&*t;o{7+s_a0gGC0e+VzRwxPj`KoD%y*CMol>tI@A4&u;-_7 z`7xX#qvIh=*A_vJ=~Hi3`fZnJ)Vx_1fuya+8r zOy5VMMGEyPZ#(+0z`s_jBM&9K|KXVN46&Rd(H?3w7a`><2WE+W*Pgxb?#4nQICN2G?z7afqH#GVF&03H;>Ch z2h)uH`=GgZ@TP?A1dlt2qaRXdgYO?ceOc0ciRU9I)q%HGHq`(cW;Ln|)*ZkQT~y5i zNXA^}7NEj>bqn`Kk%y_S+MSSH%^>CH$NNi4(OzO|a@SZ_Y5ESsZh z5cxwS-P^8LzD{GGQL`{#|1$O7jeSG0s&=HXCV3Xfj&ag818>4i{52=)JDFQ)g*;*#*RLK&+LzwGwW}3%#xkU_&ZD45soaXHC*ChnIqe z(~W==*At`FpnlgYM+tZKTQ*fmrpG~amDBi11$&Ay)Tev2qQs8kpm$m; z%lZw9n;q$MFX>a1p6g=r*-ewMjm-C2%VGF<)?79>s=2o7wWp z_m2U7Rh3)L;VBlrF7`mm#9~}_7sJ_K4)WJD&K6$2Yb~UrZF*&=Be00rV=1j|D%RVn zn=)2!1zx?fJ^X6^0F0 zh|yGEGLm$O?D*v6!M?(4{uvAvYEf2|Hu&~ZKt$Zk0_L*aDrCxHEZTA~XP61O{Q^)Z z5RMa=Dbh+&auw}w*X`gc+SfnEW)?*hE|j;kK@OOq^-f7i5V;pcH=cmck$HO&Zp6yt zOGsduwOaUJzn6(d!rCS9RSHvg2Sa@?MI_`vXw)wazq8*7>^!D*N>wuG$(~A`DLwRV zShM#%)olA-5q+v8{)v*_arsyCj(mlP{7JWkaS5zcQb;vAOazt!(oG*jb57QcuBHh= ze0-8KGhtpDmINSm+Yz!`CT)uwrVZ;Nytelos|9ObkL&7XimH^<7JO~*4CV)k$T;fH z0x1JUJE$C*>+$oC-FzC9j<^DIur+bRRKn;7#izov-^~>Kp$UY!Z=7x*J(wvS z9A06@rcu-crJ-i={(5ocIY*1n;78`dXt4A(`S_bR<{U+V0Qif7X3J=kpVj}R`kPcY zBfkDO|4k@5OGeS4rnU*T=jv1civ-4cX%@gG}8;35XBIF2Wf{*^CWekvIoBEMzu zP8xAIT%qQyye2DAQK-RX%A`wY$YOzT5g%Jq>2ON)H;o=eW`;rXqcf?6!m$hSEknr#4wTOGC#$z*aGtV6AZx#RcaLRGq-mF-<(fA=RYDTEF zsowm{+jAxWW$g1C*cH;cE?oK^JMv8{%&M0sp{v9b2kU}-DcY*48-MO3U9S10QSh~a zubr}%a+wx82tH(Ch!&4Sze=fC)IE0pLnFP-?@3iS^dvw0!0WwXQb}xoCLr1P4toXv zQ8moLtswtV%RO3A>4Gumxan*W{#Ky+;O6N+GVmVZoh{y6$c;2l7u7NDTA>&W9Ivv` zfgc(`VK^+E@KSY(5B=Dx7*siQ9Hifp!+x_!ZDYA{zHwzZ=|T;uTut>NQr#529<06V z$!W>SWv%6!8F~z!IC_UjG!0C*Z$yw%>D+IA|2fyoGYtMYD1;KCt`in$abKm;VSV`~ zTzp>d;~mpR%FQQp=v~@fILj`V!o0i2(Ge-Cexk-*Dr3H0tm{KxAJlV?^GiQSL@TD@ zg#4CADoz59lyjp{y9Q^dKQs=F(H;AzDBBp`)qjz1ZzuoI>_Wl7>*LUv@P}r_kn zIfF*@GBD3F(IHJ+GjU&KM=$1!Dq@ISFWW*R>+kZz(*A000E*x|VHpdr*ca}lX*IQd z5JI?bzf9yAu$;A(pRi@o$V;32R{!~hU;dALP3%ZHea%rNq&&B#C2Zv&HlNR2%ijQn zL1=&W3cnux4^>++-rD#@s)$0o&`^VA)VH55G4X1bxRWQ;QVXSJagUWJ@=O{V@+}!i zs^r6jP}^HzS~9{(gew`I9e zqWsRS*`U*|k^`_jZnqdzieiXp=(rpkt2JDCBoCT)pmX{tc+}=9b(>H>3Fd$Ia{P^b zJ)b1mZ|_qn!uy24bL8zFFW6C)o}YHAWL2$I+a9mLTk49sx|8X=*PLp~9g|oBfonKe zOV3OnCG0(Jm!7j|Nje6kv1j*|Q2bPPG_RYgxd+=z*@_&!F5hB|Qvk?c%(y75TW}pb zEL3V?{HTJy>^xV><)F%^(_yipXq!)+>PB89@rM_Zd%J9Jtnq=!2R%gJbMGFB!rJU4 z=b1Os!Itv^264~_V~Vqxx@$fyH^aU=?2dVH#p^{MetvgQl|lm4bUh#e)Y;{7rL)@D z{857zI4XY58p|8F^qbAz8+^nV|J?^ESwN-&COpUE9(s@vy?MBKbc*teLHV|)G0VAv z$>Lgt930wAv3Zd=*o7c!sdggwD#~dwcCw>3V(WltduQIo`}Nz5wC;HxvjBI)Z?s)+ z*|`@!EDZ`+Wz0-$nppeexY4P##p#PLTp9Ua;I~A^4fAUIfYE)VGPd+F#2|l5PH|N$JDCmg69ZGkV6#<>&-g2+hUacY;4&CmmdOb# zy2|u@0kYR4kC^6qro=@)zY^YId;0z9m8p3IShCtUz|V-}46{zTVBMMo*VmtjNT`_~ zE_r%)j~k4`!q6tcrd0cF_W)PdtxDiCr*pF19;}{EVt8f0^zypM7Doa`={1^@oT7}A zrXJZ?JAma=@FlfRidnr!E>?i^F+e)elCuO5Zv4pLfev1fL}s}fK*}Muj(z%)0+uU% zd?ihZUC#2U5N@EV%rOvJl6x-Ema5Qpc;KSuXz)$`(xoqL%Ws(fD) zsjH%xr*txKsQJR>dNTub6vm=J6vy+yPl&V3YE`sMi&=Uqm-IrH8BiK7m~Maj|G?b2 zpne&7sh+Zu8%RWPX$N@_jvaCao;EgQ=t`8H{&QKcq%4kBVrsgUbDN8c)Z7vMDx3SJ z`Tgc|Ja&lAWxM4rWBum(1#^TIc zj6|S~$LIU?C)N&U!h^eCuaYOe8pjaN9$85{cbm1jbH~Hq_j}%g7V_WA=0-F@b6nGb zcjkn+zYNPm`dtB$ipx{B1axHQ+eM&F=u}Kh)VK|7$;5yHEra;~GwL|1XiK-wy-@1x zLFl*zSG}V2Y?#E)q*wZgiVq(B3C}QSY7B_Iyzu&ql70jyLL~Q97WFH?A0k4=YBYu0 zm&7~Cc(o>#T^?XF%xmgi<*^hH{hrF zhyi}YWr@a~a@mu=j(X-pjEfBqM{`e< zut?jd5;%O<&sZNxY2lpX)dgC3_*zA7Rz5aN?(Tw;tFFXH}`EVz0r5W6r! z$-JO{MA0Qlm9K`^Rq|3l5<0>UVgh_I`?fS^vZJP^<5C{^P4%fWdtIuz-BP;d@SXhD zhui1jGm_ro|6!kcE|}=f#1tIKcgIs$;1uqu| za)9X0olo;azDD>AAp|%KBWt;vO}QNi+HCJrR07{L-uo4c)|c!ZDct@%*&`lv3IPyo zFP*t1uBwjYnXj0=D~bR!=G*EQx$p^5+LUA;a-y)8@>u=A1=UJtlK=3Daja-@lEUc; z$-&y0%bZ&YvR#hNar_QZxc;HxjO@R3E&Pgy`i$~T9wrODI*KK6^}I-+ba0W~QQyGY zpUI8POAAbj11_S2S~hsb=sW`-0%c145a5JSj511}l*GPD^4&Ddk1R5YQ_ug_z;|i1 zK3k!OnOfN+ySBhF;ahHUqMLB_HGBSxB;EFg@dqPs1pd&3B?$rpy?lw0dZ*?sU$UaJczCNYSi~2cE@;JMvD030uOGB;eh^W=!m8E9(D(EQ`7-(|f z=9zVb618r8>WQL=*0xsDNB&bQM|1fv)=LwJhFLQHc|J#p*fQt5C0 z&6Y2gx&e~1R1WN6m8AtPZf}0kg`ag>Qj#Ry$Li+icOxUe@Ap<}IZaA0zK?7!^fUn$*8bTSiA<38F+fL{u@xC?oGlQ4N}I0@DX!$$D3XkTg-R zti}R$_h@N75zgXn_hprS+35DfmBhA;=vFx2Cra9()%e#->lcjU>cUnCyk-q$z9HZ1 zA6<@+GqrcT>u#@Qfcrgu=KkqlGIgRT!ekS3@LrX*}onh)jUt(vXrqh3=ha2#MtH)B5iNL-E zmslx&8IaVD%3F=R-N+uFD9T!UtHJaJEJm`{JTo9YY#1;1Mcu$Mz2AS9wJ^8Y;vYTu zLoPS6M=i!uP5;J#E2_pZb%ta*N*70Ja?&4V5+td2l1Ufgl{_fIr99N$z(2HG{I@jL zTqunfx4Aih!b1zq)&=j>*(3hjZP)B5+OfYrBZjdnf@$C03Cgv7w5%3Qgyh~SeEli& z(l0ZoS1>cp`o#iaP*V5M}3X9^~MZcWQK$P z?|)?FKYD5fc(1pK(8IT|+N~{o?HYbMf3RWUU8Q;k5^sC&zfXp{In54azzcxQp&v8s z=2NhA6P`39$9_XFJqzgGZfGqA>T`pf)L4PW`nEcXuSo;X3f$dYG0rM-RL#$s=KsmR z87$yRUNNRff8>uodzl81PmT^XL(|l+{ru;>&GhCB6A;Le0l39{&xbL<@1Z`U8FGhL z4?yIiUgylr4mHI=AY%P`T5?cWat1_9qG5JKu-c_jwMi(NjObne@nIL--Yw+oMwWR;|`< zr@{kvlXGpXw5XL-59f1DtLL7d-?*vRiBDow42vKo$*y*2)laU80Po(qv?71dN>rSTp^+X(&7#(Q+d#&ZH0%=Q0BNpK_qICbb!M_3y*E?7C7Z3XC0{3y%=BzvtGCZxr5 zjb;VZ#fphRjD^SSzoh({-;afvdMBCa8hHiFkvqcb7g=4^1x63r-|Y@}y{jm%09E7> zHm&J5^;E}jhK=>!put!3R_nt7k5bWG(WA8fuX=iRc7_lY3FOr~)Xa!)M1j!n>jpm@ zA$2wq95C;bf;?bEeo80)Zan2#R&YaBvEir@hG^8Bch=au_*d37-Gri4&$s+^xw?$e z1$&aC<#3eKSU#l88p&>{%7Ms8Swicd>Ol|?ZhaTC11xiB(5-*v!6WU6 zdzEnY2Nd>l_B5}hNAx$dy%|w@<*v7y>u zYOwvE>o=v-$cJ2l;T|lA6|Ox0Xfrf5@Qbz}Osktu<<5oBHEpe{)|}T&uH3%y;62wN zQw0A$2mx%U-C(@=hbG6G#^d$7qL02To*B?aV&G|yc48zQn^{h48)#KFTP~ZIZ z^2a+JytslNaF$8ViFcl0J>RYr!IZ4VmfcJXzK}$FbWiS`r~RREsieF3smeQP@kWR6 zhlcz0_oA+g8%^z&7(xU5ndiog^+@=1{UdHdwt$kZ8|#VVR!IK|n|YbLAAkCfn(sq= zLlxEUM$1yGQaVbzTcN5&eu#ZU1mWl!^$5#G^^X*lRYtor_x&FlzTfIB2nXB+$3uD-W3aiBXeg){IKa}GB9N%1 z1ddg(RM%9Qus}qX7?I3^9rIgrs;g#B7Io%wQ|SlQ9H!7uSp_jXf3RUM3W;@y4CCfp zK6|;Ts$NbQH2FjGbfT=nx7}2)$<=j}CuLfaMVLuVM@QfjmtzPbeW~dKDThul{Mp-! zIJ5~Hrl*_>gD+0b7j5T0!$a4LoY^zriX*2|;#H+k5L^$MHL2*xk*~k&>Xe-UFHF+o z$zh>5_C{1d^u7kkFHdg2xb-UP>soW8Amss52iJY!$Mw-o@y`yt&w3E5sVS>Z+yeh{ zC!JGmx1~$rQg^cp+L4X&IoHtW0K&>-UHFcS2OJ7i9Q@)&Ge)M1`!$|T&pj=EdbK+_ z#*cBd)Ur(lr4%s3X2dvqgbbIbEe(my>ohnNZ|Bh7CM>f{X z%#`Lg$K_5zT@tWtAsf)WwI-EQUG&u}nQo2l#yslouHMra^TOcI7sEN1J`z$xPI`)p zB)=+9t~POu_7k89g3yXW)6e;dCXx!(4dTeajnUnLe)l7>z$rwg^HE9QQm zT#eODoEZk?Ebjkn*vAZ?&7c)z0`8Yi7Jz+a5{4Nj%PN$|v~#CtBSHMYLCrzEKsp0y z5+}#0h>P-Nw%l+sSLSYvmFx{&-OfHaX9}xbC%Itr9`^l%L=pV8OQy zy&K(2o+~Z!yH7t(wY_Trpq+POa`=UQc&mcgcy@c*-%+Cg54{7zR=R7!h_%X(-@@iV zV!E_N{;jn%ra$BD&a8S;Gj(;TgC9}UrTRV9r6u>V|a~2tX4*0k&hqmlWbM>=>Z;G zJ;q>I?6kUk(2zFthi7s&k4ZN^C1 zrbCpR?HW@1UX|WUORlW%_kL5P+)0o-)@SyD%G~-|d+_6$e5!D~nlxdnq0Mz7-zH4e z*vG0@tn^8{$JQK<0c8-xgOtKjY~XRkp$7xS4o!g~tDP@B&47gvWywk9a-Be1kMK(R zItr&%?M-8&Y}I5E9m&f~439C~Xv)yeH^&t|QPg!E6rVL1RdjQJO;uUFj#Cx+Ziu_r6D38(3sa1-*vIv1E8{RT_Z|fv%4rW?e^3P zu)Q8xltv=|o#T~k=L2N8aU`#Fb~P5LSwE|YC=|hP3!a1pDzo(M9O6l7GkmwHznAo@ zr{Nsj#*?96>ciD^)pT7Ai`Pxan%wC2_GtE#cf$aQ_L^E%Jtcps{4Oq^sr zjEiSyd!Z0>Tw3F?k~P5}SO6L6|4kbx_)S-8xf^n7;`f4zb#inSW=S!3?sk&6}N z)J#(BZorHkF)*>Z3$H zOc?X}Io?&ke@&q5vMw2jVq+33YDhXJ52=j&`ODy>Xw@WIqb0@RuZ;-d9L(frNdvxq zo@ATEk$O+1v{@`3mb|t{7T>L{^^crtEJ+X78z0eQLg@D&ka?GX)1{odczcMhH|*$2 z%tbJj4mw>FBYp&f#sY=jqk>}8^Nhv>@{^u=wzxmz0%qPP>ao6jK(V|pi3c1a z&tHfn;Ho43DBgSF_wQn)n4|<5qJHxRTv%9TF?*9cA1e?u>KC})PXtvoE^cmQQwuZ` z6_ZhrCN+@7Qv}RXH8_9Lkf!CyHo>1>s726LkfS6&T z@lIQoHo5Tu;9^!*o9RsD=~SeNeUqxVw`#&V8evazl?xs22I}fM)J21g4Id+ zzEg)H86<(Fjx2{zxpVyxC)o^iJw)^jT5{^}PkEF!fL&Z`MJi!Ftc5a#QFN*|GF2vX0H9Ojkg$!|3>@! zx#RiI?^hb8cOwO9u;E3AD0akH@bW`h`Z&{0`VyJhG~bQu6A25`;YOCKmU0+u#G<@v*pmqv%vJ z@!kz(Y9r@&k=CHRVcXDdy;NErOP{t%$~dJhaFojK3Qplw#O}&BR**bF%5~i2$rMN? zC6f$M$f-lYt85yO_d&T8J5&23e*S~b+r%x)uXwwu%=FE?WG-bSR8w3vqeaQo5CT2g z$oUbq8>+TDxEd8*M_Ys>K9_xQZhpxz9U=6}%SAj%rG{7E#rG9z=xTmQI`eH>lEXAH zc7G0*OPaVh1(&(!o?~1$DO>X*YOHfD=G-3;5B2YgUw`(2-{7{pbrplkWfM?wXowkQ zIQ#d&vD)CfK^NJ^>8`EG`YAy(FIq4nH?UmJ^Kev2D8d;HQV0sXK-K21hN>R>oU0#d5^ZD9}xG@BYHdSwFp+Alxe zN+SuV&ja}poTvORyZ`E#>NF@3T^vI$ERhuv!73gR50T5?XhCB#`~N)4O~DsnG-Ai6 zHWz+ez*f^fU1RPY7a~R+ylGA1C`6>ZzMLr@obflS`e%qXCo&FanHo{-Y`3Ze^NIHR zWs6^l9SwN#VC8OeAn4;PvvSqd59>4Pf#?4Y{ib^!43(rRsrORLj15F7ShdUXKEL5& zD0k)J+qzbOJKHci%>jf-?NJ>8>p+ThrYiz60K ztfh?#-i?)`PbxOzh#nw%PS?Z^IANz#Y`Bwk!eBr!u@o%d6NZJt(6D>}d^Au-i~1j% zV@JvFfA1hY;?J57$T;-1gu)@sce5XfY}u9Pkm2 zOzT~fZ|#&-OtwYvLj^mfoTvds(nw=d?Da8-ZR@<)g2}J^zUEumjBLL)ZUED`o#`sD zw_K%Jfd&}GUY%d?sO6SLb(fm%eTvEM-s(r)8wdm9x6}wV_wuDh50j`U<%A7#u0ebg z!FJifSP7Q0LYfLUic1|Cdt>otUq*LvPxZ(3pY%H@fDknxp8YzuJ@LSbrRI$*?%@HK(gPCws0_MV|I(cg@u0n*7D|a`+y{ z*pk14@`~ISVM1~0)KxZev*xSHyW3NeyDy?=W7p2~`sBF3)6(mBeB>mna@^-%GC5Nl z0I))U-9sS{edayCnJo>=J~+mqGC$zlq$%@x?|8Nv*Y3`l(0IeXP`1gCO#x!IZ?=4U z+RRfu9x|09O-fIBR6gKPsbQ(qh?(vT?eyw9(qj(R(d*Y`a|GVoc@|B^;U;pcI;=A7 zbI~t;8PO~i&cV61Io)5X&kahydQj1)4o&6TTBQk2vU)zcFaB2}_D0p=MC`QPJw{p& zzP7aCA>U}E;CG+9mcj6MCFe#<#6M)3BHi%xVx64_%INp&ZTMh#%HxO9MN*?mkVc7C z(9HG*4f3^ZvXl%_o`JkCA<}Dr8DLPDX@_R5y0uGPt2VnhZy?^emS#oB&4|%(mb#zp zuEM^)#-$=DftC_~wh~tp0l7%l4y=gK$bi$F)|kWx8pt*gn)#~01aK=(d{&t;>4sdk z4Ckg%0hlLP<}sfULi(59F4jinTk-rd1A9DXpPD{HDsw@8K5Q=9`9>2k&T7MXL(R4R#JvB7>$# z{T(Y!bxqnlK#ayK6)V?SzvRsIPddsxDa)Ag7MBb?f=fJeExygWwYAr#uRI@UTFP$8c63k2d$^eX=iYIfub>;h-bG&8 z@PUNe38yA|9i!~gA=Qc>$^Zlw70OBC@fNyRhRh03qXTciXObvPWdn>>M#&lQ^v=7p z!thT9RxgpcUtlTPvngr@EDYPjx`Xn#vv+uu`p=5OxF;lec)V}RUBm%`O|d)Jj`#Y8{e z|Km(ptEY1L1|`+i0reu1jZA^0n%C}^-7R$x%)1yDx=DVL!u-wDm+1_5lGlIJfeoiV zhs9g%>e}AV$`wu*Z*zBdeVj?Y!5cNk>%PGfd(ZA9cFXM#U6Hy=|4b;B>L}nsi^t^O{W)OL@m->!&r>SGgKSn)Qre1MQ0Aq87LL) z*+y{*^JLHIqfEa>jpwjUNM)VH9fpyY-M7!JX5TQ$_4B^yW~KhQISuV>Gb+%sv`V** z(5X1DOWH^&6w)2v6y4Vcj|69xhn<56!JB;hgw_53;x>$XsiGSVNEgI1f&fc zkh3*_%KKk!-j{`Kb17!T*t(nWNExb7nr~^^zlq=aXA9{lRH|tHbt-P-8(&%ihB;B% z`$Y>16^r(F$2>f;S2C%k%4Q%JbfQ1AtN31{aX}u*0$?`%y_T~oBerGG zn)SDb%z~lro!$_aa(xz~ghK$8J!t)A*47IXblBX{nC%Di79-f@8kgheGK`3J;|d+~ zfe_GHW0P(yEriko1YpBYFJgYun!Vm`ZRakJRlfZ4kS;6tMwN1%e^|C!1*b}@M|Jgn zm5+0}glqG~q4yDwk8Lc90g?KglJ(y~aF>~6H( zDCQC7cw%P@L{dYNTl_+>dAVHikbDA{F=mpf+;(b8w? z^`37;{=H|NIDL#!ziGdcAYJAk@oqZmiDnyn&m+1;i4~zuYKeX2)1w}P2Bl7k(eTWQ zuB-=*D2qLmX4?GE;hb+50+;UrqYnf1kQNwEc2;6$KDenL>>;X2E9B{)DQP4cW?LJ&C+Lz?}j1o zOx8KR!*Ldv`&}ASRS>%-$uad|xmRZ2r;SxgO9&YrWl@zHs)3o*Tb6Ie>$Pz=ayK+m zIO2OF(zO!1`~5^4J4!L*v%kk!~{e?(4F7pOjho1IoUTQ6mZ7{*nyROx#H~ z{Mtd)TbnuF<2wUKDAN)uJaCT*>1)KAI2A^O>&v?AgNL&uqr3~%8@z_n(!r9|f)~oi z>F~x}5+XPJjrNJ|p!jDa+1^U+C098Q7;b%~AFg%pd57(le-8?PsBxMU=7)zi zo3Dpti&s#d@r+8B*3iTU__LNK0Yha zcnJDl#qvT;^0^}4!&$kfGs+(B8FsZMO-5dUZc~jzJQBC<7%fj6ygXbJd4v}^iq@!Y z4tnAP(kd@{l#0z5Q*eZ0-b^aD4JD{f-7}M{0RVd~cp#}_nM8>>q$I37Uu2qG)ep3b zdw8-41zc|jr?aGu^;{#vli8Nya%hFhp9V}O^!_>#9`OtBnz?FSI zY-C+w+c(tM(%9_b$I^9!6Oo467&7&Mp32I@vQ}OdOcSnZ_x#G@!t@ zpIj`YH9*8a>&GA>^EY4`u3VB@O`2Kc`^THd9t5nWzvY=iBK+8Ur1%67b-j*y#8F+n z+7Lgc6=V7iiPd`gF23vQTI%ay=WCA+4z#DQW;(eh4Z>4E5HiaO$}_(jlErPWK}b)k zpOi}sNH$9!M_Iv=@|Sa?4+T} z_JR0M#uLHtH9==Q4|_Z2V!h0SI(?M77I3}=T20 z=B)e55}P~(za9Dh$!POX`Lx@$K{J}FNKob-bDE$ymUlSjAvB*4BRX0v8| zzvTOgmEp709iBQ&F|qC7)HIHnMZPrMkYBiepzQbHkKE0GPgPx2?L~?t^2^kf6?s=c zi2}o&m*_q?))Pdy_q9jGYrCvz{a~Xh^&f>StaOp2yu9S%3vW#}O6lkxJZUF*=Q(zF z&B>e_yz;;Oo6dj`p+>wAoHZH=FV8ceR%#~l-8p=%v0YnqOG>Q|Rp2jFzGM2(oCr9^0HdUO|1vi7@&R@-MfiN~P; z{BNdw5Y|P?fH@io`X$Wlome9>!>_}>Z1YRw84<#oo}6nMDjDuwe%F3JMcVe?`1esR zw(|?yUt27ibswlQG@tzwov<;Q!?tw8y)!qwO+44+G>C$Ht?tzas9X^)|FjxUVKdfw zg5Uq`KDJAhITRSQFspyr0b*!wVQHX7?G1o#^OR z7YX8Sx;go&;*#|9%E$cAsI57YK++giV!ZTKw-OI%hKy$m+J^e1h%%THp|Uk!Cd%b) z?WTy-Z#dwOd#Yi*Tti6SLe^BaB&oeeHE}_&z*2M5D-*`C;bSWj-A!@0?D`YuW!`;~ zSKHmjmbP5IExFR3L=C{RN1xEQ8CoqQi}zRd+~5|~tl)5$HfA{0Hw-}YT2u@NvwIjZ z#|)SST8LgBq0Ma*NrLXZLf{&9KYoSRV@j!tq|4jm2%|W~-S>fR?*{#K8M+M&l+g(D z7)=emInWj&&9kJ=>M@$*bzl3(Sn(V8TdE=+*Avd|Nz3{Jy0V>={9}dCmyrS#I@4`7TM2EE|$oeLfPd_nycp!fH=z_cRW**- z`&;E3pf3lwVf;M+H*Ds~AHcl)8t~clE^qv%!{t!ce$(Yv(2=DhxjZ%P6v&r%+bEBR zL|E*;uL$X}T?#!^ZJ+AIa^Q<)T9S~h(-B&KL=T06jJ+#%t{)xoGTNeMe#D>a{_(y7 zVKTtmHQ&)e(7t*7!JCy8<^-WzcN*&(qdDFT4_~EP+lJc)Yq_KZ7|MvGh)fv@zjg;y ze${~L4Pc5!Q8vzjUg2g1fFu2%&rAQX_*|XAuY?8cREGjTAZ8wGMt|Q5;e` z>0M^RmKith*P@9cqovZcTe`+NJG`n&I?~ZPN_<3)-Hi)p8>3n}rQ=C}C{LK)vIF7iu=!({yp1TN+0H|C!S?kCYGP$n6l?fABI4`3hp7eK6@ z521O3mORE0iNDxlKrDG17}IH_<&hVVIN`ne{TyJuG3pxS34{!)9c!k36r1PtrQNR* z&LUn8w=_SqY#{uSa+KXaI(cj4k6yN2w1G&kw}=1Osrj>0YV{iv!n2SomJ-z6VwtUx z?P8f-?V8*VOD^84n>le2w*e%t_w(81zj|717+nRY@DMEY2BS)Il9mEV1{?%rzg6yG zKt7Ph*&cx*6@gw8_|67Wzm;xt>03&8z$Zab-xcG_*b85f1D}*Iy zR^pzs7dUwXTBdg4czVk{Qh3vjEBC3=xn9%i&5}y_bAeo!t}5*aDy+tO)7rsqS&cu^ z@O64X_T9?u&TFa-Bej8eSWJYj$;t8mwMWjmFSq}X<=JsLk^5~xE=E`7H(jEf4drUp zM2d4gC1pLwL5CKI0eAr_UTnUYh50nrrGzHN8<}~Cg{fbziQyk~hor`MOrqB=uZ;Xx zhlAVrdYVyeb~VXrN$l>8k!*B51{~yxS3+wz?SM;;5;^Xu06CgG0MOx7ke?)NdCLVv z@}s6ank)GZM@vZ!7AhsLEpnQ4=mk=kOV$Eq?BuXlUj2TjnvM_l~4Uz)Hn z(;KcEBAa?=2PYs4pf7(U-W|(gv)3!wT)R$%?_@KG?!GL+=QC-4~=(O4J;ch z=ZIea=J2RJ+f&9EOo<$$;Eq1i-csrsyXe=Xz5=|G{+%N)M^+&EL6D0ol++ks#d3S7 zqB#ZY$+835e8ly#B@j){(P(c^gU^UIXMee*Ckg$-U0GpK*Jkd-APWP+pQC#k$bcBs zCfbg?VIf_!kFUP9uZ%GwW$Hwr6Shh09&q160F_eXSqTuiQi7w@XX*pe=QSOh+|y)q z)pi7#az5Mqri-mP7eGE|4qVkaqP}nRs*iIMN583z`K9-5TJO7DH%s1M|5@3b7t2~|d#s_roe$Nl6o*i1 z^vN^!hSiUzPcCIgJ=PR5C7zU{4Hyjp+34Pm7Qv*7c-<@s){uO%=8BDy^AKdCg5$6r zVKcGCtFGNsDtt1qAr$RBh4g6lhe=!F{?ZT+)r$46Tz1*$*CSctxtEE$4<@OWI3@#= zIoUa*F3OwlE!}YJr=+3;J?5Cc@9m{tugZD@e$op5Y?)O(kS)UKblBNMc`P`HRxK~x z5E%W$zlIRDZZHc`Iexpq_r%B5);HeakIq(w&)Rdht>&>7#3TbUX{@w%@TLh z;pTcWgUVjc>Qc$_v@i>)xthMEd*B!b`7E0mti`au9~zRSE(t|JGBTa6- z4Qpd3nrIDGm}fdcd8!>X#sh%(YJPhj2%wxycHu7D5SuboT~3=%i|P6KxLY9VYXVW| z!r<@}=;x0E@4WP!cwpL+7e$Wz3sBG~)|_x`^c?;1_BS0N%zdpVwb5P^N1EuT>E|JS z$t4!*66C6fi{Ar_-Wm%XyK}l)MW&7Ag7nZ+!s*1A;SHAz$EgBWiT7FG4N` zbzNLFGa!OVz5Jein|XGXREwmRc!?g*+WDY5u~1-5`bVsyO@w~o20RJjeV)FUWn(mX@U17Ie@q*y#gc?KuZqV6RMP(b^q<$V zJGy*P@kg95;jw?L*^7xZPL;N|w=~2#PCa;SP-+qq9_Z`g`wHDTHQ^epB?4OrZ9Y~6 z*Ou-a+g%;#A=(-UjW`pmU(DB1Yx zQqf_?q0mJEze>Lb{NWma2~5T&)T;mM)S$~pnUEQLTPkG5z>p|BuaDQY3A!EQXbk8&ugBbsrwrH_j?C+LR!<;`6gSZ*;5_ zL|TuRIL|zf8J?EL%PY)4W1Zp4sHZsc*39 zEvnI?eJRYDG_!7^+xJslh4Ds}?_O0k&@C)P{yO+B6w_y~3BYT-P5O?SLneeRv z!@Bc;HHo1<)Bl18ks?5wahH(MV5~fCVt%Z>g=awo?CiGKG|e=BfFr7qU4=hqaeKO6 z@ly+iKLoXcl1BaTq06i@YGcy1wh8$Wv#&BXLUZc-UHHqPNexwi3)0JM=8Q+2ClK3# zTMmrvtdca;`|fz9(~he3n!Ks4*Q@TSvCpL*jpi>>Mmw@(yM`vW-EC+OK*i&v`DY}; zr7d;uX0!2JHFS1@R|_$MqI5i8cHd31n{lUH7Ow(S5Q85pS2OhIB1Iw;XAXD%-FyFD za0}W+eK^nMmTbXE?qU#8``zD+S$A04)gnn;T2`%ZtY?F?fDJ^NW!1rP9B9u^7Qv-gB@yNZ{ zZ}ZlUepO`jCAdK8Nh+U_Wsxa$W_i7Cu|rjx(R@lphjsTWd6vs2`0ImA{Sd~!se2M) zd>uTgmXzu7mQrM$g;ll*^0vMc{_5*J)!H9(iXV70&UcSKVHPC^)y z`S!!-%Wb}|6gnQ)-*lDI)2TnT#TdAgJ2>LTuyZhTNhhiMe$mLzy1=A>V(#Xi5Q#I- z)M5E2TNvhf(Ax7ph9~J*$q0~~iM3vRXI03g&7OaVrP&I^t>CzA^;TliJc|JXQV$j| zYQ$P4|RSWObO|Fa&{cy`ZefV>0w#K=~Sk&q7xkuZ@ zJ3t=I!r*W{n*ez3eD^eJoH6=br)-M@X7?};Dj#6?Ge)~P*cq6-7jLK{Orw+azO22r;WQSeEZ0`F47i}e=6<(mn7={!ay^>wgej(CkH zMs)q&de)yi4Naoed*W!>&76n@4P6%_E=xv8<#R$66!awDgOD%Ip~BO452D?WY0m$t zbW6xmc+@4+jdpW52xY^q{lIfL^I5UvfH;rD5Jps_bivrV$!#sX=A+qX;6*^M<$!QI zrMzt&QHyQT$QU(ktgyE-Iut92Dx3V*WO9D|NEGs%>9BG&tSPis+a%u)u4z|c z9%wc5d9o%d#fa;5Rq}{9m^E6UZsxm2jk_qAnv1>=!d=R^nv(-p8zLh0Sxc`b*H>-m4Dq~2s-o&Q2hEOZds2JESeIavkbAmg*f6ca zWaSwaQ-=2UN82?Q7Hv3AOX0N*61$~b{4zm{!bEyo$vz^{a$)k4(51flOIU>)jGn1@ zg3JOXvcy=s{_+o6W3D#VTd(0$C-v}9V8n~i`7dUcC z6>T_WzS~t<0jdCC3tE>Sdkmx4wME9{`T0K2gN1}~n{CG0!BCxn``PXZ7&8tt7K1ZA ziO+D9^etOQreBc#G9`sr-7=*@uPd>=BY&8&*iK!FMJRkZ%=0SZ{my$8MOd)UR~R8? z{zIH}^xE|f3-{to3`b8_U3vtSuS`uHnMj!vWL;aPe+dZpI}FD2-?*TWH_TPWc4 ze88oCS4HpvlbLoDlc51iTnorJ&DU@+<-6hrB zc0(j~isL`-yZ%as^C=7rF8rp$T6Zf6SU{^81>&RE-ob-GmVKMt<_#-eRVAHVdUCQWJIyyRr_(V?ik`%Z)(mYY*(WH6gUs2fD*cf6D3!-G- zSP!RptBE8<^Dg{pE5m5iJ+n`0Oto@KCmVU|GA5+Yi?y~SY&~O^DcF>CUPB^PapZ`_V=){XTDSv)> zBkA{d?>H$`L7H638 zDq(SxswXjln?g;|^zbTvUBN6!su>!b$%_^=8_;V2XQ7_w zu3$^OPEiB+BKMG29`3IMJ{Y7f+qeh}jG7L%WncB4GWavnrDlZn8iQ^RE)8YCLQUhP zxYKWHE4?Q=vTe<)-69OG?rgG{Q$ONmW9{!ZN$YriNOJ{SEj^UNqdfOhc+@~yb{eQX zO3Spk8h(pMl|G(kD~Wrm03g&OCIqr92FE)!)`mc>(wujj9<=SWo@oO4NILnV9&<%f zc?V2F;N~frS&7%7AFgPxGfnBr`}t?xOJ@nc)h3d0+4W3=lle}sK4WYmz*^OY-$Csu za8$WVYKax|H9>NZow#NL@=;X&kU@c!RW5k>e*d zB$gLZYV7Vecy-Ucqq*&Lv_Yxg74cyXDYm+h5@xbm1w9?WoHn3wRRs7ad zM2>7BBhQ}|y%2=9IqazQv3^P>QA%}ttQ_AZzCZKE7HA;9yKtgL?TN3x5+)k=^rzi& zwDnT*dIRjhFzvB=YSXW1Lx0!G`2o2iw_J&!BCGzySn(z!qn68=sjapX-%|G}rP%Xp z6nqa4A)8N$#J>=%Sja$JXh_H8ZjHY!-%3G(OBL9EM&uUBDrxrj1v&BhGQLJ8qEp8L zW^4}~KZ$>#@0Tl^n9{mR6ySE#*7}?;XT;opDeu3}nJg$2i?|EifYwYT@Xp^YK0B*p zle|D5E$LT5lLHoocQvv@5&@9;l0v^6JrELcY&#cWxTeSE)h$Nw3APV3pOusS@ne4@ z)U9CU{+%lk>D*Ps=G(md$33lEt}rTCwSc%8@Lv|W;@^l<^YDx*@6Zm0e>IK9fK zxH!!2!#S8Y4^Lbr-_HxG{eZG$G|0}E3{v6#R5c-iWI9DQQ)kDc$p3iG-;2yrtG zH!eJ`?tT{uRsM^--g@&@aON5o9AiU0opsL{VgBeM0GR(nqW4;F_a&v~vgn1xm4r|K$pFGL4V8iEaM1K*Sz(F_(!`H})fDhr0#V6QBH0N5 zF++ycmd@Qy85zMTMZwbHs^Ef1?$+_ zWYwh9Ws_D;uQN49&6C{$(`mi12#VjhhJ6p@L7q7_OS?>u%A=fyyM;#H?WWhDlx2&v z#0)yi&(x{k0@eJ3-u*rslo!j$hMSKruqq#FJh*yec(P072R{^f#!Fk_0~bN42C>0X zF-v{3PUT;3n7X`g?)8(Y5mxF<;`cA@Te;HNnPUoym^YHB@xr4dbyt4&0I37rx$_~< z&mLp9_lPUPJPbU8*Zp6b#S}>kD&6{7Iq{W{W#hNi@6_G)PemVx-J1FZhU z@o)BA8@v$G<{G8amPUk#6SqhT^RaSlsd$ojTosQc@Z~_e#Tt>&&O1C7Rj@$+XyHHC z2`(JZdM1~|foM7d##q!_Qbezlq|^85zB3SkYeFB@8M;gUZ5@^Ka=V^PWLOfI`gLXz{72%k*4o`UJHgHM}QdqTDmr#5nR{ zzk5=&X1>gNk8{N!e$j}}H_>YSe$7$*zgNZod{n6<*!wdrTy_|{=B0o24bFrkzOpS; znEj;WFe5MH2^z5bWEq0<;SK3FMNaSiR@5{GriK+Gx~tt&2hb*8`&e=s-_~P5Q{`*m zSWd~yBUI=#ZaTK9LNru}CqkblM`g67p~Zm%&_n1&^PF+lZ@PrTJ>E?Yf{*Of=A9}} zlag^~ukSyyefMeh0te874iQP`oUKFia}O1)2I$pg$@QV!7_j+V0c z_2cTfZWCou4E^e_?m25drGs_r(8-uwt*8At8P^^y?7h+I-%a3uG(}G1@7^uU7dY&RF>S^VwE-}t-Hfz?9FKRtM%<7-~SAJWUV9)Ec zDh9e^U;1;`_Nl{O6e8sp(}Q~;(bUp913=np(;B7XBeO4eI7{GNe#7_d)&1r5lm)Ji zSam0kU8e@mO!>=U|6tcYv#u>?x}4XO2|?@4&Bs2O&XM8+g-otX5Bq}-lEq|P)nB+^ zZMBi$A{{%h!)%J z91BvKv)BmBs%V<^&A!n(oqXqc zwP2mj=TEngKz4GC>z`p-4}EK%Pd$bp0zgPo$+M~!z8|_(TB($6pi+@5^DBCFzl-ev!)2|8rbHm$2bnkz{| z{FaOB*q)zuh!Ib(qh-sSD6>cI)}efa4seO?9dC@p6zJ~-WQ1osjZWSxo*A)$+^foEA;WYd7u8?&uL$;{dm_}*xbd# zl?Bl~hgfm;F}?fHmq&5zFJBN(4<~hSo3YP<(KWU3&eQ~AkPDLaxF(uHL+P`CIM6Ug z#W4kjY~eF4nYg-&Vwkz7vqBc2<+G6$vg#)y>gHqk*@GK*l=CIU-KKlG#N9^(1e-g; zL^~YOx}0CSnP_T|q(@)0nb)+8o-G_00u$pa_rmiQ|KSB6hcp0U+=gr6A1%1TolL>3 z+@u5;Ft_Au1?(qK8LC>m0>2@i2W2-XWL8+no7kldsP3{no3=OF9Jq2#`<_0BR9+P5 zdd!qBViT(3`=Kb0b01+gTMkn~m71iNYoili%LvC5=+b+CF|0sn@e+X9U;&to+@aj% z%Pi`(E2MTHitIg(IXWUxd0O)!yD8%MLAv3y_ise}OCpq{_jm7?NJx+VO_vTZ3R!K= zB`8w~+6KfZo|T>FROLw47Ft|MR^#(ha3M3d!(xP1OP*1H-X!Wv(9lHu-S@tGO}1$a zD+`OSYOiEdbsH#a_!|P-?) z7BB1Tn`;j~4KDzPCt+SaMrw}-+_dwb7xenD!Ts;|It?EsmN!*i%0$qIu*?m0h+?KI z)VR+tvsj{a*zlK=LhC4?eZ894?<6HtLByIPwLB{~pr$@Ds`>WQ#$~zQ99NHVesn;~ zryRK4Q!n4pU3pC>#3WBAa5c0cpA5ACLCo?uB*z0YGPg9;Bq2bA87#wl*tmJoyCZ+B zO-)iw(y&ER75J%nai;l~H~DLiFU|iq-Tj)B9!k%bo|6Uh_y|i!X18>8CrVnXTdw<~ zl0-Sd@9Bop>GBU!l}%z@3zp-}A71?!PsjTACq~`B+NZRygct8zUTvmw#Pu`XJ#m}a z_33m3P+))i-g;*|7^|XCO0#@$_OhzHCo3>mpbRP6{q|2uk2|eYl~D@9Xjfe?zT%k` z4P&g&7#0YQwmo3GE_G2+RY#W~NaW_rB3S4mqlEPBv18|-~wLOBIK z&X@Pd@TTn3&Sq=mBc~RR+)eNsyX=%QI*q%gEKH6)oAWESZ+l<4D-Xbmqie1qZ#Y2P z^HtE$EZwlIQlgAGdu5(CUbAS;AkKk%0RJmR8zroKBJUmx)d*j_uc z7}QR?P09C#JG?#dhkL=YMtLJAqyF;B~}tdv)2S|NeWn zTW|{I!uKz=Ys6Y#bm@KLCk;a%2WxhYzbks->V!WX?~oS{^gh%9hg0ss+)5Q}u0Eo3 z?4g!NFnbR9SWiXI=f|HB;@cf1493RDOOg|-*ep#CfMzA@yeu--M zwP*G?$1O%@xnQ&Mg-8_BcQD-i*=o+WGH~)&@YJdKdHhTNeG+ZI@215 zDoY7iq38^*!XIab8YadaRRm+z)I=XnUF_iU2e~pRaPL&WP0WtnRBwe=qG9aco#cbI zMs_!JA?7m(lBY2&SzOOU65{<+J>m*+k#n+BulPIprWES=satNHNX^}T=@*}xSSpi8 zr$E=6T3hTP6mCwI&8T zZ$O**=#xjYtI>k&4c9eE%Q&LZ)Fz;T0~` zlN^A!gyp^3CoXwFT*MOq2DtNx4uDPCvK3IlSvvW zErGq2K29kj(*A91ct5u`lO2>xJjLgce!6@2Fn(Vxnabydxs+)k1wkGv<*t{ zpS+;|-f?I-(fuyM<^7X!gb@jjg8eON6&g1Q!Kslgo@%wu28X__2`9PvzU z8#VZI?nEGeqcdtPij9Oo>J)#Zrh15LB0}e)pFiUfV?ZR%c)0S|^G>6(R{hxB;pn>J z_!>tJ3w)U{izAEU;#|(fL%&GxRg*7sxa1yODihxCM~t0@v1z{xhUhsVfIoN2oBB-j z`&uYL(uUqj6_0PI+~P7|j5}RXy85=y_3QHq=6^n~)^dx!>D4cuYLa8>O6fTlwUJ9u zv3C`I_2bR2w(e?9O;1;{Jz2h6jxJbDR7=AaQ~XnNX-!C^X8 zDh`;Nx@fFb^A~@d#<^KX8vZjtYVh<-RRYRIYX>1=^oMp9{F)0S%dSCoqIk*`R~1-n2{?!yzdN4qNge7_{LZ2PXdXud0L_cJ1iX>sQ~yl_R{O?m z(l7T%e1zPZ`lhZDr8QxLx|yKtac6e-zV>@@+y@(TIKT#fZcX4|#Xs`<1OKXrIC#O( ztqPPwz&ZMxZp-6u`v1RN$@~Lhuv%98$~1zJ%F_7nhLs4xASEc{X-3a-%ny1Tb3jI`%hIo>fg%{L`hLrYq0 z4JP5rmz(}>++iO&ucwYsk=O+0*9v{wpj=FAb>q zBKc@$&NvoL-(u3=M$haz4>GsT#Ml5eEsH42H*o5hRlhLqZzQ^pktS%jz}-YGn+FC;Gb$~; zyf-LwyiSO>EVlHp|5w;~MK!&(-5zx-f&xl!f}0|}*FXeC0TT?ph9)32gpPz}+$bPj z0s*CN3^9b>YXGH6m)=W4QJNBvBF*#P?{_ZFc=s9OyH4)1#esFH0$oMmrV_;^70~m6(hqZhblG8`n73KteWb^MnwA%ZG2Wn z1eVskD2=(wH&9iRb*&Htj*)WHgWD7u5jGopMDmUw=Gp zyCL)u9;5wvF1{}Z5hvHTGhIr{lD_=sP*f+d!HDtO(>d@V!g}S6ilFZk;3mFdSO>c4 z`W&6`OMIkZc)NH|?#*u+MQ{Xo z_zmbAnYTo|PVbj;%Kj$XDm8@9i$glK1gzzom|!wvY<)6-xIA1U(%OzcIKO!+Io2YJ zXe<`7t{e$yzIYAsgJqLrR99&r0Y4TLHJw+5LGh9EPyXoL?NL;&H7v-WI1i9G`0u~! zLrj{^i2)oG5qf_^q&{T2E!C`HwSVN<$f1RwxrRaqnpu{Q?}-m9(fKWD6Fi9MqkXed z&mE{aL-qK;&6o}USulAZMY5G~(#qzZDt5LKw+xX|t0|z?sU@{P0KaFtj{2_WD;Y7r zMqP|1W66wRgf!M8e>H81JEHY>T*6XOm?#@aGyK*4dCV-g+`R3|VSJ12?e{!oyP_v@sCX7w|8 z^%y{O(UQ|2gcS5~K}WvE#@~XAD>)KWCowK=Q zy%=LvLkH}%>?J4W9?ZC{u@fK<|{2Zdf7QDh0I< zTwYkA5baTPd9xCqT}~V!YafTNa$nqgewl*ic2)I!CK$EjlVkhpKyg8kHRHI;37Aum zLKFLsZF`{M0%G5+85YzA#B|I=^-lMWO^;T)xpdHPQLf3u9X>7QNP`Q3p$)+7vkLHLuk)ua&yVV^{iOju)c zh-p*v?I@_Xh@Xuu;>2&wU|`~JCK#Z-Myn*;)=2u^VcY`S1m)C)L!Es5Rvgr+X29^y zsMD0F!+Fd~X(1YCTbdMIb=*0~<`S=nM;KzIJ;qv!u9~0hwWE1k0HAT7tzb8tvp(g5 zF<{7{pA91&o-Bc-SU6GZ<*Uz-R)>g<=(U!_1KU%N^eB-w9uSo)cn{+ zL{di|xZ*4gSUNJ0TNW~A4ktnN(nT|_51+5#pNg5fapfsOA zZa&V@4i_7yK&2ZKh*uk>fGj#h7T_pDV1{k?AYQ-cRX-#Jyq&+?m@cdc2a-KkaJi7m+E z_QiT?2M-qi64PQO5~Se)#8Esq3#t>*8v+m8u<23-bg4aFB**>!UoX(hT$iD6gEoYVJNcK@Fww$3%wn_yQr2tqbQ) zM7=Z|@lJ=<&@7A606t(TD=XU#3m?m=kB2Hj(t=T(ALj-lAVO~nUgzbfS#deVDg`?S zByhc;HIZ5+L^@%*p`q44ZZv{J(qEUXsjweEP$`IHKA3OG?@r4Q3+Tw?Zl04rvvklxyT`X2n_JZZg0DK(vKj&$$YR+gPZ%1++s z?f9LA@DJvQE(ae)kU-eVt;R?RVVP(8*^d!^#$lBymTynKRNJr$oPGOz9#u4;c~O%c zjg<2A;QrAG9=aN5IIbvjaVL3k_K$Jz0RD?ZNJ(Qlr`Dkft%S7d)Axv^XUpUTdgz{qHy53dE*HE>H0DUhk5EG zgA1Dt?lO1f`54h$B5hM2<+w~A*djXWQ$#1i*%Q`h-|qS=0#(<2vRZxQPW;#<8>oIJ z(0QreT-JoyGuus_8mr{nLQ8!=D21clHK!`XMIok&l5DvZqFJ(Z+G`AhBJzg7;#RR+#;TQr;I{`4NUkV;eUdYs7yfITzChpNOHP3Op*<9!lO*C|3N zrUiRz@znZh7ByEW-=+>wL9s_*oj4V?$;nu1`euaHNmQCb@zYJHfHQ2^A(ZndVJVCs)7Qe}kEk@SNFXO#90-UjMmI9Wh)IdFa~tTqGA& z)*0M~1uNeH-MKk04suljKTKDmY&fkfh?&M7+LTwenPeOh?M+5;>Ev~*UX2Ocuf@+M zz8oRXrCpkGl1tsVy;}3^Q6a~FoDVivvwsjByZu79qU7mc7W7H3iiSg8G&7h7{C(Aq zE&Sqxa?={f$U&bP=lwZp!A<)7m6eT#JspyGuZ2Gl_}&;Po?S~72g1hLW@2r4kTK9V z&ST|{@SJpIPqB07f2#rhvOhqt$@(KHG86ZZ>a>uquDjz_xHy3^bo0W@eT@myH^Po#=`o#CjHI?0)2CY=1vS=rt8xdn@DV+XN0@@F1TvJZ1OxAKS#rmkd3+(#{|AxfX9AF|vRvsp=b`d|6@MBxRQYTz z{!S`R+Nw<F*0y`|L_uh4A0}Rh zBf@1~W$}D5*LtYlW`Go@q^Y3WSr7x8TfIK@xKmYlKV$?b2OEsXk57)|=0(z&jsw11 z%XL59Jo!i4K?vc__`lzlZuiGA^sd^8SUeI^$YU<7`o#I>(TlG6cN`aebZ=3mt+3Qm zwOZZCZj+)k@)0HqsJ*n37AN6MXydvJc+T6wEu61IdEuRn0qYJGs<9OvOKUB4x`PBV zf3$`;RoWztdZ5DcM)#&xi&+GvpHGJ2Rhl*+ps|&siv7EZ&f}F+j(J-Z2yUWIA_qq- zQIG3IR!f5}47tx>qBAC=_{De+hJx+C)B$SAxC7fBF%~(}%qrnuQG?ZrG*g6MlSWGg ztltW^q{Gg>Mm>+zU~wq&dn&RTK?e2Uc@5MVm zetsv75n9V5+*c7Gm>9`xS_r^bEgvhPN9xfBen&9wFxRuzpRqlA#f%c-1F~}rIXflb z4>i}56x+U7)+JDiTM_}mEW>f<2qZpb6D{5^tH)2T+L+Q`UgI3mKHj=ya1-D?1B>zS zyp6;J3O^&lj%)lze)7BGz)Y8z4-n(!FpIPx0iI1g?AeNco2=I7U+1RL42CA{&_JLO z#$&9o4bxtrdnl#aeuRNCNL%okHw4rqEt&n)?vV=~y6*DsHw{a-dR{xPQHn2&_p&~3 zB&Q=aSXrL45#_P(@l~~6k1lQ{KrR)4gPD|R<&)L?8f&$~<<25ZTdI-_s~Re?*-i~H z?_J}!lU10oU*1^wDf7~r>j-+j{$^#s?)(Cm@x<5a`JV$uox@nM-mEMUo=vXK4>hk+ zpW-Cio~;tO?)S|tfEifn8GZ_aUjIumTiuCmX z+D?mGFEdO@XnZ_LIWlAlK2`yc0z@tHjFsFb@c+Q??h|!)X_yJ z%xM9s#eHupcKsvO)cXwf@zjLxPH*aFZ^nRZShep@oZDWLrgL08GgOf(E>*+UM?Xxw zif6m_^Kox%e}{O1WWPR*p*-a7i%UY2Q^t7XW_W;Go0<3ok=~T}2?XR0F@~=M(n^hi z+#$SnM5C(&9w25~2KUA5B!I??jFCFPr5u;_6?9jSQyT&G3Xx5tG@wURl=a+uoPVoY9hWey$wJby{^(k^t$ zQyJNT+Rq$x*E^B9B%Ug3DlP#s?6NqNL&XAY8m){rlMVc9oNBLqkKLcB!<;Xjj+I_q zeL1kJAl(ydetJ~=Gl3MOPRli>A4@ww3x$4(SZrdYaEaX2!dK6F@at-JF-}+B;oJ}4 zcDbHSPb$l6V@GEGTzo3~{-o506d;U5P1k-?1Eezo|KxBXtDXFDvo2peLhenoo6nQ^@4=eNy4_4(t2Yg}NMxYnRW* zOG2(~+U#_qA0MeKi;Qa&wSjG8f73iYl>H?g_&WFG!xwzIi;~N4ntA0Y77ms3p6_4E zWC}yo-Wo)CDxM568t|srOmFbY-d7G!Yuseev~Ek*5KKa;GjxP$Vki1l>mntzN7|i_pl^%&R6bL&PI|Y}jq;*j z0RWIG@m*kOtZTZh8{;#K+l8Zn5?LDB!qEpJ(xSIO+5B*{XRlF*cNpDZfDC9%>FN3Tlg|KuE zaFa^!o@6GELFUYpy~pe#GF|PM5~#vjJ7s;O#uao6&NW7|-F-Q!dL z7f1{JH|^OCrZ~O-v1G)M{;wq??C!7-#!Bc(46j=*bDVn9je^)~3O8tk{XZneBBxgbX5QtD(U61i4FU@kG=E z@2kCK7KlwyhWd}iqEdSe(rGiGL3I7NlSfIIl` z5MxkaKM;ua_YV}kqWRy=NZ~I51&6`z9|h;qKLSqrz5gyxx`4wUd4D_}n5rB-)msML zncDrlcO=-(Zl3l<=R(@r!TAX#p(Y`r*ox12e6@p}nr665bpGSge#(Ixz@#ub>RzUe zd{2#z4|67-542uZl0XTiFUxfPxZ<|JIo2XzZ9l{_wSErRyQ_dw-ie=!^qbtF@I|-d zq1TEDe2X2=DwRtZamCg)56B6Elq!9N_Ti2pG4kmZmDsA4Ld`8w3e)SZ!PxxVnjC=- z?1=)sar#Qc;Yg3_{04+hQb%w-X^0^b=HKP7KOiQ2we<(=gt(~77HqGRd|O!|0K!=P)llM{(MwXHm=aF(B7MSS*kGXs(X#wme6`{g6H<#^LdAd*Ef3MAN58C;4U-TyYhvq`MtDf zn@?9rA-RS&3I1yR7umEmNaM}_UV^mmef20~RJY=#VG`vxP1jxZc01-Yv7gOqLyzJf z$JDqqKuQ!B8H+Vp`FMC1s~-ni|Jq8Mu!bow9DE0Lo=mj|GG>F6=Wfr=?-sRMG=byo z?qi$^O^f1s%h@)@&y}pm#8CLcMr4thkx5|#b3!2$+9P4bSCM}{)5=q=-cuIvW9H>@ zvU}j=G3}NTvJBHv&LEeuy|OwA8D>J|u#R`%@JS%lhk_`4w*3l3TDJo6zG&YEl& zq<_cAJWBA{?)cS3dtw3}s*-G{ZwSxG74KJ29b!}Cl)QYk*NjyJq;GtXy3E<2g=NjOPYu7l z8@#%}=xX&0^0I@nYHY=4^?+6@+tbW#iJa61SIoO?+zc@yXtAWOZ9v+xvKA_nH~43d zInJ(B=bmy-|E8gCoC63Mv!l%Om^pxx!N3*$n?@mb&HlIuIB-ApT^EmB`!#=M?RY1J zbiWE@V9^4U=bQ7h-O5GEd7L{3DFhV8HIzrUcHm=fN62+^U-1oB_mhVs`rEIfJ>}JY z)7YNfsJB=Ah08wsKFKNld)%mo(MZXMVuPfNo@Ei^EN5t}mX3$y{CTm(Q@TgprbO2fJCbxgtol3W! zF#=atM6?v-K1EFIwBg^QF^vBk-Sh^#CKFKY<*ufV!gV=%v&`#KHYfNl4d0sRgQ?ZN zB=@;HpkEKyWREDe2#@7YjcSK~Kyb75ex_$NWK{T9r`P{};Q#v@Orl5Gg-7-VRnd^0 zmbx+zi@MO(>aHU4yygQvYj*o&fwb;UyW8#`8a<1XA#C+}Pav)=A2gT}6k3Z6&wJVp z4v*g2bBH#(JKzJis%KD1)tQZXfueAdP?Jw;Fn;@K^HgilpzWF9=*fKeMEK^3B7h+| zXUUC%Kjlcbcbg0ot7|_l-8=ajF>P?5w7mLmv=LdHdcly%)!6 zuI7f(Qr9g`v?V<8GRybfFsnra!fg2ts#3+FKk)->^T0gSJ$x>ft7S2iabwQLdgi{= zz}U{L^}Q%askHE;Cs9hP|Jg?-u=-g|iGFwQlFv$Y;t*4D=KQd-_!K+){6&~Q)!X{W zf-(>?alhbqGF*go2VbqEtA_U<0PufWMZMOxN)M(Iff0vL`T1C z)X(R&-SDeXtX*ww{IPJ_S2A8(*}9yb6mXLJGMBX`ck4GztsP3mrloN#fRHwL_iouw z>$rFMQS3F=XYgxCy@!}*fBk(vk^?K^sa{7E;OZJWxJ;r1in)#ASJkHAF&buEz29>! zzOU1jz^h#ms*As(6H(6XT(9#~b+QnqC2@TSyvWtjBBP$+=Gj9<99*hFh&Zw8KH5s0 z-2imva=Ym{U4NuMXBwS@I(E3FUcC3dg)Tj{u~MywXhda>&l3Sc?Ap@=eD3~a;W&Ss zDb5@V87ZPOA?gDHFg6Q*%Iz_r6e#o$VbL39VHnHA;%2;HV*_{JF0^V#-_5_cvBq;P zX5?B=UJW8sh?F4_ER-ezk=}M{NH*uFkF@D+Nz;o#J)XQ^{jN)b4a&ytXWv+)q>mr- zT4@lPO~_R$aSi2%d^(!MQZ*oP0K2QWn?Z+!69;ZCmyWSS{+ogNyIE%97_aPnf-?tu zc2Y&le>KL+1ObVC8ioKr@~+4ndqoRdqcNFG^V**x9?EHnBlxwA575Qs*7> z+;$;Z@g0=CEA$odLc-KejyT z;!0$LqSPj0{VS1V@d4m^$r$+d#3{WOM?; zI%j*7Mpu)dZrD_3c0pqZcgf#%;1oSmsnw`7xy{Sb#@U}!c95faQ%yCt+E(cWPPJa# zzj-+xi|0;(Y57Eo3G4ed5$`&-KHvFG^Ox^5gZFk=ADeNMcnvMYxjwjaG(kMwFHs|` zG69~9AsA3U1_>UHe-b@ScfFWnlY@r4`wu9A(ZGl|#_?!>hSZnpBwM^urR ztr~SMvY0<3&O1b^)Dgplgj41xT+Rtgd^`t+iJ=J}n(>x3=_VLhTPhYGca)7c1DWJ! znIvd<#BLPxqQDO+Nl1{-`4!wjKz@$1IRjp;0@+QwQ`D7WM6~LHK?zbSu2A=%nwK@? z5cXHWCX9H`LyqUXtr$))EKiV_WLSAQ)n>L^LeglX_QC>!?y$}BM^%P%bz?p4L4TZD z8HTcK&S=tZ>Y-Y!<}vOL7$Z!E%?Ux`evO;7!gM{FZK^K?+P}U98D+eZGfl<6>Ztw! zCG0}-SH6u^CRomxkNC!A2|TX`p0LrQD6j5L<>$9+#uU%=C%4tY*o9z3o11SA1{|$~ zs~cj?5TUPswDhJ;UZvVVSj4)wBtU)mNJ3ncfRfmF^j+1_!@@q2?Ok4>3||cKGl1d9 za65&q1ZVl0$p*?+;mzZJiT4tkpm*~N5!`QlJ&Xbx=KdagpW)hv2D096?loM}0gnQ0 ztv^k0uw!m#w$Fr@Hk3-JzsK1^e2b5eo*f6>qq;V`Vfi*)vZ0!7yzZ$3qpoI;*Lx^%5%Dd1gO7H%kW0H4j#-z5tzdwJJ ziWdVx8lbS=|2VjVkab1KjoI;LtFsi&uAA{rY@D5v>PzXdpkw zhDA`W0}%f6nQDCA#}SDMLGwl>Ba&31IvUOyjlWtw#{PNz|x$x0n z)q(OG=9p8(Vb|SOE%{h}|8syyDRA^74aJI+<&Ls)Oa*Ca(?{E$RGu<`wK{YxUpv_`EQ_gJH7>bK zr(d~qLy(N32%ip zHIDvxJ|u+psA#CK&J8Dx=zQd}y?2?0mB#SGy_>dxSfar&>N*+rC&d=s*0_*cc4WNK zZnd*eRq!pO1lxZTl|$i)gFVn|sA;Or;aZAt!$&>EfE;2UKB4CE&uD5h-XLp;7scgu z^2)T6AX+HWLTbU+={we0##mA327v4d5w@kWP1Sd%j#OZY@gnPje!2$r! zg(DE&0bWmP>zc+(rN7^m|xA(^h^~&wFIfFFJuw)yF zWsQ<_=cC8${F}L3W9KznK4b1C$3stwvr_qhfY~W4>VIO(qQHfcG|ijGDLNI%>%Q13vTBR?;5}LqN}z8 zW&slH!jPs*RM*JNi0Z_`Rh+@E%wrdaog*2%ePZfPfGGL)5s>ogtal)4z2cMLqUW4* z5$;NTk|W3#UuMq{Q{wGz&jK$Asl>ulGS38sQi7%7v&dpFGqQFhNzpN7UNj$L%M5W# zK2<~IaF(3vQ8;hMs@{HSGoBa4Y2*~kiEFKYM2S_TPwwUxefaQ#**!BF8i^k}+kH%0 z#>hII6d?35Col`lk&xO$O~a&i{++VV?Ip4FG}|PDlQPCr)d8{nZHoYp!tt+04&&v-j(&R-=EMt6NzeNq$K^~U$fso$UT3XAFArTWbzYzY@$(e z7K=|sEp~pPdwK&xHcfl< z0TZ*b6*JDn7zAX-TU)EJg(uHGprFZTM#tLrS=qWD`KxmXM9n1p$gE)tQvR0A}%jDq!>&{$H#oAcO``0BK9N4bz z>Bozx^s!>Uf}noSNO%#EXR{j5ioEbTv(HcKc9Ak4e=Q$mM{yj5x~g}wz?fnr*|{>5 z+#RiuN=!;lZz8@`ZW+jmT{w{5+U8uQDCS(0%Ae^lsj6%Q)*yGsx5|)PVKRI=GQtEE z&Ia9E+Bz^1QKCsn|NBFzxkc@P#T2zH`j1>X_a)4|w4>`eFSo0*nC@frY5fdL?335{ ze+1tB6KF?!cy2e8ekwMx7s-D5nAK;T9b4U5Qs%D)$Vlv2veu> z(P;+%p}{^IS&LZENTuw*xqMnrf_HvBKD>lEL$ zSW%ML->-3rw~vv--z0Je;97H6&MBdeTjK(&3^-ASqkA*OLPpfs~5sbSYjVYgh2!=PV2dT3oi3;zp zSBTKZ7UERR3~@9U?7Omb%}cy)4;GpejZ1VhoZf#m_akb+Q5mW0-5JQfv~1vS9@{pj zj$FcfjQt$1f)1AP)@R}uyncdG>gt~9x|ZS+z*K;iK>R+5?wJxnW0^JooJuca z(7*2Sm)TzhYW<=Xt~a4`fS7c9hSKLZFd<(P z2h0hQ!C$4#JcXO~(eIon8jrFK + + + three.js xr - cubes + + + + + + +
+ three.js xr - interactive cubes +
+ + + + + + diff --git a/src/Three.Core.js b/src/Three.Core.js index 782018000d8111..922180b084069a 100644 --- a/src/Three.Core.js +++ b/src/Three.Core.js @@ -4,6 +4,7 @@ export { WebGLArrayRenderTarget } from './renderers/WebGLArrayRenderTarget.js'; export { WebGL3DRenderTarget } from './renderers/WebGL3DRenderTarget.js'; export { WebGLCubeRenderTarget } from './renderers/WebGLCubeRenderTarget.js'; export { WebGLRenderTarget } from './renderers/WebGLRenderTarget.js'; +export { WebXRController } from './renderers/webxr/WebXRController.js'; export { FogExp2 } from './scenes/FogExp2.js'; export { Fog } from './scenes/Fog.js'; export { Scene } from './scenes/Scene.js'; diff --git a/src/renderers/common/Animation.js b/src/renderers/common/Animation.js index 195bc2bdcd4012..5d863070cbaa4c 100644 --- a/src/renderers/common/Animation.js +++ b/src/renderers/common/Animation.js @@ -89,6 +89,17 @@ class Animation { } + /** + * Returns the user-level animation loop. + * + * @return {Function} The animation loop. + */ + getAnimationLoop() { + + return this._animationLoop; + + } + /** * Defines the user-level animation loop. * @@ -100,6 +111,17 @@ class Animation { } + /** + * Returns the animation context. + * + * @return {Window|XRSession} The animation context. + */ + getContext() { + + return this._context; + + } + /** * Defines the context in which `requestAnimationFrame()` is executed. * diff --git a/src/renderers/common/Renderer.js b/src/renderers/common/Renderer.js index 7a28cfc9b167f9..e91ea9835901af 100644 --- a/src/renderers/common/Renderer.js +++ b/src/renderers/common/Renderer.js @@ -16,6 +16,7 @@ import QuadMesh from './QuadMesh.js'; import RenderBundles from './RenderBundles.js'; import NodeLibrary from './nodes/NodeLibrary.js'; import Lighting from './Lighting.js'; +import XRManager from './XRManager.js'; import NodeMaterial from '../../materials/nodes/NodeMaterial.js'; @@ -643,13 +644,11 @@ class Renderer { */ /** - * The renderer's XR configuration. + * The renderer's XR manager. * - * @type {module:Renderer~XRConfig} + * @type {XRManager} */ - this.xr = { - enabled: false - }; + this.xr = new XRManager( this ); /** * Debug configuration. @@ -1225,8 +1224,9 @@ class Renderer { // const coordinateSystem = this.coordinateSystem; + const xr = this.xr; - if ( camera.coordinateSystem !== coordinateSystem ) { + if ( camera.coordinateSystem !== coordinateSystem && xr.isPresenting === false ) { camera.coordinateSystem = coordinateSystem; camera.updateProjectionMatrix(); @@ -1250,6 +1250,13 @@ class Renderer { if ( camera.parent === null && camera.matrixWorldAutoUpdate === true ) camera.updateMatrixWorld(); + if ( xr.enabled === true && xr.isPresenting === true ) { + + if ( xr.cameraAutoUpdate === true ) xr.updateCamera( camera ); + camera = xr.getCamera(); // use XR camera for rendering + + } + // let viewport = this._viewport; @@ -1343,7 +1350,11 @@ class Renderer { // - this._background.update( sceneRef, renderList, renderContext ); + if ( xr.enabled === false || xr.isPresenting === false ) { + + this._background.update( sceneRef, renderList, renderContext ); + + } // @@ -2026,6 +2037,29 @@ class Renderer { } + /** + * Ensures the renderer is XR compatible. + * + * @async + * @return {Promise} A Promise that resolve when the renderer is XR compatible. + */ + async makeXRCompatible() { + + await this.backend.makeXRCompatible(); + + } + + /** + * Sets the XR rendering destination. + * + * @param {WebGLFramebuffer} xrTarget - The XR target. + */ + setXRTarget( xrTarget ) { + + this.backend.setXRTarget( xrTarget ); + + } + /** * Sets the given render target. Calling this method means the renderer does not * target the default framebuffer (meaning the canvas) anymore but a custom framebuffer. diff --git a/src/renderers/common/XRManager.js b/src/renderers/common/XRManager.js new file mode 100644 index 00000000000000..a46d9e214c5bfc --- /dev/null +++ b/src/renderers/common/XRManager.js @@ -0,0 +1,1075 @@ +import { ArrayCamera } from '../../cameras/ArrayCamera.js'; +import { EventDispatcher } from '../../core/EventDispatcher.js'; +import { RenderTarget } from '../../core/RenderTarget.js'; +import { PerspectiveCamera } from '../../cameras/PerspectiveCamera.js'; +import { RAD2DEG } from '../../math/MathUtils.js'; +import { Vector2 } from '../../math/Vector2.js'; +import { Vector3 } from '../../math/Vector3.js'; +import { Vector4 } from '../../math/Vector4.js'; +import { WebXRController } from '../webxr/WebXRController.js'; +import { RGBAFormat, UnsignedByteType } from '../../constants.js'; + +const _cameraLPos = /*@__PURE__*/ new Vector3(); +const _cameraRPos = /*@__PURE__*/ new Vector3(); + +/** + * The XR manager is built on top of the WebXR Device API to + * manage XR sessions with `WebGPURenderer`. + * + * XR is currently only supported with a WebGL 2 backend. + */ +class XRManager extends EventDispatcher { + + /** + * Constructs a new XR manager. + * + * @param {Renderer} renderer - The renderer. + */ + constructor( renderer ) { + + super(); + + /** + * This flag globally enables XR rendering. + * + * @type {Boolean} + * @default false + */ + this.enabled = false; + + /** + * Whether the XR device is currently presenting or not. + * + * @type {Boolean} + * @default false + * @readonly + */ + this.isPresenting = false; + + /** + * Whether the XR camera should automatically be updated or not. + * + * @type {Boolean} + * @default true + */ + this.cameraAutoUpdate = true; + + /** + * The renderer. + * + * @private + * @type {Renderer} + */ + this._renderer = renderer; + + // camera + + /** + * Represents the camera for the left eye. + * + * @private + * @type {PerspectiveCamera} + */ + this._cameraL = new PerspectiveCamera(); + this._cameraL.viewport = new Vector4(); + + /** + * Represents the camera for the right eye. + * + * @private + * @type {PerspectiveCamera} + */ + this._cameraR = new PerspectiveCamera(); + this._cameraR.viewport = new Vector4(); + + /** + * A list of cameras used for rendering the XR views. + * + * @private + * @type {Array} + */ + this._cameras = [ this._cameraL, this._cameraR ]; + + /** + * The main XR camera. + * + * @private + * @type {ArrayCamera} + */ + this._cameraXR = new ArrayCamera(); + + /** + * The current near value of the XR camera. + * + * @private + * @type {Number?} + * @default null + */ + this._currentDepthNear = null; + + /** + * The current far value of the XR camera. + * + * @private + * @type {Number?} + * @default null + */ + this._currentDepthFar = null; + + /** + * A list of WebXR controllers requested by the application. + * + * @private + * @type {Array} + */ + this._controllers = []; + + /** + * A list of XR input source. Each input source belongs to + * an instance of WebXRController. + * + * @private + * @type {Array} + */ + this._controllerInputSources = []; + + /** + * The current render target of the renderer. + * + * @private + * @type {RenderTarget?} + * @default null + */ + this._currentRenderTarget = null; + + /** + * The XR render target that represents the rendering destination + * during an active XR session. + * + * @private + * @type {RenderTarget?} + * @default null + */ + this._xrRenderTarget = null; + + /** + * The current animation context. + * + * @private + * @type {Window?} + * @default null + */ + this._currentAnimationContext = null; + + /** + * The current animation loop. + * + * @private + * @type {Function?} + * @default null + */ + this._currentAnimationLoop = null; + + /** + * The current pixel ratio. + * + * @private + * @type {Number?} + * @default null + */ + this._currentPixelRatio = null; + + /** + * The current size of the renderer's canvas + * in logical pixel unit. + * + * @private + * @type {Vector2} + */ + this._currentSize = new Vector2(); + + /** + * The default event listener for handling events inside a XR session. + * + * @private + * @type {Function} + */ + this._onSessionEvent = onSessionEvent.bind( this ); + + /** + * The event listener for handling the end of a XR session. + * + * @private + * @type {Function} + */ + this._onSessionEnd = onSessionEnd.bind( this ); + + /** + * The event listener for handling the `inputsourceschange` event. + * + * @private + * @type {Function} + */ + this._onInputSourcesChange = onInputSourcesChange.bind( this ); + + /** + * The animation loop which is used as a replacement for the default + * animation loop of the applicatio. It is only used when a XR session + * is active. + * + * @private + * @type {Function} + */ + this._onAnimationFrame = onAnimationFrame.bind( this ); + + /** + * The current XR reference space. + * + * @private + * @type {XRReferenceSpace?} + * @default null + */ + this._referenceSpace = null; + + /** + * The current XR reference space type. + * + * @private + * @type {String} + * @default 'local-floor' + */ + this._referenceSpaceType = 'local-floor'; + + /** + * A custom reference space defined by the application. + * + * @private + * @type {XRReferenceSpace?} + * @default null + */ + this._customReferenceSpace = null; + + /** + * The framebuffer scale factor. + * + * @private + * @type {Number} + * @default 1 + */ + this._framebufferScaleFactor = 1; + + /** + * The foveation factor. + * + * @private + * @type {Number} + * @default 1 + */ + this._foveation = 1.0; + + /** + * A reference to the current XR session. + * + * @private + * @type {XRSession?} + * @default null + */ + this._session = null; + + /** + * A reference to the current XR base layer. + * + * @private + * @type {XRWebGLLayer?} + * @default null + */ + this._glBaseLayer = null; + + /** + * A reference to the current XR frame. + * + * @private + * @type {XRFrame?} + * @default null + */ + this._xrFrame = null; + + } + + /** + * Returns an instance of `THREE.Group` that represents the transformation + * of a XR controller in target ray space. The requested controller is defined + * by the given index. + * + * @param {Number} index - The index of the XR controller. + * @return {Group} A group that represents the controller's transformation. + */ + getController( index ) { + + const controller = this._getController( index ); + + return controller.getTargetRaySpace(); + + } + + /** + * Returns an instance of `THREE.Group` that represents the transformation + * of a XR controller in grip space. The requested controller is defined + * by the given index. + * + * @param {Number} index - The index of the XR controller. + * @return {Group} A group that represents the controller's transformation. + */ + getControllerGrip( index ) { + + const controller = this._getController( index ); + + return controller.getGripSpace(); + + } + + /** + * Returns an instance of `THREE.Group` that represents the transformation + * of a XR controller in hand space. The requested controller is defined + * by the given index. + * + * @param {Number} index - The index of the XR controller. + * @return {Group} A group that represents the controller's transformation. + */ + getHand( index ) { + + const controller = this._getController( index ); + + return controller.getHandSpace(); + + } + + /** + * Returns the foveation value. + * + * @return {Number|undefined} The foveation value. Returns `undefined` if no base layer is defined. + */ + getFoveation() { + + if ( this._glBaseLayer === null ) { + + return undefined; + + } + + return this._foveation; + + } + + /** + * Sets the foveation value. + * + * @param {Number} foveation - A number in the range `[0,1]` where `0` means no foveation (full resolution) + * and `1` means maximum foveation (the edges render at lower resolution). + */ + setFoveation( foveation ) { + + this._foveation = foveation; + + if ( this._glBaseLayer !== null && this._glBaseLayer.fixedFoveation !== undefined ) { + + this._glBaseLayer.fixedFoveation = foveation; + + } + + } + + /** + * Returns the frammebuffer scale factor. + * + * @return {Number} The frammebuffer scale factor. + */ + getFramebufferScaleFactor() { + + return this._framebufferScaleFactor; + + } + + /** + * Sets the frammebuffer scale factor. + * + * This method can not be used during a XR session. + * + * @param {Number} factor - The frammebuffer scale factor. + */ + setFramebufferScaleFactor( factor ) { + + this._framebufferScaleFactor = factor; + + if ( this.isPresenting === true ) { + + console.warn( 'THREE.XRManager: Cannot change framebuffer scale while presenting.' ); + + } + + } + + /** + * Returns the reference space type. + * + * @return {String} The reference space type. + */ + getReferenceSpaceType() { + + return this._referenceSpaceType; + + } + + /** + * Sets the reference space type. + * + * This method can not be used during a XR session. + * + * @param {String} type - The reference space type. + */ + setReferenceSpaceType( type ) { + + this._referenceSpaceType = type; + + if ( this.isPresenting === true ) { + + console.warn( 'THREE.XRManager: Cannot change reference space type while presenting.' ); + + } + + } + + /** + * Returns the XR reference space. + * + * @return {XRReferenceSpace} The XR reference space. + */ + getReferenceSpace() { + + return this._customReferenceSpace || this._referenceSpace; + + } + + /** + * Sets a custom XR reference space. + * + * @param {XRReferenceSpace} space - The XR reference space. + */ + setReferenceSpace( space ) { + + this._customReferenceSpace = space; + + } + + /** + * Returns the XR camera. + * + * @return {ArrayCamera} The XR camera. + */ + getCamera() { + + return this._cameraXR; + + } + + /** + * Returns the environment blend mode from the current XR session. + * + * @return {'opaque'|'additive'|'alpha-blend'} The environment blend mode. + */ + getEnvironmentBlendMode() { + + if ( this._session !== null ) { + + return this._session.environmentBlendMode; + + } + + } + + /** + * Returns the current XR frame. + * + * @return {XRFrame?} The XR frame. Returns `null` when used outside a XR session. + */ + getFrame() { + + return this._xrFrame; + + } + + /** + * Returns the current XR session. + * + * @return {XRSession?} The XR session. Returns `null` when used outside a XR session. + */ + getSession() { + + return this._session; + + } + + /** + * After a XR session has been requested usually with one of the `*Button` modules, it + * is injected into the renderer with this method. This method triggers the start of + * the actual XR rendering. + * + * @async + * @param {XRSession} session - The XR session to set. + * @return {Promise} A Promise that resolves when the session has been set. + */ + async setSession( session ) { + + const renderer = this._renderer; + const gl = renderer.getContext(); + + this._session = session; + + if ( session !== null ) { + + if ( renderer.backend.isWebGPUBackend === true ) throw new Error( 'THREE.XRManager: XR is currently not supported with a WebGPU backend. Use WebGL by passing "{ forceWebGL: true }" to the constructor of the renderer.' ); + + this._currentRenderTarget = renderer.getRenderTarget(); + + session.addEventListener( 'select', this._onSessionEvent ); + session.addEventListener( 'selectstart', this._onSessionEvent ); + session.addEventListener( 'selectend', this._onSessionEvent ); + session.addEventListener( 'squeeze', this._onSessionEvent ); + session.addEventListener( 'squeezestart', this._onSessionEvent ); + session.addEventListener( 'squeezeend', this._onSessionEvent ); + session.addEventListener( 'end', this._onSessionEnd ); + session.addEventListener( 'inputsourceschange', this._onInputSourcesChange ); + + await renderer.makeXRCompatible(); + + this._currentPixelRatio = renderer.getPixelRatio(); + renderer.getSize( this._currentSize ); + + this._currentAnimationContext = renderer._animation.getContext(); + this._currentAnimationLoop = renderer._animation.getAnimationLoop(); + renderer._animation.stop(); + + const attributes = gl.getContextAttributes(); + + const layerInit = { + antialias: attributes.antialias, + alpha: true, + depth: attributes.depth, + stencil: attributes.stencil, + framebufferScaleFactor: this.getFramebufferScaleFactor() + }; + + const glBaseLayer = new XRWebGLLayer( session, gl, layerInit ); + this._glBaseLayer = glBaseLayer; + + session.updateRenderState( { baseLayer: glBaseLayer } ); + + renderer.setPixelRatio( 1 ); + renderer.setSize( glBaseLayer.framebufferWidth, glBaseLayer.framebufferHeight, false ); + + this._xrRenderTarget = new RenderTarget( + glBaseLayer.framebufferWidth, + glBaseLayer.framebufferHeight, + { + format: RGBAFormat, + type: UnsignedByteType, + colorSpace: renderer.outputColorSpace, + stencilBuffer: attributes.stencil + } + ); + + this._xrRenderTarget.isXRRenderTarget = true; // TODO Remove this when possible, see #23278 + + this.setFoveation( this.getFoveation() ); + + this._referenceSpace = await session.requestReferenceSpace( this.getReferenceSpaceType() ); + + renderer._animation.setAnimationLoop( this._onAnimationFrame ); + renderer._animation.setContext( session ); + renderer._animation.start(); + + this.isPresenting = true; + + this.dispatchEvent( { type: 'sessionstart' } ); + + } + + } + + /** + * This method is called by the renderer per frame and updates the XR camera + * and it sub cameras based on the given camera. The given camera is the "normal" + * camera created on application level and used for non-XR rendering. + * + * @param {PerspectiveCamera} camera - The camera. + */ + updateCamera( camera ) { + + const session = this._session; + + if ( session === null ) return; + + const depthNear = camera.near; + const depthFar = camera.far; + + const cameraXR = this._cameraXR; + const cameraL = this._cameraL; + const cameraR = this._cameraR; + + cameraXR.near = cameraR.near = cameraL.near = depthNear; + cameraXR.far = cameraR.far = cameraL.far = depthFar; + + if ( this._currentDepthNear !== cameraXR.near || this._currentDepthFar !== cameraXR.far ) { + + // Note that the new renderState won't apply until the next frame. See #18320 + + session.updateRenderState( { + depthNear: cameraXR.near, + depthFar: cameraXR.far + } ); + + this._currentDepthNear = cameraXR.near; + this._currentDepthFar = cameraXR.far; + + } + + cameraL.layers.mask = camera.layers.mask | 0b010; + cameraR.layers.mask = camera.layers.mask | 0b100; + cameraXR.layers.mask = cameraL.layers.mask | cameraR.layers.mask; + + const parent = camera.parent; + const cameras = cameraXR.cameras; + + updateCamera( cameraXR, parent ); + + for ( let i = 0; i < cameras.length; i ++ ) { + + updateCamera( cameras[ i ], parent ); + + } + + // update projection matrix for proper view frustum culling + + if ( cameras.length === 2 ) { + + setProjectionFromUnion( cameraXR, cameraL, cameraR ); + + } else { + + // assume single camera setup (AR) + + cameraXR.projectionMatrix.copy( cameraL.projectionMatrix ); + + } + + // update user camera and its children + + updateUserCamera( camera, cameraXR, parent ); + + + } + + /** + * Returns a WebXR controller for the given controller index. + * + * @private + * @param {Number} index - The controller index. + * @return {WebXRController} The XR controller. + */ + _getController( index ) { + + let controller = this._controllers[ index ]; + + if ( controller === undefined ) { + + controller = new WebXRController(); + this._controllers[ index ] = controller; + + } + + return controller; + + } + +} + +/** + * Assumes 2 cameras that are parallel and share an X-axis, and that + * the cameras' projection and world matrices have already been set. + * And that near and far planes are identical for both cameras. + * Visualization of this technique: https://computergraphics.stackexchange.com/a/4765 + * + * @param {ArrayCamera} camera - The camera to update. + * @param {PerspectiveCamera} cameraL - The left camera. + * @param {PerspectiveCamera} cameraR - The right camera. + */ +function setProjectionFromUnion( camera, cameraL, cameraR ) { + + _cameraLPos.setFromMatrixPosition( cameraL.matrixWorld ); + _cameraRPos.setFromMatrixPosition( cameraR.matrixWorld ); + + const ipd = _cameraLPos.distanceTo( _cameraRPos ); + + const projL = cameraL.projectionMatrix.elements; + const projR = cameraR.projectionMatrix.elements; + + // VR systems will have identical far and near planes, and + // most likely identical top and bottom frustum extents. + // Use the left camera for these values. + const near = projL[ 14 ] / ( projL[ 10 ] - 1 ); + const far = projL[ 14 ] / ( projL[ 10 ] + 1 ); + const topFov = ( projL[ 9 ] + 1 ) / projL[ 5 ]; + const bottomFov = ( projL[ 9 ] - 1 ) / projL[ 5 ]; + + const leftFov = ( projL[ 8 ] - 1 ) / projL[ 0 ]; + const rightFov = ( projR[ 8 ] + 1 ) / projR[ 0 ]; + const left = near * leftFov; + const right = near * rightFov; + + // Calculate the new camera's position offset from the + // left camera. xOffset should be roughly half `ipd`. + const zOffset = ipd / ( - leftFov + rightFov ); + const xOffset = zOffset * - leftFov; + + // TODO: Better way to apply this offset? + cameraL.matrixWorld.decompose( camera.position, camera.quaternion, camera.scale ); + camera.translateX( xOffset ); + camera.translateZ( zOffset ); + camera.matrixWorld.compose( camera.position, camera.quaternion, camera.scale ); + camera.matrixWorldInverse.copy( camera.matrixWorld ).invert(); + + // Check if the projection uses an infinite far plane. + if ( projL[ 10 ] === - 1.0 ) { + + // Use the projection matrix from the left eye. + // The camera offset is sufficient to include the view volumes + // of both eyes (assuming symmetric projections). + camera.projectionMatrix.copy( cameraL.projectionMatrix ); + camera.projectionMatrixInverse.copy( cameraL.projectionMatrixInverse ); + + } else { + + // Find the union of the frustum values of the cameras and scale + // the values so that the near plane's position does not change in world space, + // although must now be relative to the new union camera. + const near2 = near + zOffset; + const far2 = far + zOffset; + const left2 = left - xOffset; + const right2 = right + ( ipd - xOffset ); + const top2 = topFov * far / far2 * near2; + const bottom2 = bottomFov * far / far2 * near2; + + camera.projectionMatrix.makePerspective( left2, right2, top2, bottom2, near2, far2 ); + camera.projectionMatrixInverse.copy( camera.projectionMatrix ).invert(); + + } + +} + +/** + * Updates the world matrices for the given camera based on the parent 3D object. + * + * @inner + * @param {Camera} camera - The camera to update. + * @param {Object3D} parent - The parent 3D object. + */ +function updateCamera( camera, parent ) { + + if ( parent === null ) { + + camera.matrixWorld.copy( camera.matrix ); + + } else { + + camera.matrixWorld.multiplyMatrices( parent.matrixWorld, camera.matrix ); + + } + + camera.matrixWorldInverse.copy( camera.matrixWorld ).invert(); + +} + +/** + * Updates the given camera with the transfomration of the XR camera and parent object. + * + * @inner + * @param {Camera} camera - The camera to update. + * @param {ArrayCamera} cameraXR - The XR camera. + * @param {Object3D} parent - The parent 3D object. + */ +function updateUserCamera( camera, cameraXR, parent ) { + + if ( parent === null ) { + + camera.matrix.copy( cameraXR.matrixWorld ); + + } else { + + camera.matrix.copy( parent.matrixWorld ); + camera.matrix.invert(); + camera.matrix.multiply( cameraXR.matrixWorld ); + + } + + camera.matrix.decompose( camera.position, camera.quaternion, camera.scale ); + camera.updateMatrixWorld( true ); + + camera.projectionMatrix.copy( cameraXR.projectionMatrix ); + camera.projectionMatrixInverse.copy( cameraXR.projectionMatrixInverse ); + + if ( camera.isPerspectiveCamera ) { + + camera.fov = RAD2DEG * 2 * Math.atan( 1 / camera.projectionMatrix.elements[ 5 ] ); + camera.zoom = 1; + + } + +} + +function onSessionEvent( event ) { + + const controllerIndex = this._controllerInputSources.indexOf( event.inputSource ); + + if ( controllerIndex === - 1 ) { + + return; + + } + + const controller = this._controllers[ controllerIndex ]; + + if ( controller !== undefined ) { + + const referenceSpace = this.getReferenceSpace(); + + controller.update( event.inputSource, event.frame, referenceSpace ); + controller.dispatchEvent( { type: event.type, data: event.inputSource } ); + + } + +} + +function onSessionEnd() { + + const session = this._session; + const renderer = this._renderer; + + session.removeEventListener( 'select', this._onSessionEvent ); + session.removeEventListener( 'selectstart', this._onSessionEvent ); + session.removeEventListener( 'selectend', this._onSessionEvent ); + session.removeEventListener( 'squeeze', this._onSessionEvent ); + session.removeEventListener( 'squeezestart', this._onSessionEvent ); + session.removeEventListener( 'squeezeend', this._onSessionEvent ); + session.removeEventListener( 'end', this._onSessionEnd ); + session.removeEventListener( 'inputsourceschange', this._onInputSourcesChange ); + + for ( let i = 0; i < this._controllers.length; i ++ ) { + + const inputSource = this._controllerInputSources[ i ]; + + if ( inputSource === null ) continue; + + this._controllerInputSources[ i ] = null; + + this._controllers[ i ].disconnect( inputSource ); + + } + + this._currentDepthNear = null; + this._currentDepthFar = null; + + // restore framebuffer/rendering state + + renderer.setRenderTarget( this._currentRenderTarget ); + + this._session = null; + this._xrRenderTarget = null; + + // + + this.isPresenting = false; + + renderer._animation.stop(); + + renderer._animation.setAnimationLoop( this._currentAnimationLoop ); + renderer._animation.setContext( this._currentAnimationContext ); + renderer._animation.start(); + + renderer.setPixelRatio( this._currentPixelRatio ); + renderer.setSize( this._currentSize.width, this._currentSize.height, false ); + + renderer.setXRTarget( null ); + + this.dispatchEvent( { type: 'sessionend' } ); + +} + +function onInputSourcesChange( event ) { + + const controllers = this._controllers; + const controllerInputSources = this._controllerInputSources; + + // Notify disconnected + + for ( let i = 0; i < event.removed.length; i ++ ) { + + const inputSource = event.removed[ i ]; + const index = controllerInputSources.indexOf( inputSource ); + + if ( index >= 0 ) { + + controllerInputSources[ index ] = null; + controllers[ index ].disconnect( inputSource ); + + } + + } + + // Notify connected + + for ( let i = 0; i < event.added.length; i ++ ) { + + const inputSource = event.added[ i ]; + + let controllerIndex = controllerInputSources.indexOf( inputSource ); + + if ( controllerIndex === - 1 ) { + + // Assign input source a controller that currently has no input source + + for ( let i = 0; i < controllers.length; i ++ ) { + + if ( i >= controllerInputSources.length ) { + + controllerInputSources.push( inputSource ); + controllerIndex = i; + break; + + } else if ( controllerInputSources[ i ] === null ) { + + controllerInputSources[ i ] = inputSource; + controllerIndex = i; + break; + + } + + } + + // If all controllers do currently receive input we ignore new ones + + if ( controllerIndex === - 1 ) break; + + } + + const controller = controllers[ controllerIndex ]; + + if ( controller ) { + + controller.connect( inputSource ); + + } + + } + +} + +function onAnimationFrame( time, frame ) { + + if ( frame === undefined ) return; + + const cameraXR = this._cameraXR; + const renderer = this._renderer; + + const glBaseLayer = this._glBaseLayer; + + const referenceSpace = this.getReferenceSpace(); + const pose = frame.getViewerPose( referenceSpace ); + + this._xrFrame = frame; + + if ( pose !== null ) { + + const views = pose.views; + + renderer.setXRTarget( glBaseLayer.framebuffer ); + renderer.setRenderTarget( this._xrRenderTarget ); + + let cameraXRNeedsUpdate = false; + + // check if it's necessary to rebuild cameraXR's camera list + + if ( views.length !== cameraXR.cameras.length ) { + + cameraXR.cameras.length = 0; + cameraXRNeedsUpdate = true; + + } + + for ( let i = 0; i < views.length; i ++ ) { + + const view = views[ i ]; + + const viewport = glBaseLayer.getViewport( view ); + + let camera = this._cameras[ i ]; + + if ( camera === undefined ) { + + camera = new PerspectiveCamera(); + camera.layers.enable( i ); + camera.viewport = new Vector4(); + this._cameras[ i ] = camera; + + } + + camera.matrix.fromArray( view.transform.matrix ); + camera.matrix.decompose( camera.position, camera.quaternion, camera.scale ); + camera.projectionMatrix.fromArray( view.projectionMatrix ); + camera.projectionMatrixInverse.copy( camera.projectionMatrix ).invert(); + camera.viewport.set( viewport.x, viewport.y, viewport.width, viewport.height ); + + if ( i === 0 ) { + + cameraXR.matrix.copy( camera.matrix ); + cameraXR.matrix.decompose( cameraXR.position, cameraXR.quaternion, cameraXR.scale ); + + } + + if ( cameraXRNeedsUpdate === true ) { + + cameraXR.cameras.push( camera ); + + } + + } + + } + + // + + for ( let i = 0; i < this._controllers.length; i ++ ) { + + const inputSource = this._controllerInputSources[ i ]; + const controller = this._controllers[ i ]; + + if ( inputSource !== null && controller !== undefined ) { + + controller.update( inputSource, frame, referenceSpace ); + + } + + } + + if ( this._currentAnimationLoop ) this._currentAnimationLoop( time, frame ); + + if ( frame.detectedPlanes ) { + + this.dispatchEvent( { type: 'planesdetected', data: frame } ); + + } + + this._xrFrame = null; + +} + +export default XRManager; diff --git a/src/renderers/webgl-fallback/WebGLBackend.js b/src/renderers/webgl-fallback/WebGLBackend.js index 4f5b7c5df49eda..6d5898a159dc01 100644 --- a/src/renderers/webgl-fallback/WebGLBackend.js +++ b/src/renderers/webgl-fallback/WebGLBackend.js @@ -185,6 +185,16 @@ class WebGLBackend extends Backend { */ this._knownBindings = new WeakSet(); + /** + * The target framebuffer when rendering with + * the WebXR device API. + * + * @private + * @type {WebGLFramebuffer} + * @default null + */ + this._xrFamebuffer = null; + } /** @@ -284,6 +294,34 @@ class WebGLBackend extends Backend { } + /** + * Ensures the backend is XR compatible. + * + * @async + * @return {Promise} A Promise that resolve when the renderer is XR compatible. + */ + async makeXRCompatible() { + + const attributes = this.gl.getContextAttributes(); + + if ( attributes.xrCompatible !== true ) { + + await this.gl.makeXRCompatible(); + + } + + } + /** + * Sets the XR rendering destination. + * + * @param {WebGLFramebuffer} xrFamebuffer - The XR framebuffer. + */ + setXRTarget( xrFamebuffer ) { + + this._xrFamebuffer = xrFamebuffer; + + } + /** * Inits a time stamp query for the given render context. * @@ -1082,18 +1120,18 @@ class WebGLBackend extends Backend { data[ 0 ] = i; gl.bindBuffer( gl.UNIFORM_BUFFER, bufferGPU ); - gl.bufferData( gl.UNIFORM_BUFFER, data, gl.DYNAMIC_DRAW ); + gl.bufferData( gl.UNIFORM_BUFFER, data, gl.STATIC_DRAW ); indexesGPU.push( bufferGPU ); } cameraData.indexesGPU = indexesGPU; // TODO: Create a global library for this - cameraData.cameraIndex = renderObject.getBindingGroup( 'cameraIndex' ).bindings[ 0 ]; } - const cameraIndexData = this.get( cameraData.cameraIndex ); + const cameraIndex = renderObject.getBindingGroup( 'cameraIndex' ).bindings[ 0 ]; + const cameraIndexData = this.get( cameraIndex ); const pixelRatio = this.renderer.getPixelRatio(); for ( let i = 0, len = cameras.length; i < len; i ++ ) { @@ -1869,6 +1907,7 @@ class WebGLBackend extends Backend { const isCube = renderTarget.isWebGLCubeRenderTarget === true; const isRenderTarget3D = renderTarget.isRenderTarget3D === true; const isRenderTargetArray = renderTarget.isRenderTargetArray === true; + const isXRRenderTarget = renderTarget.isXRRenderTarget === true; let msaaFb = renderTargetContextData.msaaFrameBuffer; let depthRenderbuffer = renderTargetContextData.depthRenderbuffer; @@ -1883,6 +1922,10 @@ class WebGLBackend extends Backend { fb = renderTargetContextData.cubeFramebuffers[ cacheKey ]; + } else if ( isXRRenderTarget ) { + + fb = this._xrFamebuffer; + } else { renderTargetContextData.framebuffers || ( renderTargetContextData.framebuffers = {} );