BLENDER_v237REND SceneSRt[SR1-Animation<<.DATA\DATA\DATA\DATA\DATA\DDATAD\DATA\DDATA\DATA\dDATAd\DATA\dDATA\DATA<]DATA]<DATA]DDATA]\DATA\]DATA]\DATA]4DATA4]|DDATA|]4dDATA] |dDATA ]TdDATAT] DDATA]TDATA],DATA,]tDATAt],DDATA]tDATA]DATA<_;O44\DATA^ Link and MaterialsEditing>DATA ^LMeshEditingF>DATAL^$ Anim settingsObject>DATA$^LDrawObjectF>DATA^$ConstraintsObject>DATA^EffectsObjectDATA^Particle InteractionObject>DATA^\HooksObjectF>$DATA\^SoftbodyObject>DATA4L4333?<@DhCvBD_2~cCC(BDC?z?DATAT4N4333?</9DATA;_T<DATAT_|J;d|+9=5vc=o?+,|l  DATA^ Transform PropertiesView3d>DATA ^3D Viewport propertiesView3d>"DATAh|Gl 333?T????????|+9=5vc=o?;A4A?|+9=5vc=o??????;A B??=C DATATl N|333?T/9DATA|J_TdD??Pף+,   DATA ^Transform PropertiesIpo!>DATA K 333?|JzC̽̌?zC@ #< #<`jFzD OBzC̽̌?DATA O 333?|J@zAAQAQAB A@CC #<@DATAxR  333?|J6 j>DATAhG333?|J??? ???? A???PA A!O?j?}GCHB? A B? #<C@h@hDATATN333?|J/9DATA_|JD 'T,|DATA^|Link and MaterialsEditing>DATA|^MeshEditingF>DATAT$ 333?ŨzCCHBC'?CFC= ADATA$L,T333?Ũ#DhC`DpJgChCC(BDC?z?DATAT,N$333?Ũ/9SRt[YSR2-Model \,!d!4.DATA\\DATA\\DATA\4DATA4\|DATA|\4DATA\ |DATA \TDATAT\ DATA\TxDATA\xDATA,]tDATAt],\4DATA]t|DATA]L DATAL]TDATA]L TDATA]$| DATA$]lTDATAl]$|DATA]lDATA]D  DATAD ] TDATA ] D DATA ]! \|DATA!] 4DATAd!_d" T$ DATAd"_,d!T=i=o?yyy <$D+~~d#d#DATAd#^Transform PropertiesView3d>"DATAx<$R$ 333?d"$; ,?DATA $S4%<$333?d"DATA4%O&$333?d"0Ap=A|AˮAzu@A A@CC #<@,&,&DATA,,&rSC@ffDATAh&G$)4%333?d"????????=i=o?xA4A?=i=o??????4A B?=C q q DATA$)L,*&333?d"DdC8CnD fCC(BDC?z?DATA,*KD+$)333?d"zC AzC A #< #<`jFzD OBDATATD+N,*333?d"SAVE TEXT FILEATHRES/home/nmatan/n2.3//../est230//er/../city-stage10.blend BDATA,_4d"| b?? JLwww x.\3--DATA-^Transform PropertiesView3dz>DATAh.G<1333?,~?tkp=T=.:?h-7^ϼ.?X:?YW>~@jf?~?T=:^ϼrk-:?.?p=h-Y:?Q?9 A??srp!P>1K?z-?h-?5L"??~ ;X:c>){-@cAjfAqM?=jųVރ*?? PxgB0=A@5e-B@b?? JL~?tkp=T=.:?h-7^ϼ.?X:?YW>~@jf?m?eZ/0ZA B??=C]?'/"@ T T DATA<1LD2.333?,DdC8CnD fCC(BDC?z?DATAD2K\3<1333?,zC AzC A #< #<`jFzD OBDATAT\3ND2333?,Save AsCRIPT PATHRESh:\e/nmatan/n2.3//../est230//er/../city-gen-20050721.blend.blendKDADATA4_,\|4?@Pף OUtX,,55DTDATA5^6PreviewLamp>DATA6^75LampLampF>DATA7^l86SpotLamp>DATAl8^D97Texture and InputLamp>DATAD9^:l8Map ToLamp>l8DATA:^:D9PreviewMaterial>DATA:^;:MaterialMaterialF>DATA;^<:PreviewWorld>DATA<^|=;WorldWorldF>DATA|=^T><Mist Stars PhysicsWorld>DATAT>^,?|=Texture and InputWorld>DATA,?^@T>Map ToWorld>T>DATA@^@,?OutputRender>DATA@^A@RenderRenderF>DATAA^B@AnimRender>DATAB^dCAFormatRender>DATAdC^DATADATAE^EDATAE^FEMesh Tools 1Editing>DATAF^GECameraEditing@>DATAG^tHFShadersMaterial>DATAtH^LIGTextureMaterial>DATALI^$JtHAnim settingsObject>DATA$J^JLIDrawObjectF>DATAJ^K$JConstraintsObject>DATAK^LJScriptlinksScript>DATAL^MKEffectsObjectJDATAM^\NLMap InputMaterial>tHDATA\N^4OMMap ToMaterial>tHDATA4O^ P\NAnimAnim>DATA P^P4OSoundSound>DATAP^Q PListenerSoundF>DATAQ^RPSequencerSound>DATAR^lSQParticle InteractionObject>JDATAlS^DTRRampsMaterialF>:DATADT^lSMirror TranspMaterial>GDATAUL$V4DdCHV7D4CC(BEC?H?DDATAx$VRVU 333?4  =`b+yDATA VSW$V333?4DATAWOtXV333?4/iBeBA AL:lrC6TfB A@CC #<@XXDATA,XrSC0beBADATATtXNW333?4SAVE TEXT FILEh:\city-sticks-3.blend KSRtY[̖SR3-Materialodel SingZL^^d e.DATAZ\ZDATAZ\4[ZDATA4[\|[ZDATA|[\[4[DATA[\ \|[0DATA \\T\[0DATAT\\\ \DATA\\\T\DATA\\,]\0DATA,]\t]\DATAt]\],]DATA]\^t]DATA^\L^]DATAL^\^DATA^]^Z4[DATA^]$_^Z|[DATA$_]l_^Z[DATAl_]_$_|[ \DATA_]_l_[ \DATA_]D`_ZT\DATAD`]`_4[\DATA`]`D`T\\DATA`]a` \\DATAa]da`[\DATAda]aa \\DATAa]ada\,]DATAa]DATAf^g fRenderRenderF>DATAg^hfAnimRender>DATAh^gFormatRender>DATAli}GCHB? A B? #<CzzDATAmOnDk333?@̌AR|B1@lA A@CC #<@DATATnNm333?/9DATA\p_\q eT\Z4[\DATA\q_ \p\,]\ \G@? JL11KLk~z\ryDATA\r^4sOutputRender>DATA4s^ t\rRenderRender>DATA t^t4sAnimRender0>DATAt^u tFormatRenderH>DATAu^vtPreviewMaterial>DATAv^lwuMaterialMaterial>DATAlw^DxvShadersMaterial0>DATADx^ylwTextureMaterialH>DATAy^yDxMap InputMaterialD>DATAy^yMap ToMaterial`>DATAzL{333?\CqhCCyEsntCC(BDC?z?kyDATAh{Gl~z333?\J>H!?)xu?i6>Pbܗ=(?^L?a?滎z?J>#xu?ܗ=Hi6>(? ?Pb^L?\FAA?4[?[!?@jG>gb>Pb>4Im>k&?]M^L<0@AzA=>Kc<2֍7&> ?:x¸A1vB,jB~@G@? JLJ>H!?)xu?i6>Pbܗ=(?^L?a?滎z?@?$$OA  B?=Ch?j(4?t'>SSdDATAl~K{333?\zC AzC A #< #<`jFzD OBDATATNl~333?\;SAVE FILE/usr/home/intrr/blender/blend/untitled.blendDATA _L\q[t]]\U.=}=o?11KL ĆDATAh G333????h?j(4?t'>????hj(4t'?U.=}=o??OA  B??=Ch?j(4?t'>qqdDATAL 333?DdC>9C,DeCC(BDC?z?DATAKĆ333?zC AzC A #< #<`jFzD OBDATATĆN333? SAVE FILE/Users/ton/Desktop/der/blend/untitled.blendDATAL_ ^L^,]]? x? JLSLDATAhLG䋩333?6?Z޾j ?&3?=>S5z?6?&3?<Y޾=>\5L?^ ?G5NI?ECA$dYA?G?TSХ j C? ?D?S5?R)? 6Nt>B~+ rBrsBc@? x? JL6?Z޾j ?&3?=>S5z?fS?վS#OA  B??=Ch?j(4?t'>wwdDATA䋩L쌩L333?DdC>9C,DeCC(BDC?z?DATA쌩K䋩333?zC AzC A #< #<`jFzD OBDATATN쌩333? SAVE FILE/Users/ton/Desktop/der/blend/untitled.blendDATA_Lt]T\L^^(.=R`=o?SDDATAhG$333??3?3^I2(o(4?? 3?3^=i(4J2(A?(.=1n;R`=ꉖW5j@bT{:?OA@5MA(C^=j(4J2(A?(.=R`=o??3?3^I2(o(4?5?5OA  B??=C^j(4?J2(_X_XdDATA$L,333?DdC>9C,DeCC(BDC?z?DATA,KD$333?zC AzC A #< #<`jFzD OBDATATDN,333? SAVE FILE/Users/ton/Desktop/der/blend/untitled.blendSRt̖[YSR4-SequencetԚ䟩ij.DATAt\DATA\tDATA\LDATAL\DATA\ܘLDATAܘ\$DATA$\lܘDATAl\$DATA\ldDATA\DdDATAD\dDATA\DDATAԚ]DATA]dԚtLDATAd]tDATA]dLܘDATA]<ܘDATA<]$DATA]̜<lDATA̜]$lDATA]\̜DATA\]$DATA]읩\lDATA읩]4ܘDATA4]|읩DATA|]Ğ4DDATAĞ] |DDATA ]TĞ$DATAT] lDATA]TDDATA䟩_ԦtܘLDL䠩lDATA䠩^OutputRender>DATA^䠩RenderRenderF>DATA^lAnimRender>DATAl^FormatRender>DATADLL333?̅DhC ѦDۿ8aCC(BDC?z?DATATLND333?̅/9DATAԦ_ԧ䟩$lDATAԧ_̭Ԧܘ8=i>o?ccT ԨDDATAԨM333?zCAzCATT A@FB= A DATAhGDԨ333?????????8=i>o?fffAD&@??fffA B? #<CDATATDN333?AVE TARGA/t1.blend9DATA̭_ijԧDl8=H>o?eeeeR ̮<DATA̮M333?zCAzCA1||1 A@FB= A DATAhG<̮333?????????8=H>o?fffA*@??fffA B? #<C>>DATAT<N333?AVE TARGA/t1.blend9DATAij_̭$D8=>o?ee7ĴtDATAĴKܵ333?B̽̌?B̽̌?77 #< #<`jFzD SQB̽̌?DATAhܵGtĴ333?????????8=>o?fffA@??fffA B? #<CzzDATATtNܵ333?OAD FILE/9SCESCScenetageaint<ܩt<ܩ@|D]:=dd??< 2dd??Z@@????L?fff??@ A//backbuf/tmp\//ftype@&#@^@&^#DDATA<ܩ>tADATAt><ܩA$DATA(=,d'=A@WOt<WOWorldg=pb>>===??A@pA A?L=TXd$TXCityGen.py4D߱]<@GDATAtQ|DATAtQD|P p#DATAD$tQDATA$DDATA99\90DATA94:9|0DATA4:|:9䝫1DATA|::4:L8FREEDATA: ;|:ds:DATA ;T;:axX DATAT;; ;<= sDATA;;T;"= sDATA;,<;ܟ[:]DATA,<t<;$ub: DATAt<<,<tDATA<=t<DATA=L=<DATAL===LseDATA==L=DATA=$>=DATA$>l>=oneDATAl>>$>d maDATA>>l> NoDATA>D?> 0)DATAD??>LeakDATA?D?6DATA??9 ])DATA?l@\ 0)DATAl@@?%maxDATA@@l@DATA@DA@$0DATADAA@DATAAADA erDATAABA,DATABdBAtVDATAdBBBDATABBdB4 []DATABDATALZZZ>p):DATAZZLZe tDATAZ$[ZDDATA$[l[Z|3=DATAl[[$[DATA[[l[ p:DATA[D\[\DATAD\\[BStaDATA\\D\ DATA\]\Db sDATA]d]\e:DATAd]]]DATA]]d] ?nt DATA]<^]|ntDATA<^^]%DATA^^<^ "b) DATA^_^dtioDATA_\_^BnDATA\___DATA__\_L#DATA_4`_7st DATA4`|`_ DATA|``4`Dk +DATA` a|`DATA aTa`BRanDATATaa aD *crDATAaaTa DcDATAa,ba $DATA,btbat $DATAtbb,b " DATAbctb$ DATAcLcbt ::DATALccc DATAccLc esDATAc$dcd 8- DATA$dldc )DATAldd$d4 XDATAddld (inDATAdDed D(inDATADeedtDDATAeeDeDATAefe$%eroDATAfdfe|!DATAdfffDATAffdf5 DATAflf.DATADnnm̨/eftDATAnnDn,ubDATAnondDATAodon5inBDATAdooo4 inDATAoodo"iDATAo DATA4{|{z y1,DATA|{{4{츫e: rDATA{ ||{<^awX,DATA |T|{̹= ddrDATAT|| |<elf.DATA||T|t=DATA|,}|享onMDATA,}t}|JonMDATAt}},}DATA}~t}ԻFREEDATA~L~}^FREEDATAL~~~e-spDATA~~L~&DATA~$~LDATA$l~GDATAl$8DATAll DATADľDATAD(othDATAԀD\DATAԀDATAdԀܿ!SucDATAd4 DATAdlC DATA<=DATA<TDATÂ<GDAT«DATA\̂<«)DATA\«ADATA샪\ëDATA샪4Lë(eDATA4|샪ëonDATA|Ą4ënDATAĄ |,ī!TruDATA TĄīDATAT īNDATA䅪T<ūDATA䅪,tū)DATA,t䅪ūADATAt,LƫartDATAtƫ(ht DATALƫelfDATAL,ǫDATA܇Ldǫ! DATA܇$ǫDATA$l܇ǫ)DATAl$Tȫ * (mDATAlȫ] radDATAD$ɫ== NDATADtɫ%DATAԉDɫf, cDATAԉʫ7$zDATAdԉlʫ' DATAdʫDATAd ˫DATA<D˫ DATA<˫ DATA̋<˫ DATA̋$̫DATA\̋\̫DATA\̫DATA쌪\̫ # raDATA쌪4LͫueDATA4|쌪ͫBRKDATA|č4ͫgleDATAč |ΫDATA Tč\Ϋ:DATAT Ϋ-bloDATA䎪TΫDATA䎪,<ϫDATA,t䎪ϫnerDATAt,ϫ<ateDATAt,Ы>atDATALЫ/aDATALЫDATAܐL4ѫ DATAܐ$tѫ:DATA$lܐѫ:neDATAl$ҫ]DATAldҫ BDATADҫt)DATADҫ*( DATAԒDLӫDATAԒӫADATAdԒӫC DATAdtԫDATAdԫ:DATA<ԫesDATA<DիDATA̔<|ի([ DATA̔իDATA\̔իDATA\L֫ertDATA앪\֫ DATA앪4֫ertDATA4|앪$׫DATA|Ė4t׫#DATAĖ |׫$ DATA TĖ$ث DATAT dث#DATA䗪Tث$ a DATA䗪,٫DATA,t䗪L٫)aroDATAt,٫)ancDATAt ګk wDATALTګmaxDATALګ!([ DATAܙLګMDATAܙ$D۫vDYDATA$lܙ۫FREEDATAl$۫DATAlܫ* 0DATADdܫ$ rDATADܫ$FREEDATAԛDݫ3DATAԛ|ݫFREEDATAdԛݫ9DATAd$ޫ)KDATAdޫA)DATA<ޫ-DATA<\߫DATA̝<߫0 DATA̝߫FREEDATA\̝D8DATA\ DATA잪\$FREEDATA잪4DATA4|잪d@ DATA|ğ48DATAğ |0DATA Tğ$)DATAT tDATA䠪TDATA䠪,*DATA,t䠪L)DATAt,DATAt+DATAL4+)DATAL+DATAܢLDATAܢ$, LDATA$lܢt 0:DATAl$FREEDATAlDATAD<DATADtDATAԤD3eDATAԤ$3DATAdԤDATAd'eDATAd4'DATA<DATA<<DATA̦<<@geDATA̦DATA\̦"DATA\D(DATA짪\(DATA짪4DATA4|짪< DATA|Ĩ4|)DATAĨ |)DATA TĨ<DATAT t*DATA䩪T*DATA䩪,4DATA,t䩪lDATAt,DATAt DATALD'DATALDATAܫLDATAܫ$4s:DATA$lܫDATAl$DATAlDATAD4'DATADDATAԭDDATAԭ$!DATAdԭ|DATAdDATAdDATA<,DATA<tGUIDATA̯<1DATA̯DATA\̯TDATA\DATA찪\DATA찪44DATA4|찪lDATA|ı4DATAı |FREEDATA Tı<"essDATAT DATA䲪TDATA䲪,etBDATA,t䲪T|DATAt,DATAtDATALNMeDATALlNMDATAܴLDATAܴ$oopDATA$lܴ<DATAl$ DATAls:DATAD$5DATAD theDATAԶDDATAԶDATAdԶddDATAdDATAd4 (e DATA<t_)DATA<= 0DATA̸<ersDATA̸40DATA\̸DATA\ DATA칪\()DATA칪4dL_QDATA4|칪L_DATA|ĺ4&d()DATAĺ |\.d()DATA Tĺ&d()DATAT  d()DATA仪TT drDATA仪,"awXDATA,t仪C DATAt,,? 0)DATAtKDATAL [DATALTDATAܽLs:DATAܽ$L_QDATA$lܽ$!DATAl$|Jse:DATAltBoDATAD4'.deDATAD!DATAԿD$DATAԿ$<$es(DATA$lԿ.DATAl$GL_DATAl4GLDATADl DATAD!GL_DATAD.GLDATAª|GDATAªdªe:DATAdªªªsDATAªªdªD DATAª<êª,DATA<êêªodDATAêê<ê<DATAêĪê|ruDATAĪ\ĪêtDiDATA\ĪĪĪ DATAĪĪ\ĪT xtSDATAĪ4ŪĪ LenDATA4Ū|ŪĪ DATA|ŪŪ4Ū$ &* lDATAŪ ƪ|Ū| +DATA ƪTƪŪ DATATƪƪ ƪ DATAƪƪTƪd 1DATAƪ,Ǫƪ Ad()DATA,ǪtǪƪD Ad()DATAtǪǪ,Ǫ 1d()DATAǪȪtǪ$ s[)DATAȪLȪǪd ()DATALȪȪȪ DATAȪȪLȪ )DATAȪ$ɪȪ4[:]DATA$ɪlɪȪDATAlɪɪ$ɪ+DATAɪɪlɪ4+DATAɪDʪɪ 0, DATADʪʪɪDATAʪʪDʪ DATAʪ˪ʪT 0)DATA˪d˪ʪni:DATAd˪˪˪DATA˪˪d˪4DATA˪<̪˪|1d()DATA<̪̪˪1d()DATA̪̪<̪L1d()DATA̪̪ͪ1d()DATAͪ\̪ͪ DATA\ͪͪͪ\odeDATAͪͪ\ͪ)DATAͪ4Ϊͪ)DATA4Ϊ|Ϊͪ$CI DATA|ΪΪ4Ϊ\DATAΪ Ϫ|Ϊ)DATA ϪTϪΪ 9ineDATATϪϪ Ϫ|CDATAϪϪTϪeDATAϪ,ЪϪ,DATA,ЪtЪϪt DATAtЪЪ,ЪDATAЪѪtЪDATAѪLѪЪd&DATALѪѪѪ.8DATAѪѪLѪ&DATAѪ$ҪѪt FREEDATA$ҪlҪѪKDATAlҪҪ$ҪDATAҪҪlҪ4DATAҪDӪҪ>= DATADӪӪҪDATAӪӪDӪDr:DATAӪԪӪDATAԪdԪӪDATAdԪԪԪo):DATAԪԪdԪd= 0DATAԪ<ժԪDATA<ժժԪ=locDATAժժ<ժTDATAժ֪ժ.e GDATA֪\֪ժ-e DATA\֪֪֪LeDATA֪֪\֪ gDATA֪4ת֪DATA4ת|ת֪DATA|תת4תdDATAת ت|ת&DATA تTتת .DATATتت تl&DATAتتTت DATAت,٪ت DATA,٪t٪ت< DATAt٪٪,٪ -DATA٪ڪt٪ DATAڪLڪ٪$!e bDATALڪڪڪt!li DATAڪڪLڪ!l DATAڪ$۪ڪ"DATA$۪l۪ڪL"DATAl۪۪$۪"ou DATA۪۪l۪"!o DATA۪Dܪ۪<#ou DATADܪܪ۪#!o DATAܪܪDܪ#outDATAܪݪܪ$#DATAݪdݪܪt$ 0DATAdݪݪݪ$@ertDATAݪݪdݪ4%LDATAݪ<ުݪ%Bdr DATA<ުުݪ,&DATAުު<ުd&DATAުߪު& DATAߪ\ߪު 'DATA\ߪߪߪT'DATAߪߪ\ߪ'DATAߪ4ߪ'DATA4|ߪ(DATA|4l(DATA |(DATA T(eDATAT $), DATATt)d()DATA,)d()DATA,t*/d()DATAt,t*' DATAt*'DATAL$+DATALd+DATAL+DATA$+DATA$l4,HDATAl$,EERFDATAl,&\ DATAD,-.lDATAD-&DATAD- f.stDATA$.timDATAd\.DATAd.DATAd.1DATA</DATA<\/DATA</FREEDATA/DATA\40e:DATA\t0DATA\0DATA40 0)DATA4|,1r()DATA|4|1DATA |1):DATA T2DATAT L2kDATAT2(WinDATA,2DATA,t3DATAt,d3 )DATAt3: 0)DATAL,4U)DATAL4Sep"DATAL<5Wep"DATA$5E buDATA$l<6L", DATAl$6 0)DATAl6DATAD<7DATAD74Y =DATAD7Nse:DATAt8DATAd8 0)DATAd8 DATAdD93)DATA<9tsDATA<9DATA<,:DATA|:#:DATA\: ubDATA\;hubDATA\L;DATA4;DATA4|;( DATA|4<DATA |l<DATA T<(inDATAT <esDATAT4=):DATA,|=assDATA,t=,ssDATAt,,>sDATAtl>BGLDATAL>bStDATAL>(bSDATALT?bDATA$?DATA$l?sDATAl$$@*tsDATAl@sNDATAD@DATAD@ssDATADLA),DATAADATAdAsDATAd$Bke:DATAdlB,gsDATA<B8DATA< CDATA<DCDATACDATA\C2DATA\DDDATA\DbStDATA4DsDATA4E6<DATA|##hDATA|P#ThDATA# Street Map GeneratorDATA= cornerAngle:DATA| corners.append(ri)DATA return corners(DATA  DATAD# road classDATA(# roads are simply lines between hubsDATA # for now, the line is straightDATAD,# TODO add support for curved roads? maybe (gasp) spline curved?sDATA class Road:DATA( def __init__(self, hub1, hub2, rank):DATA$< self.hub1, self.hub2 = hub1, hub2DATA self.rank = rankDATA hub1.roads.append(self)DATA, hub2.roads.append(self)DATA| hub1.arrangeRoads()DATA hub2.arrangeRoads()DATA DATAD # overrides hub(DATA def setHub1(self, h):DATA  self.hub1.roads.remove(self)DATA$ self.hub1.arrangeRoads()DATAt self.hub1 = h; DATA  self.hub1.roads.append(self)DATA  self.hub1.arrangeRoads()DATA\ DATA # overrides hubhDATA def setHub2(self, h):DATA $ self.hub2.roads.remove(self)DATAt self.hub2.arrangeRoads()DATA self.hub2 = h; DATA  self.hub2.roads.append(self)DATAw self.hub2.arrangeRoads()%DATA$U DATAX def getLength(self): DATAL, return math.hypot(self.hub1.x - self.hub2.x, self.hub1.y - self.hub2.y)DATA DATA@ # gets the absolute direction angle, relative to the start hubDATA$T def getDirection(self, startHub):DATA if self.hub1 == startHub:DATAL return math.atan2(self.hub2.y - self.hub1.y, self.hub2.x - self.hub1.x)DATAL| return math.atan2(self.hub1.y - self.hub2.y, self.hub1.x - self.hub2.x)DATA DATA4rowDATAl# returns an iteratorDATA4# it cycles over a loop of roads that surround thenDATA$ # given corner of a hubDATA8l # may return repeat results (possible in some cases)DATA class roadLoop:DATA(! def __init__(self, hub, roadIndex):DATA$l! self.startHub = self.hub = hubuDATA(! self.ri = self.startRI = roadIndexDATAL DATA$ def __iter__(self): return selfseDATA܂deDATA def next(self):DATA\ # DATA, if self.hub == None: raise StopIterationDATA DATA$, road = self.hub.roads[self.ri]DATA4 if road.hub1 == self.hub: self.hub = road.hub2DATA 섫 else: self.hub = road.hub1DATA< DATA\t self.ri = (self.hub.roads.index(road) + len(self.hub.roads) - 1) % len(self.hub.roads)DATAfDATA< # bail out next time 1IDATA< if self.ri == self.startRI and self.hub == self.startHub:DATA self.hub = NoneDATADDATA| return roadDATAetDATA ifDATAD,# determines portion of first line that's cut off by the second oneDATAH# returns that portion (0 .. 1), and the portion of the second line tooDATA(# returns Nones if lines are paralleliDATA0tdef lineCross(x1, y1, x2, y2, x3, y3, x4, y4):DATAԉ DATA<  sine = 1.0 * (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1)DATA$| if sine == 0: return None, NoneDATAԊ DATA8  num1 = (x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)DATA8t num2 = (x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3)DATA<܋ k1 = num1 / sine # positions [0 .. 1] of the cross pointDATAL k2 = num2 / sineDATA DATǍ return k1, k2DATA retDATA8D# returns a set of verts approx describing a capsule])DATA,def capsuleVerts(x1, y1, x2, y2, radius):DATA etDATAD # halfcircleDATA numSlices = 4DATAĎ offsets = []DATAD baseAngle = math.atan2(x2 - x1, y1 - y2) # at 90 deg to main linevDATA | for i in range(numSlices + 1):DATA0̏ angle = baseAngle + i * math.pi / numSlicesDATAL, offsets.append([ math.cos(angle) * radius, math.sin(angle) * radius ])])DATA DATA䐫 # generate vertsDATA , verts = []DATAl DATA for off in offsets:DATA0쑫 verts.append([ x1 + off[0], y1 + off[1] ])DATAL for off in offsets:ocDATA0 verts.append([ x2 - off[0], y2 - off[1] ])DATA DATA, return vertsDATAl# hDATADATAܓ# eDATA# stateDATAL # DATA# crossing stateDATA8̔# closestPoint is similar to point but is adjusted toDATA,4# width (and angle) of the offending roadDATAclass CrossInfo:DATAܕ def __init__(self):DATA$ self.road = NoneDATAl self.point = NoneDATA self.sine = NoneDATA self.roadPoint = NoneDATAD self.closestPoint = NoneDATADATA̗ dvDATA,# harmless exception to break out of thingsDATAdclass BreakOut:DATA def __init__(self):DATA옫 passDATA$" DATA4\# harmless exception indicating a breakpoint stopatDATAęclass BreakpointStop:DATA  def __init__(self):DATAT passDATA sDATAĚclass StreetGenerator:DATA  def __init__(self):DATAT sDATA self.hubs = []DATAԛ self.roads = []DATADATAT # create seed structurenDATA@ # NOTE how we introduce the seed width and have no blank hubDATA4 # this is the equivalent of the main strip, ehRanDATA4| self.hubs.append(Hub(0, rankMinBlockSizes[0]))REEDATA4䝫 self.hubs.append(Hub(0, -rankMinBlockSizes[0]))))DATA<L self.roads.append(Road(self.hubs[0], self.hubs[1], 0)))EDATAgcoDATA # stage state DATA< self.currentRank = 0DATA$ self.growableHubs = self.hubs[:] DATAܟ seDATA$ # per-hub growth state1DATAt self.hub = NoneDATA self.corners = NoneDATA self.hubAttempts = 0DATAL self.hubDone = FalseDATA DATA # debug pictureDATA self.debugExtStart = NoneDATA d self.debugExtDirVec = None1DATA self.debugExtLen = 0DATA  self.debugExtSuccess = FalseDATAL DATA8 self.debugBounds = None # a set of roads encounteredDATA< self.debugClosestBound = None # closest bound referencegtDATADATA( self.debugDecisionMsg = "(no info)"DATA gDATA4$ # intersection checker for suggested extensions0, DATA # returns a hashDATA$ # alters the debug bounds arrayDATA, # TODO document betterDATAXt def checkExtension(self, hub, cornerIndex, extRank, extDir, extLength, minBlockSize):DATA rnDATA4 self.debugBounds = []DATA | self.debugClosestBound = NoneDATA DATA cross = CrossInfo()DATAL inDATA  extDirSine = math.sin(extDir)DATA$ extDirCosine = math.cos(extDir) DATA, DATA,d # find if we intersect any close-by roadsDATA x1, y1 = hub.x, hub.yDATAL  x2, y2 = hub.x + extDirCosine * extLength, hub.y + extDirSine * extLengthDATA len1 = extLengthDATA #DATAD  offset1 = x1 * extDirCosine + y1 * extDirSine # used for culling)DATA DATA  minDistance = minBlockSizeDATA shDATA,D for road in roadLoop(hub, cornerIndex):deDATA DATA( # ignore immediate neighbours DATA84 if road.hub1 == hub or road.hub2 == hub: continueDATA pDATA  # coordsDATA( x3, y3 = road.hub1.x, road.hub1.yDATA(l x4, y4 = road.hub2.x, road.hub2.yeDATA DATA  # skip if we're facing awayDATA<L if offset1 > x3 * extDirCosine + y3 * extDirSine and \ lDATA< offset1 > x4 * extDirCosine + y4 * extDirSine: continueDATA, iDATA(d # compute info about the main lineeDATA@ sine = 1.0 * (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1)DATA, DATAd if sine == 0:DATA k1, k2 = 0, 0DATA DATA , else: ==DATA<l num1 = (x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)1)DATA< num2 = (x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3)cosDATA@L k1 = num1 / sine # positions [0 .. 1] of the cross point)DATA k2 = num2 / sinestDATA DATA(< # make the sine within normal rangeDATA( len2 = math.hypot(y4 - y3, x4 - x3)DATA sine /= len1 * len2DATA4 DATA<l self.debugBounds.append([ x3, y3, x4, y4, minDistance ])DATA # DATA, # generate verts for the collision shapeDATA0t # TODO check if we start inside the shape!DATA8 verts = capsuleVerts(x3, y3, x4, y4, minDistance)gDATA<# gDATA0t enterK = leaveK = None # to track sidednessDATA  for i in range(len(verts)):DATA $ ni = (i + 1) % len(verts)DATAdt run, crossRun = lineCross(x1, y1, x2, y2, verts[i][0], verts[i][1], verts[ni][0], verts[ni][1])DATA  DATA4D if run == None or crossRun == None: continuedexDATA( if crossRun > 0 and crossRun < 1:DATA8 if enterK == None or enterK > run: enterK = runDATA8l if leaveK == None or leaveK < run: leaveK = runbDATA eDATA  # skip if no collisionDATA,\ if enterK > 1 or leaveK < 0: continueDATA seDATA( # see if we got the new closest lineDATADL if cross.closestPoint == None or cross.closestPoint > enterK:nd(DATA cross.point = k1DATA  cross.road = road1DATAT cross.sine = sineDATA cross.roadPoint = k2ne%DATA  cross.closestPoint = enterKDATA< DATA4t self.debugClosestBound = self.debugBounds[-1]eDATADATA return crossDATAT c DATA # breakpoint typesDATA BRK_NONE = -1DATA BRK_ATTEMPT = 0DATA\ BRK_HUB = 1DATA BRK_STAGE = 2DATATTEDATA@ # TODO don't use a maximum extLength for checks, but generateDATA@ # a real length right away - this way there's less negatives?DATA def run(self, breakpoint):DATADif DATA4| passGo = False # set to true after one small stepDATA brDATA while True:DATA\ paDATAD if breakpoint == StreetGenerator.BRK_ATTEMPT and passGo: returnDATA  iDATAD # find a hubDATA while self.hub == None::DATA alDATA@  if breakpoint == StreetGenerator.BRK_HUB and passGo: returnDATA|l DATA( # do a rank progression TODO thisDATA$  if len(self.growableHubs) < 1:DATAd DATAD if breakpoint == StreetGenerator.BRK_STAGE and passGo: returnDATA DATA$L # bailout if last rank reachedDATA8 if self.currentRank >= len(rankWidths) - 1: returnDATA  DATAD self.currentRank += 1%DATA DATAD # split roads to create growth grounds for next rank of roadsDATA,D  # this refills the growablehubs arrayDATAH  # TODO allow more than one split per road? i.e. spread them outޫDATA(  splittableRoads = self.roads[:]DATA(t  while len(splittableRoads) > 0::DATA$  road = splittableRoads.pop()eDATA $  length = road.getLength()DATA<t  if length > rankMinBlockSizes[self.currentRank] * 2:rDATA  #DATA  # do the split DATA<d  minSplitPos = rankMinBlockSizes[self.currentRank]f rDATA,  maxSplitPos = length - minSplitPosLDATA\4  splitPos = (minSplitPos + random.random() * (maxSplitPos - minSplitPos)) / lengthDATA  DATAH  splitX = road.hub1.x + (road.hub2.x - road.hub1.x) * splitPosn,DATAHt splitY = road.hub1.y + (road.hub2.y - road.hub1.y) * splitPos DATA DATA($ splitHub = Hub(splitX, splitY)DATA$| self.hubs.append(splitHub)izDATA DATA8 extRoad = Road(splitHub, road.hub2, road.rank)kDATA | road.setHub2(splitHub) DATA$̠ self.roads.append(extRoad)izDATA  DATA,$ self.growableHubs.append(splitHub)DATA$ splittableRoads.append(road)DATA(ܡ splittableRoads.append(extRoad)DATA4 DATADl # find and remove a hub (we'll add it back later if necessary)lDATAT䢫 testHub = self.growableHubs.pop(int(random.random() * len(self.growableHubs)))gDATAl tDATA< if math.hypot(testHub.x, testHub.y) > maxCityRadius: rDATA continueDATAT tDATA, # find potential corners to grow out ofDATA<줫 testCorners = testHub.getCorners(minCornerAngle * 2)od DATA \ if len(testCorners) < 1:1oDATA continueDATA쥫 whDATA$ self.hub = testHubDATA l self.corners = testCornersDATA (cDATA4 # calculate total number of attempts to givee *DATA8\ # based on total amount of space we randomize overDATAħ totalAngle = 0DATA  for i in self.corners:bDATA@\ totalAngle += self.hub.roadAngles[i] - minCornerAngle * 2EDATA0̨ self.hubAttemptsLeft = int(totalAngle * 16)DATA, inDATA d # get some semi-constants1DATA8 minBlockSize = rankMinBlockSizes[self.currentRank]:DATA 4  minExtLength = minBlockSizeDATA$ maxExtLength = 3 * minBlockSizeiDATA̪inBDATA # pick the corner DATAHT cornerIndex = self.corners[int(random.random() * len(self.corners))]DATA4̫ cornerAngle = self.hub.roadAngles[cornerIndex]erDATA4 splitAngle = cornerAngleDATA4 halfCone = cornerAngle * 0.5 - minCornerAngleDATA쬫 sDATA4$ # pick the direction (relative to corner road)ngDATAD # NOTE we actually skew the randomness to be close to midpoints)DATA, randFactor = 2 * (random.random() - 0.5)DATA8d randFactor = randFactor * randFactor * randFactorDATA<̮ splitAngle = cornerAngle * 0.5 + halfCone * randFactor*DATA< DATAt # extension infoDATA  extRank = self.currentRankDATA  DATALD extDir = self.hub.roads[cornerIndex].getDirection(self.hub) + splitAngleDATA$İ extDirSine = math.sin(extDir)DATA$ extDirCosine = math.cos(extDir)DATAPt extLength = minExtLength + random.random() * (maxExtLength - minExtLength)DATA rrDATA, # set up debug infoDATA4t self.debugExtStart = [ self.hub.x, self.hub.y ]EDATA8ܲ self.debugExtDirVec = [ extDirCosine, extDirSine ]DATA D self.debugExtLen = extLengthDATA  self.debugExtSuccess = FalseDATA䳫 DATA0 # find if we intersect any close-by roadseDATA`| cross = self.checkExtension(self.hub, cornerIndex, extRank, extDir, extLength, minBlockSize)DATA  eDATA<D # we intersect with something, see if we can cross it)]DATA< # note that as a result, extension length may be biggerkDATA<$ # we use a try .. except to allow simple falling throughDATA try:DATA̶ eDATA if cross.road != None:lDATAT DATA$ # check the resulting lengthepDATA ䷫ extLength *= cross.pointDATAP4 if extLength > maxExtLength or extLength < minBlockSize: raise BreakOutDATA DATA츫 # check the crossroadtDATA`< joinMargin = (rankWidths[extRank] + rankWidths[cross.road.rank]) / cross.road.getLength()DATA@̹ hubMargin = rankWidths[extRank] / cross.road.getLength()oDATA< DATA@t if math.fabs(cross.sine) < minCornerSine: raise BreakOutDATA享 DATAL if cross.roadPoint > joinMargin and cross.roadPoint < 1 - joinMargin:DATA DATAԻ # T-joinDATA` extHub = Hub(self.hub.x + extDirCosine * extLength, self.hub.y + extDirSine * extLength)DATA  self.hubs.append(extHub)eDATA( self.growableHubs.append(extHub)DATAL DATAH self.roads.append(Road(extHub, cross.road.hub2, cross.road.rank))DATA< self.roads.append(Road(self.hub, extHub, extRank))O)DATA$l cross.road.setHub2(extHub)b)DATAľ DATA, self.growableHubs.append(self.hub)100DATA\ self.hub = NoneDATA DATA$ܿ self.debugExtSuccess = True.hDATA4 DATADl # TODO these merges are pretty hackish and can cause artifactsDATA@ # namely, we have to look for the closest point possibleDATAT DATAH elif cross.roadPoint < hubMargin and cross.roadPoint > -hubMargin:DATA« DATA,<« # merge with existing intersection! TDATAD« self.roads.append(Road(self.hub, cross.road.hub1, extRank))DATAë DATA,Lë self.growableHubs.append(self.hub)aliDATAë self.hub = NoneDATAë DATA$,ī self.debugExtSuccess = True.hDATAī DATAPī elif cross.roadPoint < 1 + hubMargin and cross.roadPoint > 1 - hubMargin:DATA<ū DATA,tū # merge with existing intersection! TDATADū self.roads.append(Road(self.hub, cross.road.hub2, extRank))))DATALƫ DATA,ƫ self.growableHubs.append(self.hub)aliDATAƫ self.hub = NoneDATA,ǫ DATA$dǫ self.debugExtSuccess = True.hDATAǫ DATA,ǫ # we are free to extend willy-nilly! DATA Tȫ else:DATA`ȫ extHub = Hub(self.hub.x + extDirCosine * extLength, self.hub.y + extDirSine * extLength))DATA $ɫ self.hubs.append(extHub))DATA(tɫ self.growableHubs.append(extHub)DATAɫ DATA8ʫ self.roads.append(Road(self.hub, extHub, extRank))DATA(lʫ self.growableHubs.append(self.hub)DATAʫ self.hub = NoneDATA ˫ rDATA$D˫ self.debugExtSuccess = True.huDATA˫ sDATA˫ except BreakOut: pass1%DATA$̫ DATA\̫ # check attemptsDATA ̫ self.hubAttemptsLeft -= 1 DATA$̫ if self.hubAttemptsLeft <= 0:DATALͫ self.hub = NoneDATAͫDATAͫ # allow breaksDATAΫ passGo = TrueDATA\ΫdefDATA0Ϋ # returns a set of block loops feedable intoDATAΫ # the block generatorDATA<ϫ def getBlocks(self):DATAϫ fDATA@ϫ # we have to generate block boundaries based on road linesDATA@,Ы # we do that by creating proper CCW loops of one-sided edgesDATA0Ы # and assign a "shift" parameter to each edgeDATAЫ DATA4ѫ edges = []o DATAtѫ DATA<ѫ roadLeftEdges = {} # that's if ya look from hub1 to hub2sDATAҫ roadRightEdges = {}yDATAdҫ DATAҫ for road in self.roads:ocDATA,ҫ halfWidth = rankWidths[road.rank] * 0.5sDATALӫDATADӫ roadLeftEdges[road] = cwEdge = [ None, None, halfWidth, None ], DATADӫ roadRightEdges[road] = ccwEdge = [ None, None, halfWidth, None ]DATAtԫ DATAԫ edges.append(cwEdge)DATAԫ edges.append(ccwEdge)locDATADի DATA|ի for hub in self.hubs:DATAի DATAի if len(hub.roads) == 1:DATAL֫ DATA$֫ # special case for butt endsndaDATA֫ road = hub.roads[0]DATA$׫ if road.hub1 == hub:x, DATA$t׫ prevEdge = roadLeftEdges[road]DATA(׫ nextEdge = roadRightEdges[road]:DATA $ث else:e DATA$dث nextEdge = roadLeftEdges[road]DATA(ث prevEdge = roadRightEdges[road]DATA٫ DATA,L٫ v1 = [ hub.x, hub.y, prevEdge, None ]asDATA,٫ v2 = [ hub.x, hub.y, None, nextEdge ]DATA ګ prevEdge[1] = v1DATATګ nextEdge[0] = v2inDATA$ګ butt = [ v1, v2, 0, 0, None ]geDATAګ v1[3] = v2[2] = buttDATAD۫ edges.append(butt)DATA۫ DATA۫ else: EDATA,ܫ # simply create a vert for each cornerDATA(dܫ for ri in range(len(hub.roads)):tsDATA(ܫ nri = (ri + 1) % len(hub.roads)DATA4ݫ road, nextRoad = hub.roads[ri], hub.roads[nri]DATA|ݫ DATA<ݫ if road.hub2 == hub: prevEdge = roadRightEdges[road] 2DATA,$ޫ else: prevEdge = roadLeftEdges[road])DATADޫ if nextRoad.hub1 == hub: nextEdge = roadRightEdges[nextRoad]* DATA0ޫ else: nextEdge = roadLeftEdges[nextRoad]DATA\߫ DATA4߫ vert = [ hub.x, hub.y, prevEdge, nextEdge ] roDATA߫ prevEdge[1] = vertDATAD nextEdge[0] = vertDATA DATA( # first, compute the vertex nudgesDATA for edge in edges:DATAd DATA prevEdge = edge[0][2]5]DATA DATA $ dx = edge[1][0] - edge[0][0]DATA t dy = edge[1][1] - edge[0][1]DATA  edgeLen = math.hypot(dx, dy)DATA DATAL shiftX, shiftY = dy, -dxDATA DATA, prevDX = prevEdge[0][0] - prevEdge[1][0]DATA,4 prevDY = prevEdge[0][1] - prevEdge[1][1]DATA, prevEdgeLen = math.hypot(prevDX, prevDY)DATA DATA, prevShiftX = -prevDYDATAt prevShiftY = prevDXDATA DATA nudgeX = nudgeY = 0DATA< DATAt if edgeLen == 0:DATA4 nudgeX = prevEdge[2] * prevShiftX / prevEdgeLenDATA4$ nudgeY = prevEdge[2] * prevShiftY / prevEdgeLenDATA elif prevEdgeLen == 0:DATA( nudgeX = edge[2] * shiftX / edgeLenDATA(4 nudgeY = edge[2] * shiftY / edgeLenDATA  else:DATA@ prevProj = (shiftX * prevDX + shiftY * prevDY) / edgeLen0)DATAD< thisProj = (prevShiftX * dx + prevShiftY * dy) / prevEdgeLenDATA DATA$ if math.fabs(prevProj) < 0.01:DATA,D nudgeX = edge[2] * shiftX / edgeLenubDATA, nudgeY = edge[2] * shiftY / edgeLen2DATA < DATA< else: rDATA,| nudgeX = edge[2] * prevDX / prevProj 0DATA, nudgeY = edge[2] * prevDY / prevProjtyDATA< * DATA,t nudgeX += prevEdge[2] * dx / thisProj DATA, nudgeY += prevEdge[2] * dy / thisProjgDATA4 DATAl edge[0].append(nudgeX) DATA edge[0].append(nudgeY) DATA DATA(D # now apply the crap to all the vertsDATA for edge in edges:DATA edge[0][0] += edge[0][4]DATA4 edge[0][1] += edge[0][5]DATA # DATA outlines = []DATA DATA(4 # now convert all edges to good stuffDATA # TODO ensure CCWness?1DATA while len(edges) > 0:DATA$$ startEdge = curEdge = edges[0]DATA| eDATA loop = [] DATA DATA, # walk the loopDATAt while True:DATA4 loop.append([ curEdge[0][0], curEdge[0][1] ])DATA roDATAT curEdge[0] = None:DATA  nextEdge = curEdge[1][3] DATA curEdge[1] = NoneDATA4DATAl edges.remove(curEdge)DATA curEdge = nextEdgeDATA DATA$< if startEdge is curEdge: breakDATA DATA outlines.append(loop)1%DATA foDATAT return outlinesDATADATA def bakeMesh(self):DATA  mesh = Blender.NMesh.New()DATAl mesh.name = "sticks"DATA DATA  for loop in self.getBlocks():DATA < # now put the loop in fleshsDATA  baseIndex = len(mesh.verts)DATA for v in loop:DATA8$ mesh.verts.append(Blender.NMesh.Vert(v[0], v[1]))DATA foDATA  for i in range(len(loop)):DATA  i2 = (i + 1) % len(loop)DATAhd mesh.faces.append(Blender.NMesh.Face([ mesh.verts[baseIndex + i], mesh.verts[baseIndex + i2] ]))DATADATA4 return mesh)DATAt DATA DATA # draws a map on the GUI]DATA44 def paintMap(self, drawX, drawY, drawW, drawH):))DATA BDATA # clear bgDATA  BGL.glColor3f(0.8, 0.9, 1)1DATAd BGL.glBegin(BGL.GL_QUADS)DATA  BGL.glVertex2i(drawX, drawY)DATA( BGL.glVertex2i(drawX + drawW, drawY)DATA0\ BGL.glVertex2i(drawX + drawW, drawY + drawH)DATA( BGL.glVertex2i(drawX, drawY + drawH)DATA BGL.glEnd())DATAT BDATA$ # set up viewport scale and clipmDATA BGL.glPushMatrix() DATA@, BGL.glTranslatef(drawX + drawW * 0.5, drawY + drawH * 0.5, 0)DATAL BGL.glScalef(0.5 * drawW / maxCityRadius, 0.5 * drawW / maxCityRadius, 1)DATA seDATAT # draw the debug boundsiDATA if self.debugBounds:DATA DATA$$ for bound in self.debugBounds:DATAL| verts = capsuleVerts(bound[0], bound[1], bound[2], bound[3], bound[4])]DATA DATA(4 if bound == self.debugClosestBound:DATA$ BGL.glColor3f(0.6, 0.7, 0.8)DATA( else: BGL.glColor3f(0.7, 0.8, 1)1)DATA(< BGL.glBegin(BGL.GL_TRIANGLE_FAN)N)DATA0 for v in verts: BGL.glVertex2f(v[0], v[1])DATA BGL.glEnd()DATA4 DATA$l BGL.glColor3f(0.6, 0.7, 0.8)DATA$ BGL.glBegin(BGL.GL_LINE_LOOP))DATA0 for v in verts: BGL.glVertex2f(v[0], v[1])DATA| BGL.glEnd()DATA DATA  # draw the debug highlight1eDATA$D if self.debugExtStart != None: roDATA if self.debugExtSuccess:DATA BGL.glColor3f(0, 0, 1)DATA < else:DATA| BGL.glColor3f(1, 0, 1))DATA dDATA  pos = self.debugExtStartDATAT  dv = self.debugExtDirVecDATA  l = self.debugExtLenDATA  DATA($  mainX, mainY = dv[0] * l, dv[1] * lDATA,|  buttX, buttY = -dv[1] * 0.1, dv[0] * 0.1DATA  lDATA   BGL.glBegin(BGL.GL_QUADS)1DATA4d  BGL.glVertex2f(pos[0] - buttX, pos[1] - buttY) ]DATAD  BGL.glVertex2f(pos[0] + mainX - buttX, pos[1] + mainY - buttY)0]DATADD  BGL.glVertex2f(pos[0] + mainX + buttX, pos[1] + mainY + buttY)0]DATA4  BGL.glVertex2f(pos[0] + buttX, pos[1] + buttY)unDATA$  BGL.glEnd()DATAd BGDATA  # draw the roadsoDATA  BGL.glColor3f(1, 0, 0)1)DATA4 BGL.glBegin(BGL.GL_LINES)DATA for road in self.roads:YDATA, BGL.glVertex2f(road.hub1.x, road.hub1.y)DATA,4 BGL.glVertex2f(road.hub2.x, road.hub2.y)DATA BGL.glEnd()mDATADATA  # draw the hubs DATAT ptSize = 0.1DATA BGL.glColor3f(1, 0, 0)d mDATA BGL.glBegin(BGL.GL_QUADS)DATA4 for hub in self.hubs:DATA4| BGL.glVertex2f(hub.x - ptSize, hub.y - ptSize)EnDATA4 BGL.glVertex2f(hub.x - ptSize, hub.y + ptSize)d(DATA4L BGL.glVertex2f(hub.x + ptSize, hub.y + ptSize)ndDATA4 BGL.glVertex2f(hub.x + ptSize, hub.y - ptSize)EnDATA BGL.glEnd())DATA\AGEDATA # end the scaled modeDATA BGL.glPopMatrix()DATA$ BGDATA\ BGL.glColor3f(0, 0, 0)1eDATA, BGL.glRasterPos2i(drawX + 2, drawY + 2)DATA<  #Draw.Text("Sine: %.3f (vs %.3f), crosspoint: %.3f" % \3fDATAD| # (self.debugCrossSine, minCornerSine, self.debugCrossRoadPoint))DATAtDATA, # map box outlineDATAt BGL.glColor3f(0, 0, 0))%DATA  BGL.glBegin(BGL.GL_LINE_LOOP)DATA  BGL.glVertex2i(drawX, drawY) DATA(d BGL.glVertex2i(drawX + drawW, drawY)DATA0 BGL.glVertex2i(drawX + drawW, drawY + drawH)DATA( BGL.glVertex2i(drawX, drawY + drawH)DATAt BGL.glEnd()LDATA owDATA# block generator!DATA4# accepts a set of outlinesDATA@# each is an outline loop of verts (each being a [x,y] object)aDATA# works on one at a time1%DATADclass BlockGenerator:DATA  def __init__(self, outlines):DATAlasDATA  self.outlines = outlines[:]DATAd self.currentIndex = 0DATA oDATA@ print "started blockGen with", len(self.outlines), "blocks""DATAT prDATA0 # draws self on the GUI (the current outline)DATA0 def paint(self, drawX, drawY, drawW, drawH):DATAL# dDATA # clear bgREEDATA  BGL.glColor3f(0.8, 1, 0.9) DATA BGL.glBegin(BGL.GL_QUADS)DATA d BGL.glVertex2i(drawX, drawY)DATA( BGL.glVertex2i(drawX + drawW, drawY)DATA0  BGL.glVertex2i(drawX + drawW, drawY + drawH)DATA(l BGL.glVertex2i(drawX, drawY + drawH)DATA BGL.glEnd()DATA  blDATA <  if len(self.outlines) > 0:1DATA0  outline = self.outlines[self.currentIndex]DATA  DATA $! # find the outline boundsDATA t! outL = outR = outline[0][0]DATA ! outT = outB = outline[0][1]DATA" DATAL" for v in outline:DATA " if outL > v[0]: outL = v[0]DATA$" elif outR < v[0]: outR = v[0]DATA <# if outB > v[1]: outB = v[1]DATA$# elif outT < v[1]: outT = v[1]DATA# DATA$$ # set up viewport scale and clipDATAt$ BGL.glPushMatrix())DATAD$ BGL.glTranslatef(drawX + drawW * 0.5, drawY + drawH * 0.5, 0)iDATAP4% BGL.glScalef(0.8 * drawW / (outR - outL), 0.8 * drawW / (outT - outB), 1)5rDATAD% BGL.glTranslatef(-(outL + outR) * 0.5, -(outT + outB) * 0.5, 0) DATA,& BDATAd& BGL.glColor3f(0, 0, 0.5)DATA$& BGL.glBegin(BGL.GL_LINE_LOOP)clDATA ' for v in outline:DATA T' BGL.glVertex2f(v[0], v[1])DATA' BGL.glEnd()DATA'DATA( # end the scaled modeEndDATAl( BGL.glPopMatrix()deDATA( BDATA( else:DATA$) BGL.glColor3f(1, 0, 0)1DATA t) BGL.glBegin(BGL.GL_LINES)sDATA ) BGL.glVertex2f(drawX, drawY)DATA0* BGL.glVertex2f(drawX + drawW, drawY + drawH)DATA(t* BGL.glVertex2f(drawX, drawY + drawH)DATA(* BGL.glVertex2f(drawX + drawW, drawY)DATA$+ BGL.glEnd()DATAd+ lDATA+ # map box outlineDATA+ BGL.glColor3f(0, 0, 0)DATA 4, BGL.glBegin(BGL.GL_LINE_LOOP)DATA , BGL.glVertex2i(drawX, drawY)DATA(, BGL.glVertex2i(drawX + drawW, drawY)DATA0,- BGL.glVertex2i(drawX + drawW, drawY + drawH)DATA(- BGL.glVertex2i(drawX, drawY + drawH)DATA- BGL.glEnd()DATA$. woDATA\.# GUIDATA.mousePos = [0, 0]DATA. ptDATA/buttonAttemptStep = 1DATA\/buttonHubStep = 2DATA/buttonStageStep = 3DATA/buttonFinish = 4DATA40buttonBake = 5DATAt0if DATA0buttonResetBlocks = 10DATA0uttDATA ,1streetGen = StreetGenerator()# DATA |1blockGen = BlockGenerator([]) iDATA1 GDATA2def cityGenGUI(): DATAL2reDATA,2 screenW, screenH = Window.GetAreaSize()DATA2ocDATA3 # street generatorDATA$d3 streetGenX, streetGenY = 10, 10DATA<3 streetGen.paintMap(streetGenX, streetGenY + 40, 300, 300)DATAX,4 Draw.Button("Attempt Step", buttonAttemptStep, streetGenX, streetGenY + 20, 100, 20) DATAT4 Draw.Button("Hub Step", buttonHubStep, streetGenX + 100, streetGenY + 20, 100, 20)DATAX<5 Draw.Button("Stage Step", buttonStageStep, streetGenX + 200, streetGenY + 20, 100, 20)DATAH5 Draw.Button("Finish", buttonFinish, streetGenX, streetGenY, 150, 20)DATAP<6 Draw.Button("Bake Mesh", buttonBake, streetGenX + 150, streetGenY, 150, 20)5DATA6BGLDATA6 # block generatorDATA <7 blockGenX, blockGenY = 10, 360DATA87 blockGen.paint(blockGenX, blockGenY + 20, 300, 300)0)DATAP7 Draw.Button("Reset Blocks", buttonResetBlocks, blockGenX, blockGenY, 100, 20)DATAt8 reDATA8 BGL.glColor3f(0, 0, 0)DATA8 BGL.glRasterPos2i(2, 2) 0,DATA4D9 Draw.Text("CityGen (%d, %d)" % (screenW, screenH))DATA9BGLDATA9# GUI system eventsDATA,:def cityGenEvent(evt, val):DATA$|: if evt == Draw.ESCKEY and not val:DATA: Draw.Exit()DATA; DATAL; elif evt == Draw.MOUSEX:%DATA; mousePos[0] = valDATA; DATA< elif evt == Draw.MOUSEY:DATAl< mousePos[1] = valDATA<if DATA<# GUI button events DATA4=def cityGenButton(id):DATA |= if id == buttonAttemptStep:ssDATA0= streetGen.run(StreetGenerator.BRK_ATTEMPT)DATA,> Draw.Redraw()DATAl>pasDATA> elif id == buttonHubStep:DATA,> streetGen.run(StreetGenerator.BRK_HUB)DATAT? Draw.Redraw()DATA?eliDATA ? elif id == buttonStageStep:gsDATA,$@ streetGen.run(StreetGenerator.BRK_STAGE)DATA@ Draw.Redraw()DATA@eliDATA@ elif id == buttonFinish:hiDATA,LA streetGen.run(StreetGenerator.BRK_NONE)) DATAA Draw.Redraw()DATAAiniDATA$B elif id == buttonBake:DATA0lB Blender.NMesh.PutRaw(streetGen.bakeMesh())DATAB Draw.Redraw()DATA CuttDATA DC elif id == buttonResetBlocks:DATAC global blockGenDATA4C blockGen = BlockGenerator(streetGen.getBlocks())0DATADD Draw.Redraw()DATADDATAD# startup thingsthiDATA8EDraw.Register(cityGenGUI, cityGenEvent, cityGenButton)OB$7OBMesh?????????????DOBd?? #=?>=?@???OB7$OBMesh.001D?????????????DOBd?? #=?>=?@???ME+MEsticks.001???MED+MEsticks.003tbLL䟲IIP?%\}A0A?DATA}䟲0I>@>_@?@? @M.?MQ@>b\@?\@@bn@ D H@3圾@(m@o _@+s@2<@IƖ=@T?J@ S>n@?ϭ@J?@ ?@ @?W@>|{>){Y? v?S[zZ'`3<gm>ĴuK?|QeA>EA>_Agy?A`S?& A>;{A¤yAA5e{A(@OR+@z!@XDz@\@Q!@z%.@q@'@ͷg@ǎwd@|yv0' @L`@?@ qѹ@ˣ A ?<A*?I@'Ǘ?6N@,?B A?0(A8?O#≨|Q ̓Owako'ةh>?>B$@)?R @D?Z?=@ ?D{`D?`֎@#O?hL?>V?ߌ ??w>'>Y(DƾpDZ>]rx>aV4B {??JקV?Jy~?o%۹?(??Y?@l2@uĹ@<_[@@(2@lA8A@'@kKA=CA) Aё)A8hAM;AB,66 AQO!ANApAe@P6V@M@J @E#@x h@. @[A@V[K@ @-v@x'֤@&;@:@.WS@#-J@ǵy@(@z@w ?I?)=@4:@#I#@Xd2@h5B@"td@N@v3/@i\)#@zvZê@|K@<?k+a?qN?Q s?; M>ڮ)> )8zs8 1! Z}z ߿M$洿j$4ǿ m ƜgC`,YnW8mCXNӿ:O=`DK9HC-?&v `P2"e4fFU^o.J޿!%9-'!g=,tOdTc;v)vHc2N<@#`-J89!I~]'H=[)u\} ^_P 2wD>@\KwW4tk@UZ%xbK:2ًu\&^عy yҠho;o’Fvu:ׅvh8_wk̷RkFTVw+9MJ"> .C17o J6 i7 ;): fZ10 :?"y"4qj3ovԅ$[5d i!(ڿ6gn̿{,C=^NZcb1-nmmY4bmTZTNd:B %6ÿ(*6п0 D STc..X.[uZY4L>\{=0aV>Æ0'W\, >M6?C& $?2F?^Aij?dP?B]fŕ?(ls?F{y? kũ?5d@0ю0?؇?w z?k?\ ?YOâ?S`@Fӑ?1҃?8%_^?dN=?Q?3jG @;-z@, ?گo@ǡN9@ &7eB@ &!@cM@( @ͣ'@ @!@+ C@i@,@4ۓ@*C!@-+8@/s ɪ@ZR@Ra@"z@rI Ax A @@=u@@vA}1A @s@LAկRAGA4d,AQ6A^AA XaUAw_fAM(vA"(AAƸjA]ƺAu$7yAGiAXAfDAE:ALȉ/A"A~wA?4AT ADB A!Aj AAAhaALgLA?),A[N,ApEvA!"ACA^AfPAH;[ AgvGE$ADAWŜ=K-A5>+)A>ٔ)A_> Aq?&AM?C6$A ?(A$?AVU?A/O @Y)ATJ@0Au@=6A@*@sSg@0@:!(H?U*V@UN/<@I=@13 脪?3?]ԿUU? ?>s> ۿ6_?ӿ?vݿ)$ؿrڿ>Ͱ>1? ? :?W ?S.?=@]?.C4A:=|EI">U` #,2E4KL;_\uQR7?@֢\!H`3q/ޱѷͿ¡̩X,ƽ,4t!0٤k 6 TЬ3]  ̾,Īm^ۜXg>ZJR+@t)@+@n @U!@Q@?g@3G@to˿*A{;Av1@a:@'e@~܆?T@U@]m@mst@@TYo@˶j@w-? A8?%ޖ?L2?E?Wd=gI7:5>Z,@@`VW/XA1@YZ(@gT@y0}@FA!K>A N>@u+@t@L? m@Ĝ?l@p?쉠@@@^4@삏@?Gj@}&@R@"@):#@"@6@O= @Ɖ$@Ԅ?A/@@"?@s@@ @@;@@c@F@@M@@>?@T?\@4?{T@|?@\x%@Ć@>@S'@2O@*@i@@<@@v@ '@@FS @O@3?m@ ?R[Y@?wG@? ]@?m,e@Y@Ԥ;@~@@7b@;+@h@5(@-AT@@ T@x@z@@_y@-@@W@]@^@ Б@*Zl@eUx4@Gy@#̞@r@ @&[Y@A%@ OG@[.c@ЇD™Z:o 9`_7r1nHmN@aH3o@ @^*>@u@@|:%^y@j Xd괿>}KB/?l>>þ! >tK>!M)JDѪ侨Oōe<+uϟLcEZƴY80 V=&ȿ7- ǂ k<d*1W?!>?dw>ORy|?a?QS?0-Y3?vgͥ?'@\@ũ@@#@f@@@)@؛@D@@Hw҆@ @f@Qu@ X۞@I o@z@JM@GB@d@r0)@ 2`@q@TJU@MIi@Se}@]@.@ShR@ LP;O@!=ѿ>jӿ|yi"$T<0Yп]8!%9G ICr-TB\E,_!FS%H*pfF݃?fP?7q>= @G:/?`?@81?Vy'"@ gt@Jz@4c@#Ӆ@cgߧ@bVH@6N6@NIk|@&m>k@ȏot@KV5w@O;@ 7@6,I@WTG@D0E@@T?J@7?@Ǚ?)@@r kK}6c?_Or @D?v{@hB@e۽=E@KǾ \8@Z7^?jɿ@ĿC@}?ň*:?wѿ@%=h'@= ?A@?S@?F@t @@ ?]W@ގ=A?[.ӭ? ا ? ? ,7@ #y@jG@@BtV@~C@iu`@,8p@<_m6@5@Hi3dH7B X{Z3 V´w]PBf;~~M@.S~  Uۿ H"@\sV@QY@<{@gDAZ@)W@:(@A#@ @Z@@@@"|@s@y̒@&@BŚ@L@W?/?|X?+?v?,@̨?na'C@Ƥfr~@r1@*N@k5zW@[GBFh@B >@>V@a#@ @U#c@A.@4Pw@e `@o@_HW$A#AA#A H4AF#A\A^[\A/d2AV p A/ſA4ySA.R5A-5rAAOAeAa?HAa5 A̻A$3AI+g A[A3kv AtnA"|X@2bADAev(@`7X@`TeB@tbDS@Wll'@Lz,@Z|vMg@(^mS@ ^@x$@.@gd=@t%v&@B?ӌ? KU?̋@}`?D ?'?% ?'?a)T??X?Jb?.kY?Ŗb?>??ZT?#$ Z?>6?0N@ $|@@ @G@3 ]@ qn?w@Xż1@@O?+@d3 -@ pp@V@r_T1@O@p\@LrJ@S<@%B愮@Eͺ@/@߿g@Y<@Tw@\˫@0h@?;@#г@!@O;@ԃ@E@@ӂƭ@W1@)ﭘ@ɺe#@PE`c@!@)@Q֛@LIO@eAk@MVWil ;=>Mx+eV+hBASK{8w+pi 14\#a?T+80,g2Xr}vU2PM]VIfS&PV#Կ1ֿX6q4~{+A͇u?b%!#/}E{ci/'6a>.(.j,Qǃ@›@w@@@5c@*@@x@@h@4=h@U@w@PG@4d@"@:@({@@@SA@w@ @i+@Cz@A!v@#@4Ia@v@އ@o'@jO@Uɿ@6@ܴ@B@4@Z@~@<@ .b ͩ@@ü@@6"@@O@#M@L@M@@@@@@l@@4l@@@e@dv@@O@?@@X@ ?9K ?s rz?@XL ٿy<Ͼ$n>¿1֊?r0?-q(>h>T>.n*./2y;@Gt@H=@s>P@ ?k@yR?I@| @j@x?d @?g@O? @>դ@;#?\GA.%Ao=ӑAlE>O^At@Tu.9@ꝿ2@L@۾@꺿(AA]\lkA1> AGBe*N@+t5MV>ҿh۴HA:?d7E>ye CѳvoʭKοYϿpE/>>-Wz&L?_@K?/sS׬~ HyMgڿ-wܿiP>1WM>Ke?ג&xW?OUsI wݿF࿜&;@QB@,E@/6}Y@MwY@i)@!" @>@C@@ƿlC@޿c?l~?R$?|yC?Ŀb?@-߻@V@qצ@]@_^.@Y=@A@pgi@)koqpmkI.i׿#Юx@l?Z?a,@,@3G?ѣG ?q]<3>"5?/?$?z/?9/?E>)O%-2pv !d@jJ?ӅB??_h?`Մ?vX1l?;LIOS>)N?67? J^?\Lz?fH?qD{[hBTA'ͩ@S/AA|H@`A?u@rM@ϐtt@^o=@mYr@j@`/@o@-yI@sht@f⨿Κw…u#2n-/S FӯBR @a~?|[q?k](?>?&:l @`@.@;ֿ@p 1@V=:@&m.@_>@A?T@"Ϛ??@r?Ko@uj?;4@&!?B?@KR?pM@@`@? @?6@pew?h@Z?(m@M?@/?Uǽ@Z @:@]8@؇@H@-F@f?X@?B?@z@~@?_P@HĿm@pS6@d ͍@|@Ϳʩ@h@\F@Aۊ@ڏ@#@c@(qc@`ƊXF@~q<@>.@>RiR@$1?qF@p?5y8@|?t@&V@zN@:[I@;ڐ@c@R@*k7U@N[@P3O@l9r@%8@[@ݹ?2ImO?/ц @Ur*@&t:q@#}F@U@(@;0-A403mf{ލ-F+=_H@M@io?rA.?$%@ DE@Zl@7? @h? P@?FP@j}\@?N?+?*?!$@#u+@7 @cT?*R`Y^>~JA?h@@@8@)A!8@#} A^"-@t?(@@@#2@?JAHb?kp@r?RuA\? AB?A/?C A @AL ?\@vA)AA(g6 Agc<Au/Ō}`V ڹDf|r%㻏zdG?SE?#? +;%@+@m¿'dM@/J@H@Ңu\@x@͡-u@}ɂ@@Oj`@W5)@ŕA3nA'@@@ةK@ @Pd@[@<@ 8@<@(@'(8@@{p8@@k@,?OGA"?nA`?+ AB?A?ƫAzE>Aި@A@eV@i@@٧@!@#@zҬ@L@C@'W@}.Z@-¿9@ꧺDATA},I        !!""## $%%&&''$())**++(,--..//001122,3445566378899::7;<<==>>;?@@AABBCC?DEEFFGGDHIIJJKKLLHMNNOOPPMQRRSSTTQUVVWWXXUYZZ[[\\Y]^^__``aa]bccddeebfgghhiijjkkflmmnnoolpqqrrssttuuvvwwxxyyzz{{||}}~~            !!""##$$%%&&''(())**++,,--..//00112233445566778899::;;<<==>>??@@AABBCCDDEEFFGGHHIIJJKKLLMMNNOOPPQQRRSSTTUUVVWWXXYYZZ[[\\]]^^__``aabbccddeeffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~p            !""##$$%%&&!'(())**'+,,--..+/00112233/45566778849::;;<<9=>>??@@AA=BCCDDEEFFBGHHIIJJGKLLMMNNKOPPQQRROSTTUUVVWWXXSYZZ[[\\]]^^Y_``aabbccdd_effgghheijjkkllmminooppqqrrssttnuvvwwxxyyzzu{||}}~~{            !!""#$$%%&&''((#)**++,,--..)/00112233/45566774899::;;<<==8>??@@AABB>CDDEEFFCGHHIIJJKKLLGMNNOOPPMQRRSSTTQUVVWWXXYYZZU[\\]]^^__[`aabbccdd`effgghhiiejkkllmmnnoojpqqrrssptuuvvwwtxyyzz{{||}}~~x            !!""##$$%%&''(())&*++,,--..//0011*2334455267788996:;;<<==:>??@@AABBCC>DEEFFGGHHDIJJKKLLIMNNOOPPQQMRSSTTUUVVWWRXYYZZ[[\\]]X^__``aabb^cddeeffcghhiijjgkllmmnnkoppqqrrosttuuvvswxxyyzz{{w|}}~~|            !""##$$%%!&''(())**&+,,--..//+0112233440566778859::;;<<==9>??@@AABB>CDDEEFFCGHHIIJJGKLLMMNNOOKPQQRRSSPTUUVVWWTXYYZZ[[\\X]^^__``]abbccddaeffgghhiijjkkelmmnnoopplqrrssttuuvvqwxxyyzz{{||w}~~}            !!"##$$%%&&"'(())**++,,--..'/0011/2334455267788996:;;<<==>>??:@AABBCCDD@EFFGGHHEGLOB`@ DNA1[ܖSDNANAMEP*next*prev*first*lastxyzwxminxmaxyminymax*newid*libname[24]usflagpadid*idblock*filedataname[160]totcurvecurblocktypeshowkeypostyperttotelem*dataname[32]sliderminslidermax*refkeyelemstr[32]elemsizecurvalblock*ipo*fromtotkeyslurphactkey**scripts*flagactscripttotscript*line*formatlenblen*nameflagsnlineslines*curl*sellcurcselc*undo_bufundo_posundo_len*compiledsizeseekclipstaclipendlensortho_scaledrawsizeYF_dofdistYF_apertureYF_bkhtypeYF_bkhbiasYF_bkhrotscriptlink*anim*ibuf*mipmap[10]oklastframelastqualitytpageflagtotbindxrepyreptwstatwendbindcode*repbind*packedfilelastupdateanimspeedreserved1texcomaptomaptonegblendtype*object*texprojxprojyprojzmappingofs[3]size[3]texflagcolormodelrgbkdef_varcolfacnorfacvarfacdispfacwarpfac*handle*pname*stnamesstypesvars*varstr*result*cfradata[32](*doit)()(*callback)()versionaipotypedata[16]*ima*cube[6]imat[4][4]stypenotlaycuberesdepthrecalclastsizepad1noisesizeturbulbrightcontrastrfacgfacbfacfiltersizemg_Hmg_lacunaritymg_octavesmg_offsetmg_gaindist_amountns_outscalevn_w1vn_w2vn_w3vn_w4vn_mexpvn_distmvn_coltypenoisedepthnoisetypenoisebasisnoisebasis2imaflagcropxmincropymincropxmaxcropymaxxrepeatyrepeatextendcheckerdistnablaframesoffsetsfrafie_ima*plugin*coba*envfradur[4][2]modetotexenergydistspotsizespotblendhaintatt1att2bufsizesampshadspotsizebiassoftray_sampray_sampyray_sampzray_samp_typearea_shapearea_sizearea_sizeyarea_sizeztexactshadhalostepYF_numphotonsYF_numsearchYF_phdepthYF_useqmcYF_bufsizeYF_padYF_causticblurYF_ltradiusYF_glowintYF_glowofsYF_pad3YF_glowtypeYF_pad2*mtex[10]layspecrspecgspecbmirrmirgmirbambrambbambgambemitangspectraray_mirroralpharefspeczoffsaddtranslucencyfresnel_mirfresnel_mir_ifresnel_trafresnel_tra_ifilterpad0ray_depthray_depth_traharseed1seed2mode2flarecstarclinecringchasizeflaresizesubsizeflareboostrgbselpr_typepr_backpr_lampseptexpad4pad5diff_shaderspec_shaderroughnessrefracparam[4]rmsdarkness*ramp_col*ramp_specrampin_colrampin_specrampblend_colrampblend_specramp_showpad3rampfac_colrampfac_specfrictionfhreflectfhdistxyfrictdynamodepad2YF_arYF_agYF_abYF_dscaleYF_dpwrYF_dsmpYF_presetYF_djitname[256]scale*bbi1j1k1i2j2k2selcol1selcol2quat[4]expxexpyexpzradrad2s*mat*imatelemsdisp**mattotcolloc[3]rot[3]wiresizerendersizethreshvec[3][3]alfas[3][2]h1h2f1f2f3hidevec[4]s[2]mat_nrpntsupntsvresoluresolvorderuordervflaguflagv*knotsu*knotsv*bp*beztnurb*bevobj*taperobj*textoncurve*path*keybev*orcopathlenbevresolwidthext1ext2spacemodespacinglinedistshearfsizexofyof*strfamily[24]*vfontmaxrcttotrctadrcodevartypetotvertipoextrapbitmask*tpageuv[4][2]col[4]transptileunwrapeffect*mface*dface*tface*mvert*medge*dvert*mcol*msticky*texcomesh*derived*decimated*oc*sumohandletotedgetotfacecubemapsizesmoothreshsubdivsubdivrsubsurftypev1v2v3v4punoedcodecreasedef_nrweight*dwtotweightco[3]no[3]co[2]pntswtypeutypevtypew*defdvec[3]max**obpartypepar1par2par3parsubstr[32]*pardata*parent*track*action*pose*activeconconstraintChannelsnetworkdefbasedloc[3]orig[3]dsize[3]drot[3]dquat[4]obmat[4][4]parentinv[4][4]colbitstransflagipoflagtrackflagupflagipowinscaflagscavisflagboundtypedupondupoffdupstadupendsfctimemassdampinginertiaformfactorsofttimerdampingsizefacdtdtxactcolpropsensorscontrollersactuatorsbbsize[3]dfrasactdefgameflaggameflag2softflagdummyanisotropicFriction[3]constraintsnlastripshooks*pd*soft*lifelbufporttoonedgemat[4][4]cent[3]falloff*indexartotindexcurindexactiveforcedeflectforcefieldpdef_damppdef_rdamppdef_permf_strengthf_powermaxdistpdef_sbdamppdef_sbiftpdef_sbofttotpointtotspring*bpoint*bspringnodemassgravmediafrictrklimitphysics_speedgoalspringgoalfrictmingoalmaxgoaldefgoalvertgroupinspringinfrictefrainterval**keystotpointkeymistypehorrhorghorbhorkzenrzengzenbzenkambkfastcolexposureexprangelinfaclogfacgravityactivityBoxRadiusskytypemisimiststamistdistmisthistarrstargstarbstarkstarsizestarmindiststardiststarcolnoisedofstadofenddofmindofmaxaodistaodistfacaoenergyaobiasaomodeaosampaomixaocolorphysicsEnginehemiresmaxiterdrawtypesubshootpsubshootenodelimmaxsublamppamapamielmaelmimaxnodeconvergenceradfacgammaselcolsxsy*lpFormat*lpParmscbFormatcbParmsfccTypefccHandlerdwKeyFrameEverydwQualitydwBytesPerSeconddwFlagsdwInterleaveEveryavicodecname[128]*cdParms*padcdSizeqtcodecname[128]mixratemainpad[3]*avicodecdata*qtcodecdatacfraimagesframaptoframelenblurfacedgeRedgeGedgeBfullscreenxplayyplayfreqplayattribrt1rt2stereomodedimensionspresetpad[2]maximsizexschyschxaspyaspxpartsypartssafetyborderwinposplanesimtypebufflagqualityscemoderendererocresrpad[2]alphamodedogammaosafrs_secedgeintsame_mat_reduxgausspostmulpostgammapostaddpostigammaposthuepostsatdither_intensityzminfocuszgammazsigmazblurGIqualityGIcacheGImethodGIphotonsGIdirectYF_AAYFexportxmlYF_nobumpYF_clamprgbyfpad1GIdepthGIcausdepthGIpixelspersampleGIphotoncountGImixphotonsGIphotonradiusYF_numprocsYF_raydepthYF_AApassesYF_AAsamplesGIshadowqualityGIrefinementGIpowerGIindirpowerYF_gammaYF_exposureYF_raybiasYF_AApixelsizeYF_AAthresholdbackbuf[160]pic[160]ftype[160]col[3]framename[64]*camera*world*setbase*basact*groupcursor[3]twcent[3]twmin[3]twmax[3]selectmodeproportionalprop_modeeditbutsize*ed*radioframingaudiomarkers*theDagdagisvaliddagflagszoomblendximyim*rectspacetypeblockscale*areablockhandler[8]viewmat[4][4]viewinv[4][4]persmat[4][4]persinv[4][4]winmat1[4][4]viewmat1[4][4]viewquat[4]perspview*bgpic*localvdlocalviewlayactscenelockaroundcamzoomgridgridviewnearfarmxmymxomyogridlinesviewbutgridflagmodeselectmenunrtexnrtwtypetwmodetwflagtwpadtwmat[4][4]verthormaskmin[2]max[2]minzoommaxzoomscrollkeeptotkeepaspectkeepzoomoldwinxoldwinyrowbutv2d*editipoipokeytotipopinbutofschannellockmedian[3]cursenscuractaligntabomainbmainbo*lockpointexfromshowgrouprectxrectycurymodeltypescriptblockre_aligntab[7]*filelisttotfiletitle[24]dir[160]file[80]ofssortmaxnamelencollums*libfiledataretvalmenuact(*returnfunc)()*menupoopsvisiflagtree*treestoreoutlinevisstoreflagdeps_flags*imageimanrcurtile*texttopviewlinesfont_idlheightleftshowlinenrstabnumbercurrtab_setshowsyntaxunused_paddpix_per_linetxtscrolltxtbar*scriptredrawstitle[28]fasesubfasemouse_move_redrawimafasedirslidirsli_linesdirsli_sxdirsli_eydirsli_exdirsli_himaslifileselmenuitemimasli_sximasli_eyimasli_eximasli_hdssxdssydsexdseydesxdesydeexdeeyfssxfssyfsexfseydsdhfsdhfesxfesyfeexfeeyinfsxinfsyinfexinfeydnsxdnsydnwdnhfnsxfnsyfnwfnhfole[128]dor[128]file[128]dir[128]*firstdir*firstfiletopdirtotaldirshilitetopfiletotalfilesimage_sliderslider_heightslider_spacetopimatotalimacurimaxcurimay*first_sel_ima*hilite_imatotal_selectedima_redraw*cmap*arg1outline[4]neutral[4]action[4]setting[4]setting1[4]setting2[4]num[4]textfield[4]popup[4]text[4]text_hi[4]menu_back[4]menu_item[4]menu_hilite[4]menu_text[4]menu_text_hi[4]but_drawtypeback[4]header[4]panel[4]shade1[4]shade2[4]hilite[4]grid[4]wire[4]select[4]active[4]transform[4]vertex[4]vertex_select[4]edge[4]edge_select[4]edge_seam[4]edge_facesel[4]face[4]face_select[4]face_dot[4]normal[4]vertex_sizefacedot_sizebpad[2]syntaxl[4]syntaxn[4]syntaxb[4]syntaxv[4]syntaxc[4]tuitbutstv3dtfiletipotinfotsndtacttnlatseqtimatimaseltexttoopsttimespec[4]dupflagsavetimetempdir[160]fontdir[160]renderdir[160]textudir[160]plugtexdir[160]plugseqdir[160]pythondir[160]sounddir[160]yfexportdir[160]versionsvrmlflaggameflagswheellinescrolluiflaglanguageuserprefviewzoomconsole_bufferconsole_outmixbufsizefontsizeencodingtransoptsmenuthreshold1menuthreshold2fontname[256]themesundostepscurssizetb_leftmousetb_rightmouselight[3]tw_hotspottw_flagtw_handlesizetw_sizevertbaseedgebaseareabase*scenestartxendxstartyendysizexsizeyscenenrscreennrfullmainwinwinakthandler[8]*newvvec*v1*v2panelname[64]tabname[64]ofsxofsycontrolold_ofsxold_ofsysortcounter*paneltab*v3*v4*fullwinmat[4][4]headrctwinrctheadwinwinheadertypebutspacetypewinxwinyhead_swaphead_equalwin_swapwin_equalheadbutlenheadbutofscursorspacedatauiblockspanels*curscreen*curscenedisplaymodefileflagsglobalfname[80]*se1*se2*se3nrdone*stripdataorxory*newseqstartstartofsendofsstartstillendstillmachinestartdispenddispmulhandsize*strip*curelemfacf0facf1*seq1*seq2*seq3seqbase*soundlevelpancurpos*effectdata*oldbasep*parseq*seqbasepmetastackedgeWidthangleforwardwipetypefMinifClampfBoostdDistdQualitybNoCompbuttypestaendlifetimetotpartseednormfacobfacrandfactexfacrandlifeforce[3]dampvectsizedefvec[3]mult[4]life[4]child[4]mat[4]texmapcurmultstaticstep*keysheightnarrowspeedminfactimeoffs*obpremat[4][4]postmat[4][4]vec[3]faclenoalphaoeff[2]iterlastfralimbbaseeff[3]effg[3]effn[3]memslowtotytotxxyconstrainttotdefdef_scrolllimb_scrollused*idusedelemdxdylinkotypedataold*poin*oldpoinresetdistlastval*makeyqualqual2targetName[32]toggleName[32]value[32]maxvalue[32]materialName[32]damptimeraxisdelaypropname[32]matname[32]axisflag*fromObjectsubject[32]body[32]pulsefreqtotlinks**linksinvertfreq2axisfbuttonbuttonfhathatfprecisionstr[128]*mynewinputstotslinks**slinksvalvalotime*actblendinprioritystridelengthstrideaxisreserved2reserved3sndnrmakecopycopymadepad[1]trackvolume*melinVelocity[3]localflagforceloc[3]forcerot[3]linearvelocity[3]angularvelocity[3]addedlinearvelocity[3]anotherpad[4]butstabutendminvisifacminloc[3]maxloc[3]minrot[3]maxrot[3]distributionint_arg_1int_arg_2float_arg_1float_arg_2toPropName[32]*toObjectbodyTypefilename[64]loadaniname[64]goaccellerationmaxspeedmaxrotspeedmaxtiltspeedrotdamptiltdampspeeddamp*sample*stream*newpackedfile*snd_soundpanningattenuationpitchmin_gainmax_gaindistancestreamlenloopstartloopendchannelshighpriopad[10]gaindopplerfactordopplervelocitynumsoundsblendernumsoundsgameengine*gkeypadfokeygobjectgkey*activechildbaserollhead[3]tail[3]parmat[4][4]defmat[4][4]irestmat[4][4]posemat[4][4]boneclassfiller1filler2filler3bonebasechainbaseres1res2res3chanbase*achan*pchanactnrname[30]enforceoffset[3]orient[3]roll[3]*tartoleranceiterationssubtarget[32]cacheeff[3]cachemat[4][4]lockflagfollowflagzmaxvolmodeplaneorglengthbulgeactstartactendstridelenrepeatblendoutTYPEcharucharshortushortintlongulongfloatdoublevoidLinkListBasevec2svec2ivec2fvec2dvec3ivec3fvec3dvec4ivec4fvec4drctirctfIDLibraryFileDataIpoKeyBlockKeyScriptLinkTextLineTextPackedFileCameraImageanimImBufMTexObjectTexPluginTexCBDataColorBandEnvMapLampWaveMaterialVFontVFontDataMetaElemBoundBoxMetaBallBezTripleBPointNurbCurvePathIpoCurveTFaceMeshMVertMEdgeMDeformVertMColMStickyDerivedMeshDispListMeshOcInfoMFaceMDeformWeightBoneLatticebDeformGroupLBufbActionbPosebConstraintChannelPartDeflectSoftBodyLifeObHookSBVertexBodyPointBodySpringWorldRadioBaseAviCodecDataQuicktimeCodecDataAudioDataRenderDataGameFramingTimeMarkerSceneGroupDagForestBGpicView3DSpaceLinkScrAreaView2DSpaceInfoSpaceIpoSpaceButsSpaceSeqSpaceFiledirentryBlendHandleSpaceOopsTreeStoreSpaceImageSpaceNlaSpaceTextSpaceScriptScriptSpaceTimeSpaceImaSelImaDirOneSelectableImaThemeUIThemeSpacebThemeSolidLightUserDefbScreenScrVertScrEdgePanelFileGlobalStripElemStripPluginSeqSequencebSoundMetaStackEditingWipeVarsGlowVarsEffectBuildEffPartEffParticleWaveEffDeformLimbIkaTreeStoreElemOopsbPropertybNearSensorbMouseSensorbTouchSensorbKeyboardSensorbPropertySensorbCollisionSensorbRadarSensorbRandomSensorbRaySensorbMessageSensorbSensorbControllerbJoystickSensorbExpressionContbPythonContbActuatorbAddObjectActuatorbActionActuatorbSoundActuatorbCDActuatorbEditObjectActuatorbSceneActuatorbPropertyActuatorbObjectActuatorbIpoActuatorbCameraActuatorbConstraintActuatorbGroupActuatorbRandomActuatorbMessageActuatorbGameActuatorbVisibilityActuatorFreeCamerabSamplebSoundListenerSpaceSoundGroupKeyObjectKeyGroupObjectbArmaturebPoseChannelbActionChannelSpaceActionbConstraintbKinematicConstraintbTrackToConstraintbRotateLikeConstraintbLocateLikeConstraintbActionConstraintbLockTrackConstraintbFollowPathConstraintbDistanceLimitConstraintbRotationConstraintbStretchToConstraintbActionStripTLEN  0PDtdl(XP4@l<0P<  L, @,,\(PD$h$x$T x Ht8th  8( ,@0,HhH,(lDLP@< <@Lx0848l(@0pP<`|,,,8,<48STRC                    !" #$%& '()*+,-./01234 567 89:;<=>? @!AB6 "CDEFGHIJKL(M#$N%O%PQRSTUVWXYZ[!\]^_&`abc'd(efghijklmnopqrstuvw) xyz{| }~ *nop+*,'d##CDQR(43t(#)+,-2mnopqCD&(M.(/]mnop     `a++ !"#&($%&'()*+,-./012M0341!\222356789:;<=>?@ABCD3EF435 G H(/IJlKkLMNO5 PQRSTUVWX6YQZUX777[X\]^_`abcde6f5g8'35 h H'i'j'k(9lm/I noKkLlpJqrst^_38uvwxyz{|}0~:::6f5g  &; <$35  H(m/I   =>?@A<oBCD lKkLJE[>FG?F_=[@nopAH \]6(mIII DkJ''X ''(9l35KL M    H /IKkL>JM        NOPJJQQQ' N      RYOST *R!"*U7m#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMN(&MVOPQRSTUVWXYZ[\]WWW^_`'dX a bcdefghijklY m no*pZqrs[aXtYuvwxyz{|}~A]\*!]]]^'U^# W_ V \[nZM `a #(ez{Ab2ccd'abQEj     ecccdfccdgccd*e  ! "()#$%& '(hccd)*+,e - $. / 01234567*8i ccde -*jccdk9:;<=>?@AlBCDE FGmccde  H$I / JnKLMNoccde #O$PQz{'p ccd 'e qccd RST6 UVWXYZ[\]^_r ccds`*6 tccde auQccdbcdefghijklmnopqrstuvwxyz{|}~vvww*% F x*yzzz xyyyyyyyyyyyyyy{Y|' {    }   ^~~~~ ~~ !"#$%&'()ddd~~ ~*~+},-./0123456789:;<M = > ? @ ABCDE%OFGHQI 3JK<LM 3 xy| } &N 3OPQRSTUVWXYZ(^$N[\]^_ `abcd e fg h ` ijklmnopqrstt3tuvwx*yz{|}~trw ' 3 ('In X      * /  * k0 y 0'* '  R*! ' Kuv _ uvauv '< ^' ' KL uv ' uv _y'*uv  '   !\!  ( 6ccde az{'*v ''(KkL>' _ ! "#GGGG $ %&'Kk>()*+,-./ 0 1234  Kk> _L 5(  _K 567ccde K$_8'*MMM(9 (_9:;<='>?@AB_C'>_A'>_A'>_A'>OvKA'>DA'>E'>A*;   F'>GHIJA_(KOvKLMNOENDB