From 8c2b1fcbc133ed13eb6d92d6665fad840a971a5e Mon Sep 17 00:00:00 2001 From: "Mr.doob" Date: Fri, 9 Sep 2011 05:24:24 +0200 Subject: [PATCH 1/3] Early version of a GUI that spits three.js code ^^ --- gui/files/inconsolata.woff | Bin 0 -> 28040 bytes gui/index.html | 136 ++++++++++++ gui/js/Code.js | 159 ++++++++++++++ gui/js/UI.Toolbar.js | 81 +++++++ gui/js/UI.Viewports.js | 421 +++++++++++++++++++++++++++++++++++++ gui/js/UI.js | 30 +++ gui/js/libs/signals.min.js | 8 + 7 files changed, 835 insertions(+) create mode 100644 gui/files/inconsolata.woff create mode 100644 gui/index.html create mode 100644 gui/js/Code.js create mode 100644 gui/js/UI.Toolbar.js create mode 100644 gui/js/UI.Viewports.js create mode 100644 gui/js/UI.js create mode 100644 gui/js/libs/signals.min.js diff --git a/gui/files/inconsolata.woff b/gui/files/inconsolata.woff new file mode 100644 index 0000000000000000000000000000000000000000..6170a0bfc93b586d544d2e070d0b496e68efdb13 GIT binary patch literal 28040 zcmY&fV{j&Iuzh25V>=t$-e_anwr$&XHnwfswr!g?-@U(XSDl*a^PE%N&(zG+{OEC! z5fK3Z0e-?N6oB~OabV{E^8e2Ne~5@EN&x^smOm`^4{%h^UUWo-ghhV1(4QRd2LwP! z08kkPI>sNan|6uGHOQ6=k*^vMM0P+3Nu>S|xFla$z zTNA4vuH{El`=d8PXrL=L(R29mg8f$)_J08afH1LiGydUR0RTO60HEH|tflYN)JV?| z05Hz^(J=gg^<@xE+4P6};TC>!+#is@Z9}-5S~>psj30h#xctr&! z^_)WVrdDffZ}j7}`upSK{}0;Z?QX7X2D-Ysh5&y9l?P-0lY|Y5n4AX#fT$OED&W60 zLtWh+5Pc|cL|uJd(7s{*3E-ojeZa#2p#lDP-Pn8bCCD$yFJLj%2@M1!pF7aFYbv&n zq^GB6U~*`5qGzI~XQrno2O)9V*w^2ec^L&90vt@3wCT&|6BgD|EmDnNPcIhd9y*zi zU);|R3E^!@wg zJNFyx+w1G=`~9r<79s=>$Ft_TcMGB&&(f#ntG5n93Sr_3Kd>zXvS(xnpfWK6N|HK* z3g{f^8ylMH9UYwPA0MV8_)S7hL`gL8cXo8OdwO`ee}0UQh=GEGjD?1Wgo%p#3mg4k?8wa0)+&$N zP{&|IGPOpV=i!->#Zr|{v)=wurAE``N|(v=mKUrrMQNG~B^sI`AMLpQN$Q~NL{F?X zyt9@xTz|M$)TkSQv-Ra>LDAA_2)s_K`~6bmITt28o}R1YH;`=6-H=sqa`w?y)fd#S z_abS7R7R64%i#QBXg_%+eprA~pIUF!hj3~%y+HDO=(c7Wh(l(PLp_Vb~F9%#ZCB?JQlRwx<%43LEUk>+rzdGB* zpo;)%UHD=`B-M3$yVM~EuH<4xqBF9}GKfU=&)#O;el;50EYmy|&TV&5Vo^LzJQAcc z+1^Kzi3!@xsoj}8_VUT+zl4jxhD!(Ojopgc`kqyH8c^DT!C$pusjvNcg#Qa*04M`E!j$<9E2_(Cyp9@1149o+V&o5o0e!R`&aji#@_Ad80Zs@a z@1M|p`II;LYP!Ne#6Mz?xy(kZn%df|bX@VMYZCJdR`G>q$&*FQh7R?sv|{s#QfyKl z^=5x9?WWy~4-j~<+_&G`pP#!(@M4UI=I%2cvK_vT_c`=c>kjXPo%xpsPtrV(l*uZ| zCE5E=F|hH;#07*1kC`}ubj-SktT>5+neuwrUu%d&7+Kwu@8WI8$ks0QD{_vH+~Ozl z%G@H#^R0_z`)H&UJ@Tw$)(-lp+@*CTuGVw*8@j)c89n; zA8pklR!_LCiT=Z*%likAdASW^?ihxhN70GrFk)=q$oAAJe2b|VG2jrO!-^!U7jEL% z)zD#J^a;Q8V7FZwt=PW|N_(p3TNlp?)dQSz&Wh#H36m;puSRh~Sq6x{-GJ9@C+ zX3dHL5-FmD+HNv=dehKNvJ$H=kt&|t#IZtBpKzhPbQnoyQ?P()UYfdJn4ftK$A+Ih zB5a|uG^qeBbbcx0u6`N3vUcIBu?!Mznq(5`ZUq5fnxXt#5Py7lfxPZJp5O$jQPQls zET%Z@a&KN4C-B^rork3nAY=mwsb8aF7qAgfebi~lVngqI?bAx9Wpu*Z6v zkltnP+gQq+$B^o2S}!f}cz6^s530$$jHOq;V}y->3tiZQl^V9?+pP+i7^7wUXuY(| z_vqyC<+`i3Erv!`J8Qi$Hl1@z-Sg|EmW++p77r(porcGm5q9gQ>-qu0MSnR&@(K@Z zzCnD7&v<85JrmiCB-jKuSzpIw!DNmwss%N!kQFCBoq9`&D~vP^_bswZHCdw!KdP_i)lic(TSRrwIYpITWWSuf5H3<9sA4XW>SV}K zo2RF%joJ0*N%^N$Erl>!FN@1D*;DAb`^jRL3)i=dez?O!DwW3N`@Nm~7&t4phuTrN zj{|aUx<_WV#zz(wDPHcElU@&Sd@n}{4-E+q6$_X#=lesKmSsnxU!bSjeII^e5V2QX zs+0xoe_6E3)Lr6!i}kt%mK6ehn0;@|8_{s<&Gf$Q^ih576}3clbKZoUhCZ+N z(D@c@GI8B^_N9f@don?&M|Zl61mhEw;S&u1z44le#M>{<*RNm|LuV`q#b%Izx%rjC z=X!0D8#DTGF`kkZkue(3?G|yd(cndoJ>K>2)2iu$>g?T_zS@rb1<}9&L-fz^AW7b_ zI1gtYTO8tPXhL!igRe@Y{hFCu`v01^XalbMG~iF28`y!!hv^qj#HlRW5HXyul=1V~k+p)_{em&B?8W ztvD~2v+t`D=?yRA_iTX!izEAF+@1Q!o4Nupj#;;8Y|LD2Z(LJj{bPb1moss$&Ye0Q95Bb@+1tK;oDguiQ{u2VJ?HhQP@aGh`rlN$O=*v5BXZyVj9of?uggVk_A1p6Y z+CTx55I&gg%ntJ#!r=Chq&8FKG6YXi%9JBFLP~!(DG5@Up5cujC6i~_FS&bD9my01 z?OJP{QFY`z$SDlphWo?ZO+qVZ=C?{xOI}xM#A9kyeBpbK1-9VVRC@N!8bn6Feq3&+ z&HZ@Hf|r$+plV41I@p~>09%Mq*fxyeHb`BEG6bhzYnB)tzjtU)4AFr=*OmSd8O?9t z7sGi5wtaQb91G5W(0+>TNRVK@ELVWKAuEt2#hx-rv7K6AzEZ!&)kHTj((UXgH1Lza z^S?;9D76f5ODFrYfyTU#xtW7BM4`T8PnO8S`Lz{%U2fmExPEz;Y|ES6b;b?tRwNEP zgYBH}Avy|E*4U_mBK3S9E5S56#}FW0?H21HZ|%-J_fgrRAiWbixyw+3pBvt>t-}J| zQMxq2z2#O zW`^Ivx7{zt`M-lZ{!ltWbHy>H(cSLs)=}sSD2$~u{{wTv4_no*BA||%^R4{%h`@I{ z;CBIXFkbLYOUvq}=kWx2im#VadTt2&QkU}25O_kF>~i{c(9hEjMCXpQyZ?`xP$KeJ z;vdyufl0rQW0~w?_yUj)(f2^w!zRsm6oeI*c8JD^&D|%-akE^ggN4&S9KuUcOasb) z{bo=*kRJ#kRI#kV^P;Up`3T&v!=++y)>ONB=5UQ&q(6IEYEDL6H|yJ zVt8AwN5Ty$+AWydtIsN#=rmh?xz)kYf2B@A-k0lwr!^p$s6sO>?85eHjU5Deai;3w zP1VFxDxlX4kQN^WRNeL&65p%`QBkET9<66Hp51wp7DCo_J|&h6zXl??Gl6NN@7Y@5 zaZ{3^W=YK|q^9&V9?h!6%aWeRgw4-4lJ8IaF@oyl;knh4K(4mpdOHNlS3(3Xmk5B{ zq%yE{)p_4a(RORNABpb*IT8(S6LoQBxirMy_P7{vxmqUyb(>8huf}k7FF38YF&f^w z{J7}9{*8~b;b7}Sck}dnWFPTnY2tywjDb9gf=PN2S#IDSv$LmypX+zt$SDwd0ZCFL z3%U1wI;9QHjWR?B3rvs3J}7`D3n@un-Go_X3c1ZU;!u^=6oSAbk%z6xNa1?6x3-Gq zV`i%9!eTY0zS?*?j&|;As#^AHrumbmS;3?zxiVaBxIio2N`WXY5l9rHaAE|+_+V5V zaS`yCK~zf6nMeuTwX*9-xWx#PKSQC4(XjfD(U#Vx7L{176cVGZ7^Bycj`p9(W)ex4 zYZdZ{8&|~mAIQcCfXm^`Qxi{s7WUM|`h9+TcZ1t;kioEb>vygb2m&|vT)mZ@p;0GS zccD*7{XU+2_bK^pcs`H8wo218PI>s}$<-%a_G@`pR(>%)LJ)kdQe2hciXrv(>VosL zyOPR9@T(2P_b>w1tu~nzVVQsm4OePeB%SFlKdsl_@SsGLLHbpF4y7DSw;BIZ{n+tD zCFwlAuf)Nr*D>4la8s2(rh_yD;Y$U3^%VAuN_avsfpRqdXTW(>RiZM)iM}kMD1Q~n zjkytAgGg3B&w8b%h5Bv>e6Zbs3l%C_D~+BzLc8|-nmXxtYVwP3&-L84J9!K=ze}H8 zuCYEBZJw`uKn?2^Lmi!M-a^`rV79kk{|=wccXPnrE7xKyBdAV{ksRkR3}Oj%m@a$5 z+G``_W5Fv-v@$&~8xt}*(=uxC!2GK{UfOV+PtUkvqM!|$P6Xu%<##mX#UK4IYTA2~>t)To8->gnxdU&Ene ztO}9FRw*3%lGU&IVTuph9s#Y$KSY?y!xP60B_X{Xi`>FOkU_S&Z{FTVtYraCHPT?J z#T|G{6cC)LzhogCI;2yfOmC?p69v8!TKopYel=TD4rQl#W?oL#g^cpn>FGE_B~9ba z_2ce~=oOx&`QwZg0kFa3BTZ*8mU;aC;Z?cap)5HS}{!&%43ya_P1p zANL9~ekk4lwthd2Ipv0&2ncecpCiqjIb}=9I_<;eoDl+K3A-mOYyGJlC{W|%vJWS; zv@T*2rw}+kF*ni46t@TQYJJ^|zQ=C=U}b|{;ps_aaw*?3D1$Us#T!jDx34A0TbU|0 z+}&%LL`&>Ti={-Z!)iq;IUA^v5^q|)C}vlg?U;LYd=0WRi@+8Jkqp!a2cpOW{}T&R z20!LU2fvgZ11g|?HexSb@9ivQICQ4ddcAW0I;xuy`*01rG)4EM!ruJYz>6ie?RYH3 zwmBLDYsuk4FuSSV79ZnfW+W>5-U)Z;H>VU;$V2RPnP9JDV4#y!|0{L9WRah%N?V73^ zpKms^5K`VocV^!%kDV{P4Bo?oxj5C~k@mBL=|m_!v*OZa4WVXcd^pBCbL;!f=^1_U z-N<2!V+Qqg<59GziRH_H3W&qQ$}D(@xHty$$AQn*D#l*xtghFLA%q?nF&5{iC)@uD z-coeR35oWz3m7O9oP{HC!x1C!25aM?KZxA?7UJG>0?|J1c{D5)<`vdu2?gJuAj+{e ziUe&197EcA-~GaNbNLQfgZL?|#{^a`bseJQn4uI#4apn}Nz)&xLxHQ)u9q!LC1UW$dAS_`#*2Z|rqtsS z7G=;NILl>KZ5(hX#0WQ2vz=IB(N>td zYeDzzXnH=TG@hX0JtPAz7~}Ye1D%|`*6}37&b;@yxxDbw=UTrS6!sj9czLCzgsrf~ByX9n;&OA#y=D{V&O&{=Dv&f;4NM3}Jkq8j{f&@gFdR3xA zKUfg^5pY<*tSMso7zp`p@V-<==)R=U?=n!_qOmVw4bFVdWl`d3|FL<2TB<|-6#beLM@Xb2%WKKBR&0ahY{Imv{h zW9tnv91o`C&SH%m%Txha%0f^48`FfCLVtzH84=f*NwbN^P#qx+ybCC=3zuh=pIWZ> zRU_ZLYt%HTYPna=X*dFR-y4T&rgkc-MbE*TK#lJI-8xXNkSrZ$+-8+7jD0fLhqaa2jhdx zT>v+hky+QU5ll}Q zgp9v!+iQD8n&*vGvg)%Dsdqd&XbJ~atw1(9?vMs>C%N7-!{YX3$4DSd2xcF3B_HBpMXHem%A{qJarvgsJu!k?i8top zxYRO-K{^|iZH{l^Swzx*Dav2tr5U6Su2P34l@o|FgZC?NT-9xw=2UY{^T^BC=uY+8 zsE44Hssb|CLfeBeLbFe-vSjMwdpO6>_to&nedyNNdrT%-^O+yv*Ud8Bt;#fYU97X+ z@sAsSx$=TPumM=*9>cWf$y*0u9mLO1#h0*snHBHQ|*@$$?DWF9v8HoZ+-=PcvDL7rd5R0Rt44K2i0oKC=?j54bE{#XDRv2 zyCO>hI&`Tsc65PLvu8>vpfd+#1i#;iIiVCtt5eD4GaaG&|KhYj9jV>sCr+6Pj>BdH z=VK!7(B>8_uIpA<;OpMQ*X8}aO5+@tk#4fbtXGQX6|=pT;w;@P1KND;m>OYEd!3lv zvB=$|oMF(?Z7u=M3gIlwj8=}Qe`(a*0$#|bMWj;W-(ar>D3a+(q7bhcDbci9m36C+ za{i`P{G?e(MAoRUa4~Fgp5Laiuqx%KZ*^X8+ImXwf*UQWy)#sL%}yT3@?tsglK;ry z@hV)u;!6Bv_b^>wKHBbzx!8JsTM`mozM0nEYTMfOYN_MYQAC^8 zvXAg#*s?duG)y&CJXLqku=lwaR389Y0eYUk-XHKDWt_hT#e zWm7JSeJx8y)#HaLg9UEStX-KHA;8*vmNNOv&!m2ss9}USIhOzJe^mZgi`0b3=BlWC zAaYR<`8PxP;WWcK-t357BzbNnWYP(BlU{{9Mdw$HDepq4S z_@0Fih$I~T`L_2EpHpzuq#kvn=(*k}x1Sr#k%VL$qe+Y=J41JJdCfnWq@EWE!!n@p z#WP>UFsK#{Rf`M5?fENye~o#|$<&Hz6~?a^V1g`5ig4BnVRr0N8WS*t0FY}gD4 z42LU%6f$VgBd!RMQ1n9-?uuf%m(?Nd9o_J0r%kCBrT^863yx35$| zF7f?!D&}`uvnOG@AyY|>!3a$4N=~K`Q#y(l1pP-$1jQui(kusA#{gClVw~Uj8WTq- zisSH#8Xk#B19?5sOUbx?J+z{BAFI8&{{}wc@4Tw~(1lWFSvgv*j1)916#AE2Q4{!1 zKi2BHxUMfG;L96A{i66p?{x$zX?m(b$rI)RV{((0=Xa5Jc;yzktH}msUH@IWxuBzJ z+fsueYWsifpBim@q+n5Can5Rr+tNGby!GZF(fH=Qg~Kz8lVEW1D<_=stVX-@a$z1# zd2vG-!1S$b<<=h5pM^_AfUDZK-a@%^@>VFzi89$e@zIv$_qs+`1jrSJ9wKKJO(aVc zTYMk7Y|maGt;yqPg(sOEoIS`KY=4SJy-*-u)|fGit4rWXI9Q4)%Pay27?yXs>`W5Y^SvSza0dAL4mtmaBAGn&8T=c9X#qR z`MPn9F(f2teh(*LY>pjXVqRgMeSc`zLu270N)&Kp@t^W*;Y(H#7wqJPQaY;d#sDow zmw?AmQ&uKdbk+PKcX})K^YQY_HdT@2Z?x+>!D%57%GqSsgNwe&T>p5mg4ecHWoSM) zN8c)Lmbz=%B4L+(pI?6~x5h5E>CeEvolLXqJC9PI&37)Eg&qv}!e@?!pG)Ae3r!7s zk$p0&`>L+9G1)e7sSi-2bMr92ULbg7ry}T#=dVWh)h1#p6Y)5PZtxpQ4Q+cGVSbW# zWZJV@&|Sgb{>Tq+;_n(XdzJ2bFF!sSW2+uxgUO@WqvoF|c8j`$b0>NQRTGDXH^zTu z&8hsn2p%1+_{%%@0Cq;4cwdFdU6#s>AE=~2&Ounc^-PB#Ehxwc^Z}+=D5@xIdXrS+ z&x;-|ms^IUb;k}h0OF1us_da@v07USl9`az_U|&;ADOG?I0oMHu4&*(*@AK+C8L#A z3*lrKGOF)v;WxEheoYBniM^ry7!o(36vY`cTT1Hck!5^`t$2;i`%BdOS4SII-VzOB zg~rZ88<@5Ara!U3gF*krO3hT)-u@@c-~L}I8LJ5P21}xfMtA}c(&cqMK>$u-mB>8$ zRt68jv!^A`$yoF;owK6h!{*V0sFKl@nNRv^ zvseh<r_fs7vhm~TA*c9@>Yc49(-Qs3LU@ntwMP%rH z6{d?5h{%4JGs{uOh%kVpis#t)3MM3ochML$q9-fPd}z0TZeIBtG8)ZVl-39?((H%5L-I&v^@1>#Ur%_=N=>dwCn?5@9kehqvML!^snZ+UXd*S^n`^7y>p3{^c{ z7JC0fWL|ouqTZ^?dy3|3xJKZ>wY0s@v$j{cUNKQuf0E+qbUwIQdg~gp|CZY2r}6Xg zKhYFCt%Wmyt=YOu75%tokJcDZivaLc~YoIx~~zZ`iE{v!`#a+sj~5KH+_lIXTEdG zQ>%TJNL&HG!86zR=3&Wd+DdD7ttRS2Z@RB-DwbM>+1loMb6uHqyCV zco$4C54T4Xs^PhBr{ym$PM7a}%)VHIfz^3lYEYW1SibADewmN`PLOw~qeg%ZK0q4< znC?n{&iOzX555#MSm+$b3FaQQ)i!So2LGn7c#X^hl0+W3#k3$gKtDo0IFuKWR|^mL zGKf?)We+(H1Uw7w7ym+%z8!oM#-1pFXH7+NNwg)=@d%l{wW7@YQthG_0vLXCXoX$3 zs$EODnd5$Vi2h~PZgRE9<-pmdmqbf`Wq1eg+r`is-NwYw1bqF2m=*O2Tyx{o0_^8O zPf`A*k=JEo#?!)sH{nb}NY&`JJ%ar-{i`H}$P*8{QG4_fdVpv-C{b!qq1nGWvydiV z&IVqZbVUDcUKq*f`uUCI*<@A&9*Bum{bh5mL|~0@26HuB6xMV-_?*;Iqts}C6Ps;1 z2!2-CYF(}{tF3~|9hJ>>%yoCA*UKUkKHo&0<>i^j*!sHp2n;@={9H%A$LJit*mqY^ zkCv4O`RF8T>+{j{yLpIgb2M<5D~O{J(!FqF8%P8`%);JqN6B7j$s=_`Pp@8IpQw+} zt(>Lu?-~8qKlocz)PUhWmC#~dGV}!p#7RT0y;|3*SdirCpMi=U;<9aqH~osU0e<6t z%B_JrzbLAqcmd?`?9F~@_(z;COO4?ZX}N}TVipSvd`%wa!TJPqI3bHCNS9=;enloJ zN$h*%1no$c1Qv6mQo?x301gxpd77JYnml%W3|jzs^6!69zk}~fjWPHFT9ZLDna9N$ zh$OUWIF5-^Tl(vbITphy1zXs)Q?@DRP_)Z%tC-1k?Wv_kAjJw7yZTgB4Yg}piu4|7 ztWG$WR^^fDIZ;Q4Q(IU{S8-pOcKR{t>7Rs_?0axU-2j(uY{e?mb5>S_AM8&*2X4YGGmNz5#wOPL+VeQ8-dm4aOAZDk358eJ-(b-iuQ^{J>&OX_&_oz}?27GrU`lzhL=9cw~F3;hrIwqc$1&s?j z+KcjSe^6X=qrD)$-7yZW=;*DfP7wG+w2StSO4uY{nSUGp>6GKP8hwxhB~@yf7Msjj z^Zfu?AiU=2~M1iiRHvDYb-GYRs#c$qF((aX);J>zQUVx3?45afkkXLQfX5(*tg!;0G5xlSv{s(hkP#O>ynS#ETPF z*an7nlQUAk4u({oip8wQz77-pHx7z@C5rsqPd-wOR!J?*dk9U@Fs64Tx6GC1I}i;% z3MB`&%AIl^7*;EwE4iG1`wzrkehvGtLa}|}9Knk?CDJhbR>2gF=zzx6k~)5xl%*Lm z>v6ljG0jk6C79pfLqb`Er7a7{(ef1yd$3|wPGv9&Sb;=KA-trG=I-ft>AY5(n5r2i zpYf|)EoFS>&9w-rJhka%cUs`nV{hX4E*<2`F6VV?$r>FrwUln=G#;j%bW3vEyiUHG zoBK9r;tkT5gKk$toV=+fKu0AdQw-DDMq?bmLTF{lRR|0${gek$^_9E$g&!%%@6s}u zLdp}zuLA7K)cv>j?zxpJA9Y}qZHHsDG)ikE-+yLR5_}(}cGj6oSgKpJl^jK>7Vb}a z8WsYzqWonYZP+YGj83GuCuk>jJ(hP>5Bg!GJ=!5Mnu?G3)f znK8r_BZb8B6@pT>$)-s6;;wsD>Y{SvImq{WhSK8wWhwsjqGnq zaj{mmnT=N+O?^hFF6lpQEuZMDc5!Rgc62UnKN#6~KY{++T)#sfrIE40b+dMLvoK)o zb8=*LLS5Q2EH%ZtJXv2xi?h~_Q#@XRa#$by#AtB!JvE$L!pUQ0NY}@lM&}TN!6-+P zrcP`qe-qXLATE^*vPp$*uv0}Lwj;KjO^%wqfYT)t2t<{xuh@T3b=Wf`@5I8XFnaxd>m%!G4J6&62&Ij@4o3KdsW0TQ}h*fR)C6#>?{p(G8KdgE3bn;TgF%?8-rn?%xX@ z?)dlH4S~t5&+wAY)+fb>vy4{Is~*IH!svUyR?q;JTmIrc$+H!W(*KI^`?h1~Ch^~~ z%H=tv`BRl#V&~J`Y^z6mMR!nEDTr})tmMkdbrGY@2WBRSE28XJwX({6(_@uulG(+t zQScE&Tzz%IjNIjDqVnF!Q;5HK;m&b?_4Mf(x7BVcHXNP|?J=jDNJ+Uy#mdvy2`wtwZJ47yvu7W{d031aSHcNjHr|_xs?Z~SL zj*Dh$!`(+;L0o#DetN=U;e_eK092Mdbxi$WCP;Hk4E6-kl4v12((f0P@i1_QTS+U$ zF+WrcYtSAF6(rO*A=r@sY$Cu?dEm@PvMedgix1s<^_^TYOWkYe)un%Jd67$v{`9^_ z`W=ibIXdQ7OONGKs15ADx38(OrA1u9b8!F9$FOG~2!}0r-W&KU_Wk~f5)dO^zLX7t zU6le1x$uQ7Ck)0SG_hKt+K*V{zgm#!!qDhpe}_9u#w7HaN<$Hghn<<8 za+>Mn_)vb6LPUnRHSMiy@x-L0#1E_OFNCz8?T@b~vuq6CCCCf`cio&VRdKa(HMC8R z;|FwmXVx;VD_sKTOE6Ja!sRx$ilkF5JAY<*Uv+JB)8n2kk7JywfaKbbQEGB_K5SI` zh}cNjVxxuUpewke8=*77(@`gxgOO*8FHz;+TOWYfDU$22_~vNo2`B%Bc>mz~W8vdO z=c4&==TE;V;7*IfbNjVmvv>=^-`xSe@4`gKWX3kPc4a%O2{t7V%;9S9mZ+G`8G^t3 z`5bj-j&=g-$eHR(P`uG5QJg~e$|FI(;}6A7F3%|-31yw?>%I3NBmMdAjq1%osX$u{ z`COPN&;gpjrS<%Z@K51-m5NkdRTohX3Y%NinXuS!nlze2IN=xB@xvdsa&*J?{!@FM zxEfiCJaq0Jw~(x(E(7XGO;EhuUWHYsf_KR|W5RZGoAu9wUj)|jU7IY6<9M0sG9uUA z?@ZDjtcg)IoeH89S#R{iaE^=&_?mI!y47*xJ(?7649n6cijxIQXffSi&CC(Edp;k{ zQ0{qJt=gOhPnQ-2OnYBG)}OylBUhWhFC2qYikKjmMbqnL@IQC!To%J$6xfzQm&|>|7uOCDV>V?z22tzhM z8;UgIETMD7VNrl9dCRJZL6@cL#eOB-!l^Y^mUwvDV9cliEs+OWT`GxSoqcZ>(HvDwRDcp1+tV!zsMXJveu+uQ5TuAOp^66Oppx*Zh zsdRIa%jmb=a)(i+kej8thj=-i!D1)-D?9soc{}P-hM6JvS&n5NVL84|n53~p)^W#+ z_xx?}fBb;7HXsuB5Ndt&6gLGwsR!WRgqt#ZodYvdHRrY8as*<89p3c9i3QabqHToJ z2Q1MXugeF!sb0ruP?(bZPG2wW)YR#3$ zU$Ib7yY6G>BLMR}bdxjDgauD#6OZZ&&sms47rtVra14cSuAEWNqq}KhPDu`D5M9wS zzf-3P5Q+?GA8G9kKalm-=`E#8+hnc(ZF_+@eurjY>EdnU{XNzd#IkCsE76-J1f3Evf;kF2$~za&FoU;@3NgEbDFt%H$-L zW)%0w!6x90^^+6C>1t*&0Po9S$Rt1+nJZJ(|qdAE*- zQX9MZTN;81(32v#T|*%@k#!V#!_j-XOqlKps2OOd^Ne&3WC3S1r~bU~$t!PEk`l=M zgW(;6P#L;5qk7HYE#$!xf}fRSjEllCaj?8Z7yY6SdhVWN2P-2y3=mw%-cp)^Jk&Xg ztgJ}X8tZZ!53^ORV9%+m&V&QoTThChC9hUqY}X|BahK1;N#?4ARGx_TKzYiCVpC7G zg%+ViC;a06bhf!kp9?1zNQJ6~9BAN$W`KQ(twoyF|E4?io z@7&Pi9YW7s z0F7z8CHNBWFI3CZiI?ox*hwQCH53ZytPu)85Qz>+iT>z|-$~lE^oP&jG0>l&Wpjtj zl+sfYt%gtVR9?#`4a8)EXRt{<5e#E|c;ki-dyvU~ywtzUy#MRb{CB|c+A5@Zqhmkw zqPzNLrqpKBL1X!Zf%OhKPRd5Yxcjl?n-303zH3F5z42ws&#Sws>lfKXy#XJ!(LeNm z;A&Rwo_-$5{|xsc`wI3!wYp!3!mR24j;lv$QKF?pkQ1Hcm`LhtHU-vpM?ql(e&&^# zsm*ZTz#Yv}-*xyBa$jYThwf_5qfD$O3eTfqZ8T%>KkCBE)ewZU`aMkd*ID?Ceqg{s z5AEepQr6l)tIxeQ^hbr--75NtSpkuh)A%Bft3kK>-=?b5vvk(}Y80J7bv(~n<%mHVuw)=B(mr zWP``zLmj#WfEqbl0*&(Zp-Q`lO1FErYCP;%I;D-4GM4xiZ~D>cEa zCDLTc5R2DziAIzWPOyi`CH@s}Hq5xZUyFWz@o0>9$sE4x6scQ4n z{WG&wDd9N8D2(ej)fpaW&rz{}%prqM^_y<}xiKSads6L;yjRAUg#+`x{k+8=SObA@ zj6!Ve#l7?-b2}-#qF7wrv|9QVU7+!b@q8!ZJi^EsnwX`E!ACMw+nRQr0NpCfZ+iC(`cI$HId@g@z$xB7?thy*`n}xSWIyo(+(xTo&RQ}ptyUyZ0p&(qU%?*{ET*w%bd_W0lllfl{s_!jIQKO&l^Gw)kMN#2 z-erw&?b4#txmY1*O8|ZU-Il9NhlzvD>-cSLcCywl5Ad%dbI6)9PY;LlH>s}ALm8I} zERV09HGFt$_zQT}1iJU8<#8Tk9aZO(1qE!vyUVdH;g z62!w%vcPGkPQ6AT6>rF>Ap_dV`#3t0IGQz>nh9So53^WUvI@$I99HY3ztW}-A6W1N z+AGY%{;iT8EOQgI{oLwB;P>|L+_3Z1hA?}}Pc6=fYAjN9Qj(s6U{ShrZ`2_LO+ zQWrJBCoEo;*v4G>(K*doi|f{Pk*l+}7whT;VztJ(-4;0S{qom!P^a)&AbM z_g8>v>S|G^r9$JLPwKIotZOay(@Tp<%;b^qUtO+0ult_6=bF3w@>qSi22YCH;;DiI zC~K8dsyADjm7BY`gt%;R+s9YBXDJ%#xL-bANEDnkDkP}YF=R|eW@~OEA%9kIV4PiF zy^fo@s(nrtGmv|ylC(5_4BIMCQR_7wKf&dr!U!{>o~`adp79hQsdD{8tB{(r+JIRg z$vVtx)`c{=L2wu5sMZ$IP#I042dw;2-%yrdW+PpvJ?vovZh%WU+H&e^^0vP$Z{;9PhJWz!?TXFxfqx$B?INP`Wp`@!N@D}HDW^d>;CfwRP?)R(bBL|4S z?qFyZ@u>qE6R$~=>Gkp3V9i@*&=KS03l0cp$Z`akRQ{wJ%l!I4KDqnlGHu-flMkq9 zS@^&@umASJB4p{wi`Ua1uG6WkTpAv!vsTuppC6*o4xQ_c+w^Z$k%$i7VEnjzRoq~q zPKvp7z^sZ_K@2SSO`WlKzdybdJ~Ex~4Jp&MC$(P(k*K>U78zc5NWsK!??I$%dXnNI zCA{>L@j^8P5kQp)*yzeYPmQq#u_qJDm&b@tIws^1B8)+ES7Kmq(JdaM-`Kvz9`(YF zNC8DzPr^otdE)Vu(550Jp?LYd)&dH0)(R~Jd(Fk98GkK&fd|d&!{jy68K7SN7V?mK zBrMM|z-v%9yY=NB`_pD%DfgzwSXiVUdv9Qe(Uiu-JX&qHc5xtnT)o{`=O zSK#qi;4#}PPR+WZ7ewzQ9}}b0VFT1X402R~E=4=lYt!m5j2~B}M#(nbN6$mmkCQFT za~ln)Ur$cfMPs_O)_CSN8?(4xmS*#9a7j1YmnvFIb7d}Pdq7+FKM2>l?^r8P2J^Y_@#}|u=rH(<8)~I*(X#r z;X=TfGRhcOA2%39wZW|0l?SlNgU2+S&w@>!B+LmNWagBZXE3_dMnp8xF!wbTYytD* z5-{KiN7|bbeLlg+^PAhcztOk0%Xy?ll=#u^#HM6B-`N~%t|}G1BFg65EX&pDyiAzs zXOsmI(7_i$pJPu^R0H{uOwmkxEW>&1M}a~{JC+1g5yKt#1~<%M9=2H$P`Wr0LXhXU zvPG7IwtPvTq|sncd^**BWs9tmx7Ub9W5e3!4c5S|OZ-JnS5Iqa{ot+5oBn#s;rdwp z=TC1_*qs}UAwvUcO~}EJo4<>#4M&=LTegpVG0`O(?^xN7efW;@73`}z>}*$zbq%v2_FcMmtFkA!54hui4AwB|d6<_fishD|C#t6Q zd6t%B(e51_Ei_kaA*a5I4ej*#x~md*6nMwv{BnOnGB0VltNu%3>CU#6kpP=Lv4u?TWQ|j= z4Amx#!Yls^Gd}_s74_Yq+{z%%Wn_iK) z1zN_QzGwzw)C^<*2^e@<`KWGR#lB9lX^e_JkE&z1aPhxNGPb#Y;CaGqJ^Yo!=eUph zo(P9O4(ir@e2^ThW1Z=mm4pFO~# z26kh<0QYudY$6W^?V7P}9&9j%Ek)gG`)>heVpnH^uB+KZJ4gU}aj6*(qb)`3nDOz%+}4F?5MAM3s+zMx`pt*6@(jQMKryXza-3!TlR$mR5%>|=S0Z&ghX z0os4e3haPR25NelPwP6U|Cq?#V}HjFKRWp#d*@rw!OS@78srGi#Dr6FCxy{PVX32PH)?u`ReAD z=DRl@+>Ef2UH;^2KRWsS7tTC6JT|&*WcThX@#FhB{K!RUc2~l}EOp5MPeIydgU7j> zDJs901BGfUlbO8~b9RcHKKGCcGQqxzSK&;H9v{_fxUll4zvxikQcv+CphL6z93o7H zqD}gi|LNzP+Al>EXG2ZqDZ=Z-+)ght=T)vL5D6uSi_wKWZb1 z>Ca8;gnwDr#MzX=*=Fx@&dD!8= z9K|Ld1`^hyF)CG5>KQTkCaM(DiUp%v{^_u~m9y7Ik-^z~mPmR1on(FSnv-g<^{(~=1Jxt!6 z|4ET%9fA!6Ew z?68k$SeVro84R!6Tqdd#Fqg1LlY@OPN~YX3`ZrM&v7sfIa!S=mhRNu8v`C zItuvWXnIi%GGI{>gtTT6p4LP`NEbwKPZs`(id*t|wFCXa^E7l4QrVe9EO;K0Q?i#=kJ6^*57d@th?b~!{_ZbA)BV(iiIiQqq*y0ThnN22KhPjNt=JG8;nR`N{^B?E zid`O;?N(X=hkMW9?wrE6Sv%1b8KAmg<#;fC(@=fxYqeE4I8aaJ`L$MSOsYH&L9WqT zINh><#$jT}5Q(1?xyt!hyS&L@8=nm92-FGnMU~Exp4LaA>*`;*@A&ioMsW+E*q)Y9 zJs;~{+1c5CPlLEJRNq+E{q;5Nw-0PN$9TnKkndpv`)% zu3++YyMjrxyMjq{6QVTJ6-<)Hb<%WKFbODZ#v@+0NV%?H(sWlavqhRAVv5JDa-xxL zYM<^8meA?RoE~9Y+ek8!Ju|ygnC{HpQ=OCFrtQN1|2F?pkB*x&|9xa>d-hm(&is#@ z+B!pEG~c74wgI^dbG+HgToITrs)o+^?6;A;Rt#&$NDP&*XQ33^^LC2O1QEumA2G z8l>}hwckQU2r!Z*td!6#yGRgSRPjaB{f_glMVHd+(j_>XEl;pQ;ZTno^eA!cAvE|)b+Z`)!jn(@?@$iy4q&=PPswYOTlwbVW=BBEp zRZCV+ZbWJ0H9EJ^yoDXSi&w8DZL&&STND>tKJ|?;ap8*Qwg+fbo=Ib99cwaq>Z`mN z4isLO1NPY*uu~4$XE*>VUuU1@fE{a~@rc)L_8bT7(;S$i-e<{UPFXuc{a^#G8XqWV@^xZ?2p;je1Fs{^%ubbNW-FG4&XU>!m)2v5N%^opEpPB7 zRr#b_?^JA}^?)>yTx?PBlkYe6ZT|MAzGiY^x+mmkVmC#jH^o@~Lvd|m^ZND8jq8L@ z%(*6!$SZt;ppo6w>$w)G7#Us&1edg&#eNJqy zifL<6+pri-ixks~EVkFJZ$;0>9`tcR5hX@W?&I z5XmY#W=m8ItGON8j}52*xLYLOVsFYm&XREURi1Qa%d;PDe&FBT(>(`CclH>0nLVlX z{Ky`l{UVp*9@AW#NbD3_sR>F=u3@C&ma!R6rc8}mECacy0(`l`AUN`i1Lfg(H3cn| z<$yWE2s5#-WZA+`?<;8~xp+oNXjYixy3Hoz$NNoctYhcKT=>J;{>ZMjKhb@%bECOc zi-z2yg+~sFw|px*-4AOg*gA|ge`@DP`O`W-+OF#SNC1D#>i#%&6w${tKXlIn@c7>| z4!{Ak$8muyY0v(bnSneG2w?6w?969AZ5)nI8wWNGqpcUr$*aag?egp)^$}}0+wjU; zGlSYiEi%O<>bTlqTn@&I-$L-GMur0`pdba6KlTkPy#7cn24=cW50xIQ&P=}gN{G^3 z;x+>|OL8QyoC9-3l6>}LdX{z8)^?Iu4J!1R89hBabB^?;y&-4#e%9Q23_%L{ilIzhw*{d$}=W%cpO)A-v zDju9O9x8j&WI3S0!I?qr)&!5!#+8%1uU&U!*A%%=AL+Qwz=|`VC2~zUr0pZ-PT@+? zo1V+zTCC6@(HfMpnF&2}rQFrRyiW6zfE|L&o!VYId#+EvA664#tQ>{5H04$trGQqZ z$u-<`=Z~iCGET%^VhE>Yx>H%kIoZ{EETal`)$bZi8S~UYZ){H2-hj=aww9Aam28+` zV4?O7QrP>A+RYok^H9hB?Bv+Covq#d8$+9Js^0hNtL(b1tj}N3o_*!yx$LP`A$EP% z60iNkA;RuYEEBUmTVYQ~y|64oE~ zw_M1yT(84r#kD$IR%#tC$7P{BOo70k-Q*J8^c!e&*^LV9hPqv{e}l^H|NOi__1(a{ z9-~U}#wPZksinS>XOZjAZPB&nRyAvG3;$>5M%CyIOs|MoDkdAwy>(*~+^j0!-2B$V z{3@Ax=09umTddBnjMu(1j81ep=%{cc<-z%`qVv@{`X{ydHeioXT%O?SCT&m2o|3Xk zfwl_8FTi0^%NI}2KIJWgb60sKF3zwGzaPhAPvw_fhc4G!pxg~~a$R-Zg?r15^myf! zt5@?>;Whfc@)|AMsH`kvmf*LpT}xU}SQ4?!Le-4L)Q+n&(z5_;Ql)C4DrMX;oT*k{ zRnJHkR;5KNQL+kzdH-{gb!GM84TzX?Hr~21IXgPnCKBc(Dd)EE0@(VGu#ySv24)X+ zv-=(jU=YNpwj+>6>P>3y(1ekComw-lo2eq7$ruuvvteldhL(ywbnZhMOU`W&$VtLx zvwc~@-k$vr!uMt;FEeB}u@Jd8`vEa`XWz^IdoPi*A8ER1JNLY9z50E#M90uZV42V? z=_;n(PN+J{J3sEuV{hfjM8TjQK1vnT9vO*QH4%0-7Pod`~pF z^L<67k(v7WE3eS#{X#FsDx4UrD8|Z5#+sb=d}%fPw77?G`w4#6Ang_9K*fQAA0euY zk8bGQJm|4gIUn74=lbDqK6n#3+R~3A{zywNm3V<2-HX!Qo~}9PFVQ6Yv(F^nRLCtC zc5!ku2=~;{2BONkMa`ekez9OH0!%5h>RKIR%l<^i*pSvSc3dhfnWyev`t+u;Xwt9O zIQECsj(=MBSpIgj;r~a*4rcp$W1m!Q^`{PgnP#VFkAFV;Hdl|o{7;O3LC%FPNz!>d zB^3temCZ-f<+g#O-r#(wslMKnMsxQ0QzsS5*=BW4Z8RTOg|_+1S>dD>(Ka<`9~MS) zUwk$*%kd!fyhGC-k2dA;h}!|z!|L^LBok4+AglooVY&0Xa%z}Ug%YMT?Wu}IH`vGc zO1pABdVI51t#)7DQB%|L=|t(CV@O!FH!Sd5WX#MX*Xj;y`Sk9v(*K(7u<+JEFl;Z9 z;&kYUso9a~j>pMdc>e+{=FCQv4Xwq4QP3Y}r zkCWma4=!6LZNy>4CV~NsgW*OM1D&thcyD%!J(SSW@7i|+O@Fy3c7WLeD`EYi*E(AU zcfI!bP+wDRYyU$nHTCx{UzQBkG>!EPHu?$#uK)YDuN!)GU)RH-;Lo-n|7G1^)uWqR zcb1mlXUqRe^T4jPq4mwnCJ(9p1MO$3JIE934tiCn4bG;Ov~+9a9(xMA8LX_BD&md>USu9<2AxUD)*qOBaUkWeg- z#VE;YX3$_Vh6pg0)JkBY|J0)9p<=SKctT0a$`ZAjE>VroRVUQv&VK!$Xv2~_LRR>aiQ<=|8m0|DkuKzFPqN2 zJj0_=-8$e=g1H61)oq4HHCOVeaW;=45&HdkizBKIY@xhb0&H2LNprm_&0x+`x5Dcs z7~7NmNhI0|15hn6FOsNfL~N3Wi6AD`SaTKqQl$}a2mMjnZF4dGO6Pz*6%2nmWv`Qw z=B_6Abt!$Pi+|kM?}kbS}HSd9|9$-gyN- zz~5HaNjqI9OPPA+xofPHYAhM7jb)aq80mjBclNPuUDpABkB?uH`0?J8M2ey)ir=DX z>Y1b@`dOAN%QCIWs-~!_Y6zO<8nWuTPBcOF3|BCWtO*7$aoxbq2Z|sKvdl9w)Zn8S zZ!x-{OS%oihV_r2L5;x3(ykkdZdgzR12W9q?m729lA=giUW=?iEK<+UdH0?Ban3#W zoZmT|Zn&--sh&0cWZS);8b|xLt};+jb`*lp4${9qs1!%3?KEClezg7I>Tm|TK>i0M zEeWB<9$6b6BcG#^HgZ_~wGI4QgKPIQz*_Cc-t|0qX6u%|+z-#Nei-N8-u;SoKq-#U zpuZzZagZH}9 zWQ6QpGTHt8c$oTs?txhOfPD9TuyF3>)zz1c>7$v<(e$qSVByBuvp3G(iDk1f@(0$V zHqr;52;bu}T#lRN-sK7j@XDt$2m;Qg3lc>RK~NRsd{3u~$9fWyoy>@gb`0}<^2fyd z1Pp9HL#lrsyP=N@x?1TR5%xuA%Ll|W*n-rO97Gr`)o)%Yy`Jp9bh!YT;?Va9GMA?Vq zyf;K798vT8B&{b(Dq&r82p*d8fx=NJ5Y?`9f;0O zMhDkyc6BQnoF~(nV!d)UG z&liDMRF|7BDwzA*Oe^R#Zbntv7LmH^#oEb6ljad3g7-P>Fxl*mn#m?QF^tfuhY@lG zTA-6>pE~8R>OFBLF;RbyP8a=c7t3=)VDCGNoOlm+Ve1>)jp()n00TyhR`)?CB=F_A zG$X=8wY}}q*le{xD2KZO{Bpv)Fd2!0bAvh8=27dj;n~Y6 zMx-+(_%5-|l)m}S*YNDcDsEb=5SZO0ZZDklW##ta6){ zW~WR~pY(6I0S|WpAI)U*&;$rSh>W8l%ce5AIT|y?vQeV{;aEl1!S-lejTmSWi+Q$m z`?=GH)=Hm-e{^!~=E>Rnq1*pDtros=r}W>i-1=H_VJndmaw2Wm zIg`ax^TD_oXuvKXglspkNWJ~!{p?cF?CaT^f>qNdYrS!`LNwO`d&y?at5A%M1ZJsE z*8IKd&aCr>Q6qIA=;zliPJdx|kHc+mv&bFChfm-cv@eoPG{U1B?^KSR^*u1mFFGb) zLT0)bBFXAd)4S?X(|wGZz9}?ybYk!C0-O%kQayP3H^4rs2T(WsHS_O%w(SJVs9rmZ zU<=i2C;#tN{x;gy4Qy*Scc)HU^WBOb(#@I+@mG42dn(hqn;xll*RIPQV&3!pe7BhQ z(RI1Y3+uACt7cv9_F2gSLT+*Z53rN0%brdjuFLcj=kTMk@0kr$PdZ^{_0$#6hx($f z%jXP{PlQVW*BRv#*X5%imjNpR1r^F*r=I;NaP&kxdx%pWtHHGxHco^ zPI5g!uLI_VD!n);mo^qGn-552p16G=#ZFlZMKO}!U3XBFZNDnf=-RPLMAuOT4wS{Q zf;g(JQhA5kdh`0EKdd{01nxQR=fb+tL%xATvK-k;fUn1mhyk<%S`~=kbb|rhhQJ|P z8qy(xnCb)(nGBwyx6QylpELZVG?bkh7-0VaAgAX) zXo;bZ)=*<(W|g@W((*U0q6IWI{DkW=TqjS1pKkr0F1#lMKMUlBDrN2h3<*)m1@b?D z-@8-@k+Q1XpPQ^s+2!sERiY(ouizpPfFUAK3_v#`57=nHPzei+2n>_RLYRbwtn_qH z#9$=MO--Hq?U(rfyuG|I`_+XPUp~qo%-Hpt8vi|$H07T6-pw;huGhp04v4<^yEPaLg} zUZH@gwMO!~&Q#k@5<6Kr&=Hu-W{J!qT#~z1E42VD<-Jv*7L{?(r;me8zW^(Fh_2XM z2E}GVY_Ei2#1s~Ifz{PR@a~}L@-a#CSXC$+q{a6>f-GuJ02&Epr5Z4}qiEi#@$nld zzn;tq@N(55*hk6)`{-{p!5-$=E-3am-5!FnH~k}>ajaet`hyhii*)4RK9SZ7f{I;D zpnDQ5P?)2FGP%-eNSY)n1}c?cv~UDcMh#7^=+a4G{JP7mR}5-nMcp1&H0X8buBrx^ zZ#g1TsbyD{g9O(9v!wsQ`f{|St16D;RZ)6a`Gr^{+jK;cKde3_RhD=)23WdW8iS($*{D+V#M zL~2Upo6_WqqbY$#d(ewD1v$;%ia|D-4YwO!EEh!V5zQJU*DW9~krucds3dL$29R_W zZ55Gyk(ChiYB9?>fCS31mAO}X_dTVmUmlosxE~uy&3Stbm-)bV z9zS(_h-Gyhn&vM*{UYB|`uN$a^G6K#a%;0Q7sEdBmkBP|SFaz{*?*r}-KuU2@8>7f5@>^jHb8W^3h#;njAjaZw zzG7eioZV#AXUGe5l!WAoUq51vWro$6(bmhEsnt=`lQiybhO=@a z*8zLw+Q>UFujx5s8zx0pp`=+PUUN$Vh(*ZEEyv|;$|ft(kghT=w}v16D+lShAT+PF zV{2%hp=KUe!u0-SYi?mxwB8SD<|fa}Mp-Ztd&|sylLH`~Ia4$so-WTN~Z#@RZcTYK(zsv zD#pP&)Vx8~jCNEdOt^=Lgh6ZJE>-?EGQ&Fp^uyy0WR3nnj_5xpG1iwsy= zp4D8Z9&E^lO>1UOvEKR{vK%c#4_*giD?-JmqL27w_ zh6xTAjbI(w0e(W_(QYVoK*B%Q(M8$-8!ic)|4_*enT2K9QrKOjR@krI%Mn?p)m%!Q z<8R$NN*bF|dHAhX@Kf9S!N6T2ZO>KOP8PgChKVWPMcckjQn1vu)0&}$c0XKg_pr9N z1K3Ln(6-k~GE#ft(ooVzB%4vcaF0J(`Ci+X!?j%t?JnICa@e;4Zie>mZ$Qgy$H#EZ zaN+qSzG%2BG*>evZImf#+rpHzQKqDAJ5zG$%hy&`t{FU6mzS@eMm^>r`@MI$A0ZRP z4bj#XjIDQNGK^KJHOuKVUM<5bJF4K7RYZ4*qEI9X`2gmX2cJGzqg?b)M{XsTTj9Nw z7v-H;&gGVqr*b(!Lsfo~_l}d1_BOH>pGDH5K|yW8<1ra&MoUFgS{qWj|A5jCDLm2f zP)aw2bQ7IprJ!y&hB2ZZHR`8=JSAxJaXt&^?8hqT>^f~06kP*W8f@TqP=pnXBPv2; zV>G1BajZc@a%9T|Dv;Np;jGOJ*+|-Kt|c{69W+kH!yVGZeu%~C)BW3afx2>w9N%ZB znc5stl;L#IV#W*I8LV9fb7uhQm;Gri2sJ;`cmNeNU@9`F#rw#Yy--0apP)yT5T<6Q zkxs2ys1P5@W(Kq6nxs^lnk@lK07}JMh^gpugQaK*_6f1^&ROH{b$-ROZ{ptCt#cWx z(P)jV4xf1|ZZ`6tCQAV$e^V(v?;c+Mv&)M^7yl&t)s0irPX6r+f!y$g^K+MJ z&)ghHUAflQejz)SxNzz7SNOS=GrW6z`Hge1RzwWfg!`s8GCy39smGC?%m9$o12Y54 ze=s_+0HFC3F;*38^$+VZ1yr7r;LmT5u5V3*YR#z_IAT$J?Eo zoqe-=mlS&v9g(CcK?OPh%b)>rAdh$(%wT*6cEJJWMQ8*)g zZTW8Pw$+g$^VUIz>vRvTTL(|(!Oh`AN?;GPn5X-$GFP<<%B&Z%mwD#qEEc4>X9v8Q z7uR2jKCASm^K(!Dx1djdE%sEfo?H(N`g#X7<~R9n794>rJ)K~`9<)ba!?V}gJFJ;! z&L#K+>hF=~*|oEGu^;e7zXQt+)Z3Ev=+1isLf^;r$EQukrk2AvdB;qb0Wb5m@wo6x&_^L z|4uX{W&cFYzH#@R>s_1~!69^9*I~S}gY+|{`%Es!!TEjYp^#JP!whXpD_AvGn97-IMI0ZQ4IPY;qaZTZR!>z|1z&(#g zgl8MC2Jal+cYIcSWqfP+<@huB7x8}+ND`PP@I}x|aGl^Ep&FrA!b!rDgkOl5iR=;$ z5?v+wNlZq}N32Zjir5=*AMq;^AriAB#Uz^~A4u(zmXOYpz98cx(;)Lj)=9Qc_K#eQ z+yeO+`D+R~3O$MniaV6-lvnxeHw z>x%X)?HxJ{I(|AYbR%>tbYJP|=!NO6&^w_oqrbx-$WY0M%jkfygYf|qCzEfcQ_Sql zwwRllSDEj#;Ib&Q*kSR@(#>*{m7LWsYc=aBHY_%)Y;A0B*{!nYu+Ol++HFWe5fySXp%VDgyfY2sPpxy4JzYm&E@_Z=StpEh4H-z9!JemVXI z{(b)M0y+XE0+$6z1l<;!otfd4Dhj@>)n$vz zjcRcq`2o=WY03Zqc-n2yHEfk(7>42ND}@#<#ob*`PbqFiio3hJOK}aZfsn94umuRN zfdB&#+=2ucm>BRd04vs?jVF0?ZTIj>@OM9%=zn|r`+@|yB+4z1B+2s1C%*y;DkMc= zsfsA7nBqz(sg%;nD65?EDyXQE%BrZUn(At(sg~O6sH>j(8fYjcOI+G($Yj)T z*12N0ch=i(i#-lI6mr?@wKaBy#E{#zkjF;Xy$MP7I^w%;emLNmJ8n5{tZ{Z2@16;6 zyX%qr9(d^e@9#bJ*b^sA^3_f+JoDUSAAPpTR8ved!*nz4Gs_&a%{5Q9`4(8{gGH8D zY^mjzxoE$YR#;`VPrkV1q*E??=~YM$c|*RCKNJWBL!poo3WwBCBoqzBoOZ@}7u;~x zIX7)^G!%E$wNN6Iv^6Pv=9E}0GZxt)$9D0^^vI0JW`B&wVzJ1y$arLWWTVK8$i|UP zBAZ73>t*Jc7Io92Zagc;jI6|t*>h+80uP6Yt^fc4xB>r#umOz#ORxw~Sg`>Cj#;rr v1}j)0un<{GuoO~QA+Ug19k2!~Tv!0G1t3MR11m%Uum&JSumdYZS+Eo + + three.js gui + + + + + + + + + + + + + + + + diff --git a/gui/js/Code.js b/gui/js/Code.js new file mode 100644 index 00000000..95cca97e --- /dev/null +++ b/gui/js/Code.js @@ -0,0 +1,159 @@ +var Code = function () { + + var _domElement = document.createElement( 'div' ); + _domElement.style.position = 'absolute'; + _domElement.style.backgroundColor = '#f0f0f0'; + _domElement.style.overflow = 'auto'; + + // + + var _html = false; + + var _checkbox = document.createElement( 'input' ); + _checkbox.type = 'checkbox'; + _checkbox.style.margin = '20px 6px 0px 20px'; + _checkbox.addEventListener( 'click', function () { _html = !_html; _update(); }, false ); + _domElement.appendChild( _checkbox ); + + /* + var _checkboxText = document.createElement( 'span' ); + _checkboxText.style.fontFamily = 'Monospace'; + _checkboxText.innerText = 'HTML'; + _domElement.appendChild( _checkboxText ); + */ + + // + + var _code = document.createElement( 'pre' ); + _code.style.color = '#404040'; + _code.style.margin = '20px'; + _code.style.fontSize = '13px'; + _code.style.whiteSpace = 'pre'; // 'pre-wrap' + _domElement.appendChild( _code ); + + // + + var _list = []; + + var _update = function () { + + var string = ''; + + string += [ + + 'var camera, scene, renderer;', + '', + 'init();', + 'animate();', + '', + 'function init() {', + '', + '\tcamera = new THREE.Camera();', + '', + '\tscene = new THREE.Scene();', + '' + + ].join( '\n' ); + + for ( var i = 0, l = _list.length; i < l; i ++ ) { + + string += _list[ i ] + '\n'; + + } + + string += [ + + '', + '\trenderer = new THREE.WebGLRenderer()', + '', + '}', + '', + 'function animate() {', + '', + '\trequestAnimationFrame( animate );', + '\trender();', + '', + '}', + '', + 'function render() {', + '', + '\trenderer.render( scene, camera );', + '', + '}' + + ].join( '\n' ); + + if ( _html ) { + + string = '\n\n\t\n\t\t\n\t\t\n\t\t\n\t\n'; + + } + + _code.innerHTML = string; + + } + + // signals + + signals.updated.add( function ( scene ) { + + _list.length = 0; + + for ( var i = 0, l = scene.objects.length; i < l; i ++ ) { + + var object = scene.objects[ i ]; + + if ( object instanceof THREE.Mesh ) { + + var string = ''; + string += '\n\tvar geometry = ' + object.geometry.code + ';'; + string += '\n\tvar material = ' + object.materials[ 0 ].code + ';'; + string += '\n\tvar mesh = new THREE.Mesh( geometry, material );'; + + if ( object.position.x != 0 ) string += '\n\tmesh.position.x = ' + object.position.x + ';'; + if ( object.position.y != 0 ) string += '\n\tmesh.position.y = ' + object.position.y + ';'; + if ( object.position.z != 0 ) string += '\n\tmesh.position.z = ' + object.position.z + ';'; + + if ( object.rotation.x != 0 ) string += '\n\tmesh.rotation.x = ' + object.rotation.x + ';'; + if ( object.rotation.y != 0 ) string += '\n\tmesh.rotation.y = ' + object.rotation.y + ';'; + if ( object.rotation.z != 0 ) string += '\n\tmesh.rotation.z = ' + object.rotation.z + ';'; + + if ( object.scale.x != 1 ) string += '\n\tmesh.scale.x = ' + object.scale.x + ';'; + if ( object.scale.y != 1 ) string += '\n\tmesh.scale.y = ' + object.scale.y + ';'; + if ( object.scale.z != 1 ) string += '\n\tmesh.scale.z = ' + object.scale.z + ';'; + + string += '\n\tscene.add( mesh );'; + + _list.push( string ); + + } + + } + + _update(); + + } ); + + // + + this.getDOMElement = function () { + + return _domElement; + + } + + this.setPosition = function ( x, y ) { + + _domElement.style.left = x + 'px'; + _domElement.style.top = y + 'px'; + + } + + this.setSize = function ( width, height ) { + + _domElement.style.width = width + 'px'; + _domElement.style.height = height + 'px'; + + } + +} diff --git a/gui/js/UI.Toolbar.js b/gui/js/UI.Toolbar.js new file mode 100644 index 00000000..52a1bb10 --- /dev/null +++ b/gui/js/UI.Toolbar.js @@ -0,0 +1,81 @@ +UI.Toolbar = function () { + + var _domElement = document.createElement( 'div' ); + _domElement.style.position = 'absolute'; + _domElement.style.backgroundColor = '#404040'; + + // CUBE + + var _button = document.createElement( 'button' ); + _button.innerHTML = 'Cube'; + _button.addEventListener( 'click', function ( event ) { + + var geometry = new THREE.CubeGeometry( 100, 100, 100, 4, 4, 4 ); + var material = new THREE.MeshBasicMaterial( { color: 0xffffff } ); + var mesh = new THREE.Mesh( geometry, material ); + + geometry.code = 'new THREE.CubeGeometry( 100, 100, 100, 4, 4, 4 )'; + material.code = 'new THREE.MeshBasicMaterial( { color: 0xffffff } )'; + + signals.added.dispatch( mesh ); + + }, false ); + _domElement.appendChild( _button ); + + // SPHERE + + var _button = document.createElement( 'button' ); + _button.innerHTML = 'Sphere'; + _button.addEventListener( 'click', function ( event ) { + + var geometry = new THREE.SphereGeometry( 75, 20, 10 ); + var material = new THREE.MeshBasicMaterial( { color: 0xffffff } ); + var mesh = new THREE.Mesh( geometry, material ); + + geometry.code = 'new THREE.SphereGeometry( 75, 20, 10 )'; + material.code = 'new THREE.MeshBasicMaterial( { color: 0xffffff } )'; + + signals.added.dispatch( mesh ); + + }, false ); + _domElement.appendChild( _button ); + + // TORUS + + var _button = document.createElement( 'button' ); + _button.innerHTML = 'Torus'; + _button.addEventListener( 'click', function ( event ) { + + var geometry = new THREE.TorusGeometry( 50, 20, 20, 20 ); + var material = new THREE.MeshBasicMaterial( { color: 0xffffff } ); + var mesh = new THREE.Mesh( geometry, material ); + + geometry.code = 'new THREE.TorusGeometry( 50, 20, 20, 20 )'; + material.code = 'new THREE.MeshBasicMaterial( { color: 0xffffff } )'; + + signals.added.dispatch( mesh ); + + }, false ); + _domElement.appendChild( _button ); + + this.getDOMElement = function () { + + return _domElement; + + }; + + this.setPosition = function ( x, y ) { + + _domElement.style.left = x + 'px'; + _domElement.style.top = y + 'px'; + + }; + + this.setSize = function ( width, height ) { + + _domElement.style.width = width + 'px'; + _domElement.style.height = height + 'px'; + + }; + +}; diff --git a/gui/js/UI.Viewports.js b/gui/js/UI.Viewports.js new file mode 100644 index 00000000..2a2a7ef0 --- /dev/null +++ b/gui/js/UI.Viewports.js @@ -0,0 +1,421 @@ +UI.Viewports = function () { + + var _width, _height; + var _xhalf = 0.5, _yhalf = 0.5; + + var _HOVERED, _SELECTED; + var _offset = new THREE.Vector3(); + + var _views = [ + { x: 0, y: 0, width: 0, height: 0 }, + { x: 0, y: 0, width: 0, height: 0 }, + { x: 0, y: 0, width: 0, height: 0 }, + { x: 0, y: 0, width: 0, height: 0 } + ]; + + // + + var _domElement = document.createElement( 'div' ); + _domElement.style.position = 'absolute'; + _domElement.style.backgroundColor = '#808080'; + + // + + var _cameras = []; + + _cameras[ 0 ] = new THREE.Camera( 50, 1, 1, 5000 ); // top + _cameras[ 0 ].useTarget = false; + _cameras[ 0 ].position.y = 1000; + _cameras[ 0 ].rotation.x = - Math.PI / 2; + + _cameras[ 1 ] = new THREE.Camera( 50, 1, 1, 5000 ); // front + _cameras[ 1 ].position.z = 1000; + + _cameras[ 2 ] = new THREE.Camera( 50, 1, 1, 5000 ); // left + _cameras[ 2 ].position.x = - 1000; + + _cameras[ 3 ] = new THREE.Camera( 50, 1, 1, 5000 ); // perspective + _cameras[ 3 ].position.x = 1000; + _cameras[ 3 ].position.y = 1000; + _cameras[ 3 ].position.z = 1000; + + // guides + + var _sceneHelpers = new THREE.Scene(); + + var _grid = new THREE.Mesh( new THREE.PlaneGeometry( 1000, 1000, 20, 20 ), new THREE.MeshBasicMaterial( { color: 0x606060, wireframe: true, transparent: true } ) ); + _grid.rotation.x = Math.PI / 2; + _sceneHelpers.add( _grid ); + + // + + var _scene = new THREE.Scene(); + + /* + var light = new THREE.AmbientLight( 0x404040 ); + _scene.add( light ); + + var light = new THREE.DirectionalLight( 0xffffff ); + light.position.set( 1000, 1000, - 1000 ); + light.position.normalize(); + _scene.add( light ); + */ + + var _plane = new THREE.Mesh( new THREE.PlaneGeometry( 2000, 2000, 8, 8 ), new THREE.MeshBasicMaterial( { color: 0x000000, opacity: 0.25, transparent: true, wireframe: true } ) ); + _plane.visible = false; + _sceneHelpers.add( _plane ); + + var _projector = new THREE.Projector(); + + var _renderer = new THREE.WebGLRenderer( /*{ antialias: true }*/ ); + _renderer.autoClear = false; + _renderer.domElement.addEventListener( 'mousedown', function ( event ) { + + event.preventDefault(); + + var mouse = getViewportMouse( event.clientX, event.clientY ); + + var camera = _cameras[ mouse.id ]; + var vector = new THREE.Vector3( mouse.x * 2 - 1, - mouse.y * 2 + 1, 0.5 ); + _projector.unprojectVector( vector, camera ); + + var ray = new THREE.Ray( camera.position, vector.subSelf( camera.position ).normalize() ); + var intersects = ray.intersectScene( _scene ); + + if ( intersects.length ) { + + _SELECTED = intersects[ 0 ].object; + + var intersects = ray.intersectObject( _plane ); + _offset.copy( intersects[ 0 ].point ).subSelf( _plane.position ); + + } + + }, false ); + _renderer.domElement.addEventListener( 'mousemove', function ( event ) { + + event.preventDefault(); + + var mouse = getViewportMouse( event.clientX, event.clientY ); + + var camera = _cameras[ mouse.id ]; + var vector = new THREE.Vector3( mouse.x * 2 - 1, - mouse.y * 2 + 1, 0.5 ); + _projector.unprojectVector( vector, camera ); + + var ray = new THREE.Ray( camera.position, vector.subSelf( camera.position ).normalize() ); + var intersects = ray.intersectScene( _scene ); + + if ( _SELECTED ) { + + var intersects = ray.intersectObject( _plane ); + _SELECTED.position.copy( intersects[ 0 ].point.subSelf( _offset ) ); + + _render(); + + signals.updated.dispatch( _scene ); + + return; + + } + + if ( intersects.length ) { + + _HOVERED = intersects[ 0 ].object; + + _plane.position.set( 0, 0, 0 ); + _plane.lookAt( _cameras[ mouse.id ].position ); + _plane.position.copy( _HOVERED.position ); + + _render(); + + } else { + + _HOVERED = null; + + } + + }, false ); + _renderer.domElement.addEventListener( 'mouseup', function ( event ) { + + event.preventDefault(); + + if ( _SELECTED ) { + + _plane.position.copy( _SELECTED.position ); + _SELECTED = null; + + } + + }, false ); + _renderer.domElement.addEventListener( 'mousewheel', function ( event ) { + + if ( event.wheelDeltaY ) { + + event.preventDefault(); + + var id = getViewportMouse( event.clientX, event.clientY ).id; + var amount = event.wheelDeltaY * 0.2; + var vector = _cameras[ id ].position.clone(); + + if ( vector.length() - amount < 10 ) return; + + vector.normalize().multiplyScalar( amount ); + _cameras[ id ].position.subSelf( vector ); + _render(); + + } + + }, false ); + _domElement.appendChild( _renderer.domElement ); + + // + + var _xr = document.createElement( 'div' ); + _xr.style.position = 'absolute'; + _xr.style.top = '0px'; + _xr.style.width = '1px'; + _xr.style.borderLeft = '1px solid #808080'; + _xr.style.borderRight = '1px solid #808080'; + _xr.style.backgroundColor = '#404040'; + _xr.style.cursor = 'col-resize'; + _xr.addEventListener( 'mousedown', function ( event ) { + + event.preventDefault(); + + document.body.style.cursor = 'col-resize'; + document.addEventListener( 'mousemove', onMouseMove, false ); + document.addEventListener( 'mouseup', onMouseUp, false ); + + function onMouseMove( event ) { + + event.preventDefault(); + + _xhalf = Math.max( 0, Math.min( 1, event.clientX / _width ) ); + + _updateViews(); + _updateCameras(); + _render(); + + } + + function onMouseUp( event ) { + + document.body.style.cursor = 'auto'; + document.removeEventListener( 'mousemove', onMouseMove, false ); + document.removeEventListener( 'mouseup', onMouseUp, false ); + + } + + }, false ); + _xr.addEventListener( 'dblclick', function ( event ) { + + _xhalf = 0.5; + + _updateViews(); + _updateCameras(); + _render(); + + }, false ); + _domElement.appendChild( _xr ); + + var _yr = document.createElement( 'div' ); + _yr.style.position = 'absolute'; + _yr.style.height = '1px'; + _yr.style.borderTop = '1px solid #808080'; + _yr.style.borderBottom = '1px solid #808080'; + _yr.style.backgroundColor = '#404040'; + _yr.style.cursor = 'row-resize'; + _yr.addEventListener( 'mousedown', function ( event ) { + + event.preventDefault(); + + document.body.style.cursor = 'row-resize'; + document.addEventListener( 'mousemove', onMouseMove, false ); + document.addEventListener( 'mouseup', onMouseUp, false ); + + function onMouseMove( event ) { + + event.preventDefault(); + + _yhalf = Math.max( 0, Math.min( 1, event.clientY / _height ) ); + + _updateViews(); + _updateCameras(); + _render(); + + } + + function onMouseUp( event ) { + + document.body.style.cursor = 'auto'; + document.removeEventListener( 'mousemove', onMouseMove, false ); + document.removeEventListener( 'mouseup', onMouseUp, false ); + + } + + }, false ); + _yr.addEventListener( 'dblclick', function ( event ) { + + _yhalf = 0.5; + + _updateViews(); + _updateCameras(); + _render(); + + }, false ); + _domElement.appendChild( _yr ); + + function getViewportMouse( x, y ) { + + var width = _views[ 0 ].width; + var height = _views[ 0 ].height; + + if ( x < width && y < height ) { + + return { + + id: 0, + x: x / _views[ 0 ].width, + y: y / _views[ 0 ].height + + }; + + } else if ( x > width && y < height ) { + + return { + + id: 1, + x: ( x - _views[ 1 ].x ) / _views[ 1 ].width, + y: y / _views[ 1 ].height + + }; + + } else if ( x < width && y > height ) { + + return { + + id: 2, + x: x / _views[ 2 ].width, + y: ( y - _views[ 2 ].y ) / _views[ 2 ].height + + }; + + } else if ( x > width && y > height ) { + + return { + + id: 3, + x: ( x - _views[ 3 ].x ) / _views[ 3 ].width, + y: ( y - _views[ 3 ].y ) / _views[ 3 ].height + + }; + + } + + } + + // signals + + signals.added.add( function ( object ) { + + _scene.add( object ); + _render(); + + signals.updated.dispatch( _scene ); + + } ); + + // + + this.getDOMElement = function () { + + return _domElement; + + }; + + this.setSize = function ( width, height ) { + + _width = width; + _height = height; + + _updateViews(); + _updateCameras(); + + _renderer.setSize( _width, _height ); + + _render(); + + }; + + var _updateViews = function () { + + _views[ 0 ].x = 0; + _views[ 0 ].y = 0; + _views[ 0 ].width = _width * _xhalf; + _views[ 0 ].height = _height * _yhalf; + + _views[ 1 ].x = _width * _xhalf; + _views[ 1 ].y = 0; + _views[ 1 ].width = _width - _width * _xhalf; + _views[ 1 ].height = _height * _yhalf; + + _views[ 2 ].x = 0; + _views[ 2 ].y = _height * _yhalf; + _views[ 2 ].width = _width * _xhalf; + _views[ 2 ].height = _height - _height * _yhalf; + + _views[ 3 ].x = _width * _xhalf; + _views[ 3 ].y = _height * _yhalf; + _views[ 3 ].width = _width - _width * _xhalf; + _views[ 3 ].height = _height - _height * _yhalf; + + }; + + var _updateCameras = function () { + + _cameras[ 0 ].aspect = _views[ 0 ].width / _views[ 0 ].height; + _cameras[ 0 ].updateProjectionMatrix(); + + _cameras[ 1 ].aspect = _views[ 1 ].width / _views[ 1 ].height; + _cameras[ 1 ].updateProjectionMatrix(); + + _cameras[ 2 ].aspect = _views[ 2 ].width / _views[ 2 ].height; + _cameras[ 2 ].updateProjectionMatrix(); + + _cameras[ 3 ].aspect = _views[ 3 ].width / _views[ 3 ].height; + _cameras[ 3 ].updateProjectionMatrix(); + + + }; + + var _render = function () { + + _xr.style.left = ( _width * _xhalf ) + 'px'; + _xr.style.height = _height + 'px'; + + _yr.style.top = ( _height * _yhalf ) + 'px'; + _yr.style.width = _width + 'px'; + + // + + _renderer.clear(); + + _renderer.setViewport( 0, _height - _height * _yhalf, _views[ 0 ].width, _views[ 0 ].height ); + _renderer.render( _sceneHelpers, _cameras[ 0 ] ); + _renderer.render( _scene, _cameras[ 0 ] ); + + _renderer.setViewport( _width * _xhalf, _height - _height * _yhalf, _views[ 1 ].width, _views[ 1 ].height ); + _renderer.render( _sceneHelpers, _cameras[ 1 ] ); + _renderer.render( _scene, _cameras[ 1 ] ); + + _renderer.setViewport( 0, 0, _views[ 2 ].width, _views[ 2 ].height ); + _renderer.render( _sceneHelpers, _cameras[ 2 ] ); + _renderer.render( _scene, _cameras[ 2 ] ); + + _renderer.setViewport( _width * _xhalf, 0, _views[ 3 ].width, _views[ 3 ].height ); + _renderer.render( _sceneHelpers, _cameras[ 3 ] ); + _renderer.render( _scene, _cameras[ 3 ] ); + + }; + +} diff --git a/gui/js/UI.js b/gui/js/UI.js new file mode 100644 index 00000000..270a6989 --- /dev/null +++ b/gui/js/UI.js @@ -0,0 +1,30 @@ +var UI = function () { + + var _domElement = document.createElement( 'div' ); + _domElement.style.position = 'absolute'; + + var _viewports = new UI.Viewports(); + _domElement.appendChild( _viewports.getDOMElement() ); + + var _toolbar = new UI.Toolbar(); + _domElement.appendChild( _toolbar.getDOMElement() ); + + this.getDOMElement = function () { + + return _domElement; + + } + + this.setSize = function ( width, height ) { + + _domElement.style.width = width + 'px'; + _domElement.style.height = height + 'px'; + + _viewports.setSize( width, height - 50 ); + + _toolbar.setPosition( 0, height - 50 ); + _toolbar.setSize( width, 50 ); + + } + +}; diff --git a/gui/js/libs/signals.min.js b/gui/js/libs/signals.min.js new file mode 100644 index 00000000..9a6c3723 --- /dev/null +++ b/gui/js/libs/signals.min.js @@ -0,0 +1,8 @@ +/*! + * JS Signals + * Released under the MIT license + * @author Miller Medeiros + * @version 0.6.3 + * @build 187 (07/11/2011 10:14 AM) + */ +(function(d){var b={VERSION:"0.6.3"};function c(i,h,f,g,e){this._listener=h;this._isOnce=f;this.context=g;this._signal=i;this._priority=e||0}c.prototype={active:true,params:null,execute:function(e){var g,f;if(this.active&&!!this._listener){f=this.params?this.params.concat(e):e;g=this._listener.apply(this.context,f);if(this._isOnce){this.detach()}}return g},detach:function(){return this.isBound()?this._signal.remove(this._listener):null},isBound:function(){return(!!this._signal&&!!this._listener)},getListener:function(){return this._listener},_destroy:function(){delete this._signal;delete this._listener;delete this.context},isOnce:function(){return this._isOnce},toString:function(){return"[SignalBinding isOnce: "+this._isOnce+", isBound: "+this.isBound()+", active: "+this.active+"]"}};function a(e,f){if(typeof e!=="function"){throw new Error("listener is a required param of {fn}() and should be a Function.".replace("{fn}",f))}}b.Signal=function(){this._bindings=[]};b.Signal.prototype={_shouldPropagate:true,active:true,_registerListener:function(i,h,g,f){var e=this._indexOfListener(i),j;if(e!==-1){j=this._bindings[e];if(j.isOnce()!==h){throw new Error("You cannot add"+(h?"":"Once")+"() then add"+(!h?"":"Once")+"() the same listener without removing the relationship first.")}}else{j=new c(this,i,h,g,f);this._addBinding(j)}return j},_addBinding:function(e){var f=this._bindings.length;do{--f}while(this._bindings[f]&&e._priority<=this._bindings[f]._priority);this._bindings.splice(f+1,0,e)},_indexOfListener:function(e){var f=this._bindings.length;while(f--){if(this._bindings[f]._listener===e){return f}}return -1},add:function(g,f,e){a(g,"add");return this._registerListener(g,false,f,e)},addOnce:function(g,f,e){a(g,"addOnce");return this._registerListener(g,true,f,e)},remove:function(f){a(f,"remove");var e=this._indexOfListener(f);if(e!==-1){this._bindings[e]._destroy();this._bindings.splice(e,1)}return f},removeAll:function(){var e=this._bindings.length;while(e--){this._bindings[e]._destroy()}this._bindings.length=0},getNumListeners:function(){return this._bindings.length},halt:function(){this._shouldPropagate=false},dispatch:function(f){if(!this.active){return}var e=Array.prototype.slice.call(arguments),h=this._bindings.slice(),g=this._bindings.length;this._shouldPropagate=true;do{g--}while(h[g]&&this._shouldPropagate&&h[g].execute(e)!==false)},dispose:function(){this.removeAll();delete this._bindings},toString:function(){return"[Signal active: "+this.active+" numListeners: "+this.getNumListeners()+"]"}};d.signals=b}(window||this)); \ No newline at end of file From 37f9b3c96d1c55c2ee563c595577d283fa997360 Mon Sep 17 00:00:00 2001 From: "Mr.doob" Date: Fri, 9 Sep 2011 06:20:58 +0200 Subject: [PATCH 2/3] GUI: Minor refactoring and keeping backwards compatibility by now... --- gui/js/Code.js | 2 +- gui/js/UI.Viewports.js | 92 +++++++++++++++++++++--------------------- 2 files changed, 47 insertions(+), 47 deletions(-) diff --git a/gui/js/Code.js b/gui/js/Code.js index 95cca97e..b55ed796 100644 --- a/gui/js/Code.js +++ b/gui/js/Code.js @@ -122,7 +122,7 @@ var Code = function () { if ( object.scale.y != 1 ) string += '\n\tmesh.scale.y = ' + object.scale.y + ';'; if ( object.scale.z != 1 ) string += '\n\tmesh.scale.z = ' + object.scale.z + ';'; - string += '\n\tscene.add( mesh );'; + string += '\n\tscene.addObject( mesh );'; // string += '\n\tscene.add( mesh );'; _list.push( string ); diff --git a/gui/js/UI.Viewports.js b/gui/js/UI.Viewports.js index 2a2a7ef0..3aa847b9 100644 --- a/gui/js/UI.Viewports.js +++ b/gui/js/UI.Viewports.js @@ -6,13 +6,6 @@ UI.Viewports = function () { var _HOVERED, _SELECTED; var _offset = new THREE.Vector3(); - var _views = [ - { x: 0, y: 0, width: 0, height: 0 }, - { x: 0, y: 0, width: 0, height: 0 }, - { x: 0, y: 0, width: 0, height: 0 }, - { x: 0, y: 0, width: 0, height: 0 } - ]; - // var _domElement = document.createElement( 'div' ); @@ -21,23 +14,28 @@ UI.Viewports = function () { // - var _cameras = []; + var _views = [ + { x: null, y: null, width: null, height: null, camera: null }, + { x: null, y: null, width: null, height: null, camera: null }, + { x: null, y: null, width: null, height: null, camera: null }, + { x: null, y: null, width: null, height: null, camera: null } + ]; - _cameras[ 0 ] = new THREE.Camera( 50, 1, 1, 5000 ); // top - _cameras[ 0 ].useTarget = false; - _cameras[ 0 ].position.y = 1000; - _cameras[ 0 ].rotation.x = - Math.PI / 2; + _views[ 0 ].camera = new THREE.Camera( 50, 1, 1, 5000 ); // top + _views[ 0 ].camera.useTarget = false; + _views[ 0 ].camera.position.y = 1000; + _views[ 0 ].camera.rotation.x = - Math.PI / 2; - _cameras[ 1 ] = new THREE.Camera( 50, 1, 1, 5000 ); // front - _cameras[ 1 ].position.z = 1000; + _views[ 1 ].camera = new THREE.Camera( 50, 1, 1, 5000 ); // front + _views[ 1 ].camera.position.z = 1000; - _cameras[ 2 ] = new THREE.Camera( 50, 1, 1, 5000 ); // left - _cameras[ 2 ].position.x = - 1000; + _views[ 2 ].camera = new THREE.Camera( 50, 1, 1, 5000 ); // left + _views[ 2 ].camera.position.x = - 1000; - _cameras[ 3 ] = new THREE.Camera( 50, 1, 1, 5000 ); // perspective - _cameras[ 3 ].position.x = 1000; - _cameras[ 3 ].position.y = 1000; - _cameras[ 3 ].position.z = 1000; + _views[ 3 ].camera = new THREE.Camera( 50, 1, 1, 5000 ); // perspective + _views[ 3 ].camera.position.x = 1000; + _views[ 3 ].camera.position.y = 1000; + _views[ 3 ].camera.position.z = 1000; // guides @@ -75,7 +73,7 @@ UI.Viewports = function () { var mouse = getViewportMouse( event.clientX, event.clientY ); - var camera = _cameras[ mouse.id ]; + var camera = _views[ mouse.view ].camera; var vector = new THREE.Vector3( mouse.x * 2 - 1, - mouse.y * 2 + 1, 0.5 ); _projector.unprojectVector( vector, camera ); @@ -98,7 +96,7 @@ UI.Viewports = function () { var mouse = getViewportMouse( event.clientX, event.clientY ); - var camera = _cameras[ mouse.id ]; + var camera = _views[ mouse.view ].camera; var vector = new THREE.Vector3( mouse.x * 2 - 1, - mouse.y * 2 + 1, 0.5 ); _projector.unprojectVector( vector, camera ); @@ -123,7 +121,7 @@ UI.Viewports = function () { _HOVERED = intersects[ 0 ].object; _plane.position.set( 0, 0, 0 ); - _plane.lookAt( _cameras[ mouse.id ].position ); + _plane.lookAt( camera.position ); _plane.position.copy( _HOVERED.position ); _render(); @@ -153,14 +151,16 @@ UI.Viewports = function () { event.preventDefault(); - var id = getViewportMouse( event.clientX, event.clientY ).id; + var mouse = getViewportMouse( event.clientX, event.clientY ); + var camera = _views[ mouse.view ].camera; + var vector = camera.position.clone(); var amount = event.wheelDeltaY * 0.2; - var vector = _cameras[ id ].position.clone(); if ( vector.length() - amount < 10 ) return; vector.normalize().multiplyScalar( amount ); - _cameras[ id ].position.subSelf( vector ); + camera.position.subSelf( vector ); + _render(); } @@ -274,7 +274,7 @@ UI.Viewports = function () { return { - id: 0, + view: 0, x: x / _views[ 0 ].width, y: y / _views[ 0 ].height @@ -284,7 +284,7 @@ UI.Viewports = function () { return { - id: 1, + view: 1, x: ( x - _views[ 1 ].x ) / _views[ 1 ].width, y: y / _views[ 1 ].height @@ -294,7 +294,7 @@ UI.Viewports = function () { return { - id: 2, + view: 2, x: x / _views[ 2 ].width, y: ( y - _views[ 2 ].y ) / _views[ 2 ].height @@ -304,7 +304,7 @@ UI.Viewports = function () { return { - id: 3, + view: 3, x: ( x - _views[ 3 ].x ) / _views[ 3 ].width, y: ( y - _views[ 3 ].y ) / _views[ 3 ].height @@ -373,17 +373,17 @@ UI.Viewports = function () { var _updateCameras = function () { - _cameras[ 0 ].aspect = _views[ 0 ].width / _views[ 0 ].height; - _cameras[ 0 ].updateProjectionMatrix(); + _views[ 0 ].camera.aspect = _views[ 0 ].width / _views[ 0 ].height; + _views[ 0 ].camera.updateProjectionMatrix(); - _cameras[ 1 ].aspect = _views[ 1 ].width / _views[ 1 ].height; - _cameras[ 1 ].updateProjectionMatrix(); + _views[ 1 ].camera.aspect = _views[ 1 ].width / _views[ 1 ].height; + _views[ 1 ].camera.updateProjectionMatrix(); - _cameras[ 2 ].aspect = _views[ 2 ].width / _views[ 2 ].height; - _cameras[ 2 ].updateProjectionMatrix(); + _views[ 2 ].camera.aspect = _views[ 2 ].width / _views[ 2 ].height; + _views[ 2 ].camera.updateProjectionMatrix(); - _cameras[ 3 ].aspect = _views[ 3 ].width / _views[ 3 ].height; - _cameras[ 3 ].updateProjectionMatrix(); + _views[ 3 ].camera.aspect = _views[ 3 ].width / _views[ 3 ].height; + _views[ 3 ].camera.updateProjectionMatrix(); }; @@ -401,20 +401,20 @@ UI.Viewports = function () { _renderer.clear(); _renderer.setViewport( 0, _height - _height * _yhalf, _views[ 0 ].width, _views[ 0 ].height ); - _renderer.render( _sceneHelpers, _cameras[ 0 ] ); - _renderer.render( _scene, _cameras[ 0 ] ); + _renderer.render( _sceneHelpers, _views[ 0 ].camera ); + _renderer.render( _scene, _views[ 0 ].camera ); _renderer.setViewport( _width * _xhalf, _height - _height * _yhalf, _views[ 1 ].width, _views[ 1 ].height ); - _renderer.render( _sceneHelpers, _cameras[ 1 ] ); - _renderer.render( _scene, _cameras[ 1 ] ); + _renderer.render( _sceneHelpers, _views[ 1 ].camera ); + _renderer.render( _scene, _views[ 1 ].camera ); _renderer.setViewport( 0, 0, _views[ 2 ].width, _views[ 2 ].height ); - _renderer.render( _sceneHelpers, _cameras[ 2 ] ); - _renderer.render( _scene, _cameras[ 2 ] ); + _renderer.render( _sceneHelpers, _views[ 2 ].camera ); + _renderer.render( _scene, _views[ 2 ].camera ); _renderer.setViewport( _width * _xhalf, 0, _views[ 3 ].width, _views[ 3 ].height ); - _renderer.render( _sceneHelpers, _cameras[ 3 ] ); - _renderer.render( _scene, _cameras[ 3 ] ); + _renderer.render( _sceneHelpers, _views[ 3 ].camera ); + _renderer.render( _scene, _views[ 3 ].camera ); }; From a885f9f4b9e6872653daa47167087574b0d50f79 Mon Sep 17 00:00:00 2001 From: "Mr.doob" Date: Fri, 9 Sep 2011 06:35:35 +0200 Subject: [PATCH 3/3] GUI: Fixed broken HTML generation (because of the innerText > innerHTML change). --- gui/js/Code.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gui/js/Code.js b/gui/js/Code.js index b55ed796..a79f17db 100644 --- a/gui/js/Code.js +++ b/gui/js/Code.js @@ -85,7 +85,7 @@ var Code = function () { if ( _html ) { - string = '\n\n\t\n\t\t\n\t\t\n\t\t\n\t\n'; + string = '<!doctype html>\n<html>\n\t<body>\n\t\t<script src=\"js/Three.js\"></script>\n\t\t<script src=\"js/RequestAnimationFrame.js\"></script>\n\t\t<script>\n' + ( '\n' + string ).replace( /\n/gi, '\n\t\t\t' ) + '\n\n\t\t</script>\n\t</body>\n</html>'; }