| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657 |
- from ShowBaseGlobal import *
- from PandaObject import *
- from PieMenu import *
- from GuiGlobals import *
- from Tkinter import *
- from DirectGeometry import *
- from SceneGraphExplorer import *
- from tkMessageBox import showinfo
- from tkFileDialog import *
- from whrandom import *
- import Pmw
- import Floater
- import EntryScale
- import VectorWidgets
- import string
- import os
- import getopt
- import sys
- import whrandom
- import __builtin__
- visualizeZones = base.config.GetBool("visualize-zones", 0)
- # Colors used by all color menus
- DEFAULT_COLORS = [
- Vec4(1,1,1,1),
- Vec4(0.75, 0.75, 0.75, 1.0 ),
- Vec4(0.5, 0.5, 0.5, 1.0),
- Vec4(0.25, 0.25, 0.25, 1.0)]
- # The list of items with color attributes
- COLOR_TYPES = ['wall_color', 'window_color',
- 'window_awning_color', 'sign_color', 'door_color',
- 'door_awning_color', 'cornice_color',
- 'prop_color']
- # The list of dna components maintained in the style attribute dictionary
- DNA_TYPES = ['wall', 'window', 'sign', 'door', 'cornice', 'toon_landmark',
- 'prop', 'street']
- BUILDING_TYPES = ['10_10', '20', '10_20', '20_10', '10_10_10',
- '4_21', '3_22', '4_13_8', '3_13_9', '10',
- '12_8', '13_9_8'
- ]
- BUILDING_HEIGHTS = [10, 20, 25, 30]
- NUM_WALLS = [1,2,3]
- OBJECT_SNAP_POINTS = {
- 'street_5x20': [(Vec3(5.0,0,0), Vec3(0)),
- (Vec3(0), Vec3(0))],
- 'street_10x20': [(Vec3(10.0,0,0), Vec3(0)),
- (Vec3(0), Vec3(0))],
- 'street_20x20': [(Vec3(20.0,0,0), Vec3(0)),
- (Vec3(0), Vec3(0))],
- 'street_30x20': [(Vec3(30.0,0,0), Vec3(0)),
- (Vec3(0), Vec3(0))],
- 'street_40x20': [(Vec3(40.0,0,0), Vec3(0)),
- (Vec3(0), Vec3(0))],
- 'street_80x20': [(Vec3(80.0,0,0), Vec3(0)),
- (Vec3(0), Vec3(0))],
- 'street_5x40': [(Vec3(5.0,0,0), Vec3(0)),
- (Vec3(0), Vec3(0))],
- 'street_10x40': [(Vec3(10.0,0,0), Vec3(0)),
- (Vec3(0), Vec3(0))],
- 'street_20x40': [(Vec3(20.0,0,0), Vec3(0)),
- (Vec3(0), Vec3(0))],
- 'street_20x40_15': [(Vec3(20.0,0,0), Vec3(0)),
- (Vec3(0), Vec3(0))],
- 'street_30x40': [(Vec3(30.0,0,0), Vec3(0)),
- (Vec3(0), Vec3(0))],
- 'street_40x40': [(Vec3(40.0,0,0), Vec3(0)),
- (Vec3(0), Vec3(0))],
- 'street_20x60': [(Vec3(20.0,0,0), Vec3(0)),
- (Vec3(0), Vec3(0))],
- 'street_40x60': [(Vec3(40.0,0,0), Vec3(0)),
- (Vec3(0), Vec3(0))],
- 'street_40x40_15': [(Vec3(40.0,0,0), Vec3(0)),
- (Vec3(0), Vec3(0))],
- 'street_80x40': [(Vec3(80.0,0,0), Vec3(0)),
- (Vec3(0), Vec3(0))],
- 'street_angle_30': [(Vec3(0), Vec3(-30,0,0)),
- (Vec3(0), Vec3(0))],
- 'street_angle_45': [(Vec3(0), Vec3(-45,0,0)),
- (Vec3(0), Vec3(0))],
- 'street_angle_60': [(Vec3(0), Vec3(-60,0,0)),
- (Vec3(0), Vec3(0))],
- 'street_inner_corner': [(Vec3(20.0,0,0), Vec3(0)),
- (Vec3(0), Vec3(0))],
- 'street_outer_corner': [(Vec3(20.0,0,0), Vec3(0)),
- (Vec3(0), Vec3(0))],
- 'street_full_corner': [(Vec3(40.0,0,0), Vec3(0)),
- (Vec3(0), Vec3(0))],
- 'street_tight_corner': [(Vec3(40.0,0,0), Vec3(0)),
- (Vec3(0), Vec3(0))],
- 'street_tight_corner_mirror': [(Vec3(40.0,0,0), Vec3(0)),
- (Vec3(0), Vec3(0))],
- 'street_double_corner': [(Vec3(40.0,0,0), Vec3(0)),
- (Vec3(0), Vec3(0))],
- 'street_curved_corner': [(Vec3(40.0,0,0), Vec3(0)),
- (Vec3(0), Vec3(0))],
- 'street_curved_corner_15': [(Vec3(40.0,0,0), Vec3(0)),
- (Vec3(0), Vec3(0))],
- 'street_t_intersection': [(Vec3(40.0,0,0), Vec3(0)),
- (Vec3(0), Vec3(0))],
- 'street_y_intersection': [(Vec3(30.0,0,0), Vec3(0)),
- (Vec3(0), Vec3(0))],
- 'street_street_20x20': [(Vec3(20.0,0,0), Vec3(0)),
- (Vec3(0), Vec3(0))],
- 'street_street_40x40': [(Vec3(40.0,0,0), Vec3(0)),
- (Vec3(0), Vec3(0))],
- 'street_sidewalk_20x20': [(Vec3(20.0,0,0), Vec3(0)),
- (Vec3(0), Vec3(0))],
- 'street_sidewalk_40x40': [(Vec3(40.0,0,0), Vec3(0)),
- (Vec3(0), Vec3(0))],
- 'street_divided_transition': [(Vec3(40.0,0,0), Vec3(0)),
- (Vec3(0), Vec3(0))],
- 'street_divided_40x70': [(Vec3(40.0,0,0), Vec3(0)),
- (Vec3(0), Vec3(0))],
- 'street_divided_transition_15': [(Vec3(40.0,0,0), Vec3(0)),
- (Vec3(0), Vec3(0))],
- 'street_divided_40x70_15': [(Vec3(40.0,0,0), Vec3(0)),
- (Vec3(0), Vec3(0))],
- 'street_stairs_40x10x5': [(Vec3(40.0,0,0), Vec3(0)),
- (Vec3(0), Vec3(0))],
- 'street_4way_intersection': [(Vec3(40.0,0,0), Vec3(0)),
- (Vec3(0), Vec3(0))],
- 'street_incline_40x40x5': [(Vec3(40.0,0,0), Vec3(0)),
- (Vec3(0), Vec3(0))],
- 'street_square_courtyard': [(Vec3(0.0,0,0), Vec3(0)),
- (Vec3(0), Vec3(0))],
- 'street_courtyard_70': [(Vec3(0.0,0,0), Vec3(0)),
- (Vec3(0), Vec3(0))],
- 'street_courtyard_70_exit': [(Vec3(0.0,0,0), Vec3(0)),
- (Vec3(0), Vec3(0))],
- 'street_courtyard_90': [(Vec3(0.0,0,0), Vec3(0)),
- (Vec3(0), Vec3(0))],
- 'street_courtyard_90_exit': [(Vec3(0.0,0,0), Vec3(0)),
- (Vec3(0), Vec3(0))],
- 'street_courtyard_70_15': [(Vec3(0.0,0,0), Vec3(0)),
- (Vec3(0), Vec3(0))],
- 'street_courtyard_70_15_exit': [(Vec3(0.0,0,0), Vec3(0)),
- (Vec3(0), Vec3(0))],
- 'street_courtyard_90_15': [(Vec3(0.0,0,0), Vec3(0)),
- (Vec3(0), Vec3(0))],
- 'street_courtyard_90_15_exit': [(Vec3(0.0,0,0), Vec3(0)),
- (Vec3(0), Vec3(0))],
- 'street_50_transition': [(Vec3(10.0,0,0), Vec3(0)),
- (Vec3(0), Vec3(0))],
- 'street_20x50': [(Vec3(20.0,0,0), Vec3(0)),
- (Vec3(0), Vec3(0))],
- 'street_40x50': [(Vec3(40.0,0,0), Vec3(0)),
- (Vec3(0), Vec3(0))],
- 'street_keyboard_10x40': [(Vec3(10.0,0,0), Vec3(0)),
- (Vec3(0), Vec3(0))],
- 'street_keyboard_20x40': [(Vec3(20.0,0,0), Vec3(0)),
- (Vec3(0), Vec3(0))],
- 'street_keyboard_40x40': [(Vec3(40.0,0,0), Vec3(0)),
- (Vec3(0), Vec3(0))],
- }
- # NEIGHBORHOOD DATA
- # If you run this from the command line you can pass in the hood codes
- # you want to load. For example:
- # ppython LevelEditor.py DD TT BR
- #
- if sys.argv[1:]:
- try:
- opts, pargs = getopt.getopt(sys.argv[1:], '')
- hoods = pargs
- except Exception, e:
- print e
- # If you do not run from the command line, we just load all of them
- # or you can hack this up for your own purposes.
- else:
- hoodString = base.config.GetString('level-editor-hoods',
- 'TT DD BR DG DL MM')
- hoods = string.split(hoodString)
- # The list of neighborhoods to edit
- hoodIds = {'TT' : 'toontown_central',
- 'DD' : 'donalds_dock',
- 'MM' : 'minnies_melody_land',
- 'BR' : 'the_burrrgh',
- 'DG' : 'daisys_garden',
- 'DL' : 'donalds_dreamland',
- }
- # Init neighborhood arrays
- NEIGHBORHOODS = []
- NEIGHBORHOOD_CODES = {}
- for hoodId in hoods:
- if hoodIds.has_key(hoodId):
- hoodName = hoodIds[hoodId]
- NEIGHBORHOOD_CODES[hoodName] = hoodId
- NEIGHBORHOODS.append(hoodName)
- else:
- print 'Error: no hood defined for: ', hoodId
- # Load DNA
- try:
- if dnaLoaded:
- pass
- except NameError:
- print "Loading LevelEditor for hoods: ", hoods
- # DNAStorage instance for storing level DNA info
- __builtin__.DNASTORE = DNASTORE = DNAStorage()
- # Load the generic storage files
- loadDNAFile(DNASTORE, 'phase_4/dna/storage.dna', CSDefault, 1)
- loadDNAFile(DNASTORE, 'phase_5/dna/storage_town.dna', CSDefault, 1)
- # Load all the neighborhood specific storage files
- if 'TT' in hoods:
- loadDNAFile(DNASTORE, 'phase_4/dna/storage_TT.dna', CSDefault, 1)
- loadDNAFile(DNASTORE, 'phase_4/dna/storage_TT_sz.dna', CSDefault, 1)
- loadDNAFile(DNASTORE, 'phase_5/dna/storage_TT_town.dna', CSDefault, 1)
- if 'DD' in hoods:
- loadDNAFile(DNASTORE, 'phase_6/dna/storage_DD.dna', CSDefault, 1)
- loadDNAFile(DNASTORE, 'phase_6/dna/storage_DD_sz.dna', CSDefault, 1)
- loadDNAFile(DNASTORE, 'phase_6/dna/storage_DD_town.dna', CSDefault, 1)
- if 'MM' in hoods:
- loadDNAFile(DNASTORE, 'phase_6/dna/storage_MM.dna', CSDefault, 1)
- loadDNAFile(DNASTORE, 'phase_6/dna/storage_MM_sz.dna', CSDefault, 1)
- loadDNAFile(DNASTORE, 'phase_6/dna/storage_MM_town.dna', CSDefault, 1)
- if 'BR' in hoods:
- loadDNAFile(DNASTORE, 'phase_8/dna/storage_BR.dna', CSDefault, 1)
- loadDNAFile(DNASTORE, 'phase_8/dna/storage_BR_sz.dna', CSDefault, 1)
- loadDNAFile(DNASTORE, 'phase_8/dna/storage_BR_town.dna', CSDefault, 1)
- if 'DG' in hoods:
- loadDNAFile(DNASTORE, 'phase_8/dna/storage_DG.dna', CSDefault, 1)
- loadDNAFile(DNASTORE, 'phase_8/dna/storage_DG_sz.dna', CSDefault, 1)
- loadDNAFile(DNASTORE, 'phase_8/dna/storage_DG_town.dna', CSDefault, 1)
- if 'DL' in hoods:
- loadDNAFile(DNASTORE, 'phase_8/dna/storage_DL.dna', CSDefault, 1)
- loadDNAFile(DNASTORE, 'phase_8/dna/storage_DL_sz.dna', CSDefault, 1)
- loadDNAFile(DNASTORE, 'phase_8/dna/storage_DL_town.dna', CSDefault, 1)
- __builtin__.dnaLoaded = 1
- # Precompute class types for type comparisons
- DNA_CORNICE = DNACornice.getClassType()
- DNA_DOOR = DNADoor.getClassType()
- DNA_FLAT_BUILDING = DNAFlatBuilding.getClassType()
- DNA_NODE = DNANode.getClassType()
- DNA_GROUP = DNAGroup.getClassType()
- DNA_VIS_GROUP = DNAVisGroup.getClassType()
- DNA_LANDMARK_BUILDING = DNALandmarkBuilding.getClassType()
- DNA_NODE = DNANode.getClassType()
- DNA_PROP = DNAProp.getClassType()
- DNA_SIGN = DNASign.getClassType()
- DNA_SIGN_BASELINE = DNASignBaseline.getClassType()
- DNA_SIGN_TEXT = DNASignText.getClassType()
- DNA_SIGN_GRAPHIC = DNASignGraphic.getClassType()
- DNA_STREET = DNAStreet.getClassType()
- DNA_WALL = DNAWall.getClassType()
- DNA_WINDOWS = DNAWindows.getClassType()
- # DNA Utility functions (possible class extensions?)
- def DNARemoveChildren(dnaObject):
- """ Utility function to delete all the children of a DNANode """
- children = []
- for i in range(dnaObject.getNumChildren()):
- children.append(dnaObject.at(i))
- for child in children:
- dnaObject.remove(child)
- DNASTORE.removeDNAGroup(child)
- def DNARemoveChildOfClass(dnaNode, classType, childNum = 0):
- """ Remove the nth object of that type you come across """
- childCount = 0
- for i in range(dnaNode.getNumChildren()):
- child = dnaNode.at(i)
- if DNAClassEqual(child, classType):
- if childCount == childNum:
- dnaNode.remove(child)
- DNASTORE.removeDNAGroup(child)
- return 1
- childCount = childCount + 1
- # None found
- return 0
- def DNARemoveAllChildrenOfClass(dnaNode, classType):
- """ Remove the objects of that type """
- children = []
- for i in range(dnaNode.getNumChildren()):
- child=dnaNode.at(i)
- if DNAClassEqual(child, classType):
- children.append(child)
- for child in children:
- dnaNode.remove(child)
- DNASTORE.removeDNAGroup(child)
- def DNAGetChildren(dnaNode, classType=None):
- """ Return the objects of that type """
- children = []
- for i in range(dnaNode.getNumChildren()):
- child=dnaNode.at(i)
- if ((not classType)
- or DNAClassEqual(child, classType)):
- children.append(child)
- return children
- def DNAGetChild(dnaObject, type = DNA_NODE, childNum = 0):
- childCount = 0
- for i in range(dnaObject.getNumChildren()):
- child = dnaObject.at(i)
- if DNAClassEqual(child, type):
- if childCount == childNum:
- return child
- childCount = childCount + 1
- # Not found
- return None
- def DNAGetChildRecursive(dnaObject, type = DNA_NODE, childNum = 0):
- childCount = 0
- for i in range(dnaObject.getNumChildren()):
- child = dnaObject.at(i)
- if DNAClassEqual(child, type):
- if childCount == childNum:
- return child
- childCount = childCount + 1
- else:
- child = DNAGetChildRecursive(child, type, childNum-childCount)
- if child:
- return child
-
- # Not found
- return None
- def DNAGetChildOfClass(dnaNode, classType):
- for i in range(dnaNode.getNumChildren()):
- child = dnaNode.at(i)
- if DNAClassEqual(child, classType):
- return child
- # Not found
- return None
- def DNAGetClassType(dnaObject):
- return dnaObject.__class__.getClassType()
- def DNAClassEqual(dnaObject, classType):
- return DNAGetClassType(dnaObject).eq(classType)
- def DNAIsDerivedFrom(dnaObject, classType):
- return DNAGetClassType(dnaObject).isDerivedFrom(classType)
- def DNAGetWallHeights(aDNAFlatBuilding):
- """ Get a list of wall heights for a given flat building """
- # Init variables
- heightList = []
- offsetList = []
- offset = 0.0
- # Compute wall heights
- for i in range(aDNAFlatBuilding.getNumChildren()):
- child = aDNAFlatBuilding.at(i)
- if DNAClassEqual(child, DNA_WALL):
- height = child.getHeight()
- heightList.append(height)
- offsetList.append(offset)
- offset = offset + height
- return heightList, offsetList
- def DNAGetBaselineString(baseline):
- s=""
- for i in range(baseline.getNumChildren()):
- child = baseline.at(i)
- if DNAClassEqual(child, DNA_SIGN_TEXT):
- s=s+child.getLetters()
- elif DNAClassEqual(child, DNA_SIGN_GRAPHIC):
- s=s+'['+child.getCode()+']'
- return s
- def DNASetBaselineString(baseline, text):
- # TODO: Instead of removing all the text and replacing it,
- # replace each text item and then add or remove at the end.
- # This should allow inlined graphics to stay in place.
- # end of todo.
- DNARemoveAllChildrenOfClass(baseline, DNA_SIGN_TEXT);
- for i in text:
- text=DNASignText("text")
- text.setLetters(i)
- baseline.add(text)
- class LevelEditor(NodePath, PandaObject):
- """Class used to create a Toontown LevelEditor object"""
- # Init the list of callbacks:
- selectedNodePathHookHooks=[]
- deselectedNodePathHookHooks=[]
- # Primary variables:
- # DNAData: DNA object holding DNA info about level
- # DNAToplevel: Top level DNA Node, all DNA objects descend from this node
- # NPToplevel: Corresponding Node Path
- # DNAParent: Current DNA Node that new objects get added to
- # NPParent: Corresponding Node Path
- # DNAVisGroup: Current DNAVisGroup that new objects get added to
- # NPVisGroup: Corresponding Node Path
- # selectedDNARoot: DNA Node of currently selected object
- # selectedNPRoot: Corresponding Node Path
- # DNATarget: Subcomponent being modified by Pie Menu
- def __init__(self, hoods = hoods):
- # Make the level editor a node path so that you can show/hide
- # The level editor separately from loading/saving the top level node
- # Initialize superclass
- NodePath.__init__(self)
- # Become the new node path
- self.assign(hidden.attachNewNode('LevelEditor'))
- # Enable replaceSelected by default:
- self.replaceSelectedEnabled=1
-
- self.removeHookList=[self.landmarkBlockRemove]
-
- # Start block ID at 0 (it will be incremented before use (to 1)):
- self.landmarkBlock=0
-
- # Create ancillary objects
- # Style manager for keeping track of styles/colors
- self.styleManager = LevelStyleManager()
- # Load neighborhood maps
- self.createLevelMaps()
- # Marker for showing next insertion point
- self.createInsertionMarker()
- # Create level Editor Panel
- self.panel = LevelEditorPanel(self)
- # Used to store whatever edges and points are loaded in the level
- self.edgeDict = {}
- self.pointDict = {}
- self.point2edgeDict = {}
- self.cellDict = {}
- self.visitedPoints = []
- self.visitedEdges = []
-
- # Initialize LevelEditor variables DNAData, DNAToplevel, NPToplevel
- # DNAParent, NPParent, groupNum, lastAngle
- # Pass in the new toplevel group and don't clear out the old
- # toplevel group (since it doesn't exist yet)
- self.reset(fDeleteToplevel = 0, fCreateToplevel = 1)
-
- # The list of events the level editor responds to
- self.actionEvents = [
- # Node path events
- ('preRemoveNodePath', self.removeNodePathHook),
- # Actions in response to DIRECT operations
- ('DIRECT_selectedNodePath', self.selectedNodePathHook),
- ('DIRECT_deselectedNodePath', self.deselectedNodePathHook),
- ('DIRECT_manipulateObjectCleanup', self.updateSelectedPose),
- ('DIRECT_nodePathSetName', self.setName),
- ('DIRECT_activeParent', self.setActiveParent),
- ('DIRECT_reparent', self.reparent),
- ('RGBPanel_setColor', self.setColor),
- # Actions in response to Level Editor Panel operations
- ('SGE_Add Group', self.addGroup),
- ('SGE_Add Vis Group', self.addVisGroup),
- # Actions in response to Pie Menu interaction
- ('select_building_style_all', self.setBuildingStyle),
- ('select_building_type', self.setBuildingType),
- ('select_building_width', self.setBuildingWidth),
- ('select_cornice_color', self.setDNATargetColor),
- ('select_cornice_orientation', self.setDNATargetOrientation),
- ('select_cornice_texture', self.setDNATargetCode, ['cornice']),
- ('select_sign_color', self.setDNATargetColor),
- ('select_sign_orientation', self.setDNATargetOrientation),
- ('select_sign_texture', self.setDNATargetCode, ['sign']),
- ('select_baseline_style', self.panel.setSignBaselineStyle),
- ('select_door_color', self.setDNATargetColor),
- ('select_door_orientation', self.setDNATargetOrientation),
- ('select_door_texture', self.setDNATargetCode, ['door']),
- ('select_door_awning_texture', self.setDNATargetCode,
- ['door_awning']),
- ('select_door_awning_color', self.setDNATargetColor),
- ('select_window_color', self.setDNATargetColor),
- ('select_window_count', self.setWindowCount),
- ('select_window_orientation', self.setDNATargetOrientation),
- ('select_window_texture', self.setDNATargetCode, ['windows']),
- ('select_window_awning_texture', self.setDNATargetCode,
- ['window_awning']),
- ('select_window_awning_color', self.setDNATargetColor),
- ('select_wall_style', self.setWallStyle),
- ('select_wall_color', self.setDNATargetColor),
- ('select_wall_orientation', self.setDNATargetOrientation),
- ('select_wall_texture', self.setDNATargetCode, ['wall']),
- ('select_toon_landmark_texture', self.setDNATargetCode,
- ['landmark']),
- ('select_toon_landmark_door_color', self.setDNATargetColor),
- ('select_toon_landmark_door_orientation',
- self.setDNATargetOrientation),
- ('select_landmark_door_texture', self.setDNATargetCode,
- ['landmark_door']),
- ('select_street_texture', self.setDNATargetCode, ['street']),
- ('select_prop_texture', self.setDNATargetCode, ['prop']),
- ('select_prop_color', self.setDNATargetColor),
- # Hot key actions
- ('a', self.autoPositionGrid),
- ('j', self.jumpToInsertionPoint),
- ('left', self.keyboardXformSelected, ['left']),
- ('right', self.keyboardXformSelected, ['right']),
- ('up', self.keyboardXformSelected, ['up']),
- ('down', self.keyboardXformSelected, ['down']),
- ('S', self.placeSuitPoint),
- ('C', self.placeBattleCell),
- ('o', self.addToLandmarkBlock),
- ('O', self.toggleShowLandmarkBlock),
- ('%', self.pdbBreak),
- ]
-
- # Initialize state
- # Make sure direct is running
- direct.enable()
- # And only the appropriate handles are showing
- direct.widget.disableHandles(['x-ring', 'x-disc',
- 'y-ring', 'y-disc',
- 'z-post'])
- # Initialize camera
- base.cam.node().setNear(1.0)
- base.cam.node().setFar(3000)
- direct.camera.setPos(0,-10,10)
- # Initialize drive mode
- self.configureDriveModeCollisionData()
- # Init visibility variables
- self.__zoneId = None
- # Hide (disable) grid initially
- self.showGrid(0)
- # Create variable for vis groups panel
- self.vgpanel = None
- # Start off enabled
- self.enable()
- # SUIT POINTS
- # Create a sphere model to show suit points
- self.suitPointMarker = loader.loadModel('models/misc/sphere')
- self.suitPointMarker.setScale(0.25)
- # Initialize the suit points
- self.startSuitPoint = None
- self.endSuitPoint = None
- self.currentSuitPointType = DNASuitPoint.STREETPOINT
- # BATTLE CELLS
- self.battleCellMarker = loader.loadModel('models/misc/sphere')
- self.battleCellMarker.setName('battleCellMarker')
- self.battleCellMarker.setScale(1)
- self.currentBattleCellType = "20w 20l"
- # Update panel
- # Editing the first hood id on the list
- self.setEditMode(NEIGHBORHOODS[0])
- # Start of with first item in lists
- self.panel.streetSelector.selectitem(0)
- self.panel.streetSelector.invoke()
- self.panel.toonBuildingSelector.selectitem(0)
- self.panel.toonBuildingSelector.invoke()
- self.panel.landmarkBuildingSelector.selectitem(0)
- self.panel.landmarkBuildingSelector.invoke()
- self.panel.propSelector.selectitem(0)
- self.panel.propSelector.invoke()
- # Start off with 20 foot buildings
- self.panel.twentyFootButton.invoke()
- # Update scene graph explorer
- self.panel.sceneGraphExplorer.update()
- # ENABLE/DISABLE
- def enable(self):
- """ Enable level editing and show level """
- # Make sure level is visible
- self.reparentTo(direct.group)
- self.show()
- # Add all the action events
- for event in self.actionEvents:
- if len(event) == 3:
- self.accept(event[0], event[1], event[2])
- else:
- self.accept(event[0], event[1])
- # Enable mouse interaction (pie menus)
- self.enableMouse()
- # Spawn task to keep insertion marker aligned with grid
- self.spawnInsertionMarkerTask()
- def disable(self):
- """ Disable level editing and hide level """
- # Deselect everything as a precaution
- direct.deselectAll()
- # Hide the level
- self.reparentTo(hidden)
- # Ignore the hooks
- for eventPair in self.actionEvents:
- self.ignore(eventPair[0])
- # These are added outside of actionEvents list
- self.ignore('insert')
- self.ignore('space')
- # Disable Pie Menu mouse interaction
- self.disableMouse()
- # Remove insertion marker task
- taskMgr.removeTasksNamed('insertionMarkerTask')
- def reset(self, fDeleteToplevel = 1, fCreateToplevel = 1,
- fUpdateExplorer = 1):
- """
- Reset level and re-initialize main class variables
- Pass in the new top level group
- """
- # Reset path markers
- self.resetPathMarkers()
- # Reset battle cell markers
- self.resetBattleCellMarkers()
- if fDeleteToplevel:
- # First destroy existing scene-graph/DNA hierarchy
- self.deleteToplevel()
-
- # Clear DNASTORE
- DNASTORE.resetDNAGroups()
- # Reset DNA VIS Groups
- DNASTORE.resetDNAVisGroups()
- DNASTORE.resetSuitPoints()
- DNASTORE.resetBattleCells()
-
- # Create fresh DNA DATA
- self.DNAData = DNAData('level_data')
-
- # Create new toplevel node path and DNA
- if fCreateToplevel:
- self.createToplevel(DNANode('level'))
-
- # Initialize variables
- # Reset grid
- direct.grid.setPosHprScale(0,0,0,0,0,0,1,1,1)
- # The selected DNA Object/NodePath
- self.selectedDNARoot = None
- self.selectedNPRoot = None
- self.selectedSuitPoint = None
- self.lastLandmarkBuildingDNA = None
- self.showLandmarkBlockToggleGroup = None
- # Set active target (the subcomponent being modified)
- self.DNATarget = None
- self.DNATargetParent = None
- # Set count of groups added to level
- self.setGroupNum(0)
- # Heading angle of last object added to level
- self.setLastAngle(0.0)
- # Last wall and building modified using pie menus
- self.lastSign = None
- self.lastWall = None
- self.lastBuilding = None
- # Code of last selected object (for autopositionGrid)
- self.snapList = []
- # Last menu used
- self.activeMenu = None
- # For highlighting suit paths
- self.visitedPoints = []
- self.visitedEdges = []
- # Update scene graph explorer
- if fUpdateExplorer:
- self.panel.sceneGraphExplorer.update()
- def deleteToplevel(self):
- # Destory old toplevel node path and DNA
- # First the toplevel DNA
- self.DNAData.remove(self.DNAToplevel)
- if self.NPToplevel.hasArcs():
- # Then the toplevel Node Path
- self.NPToplevel.reparentTo(hidden)
- self.NPToplevel.removeNode()
- def createToplevel(self, dnaNode, nodePath = None):
- # When you create a new level, data is added to this node
- # When you load a DNA file, you replace this node with the new data
- self.DNAToplevel = dnaNode
- self.DNAData.add(self.DNAToplevel)
- if nodePath:
- # Node path given, use it
- self.NPToplevel = nodePath
- self.NPToplevel.reparentTo(self)
- else:
- # No node path given, traverse
- self.NPToplevel = self.DNAToplevel.traverse(self, DNASTORE, 1)
- # Update parent pointers
- self.DNAParent = self.DNAToplevel
- self.NPParent = self.NPToplevel
- self.VGParent = None
- # Add toplevel node path for suit points
- self.suitPointToplevel = self.NPToplevel.attachNewNode('suitPoints')
- def destroy(self):
- """ Disable level editor and destroy node path """
- self.disable()
- self.removeNode()
- self.panel.destroy()
- if self.vgpanel:
- self.vgpanel.destroy()
- def useDirectFly(self):
- """ Disable player camera controls/enable direct camera control """
- # Turn off collision traversal
- self.traversalOff()
- # Turn on collisions
- self.collisionsOff()
- # Turn on visiblity
- self.visibilityOff()
- # Reset cam
- base.camera.iPos(base.cam)
- base.cam.iPosHpr()
- # Renable mouse
- self.enableMouse()
- direct.enable()
- def useDriveMode(self):
- """ Lerp down to eye level then switch to Drive mode """
- pos = direct.camera.getPos()
- pos.setZ(4.0)
- hpr = direct.camera.getHpr()
- hpr.set(hpr[0], 0.0, 0.0)
- t = direct.camera.lerpPosHpr(pos, hpr, 1.0, blendType = 'easeInOut',
- task = 'manipulateCamera')
- # Note, if this dies an unatural death, this could screw things up
- t.uponDeath = self.switchToDriveMode
- def switchToDriveMode(self,state):
- """ Disable direct camera manipulation and enable player drive mode """
- direct.minimumConfiguration()
- direct.manipulationControl.disableManipulation()
- # Update vis data
- self.initVisibilityData()
- # Switch to drive mode
- base.useDrive()
- # Move cam up and back
- base.cam.setPos(0,-5,4)
- # And move down and forward to compensate
- base.camera.setPos(base.camera, 0, 5, -4)
- # Make sure we're where we want to be
- pos = direct.camera.getPos()
- pos.setZ(0.0)
- hpr = direct.camera.getHpr()
- hpr.set(hpr[0], 0.0, 0.0)
- # Fine tune the drive mode
- base.mouseInterface.node().setPos(pos)
- base.mouseInterface.node().setHpr(hpr)
- base.mouseInterface.node().setForwardSpeed(20.0)
- base.mouseInterface.node().setReverseSpeed(20.0)
- # Turn on collisions
- if self.panel.fColl.get():
- self.collisionsOn()
- # Turn on visiblity
- if self.panel.fVis.get():
- self.visibilityOn()
- # Turn on collision traversal
- if self.panel.fColl.get() or self.panel.fVis.get():
- self.traversalOn()
- def configureDriveModeCollisionData(self):
- """initializeCollisions(self)
- Set up the local avatar for collisions
- """
- # Set up the collision sphere
- # This is a sphere on the ground to detect barrier collisions
- self.cSphere = CollisionSphere(0.0, 0.0, 0.0, 1.5)
- self.cSphereNode = CollisionNode('cSphereNode')
- self.cSphereNode.addSolid(self.cSphere)
- self.cSphereNodePath = camera.attachNewNode(self.cSphereNode)
- self.cSphereNodePath.hide()
- self.cSphereBitMask = BitMask32.bit(0)
- self.cSphereNode.setFromCollideMask(self.cSphereBitMask)
- self.cSphereNode.setIntoCollideMask(BitMask32.allOff())
- # Set up the collison ray
- # This is a ray cast from your head down to detect floor polygons
- self.cRay = CollisionRay(0.0, 0.0, 6.0, 0.0, 0.0, -1.0)
- self.cRayNode = CollisionNode('cRayNode')
- self.cRayNode.addSolid(self.cRay)
- self.cRayNodePath = camera.attachNewNode(self.cRayNode)
- self.cRayNodePath.hide()
- self.cRayBitMask = BitMask32.bit(1)
- self.cRayNode.setFromCollideMask(self.cRayBitMask)
- self.cRayNode.setIntoCollideMask(BitMask32.allOff())
- # set up wall collision mechanism
- self.pusher = CollisionHandlerPusher()
- self.pusher.setInPattern("enter%in")
- self.pusher.setOutPattern("exit%in")
- # set up floor collision mechanism
- self.lifter = CollisionHandlerFloor()
- self.lifter.setInPattern("on-floor")
- self.lifter.setOutPattern("off-floor")
- self.floorOffset = 0.1
- self.lifter.setOffset(self.floorOffset)
- # Limit our rate-of-fall with the lifter.
- # If this is too low, we actually "fall" off steep stairs
- # and float above them as we go down. I increased this
- # from 8.0 to 16.0 to prevent this
- self.lifter.setMaxVelocity(16.0)
- # set up the collision traverser
- self.cTrav = CollisionTraverser()
- # activate the collider with the traverser and pusher
- self.pusher.addCollider(self.cSphereNode, base.drive.node())
- self.lifter.addCollider(self.cRayNode, base.drive.node())
- # A map of zone ID's to a list of nodes that are visible from
- # that zone.
- self.nodeDict = {}
- # A map of zone ID's to the particular node that corresponds
- # to that zone.
- self.zoneDict = {}
- # A list of all visible nodes
- self.nodeList = []
- # Flag for bootstrapping visibility
- self.fVisInit = 0
- def traversalOn(self):
- base.cTrav = self.cTrav
- def traversalOff(self):
- base.cTrav = 0
- def collisionsOff(self):
- self.cTrav.removeCollider(self.cSphereNode)
- def collisionsOn(self):
- self.collisionsOff()
- self.cTrav.addCollider(self.cSphereNode, self.pusher)
- def toggleCollisions(self):
- if self.panel.fColl.get():
- print 'ON'
- self.collisionsOn()
- self.traversalOn()
- else:
- self.collisionsOff()
- if (not (self.panel.fColl.get() or self.panel.fVis.get())):
- self.traversalOff()
- def initVisibilityData(self):
- # First make sure everything is shown
- self.showAllVisibles()
- # A map of zone ID's to a list of nodes that are visible from
- # that zone.
- self.nodeDict = {}
- # A map of zone ID's to the particular node that corresponds
- # to that zone.
- self.zoneDict = {}
- # A list of all visible nodes
- self.nodeList = []
- # NOTE: this should change to find the groupnodes in
- # the dna storage instead of searching through the tree
- for i in range(DNASTORE.getNumDNAVisGroups()):
- groupFullName = DNASTORE.getDNAVisGroupName(i)
- groupName = self.extractGroupName(groupFullName)
- zoneId = int(groupName)
- self.nodeDict[zoneId] = []
- self.zoneDict[zoneId] = self.NPToplevel.find("**/" + groupName)
-
- # TODO: we only need to look from the top of the hood
- # down one level to find the vis groups as an optimization
- groupNode = self.NPToplevel.find("**/" + groupFullName)
- if groupNode.isEmpty():
- print "Could not find visgroup"
- self.nodeList.append(groupNode)
- for j in range(DNASTORE.getNumVisiblesInDNAVisGroup(i)):
- visName = DNASTORE.getVisibleName(i, j)
- visNode = self.NPToplevel.find("**/" + visName)
- self.nodeDict[zoneId].append(visNode)
- # Rename the floor polys to have the same name as the
- # visgroup they are in... This makes visibility possible.
- self.renameFloorPolys(self.nodeList)
- # Init vis flag
- self.fVisInit = 1
- def extractGroupName(self, groupFullName):
- # The Idea here is that group names may have extra flags associated
- # with them that tell more information about what is special about
- # the particular vis zone. A normal vis zone might just be "13001",
- # but a special one might be "14356:safe_zone" or
- # "345:safe_zone:exit_zone"... These are hypotheticals. The main
- # idea is that there are colon separated flags after the initial
- # zone name.
- return(string.split(groupFullName, ":", 1)[0])
-
- def renameFloorPolys(self, nodeList):
- for i in nodeList:
- # Get all the collision nodes in the vis group
- collNodePaths = i.findAllMatches("**/+CollisionNode")
- numCollNodePaths = collNodePaths.getNumPaths()
- visGroupName = i.node().getName()
- for j in range(numCollNodePaths):
- collNodePath = collNodePaths.getPath(j)
- bitMask = collNodePath.node().getIntoCollideMask()
- if bitMask.getBit(1):
- # Bit 1 is the floor collision bit. This renames
- # all floor collision polys to the same name as their
- # visgroup.
- collNodePath.node().setName(visGroupName)
- def hideAllVisibles(self):
- for i in self.nodeList:
- i.hide()
- def showAllVisibles(self):
- for i in self.nodeList:
- i.show()
- i.clearColor()
- def visibilityOn(self):
- self.visibilityOff()
- # Accept event
- self.accept("on-floor", self.enterZone)
- # Add collider
- self.cTrav.addCollider(self.cRayNode, self.lifter)
- # Reset lifter
- self.lifter.clear()
- # Reset flag
- self.fVisInit = 1
- def visibilityOff(self):
- self.ignore("on-floor")
- self.cTrav.removeCollider(self.cRayNode)
- self.showAllVisibles()
- def toggleVisibility(self):
- if self.panel.fVis.get():
- self.visibilityOn()
- self.traversalOn()
- else:
- self.visibilityOff()
- if (not (self.panel.fColl.get() or self.panel.fVis.get())):
- self.traversalOff()
- def enterZone(self, newZone):
- """
- Puts the toon in the indicated zone. newZone may either be a
- CollisionEntry object as determined by a floor polygon, or an
- integer zone id. It may also be None, to indicate no zone.
- """
- # First entry into a zone, hide everything
- if self.fVisInit:
- self.hideAllVisibles()
- self.fVisInit = 0
- # Get zone id
- if isinstance(newZone, CollisionEntry):
- # Get the name of the collide node
- newZoneId = int(newZone.getIntoNode().getName())
- else:
- newZoneId = newZone
- # Ensure we have vis data
- assert(self.nodeDict)
- # Hide the old zone (if there is one)
- if self.__zoneId != None:
- for i in self.nodeDict[self.__zoneId]:
- i.hide()
- # Show the new zone
- if newZoneId != None:
- for i in self.nodeDict[newZoneId]:
- i.show()
- # Make sure we changed zones
- if newZoneId != self.__zoneId:
- if self.panel.fVisZones.get():
- # Set a color override on our zone to make it obvious what
- # zone we're in.
- if self.__zoneId != None:
- self.zoneDict[self.__zoneId].clearColor()
- if newZoneId != None:
- self.zoneDict[newZoneId].setColor(0, 0, 1, 1, 100)
- # The new zone is now old
- self.__zoneId = newZoneId
-
- def enableMouse(self):
- """ Enable Pie Menu interaction (and disable player camera control) """
- # Turn off player camera control
- base.disableMouse()
- # Handle mouse events for pie menus
- self.accept('DIRECT_mouse3',self.levelHandleMouse3)
- self.accept('DIRECT_mouse3Up',self.levelHandleMouse3Up)
- def disableMouse(self):
- """ Disable Pie Menu interaction """
- # Disable handling of mouse events
- self.ignore('DIRECT_mouse3')
- self.ignore('DIRECT_mouse3Up')
- # LEVEL OBJECT MANAGEMENT FUNCTIONS
- def findDNANode(self, nodePath):
- """ Find node path's DNA Object in DNAStorage (if any) """
- if nodePath:
- return DNASTORE.findDNAGroup(nodePath.id())
- else:
- return None
- def replaceSelected(self):
- if self.replaceSelectedEnabled:
- # Update visible geometry using new DNA
- newRoot = self.replace(self.selectedNPRoot, self.selectedDNARoot)
- # Reselect node path and respawn followSelectedNodePathTask
- direct.select(newRoot)
- def replace(self, nodePath, dnaNode):
- """ Replace a node path with the results of a DNANode traversal """
- # Find node path's parent
- parent = nodePath.getParent()
- dnaParent = dnaNode.getParent()
- # Get rid of the old node path and remove its DNA and
- # node relations from the DNA Store
- self.remove(dnaNode, nodePath)
- # Traverse the old (modified) dna to create the new node path
- newNodePath = dnaNode.traverse(parent, DNASTORE, 1)
- # Add it back to the dna parent
- dnaParent.add(dnaNode)
- # Update scene graph explorer
- # self.panel.sceneGraphExplorer.update()
- # Return new node path
- return newNodePath
- def remove(self, dnaNode, nodePath):
- """
- Delete DNA and Node relation from DNA Store and remove the node
- path from the scene graph.
- """
- # First delete DNA and node relation from the DNA Store
- if dnaNode:
- # Get DNANode's parent
- parentDNANode = dnaNode.getParent()
- if parentDNANode:
- # Remove DNANode from its parent
- parentDNANode.remove(dnaNode)
- # Delete DNA and associated Node Relations from DNA Store
- DNASTORE.removeDNAGroup(dnaNode)
- if nodePath:
- # Next deselect nodePath to avoid having bad node paths in the dict
- direct.deselect(nodePath)
- # Now you can get rid of the node path
- nodePath.removeNode()
- def removeNodePathHook(self, nodePath):
- dnaNode = self.findDNANode(nodePath)
- # Does the node path correspond to a DNA Object
- if dnaNode:
- for hook in self.removeHookList:
- hook(dnaNode, nodePath)
- # Get DNANode's parent
- parentDNANode = dnaNode.getParent()
- if parentDNANode:
- # Remove DNANode from its parent
- parentDNANode.remove(dnaNode)
- # Delete DNA and associated Node Relations from DNA Store
- DNASTORE.removeDNAGroup(dnaNode)
- else:
- pointOrCell, type = self.findPointOrCell(nodePath)
- if pointOrCell and type:
- if (type == 'suitPointMarker'):
- print 'Suit Point:', pointOrCell
- if DNASTORE.removeSuitPoint(pointOrCell):
- print "Removed from DNASTORE"
- else:
- print "Not found in DNASTORE"
- # Remove point from pointDict
- del(self.pointDict[pointOrCell])
- # Remove point from visitedPoints list
- if pointOrCell in self.visitedPoints:
- self.visitedPoints.remove(pointOrCell)
- # Update edge related dictionaries
- for edge in self.point2edgeDict[pointOrCell]:
- # Is it still in edge dict?
- oldEdgeLine = self.edgeDict.get(edge, None)
- if oldEdgeLine:
- del self.edgeDict[edge]
- oldEdgeLine.reset()
- del oldEdgeLine
- # Find other endpoints of edge and clear out
- # corresponding point2edgeDict entry
- startPoint = edge.getStartPoint()
- endPoint = edge.getEndPoint()
- if pointOrCell == startPoint:
- self.point2edgeDict[endPoint].remove(edge)
- elif pointOrCell == endPoint:
- self.point2edgeDict[startPoint].remove(edge)
- # Is it in the visited edges list?
- if edge in self.visitedEdges:
- self.visitedEdges.remove(edge)
- # Now delete point2edgeDict entry for this point
- del(self.point2edgeDict[pointOrCell])
- elif (type == 'battleCellMarker'):
- # Get parent vis group
- visGroupNP, visGroupDNA = self.findParentVisGroup(nodePath)
- print 'Battle Cell:', pointOrCell
- # Remove cell from vis group
- if visGroupNP and visGroupDNA:
- if visGroupDNA.removeBattleCell(pointOrCell):
- print "Removed from Vis Group"
- else:
- print "Not found in Vis Group"
- else:
- print "Parent Vis Group not found"
- # Remove cell from DNASTORE
- if DNASTORE.removeBattleCell(pointOrCell):
- print "Removed from DNASTORE"
- else:
- print "Not found in DNASTORE"
- # Remove cell from cellDict
- del(self.cellDict[pointOrCell])
- def reparent(self, nodePath, oldParent, newParent):
- """ Move node path (and its DNA) to active parent """
- # Does the node path correspond to a DNA Object
- dnaNode = self.findDNANode(nodePath)
- if dnaNode:
- # Find old parent DNA
- oldParentDNANode = self.findDNANode(oldParent)
- # Remove DNA from old parent
- if oldParentDNANode:
- oldParentDNANode.remove(dnaNode)
- if newParent:
- # Update active parent just to be safe
- self.setActiveParent(newParent)
- # Move DNA to new parent (if active parent set)
- if self.DNAParent != None:
- self.DNAParent.add(dnaNode)
- # It is, is it a DNA_NODE (i.e. it has pos/hpr/scale)?
- # Update pose to reflect new relationship
- if DNAIsDerivedFrom(dnaNode, DNA_NODE):
- # Update DNA
- self.updatePose(dnaNode, nodePath)
- def setActiveParent(self, nodePath = None):
- """ Set NPParent and DNAParent to node path and its DNA """
- # If we've got a valid node path
- if nodePath:
- # See if this is in the DNA database
- newDNAParent = self.findDNANode(nodePath)
- if newDNAParent:
- self.DNAParent = newDNAParent
- self.NPParent = nodePath
- else:
- print 'LevelEditor.setActiveParent: nodePath not found'
- else:
- print 'LevelEditor.setActiveParent: nodePath == None'
- def setName(self, nodePath, newName):
- """ Set name of nodePath's DNA (if it exists) """
- # Find the DNA that corresponds to this node path
- dnaNode = self.findDNANode(nodePath)
- if dnaNode:
- # If it exists, set the name of the DNA Node
- dnaNode.setName(newName)
- def updateSelectedPose(self):
- """
- Update the DNA database to reflect selected objects current positions
- """
- for selectedNode in direct.selected:
- # Is this a DNA Object in the DNASTORE database?
- dnaObject = self.findDNANode(selectedNode)
- if dnaObject:
- # It is, is it a DNA_NODE (i.e. does it have pos/hpr/scale)?
- if DNAIsDerivedFrom(dnaObject, DNA_NODE):
- # First snap selected node path to grid
- pos = selectedNode.getPos(direct.grid)
- snapPos = direct.grid.computeSnapPoint(pos)
- if self.panel.fPlaneSnap.get():
- zheight = 0
- else:
- zheight = snapPos[2]
- selectedNode.setPos(direct.grid,
- snapPos[0], snapPos[1], zheight)
- # Angle snap
- h = direct.grid.computeSnapAngle(selectedNode.getH())
- selectedNode.setH(h)
- if selectedNode == direct.selected.last:
- self.setLastAngle(h)
- # Update DNA
- self.updatePose(dnaObject, selectedNode)
- else:
- pointOrCell, type = self.findPointOrCell(selectedNode)
- if pointOrCell and type:
- # First snap selected node path to grid
- pos = selectedNode.getPos(direct.grid)
- snapPos = direct.grid.computeSnapPoint(pos)
- if self.panel.fPlaneSnap.get():
- zheight = 0
- else:
- zheight = snapPos[2]
- selectedNode.setPos(
- direct.grid,
- snapPos[0], snapPos[1], zheight)
- newPos = selectedNode.getPos(self.NPToplevel)
- # Update DNA
- pointOrCell.setPos(newPos)
- if (type == 'suitPointMarker'):
- print "Found suit point!", pointOrCell
- # Ok, now update all the lines into that node
- for edge in self.point2edgeDict[pointOrCell]:
- # Is it still in edge dict?
- oldEdgeLine = self.edgeDict.get(edge, None)
- if oldEdgeLine:
- del self.edgeDict[edge]
- oldEdgeLine.reset()
- del oldEdgeLine
- newEdgeLine = self.drawSuitEdge(
- edge, self.NPParent)
- self.edgeDict[edge] = newEdgeLine
- elif (type == 'battleCellMarker'):
- print "Found battle cell!", pointOrCell
- def updatePose(self, dnaObject, nodePath):
- """
- Update a DNA Object's pos, hpr, and scale based upon
- node path's current pose
- """
- # Set DNA's pos, hpr, and scale
- dnaObject.setPos(nodePath.getPos())
- dnaObject.setHpr(nodePath.getHpr())
- dnaObject.setScale(nodePath.getScale())
-
- # LEVEL OBJECT CREATION FUNCTIONS
- def initDNANode(self, dnaNode):
- """
- This method adds a new DNA object to the scene and adds hooks that
- allow duplicate copies of this DNA node to be added using the
- space bar. For DNAFlatBuildings, a new copy with random style is
- generated by hitting the insert key.
- """
- # First create the visible geometry for this DNA Node
- self.initNodePath(dnaNode)
- # And add hooks to insert copies of dnaNode
- self.addReplicationHooks(dnaNode)
- def addReplicationHooks(self, dnaNode):
- # Now add hook to allow placement of a new dna Node of this type
- # by simply hitting the space bar or insert key. Note, extra paramter
- # indicates new dnaNode should be a copy
- self.accept('space', self.initNodePath, [dnaNode, 'space'])
- self.accept('insert', self.initNodePath, [dnaNode, 'insert'])
- def setRandomBuildingStyle(self, dnaNode, name = 'building'):
- """ Initialize a new DNA Flat building to a random building style """
- # What is the current building type?
- buildingType = self.getCurrent('building_type')
- # If random
- if buildingType == 'random':
- # Generate height list based on current building height
- buildingHeight = self.getCurrent('building_height')
- heightList = self.getRandomHeightList(buildingHeight)
- # Convert height list to building type
- buildingType = createHeightCode(heightList)
- else:
- # Use specified height list
- heightList = map(string.atof, string.split(buildingType, '_'))
- height = calcHeight(heightList)
- # Is this a never before seen height list? If so, record it.
- try:
- attr = self.getAttribute(`height` + '_ft_wall_heights')
- if heightList not in attr.getList():
- print 'Adding new height list entry'
- attr.add(heightList)
- except KeyError:
- print 'Non standard height building'
- # See if this building type corresponds to existing style dict
- try:
- dict = self.getDict(buildingType + '_styles')
- except KeyError:
- # Nope
- dict = {}
-
- # No specific dict or empty dict, try to pick a dict
- # based on number of walls
- if not dict:
- # How many walls?
- numWalls = len(heightList)
- # Get the building_style attribute dictionary for
- # this number of walls
- dict = self.getDict(`numWalls` + '_wall_styles')
-
- if not dict:
- # Still no dict, create new random style using height list
- styleList = []
- # Build up wall styles
- for height in heightList:
- wallStyle = self.getRandomDictionaryEntry(
- self.getDict('wall_style'))
- styleList.append((wallStyle, height))
- # Create new random flat building style
- style = DNAFlatBuildingStyle(styleList = styleList)
- else:
- # Pick a style
- style = self.getRandomDictionaryEntry(dict)
-
- # Set style....finally
- self.styleManager.setDNAFlatBuildingStyle(
- dnaNode, style, width = self.getRandomWallWidth(),
- heightList = heightList, name = name)
- def getRandomHeightList(self, buildingHeight):
- # Select a list of wall heights
- heightLists = self.getList(`buildingHeight` + '_ft_wall_heights')
- l = len(heightLists)
- if l > 0:
- # If a list exists for this building height, pick randomly
- return heightLists[randint(0,l - 1)]
- else:
- # No height lists exists for this building height, generate
- chance = randint(0,100)
- if buildingHeight <= 10:
- return [buildingHeight]
- elif buildingHeight <= 20:
- if chance <= 30:
- return [20]
- elif chance <= 80:
- return [10, 10]
- else:
- return [12, 8]
- elif buildingHeight <= 25:
- if chance <= 25:
- return [3, 22]
- elif chance <= 50:
- return [4, 21]
- elif chance <= 75:
- return [3, 13, 9]
- else:
- return [4, 13, 8]
- else:
- if chance <= 20:
- return [10, 20]
- elif chance <= 35:
- return [20, 10]
- elif chance <= 75:
- return [10, 10, 10]
- else:
- return [13, 9, 8]
- def getRandomWallWidth(self):
- chance = randint(0,100)
- if chance <= 15:
- return 5.0
- elif chance <= 30:
- return 10.0
- elif chance <= 65:
- return 15.0
- elif chance <= 85:
- return 20.0
- else:
- return 25.0
- def initNodePath(self, dnaNode, hotKey = None):
- """
- Update DNA to reflect latest style choices and then generate
- new node path and add it to the scene graph
- """
- # Determine dnaNode Class Type
- nodeClass = DNAGetClassType(dnaNode)
- # Did the user hit insert or space?
- if hotKey:
- # Yes, make a new copy of the dnaNode
- dnaNode = dnaNode.__class__(dnaNode)
- # And determine dnaNode type and perform any type specific updates
- if nodeClass.eq(DNA_PROP):
- dnaNode.setCode(self.getCurrent('prop_texture'))
- elif nodeClass.eq(DNA_STREET):
- dnaNode.setCode(self.getCurrent('street_texture'))
- elif nodeClass.eq(DNA_FLAT_BUILDING):
- # If insert, pick a new random style
- if hotKey == 'insert':
- self.setRandomBuildingStyle(dnaNode, dnaNode.getName())
- # Get a new building width
- self.setCurrent('building_width',
- self.getRandomWallWidth())
- dnaNode.setWidth(self.getCurrent('building_width'))
-
- # Position it
- # First kill autoposition task so grid can jump to its final
- # destination (part of cleanup
- taskMgr.removeTasksNamed('autoPositionGrid')
- # Now find where to put node path
- if (hotKey is not None) and nodeClass.eq(DNA_PROP):
- # If its a prop and a copy, place it based upon current
- # mouse position
- hitPt = self.getGridIntersectionPoint()
- # Attach a node, so we can set pos with respect to:
- tempNode = hidden.attachNewNode('tempNode')
- # Place it:
- tempNode.setPos(direct.grid, hitPt)
- # Copy the pos to where we really want it:
- dnaNode.setPos(tempNode.getPos())
- # Clean up:
- tempNode.removeNode()
- else:
- # Place the new node path at the current grid origin
- dnaNode.setPos(direct.grid.getPos())
- # Initialize angle to match last object
- dnaNode.setHpr(Vec3(self.getLastAngle(), 0, 0))
-
- # Add the DNA to the active parent
- self.DNAParent.add(dnaNode)
- # And create the geometry
- newNodePath = dnaNode.traverse(self.NPParent, DNASTORE, 1)
- # Update scene graph explorer
- # self.panel.sceneGraphExplorer.update()
- # Reset last Code (for autoPositionGrid)
- if DNAClassEqual(dnaNode, DNA_STREET):
- self.snapList = OBJECT_SNAP_POINTS[dnaNode.getCode()]
- # Select the instance
- direct.select(newNodePath)
- # Update grid to get ready for the next object
- self.autoPositionGrid()
- def addGroup(self, nodePath):
- """ Add a new DNA Node Group to the specified Node Path """
- # Set the node path as the current parent
- direct.setActiveParent(nodePath)
- # Add a new group to the selected parent
- self.createNewGroup()
- def addVisGroup(self, nodePath):
- """ Add a new DNA Group to the specified Node Path """
- # Set the node path as the current parent
- direct.setActiveParent(nodePath)
- # Add a new group to the selected parent
- self.createNewGroup(type = 'vis')
- def createNewGroup(self, type = 'dna'):
- """ Create a new DNA Node group under the active parent """
- # Create a new DNA Node group
- if type == 'dna':
- newDNANode = DNANode('group_' + `self.getGroupNum()`)
- else:
- newDNANode = DNAVisGroup('VisGroup_' + `self.getGroupNum()`)
- # Increment group counter
- self.setGroupNum(self.getGroupNum() + 1)
- # Add new DNA Node group to the current parent DNA Object
- self.DNAParent.add(newDNANode)
- # The new Node group becomes the active parent
- self.DNAParent = newDNANode
- # Traverse it to generate the new node path as a child of NPParent
- newNodePath = self.DNAParent.traverse(self.NPParent, DNASTORE, 1)
- # Update NPParent to point to the new node path
- self.NPParent = newNodePath
- # Update scene graph explorer
- # self.panel.sceneGraphExplorer.update()
- def addFlatBuilding(self, buildingType):
- # Create new building
- newDNAFlatBuilding = DNAFlatBuilding()
- self.setRandomBuildingStyle(newDNAFlatBuilding,
- name = 'tb0:'+ buildingType + '_DNARoot')
- # Now place new building in the world
- self.initDNANode(newDNAFlatBuilding)
- def getNextLandmarkBlock(self):
- self.landmarkBlock=self.landmarkBlock+1
- return str(self.landmarkBlock)
-
- def addLandmark(self, landmarkType):
- # Record new landmark type
- self.setCurrent('toon_landmark_texture', landmarkType)
- # And create new landmark building
- block=self.getNextLandmarkBlock()
- newDNALandmarkBuilding = DNALandmarkBuilding(
- 'tb'+block+':'+landmarkType + '_DNARoot')
- newDNALandmarkBuilding.setCode(landmarkType)
- newDNALandmarkBuilding.setPos(VBase3(0))
- newDNALandmarkBuilding.setHpr(VBase3(0))
- newDNADoor = self.createDoor()
- newDNALandmarkBuilding.add(newDNADoor)
- # Now place new landmark building in the world
- self.initDNANode(newDNALandmarkBuilding)
- def addProp(self, propType):
- # Record new prop type
- self.setCurrent('prop_texture', propType)
- # And create new prop
- newDNAProp = DNAProp(propType + '_DNARoot')
- newDNAProp.setCode(propType)
- newDNAProp.setPos(VBase3(0))
- newDNAProp.setHpr(VBase3(0))
- # Now place new prop in the world
- self.initDNANode(newDNAProp)
- def addStreet(self, streetType):
- # Record new street type
- self.setCurrent('street_texture', streetType)
- # And create new street
- newDNAStreet = DNAStreet(streetType + '_DNARoot')
- newDNAStreet.setCode(streetType)
- newDNAStreet.setPos(VBase3(0))
- newDNAStreet.setHpr(VBase3(0))
- # Set street texture to neighborhood dependant texture
- newDNAStreet.setStreetTexture(
- 'street_street_' + self.neighborhoodCode + '_tex')
- newDNAStreet.setSidewalkTexture(
- 'street_sidewalk_' + self.neighborhoodCode + '_tex')
- # Now place new street in the world
- self.initDNANode(newDNAStreet)
- def createCornice(self):
- newDNACornice = DNACornice('cornice')
- newDNACornice.setCode(self.getCurrent('cornice_texture'))
- newDNACornice.setColor(self.getCurrent('cornice_color'))
- return newDNACornice
- def createDoor(self):
- if not (self.getCurrent('door_texture')):
- doorStyles = self.styleManager.attributeDictionary['door_texture'].getList()[:-1]
- defaultDoorStyle = doorStyles[randint(0, len(doorStyles) - 1)]
- self.setCurrent('door_texture', defaultDoorStyle)
- newDNADoor = DNADoor('door')
- newDNADoor.setCode(self.getCurrent('door_texture'))
- newDNADoor.setColor(self.getCurrent('door_color'))
- return newDNADoor
- def createSign(self):
- if not (self.getCurrent('sign_texture')):
- defaultSignStyle = self.styleManager.attributeDictionary['sign_texture'].getList()[0]
- self.setCurrent('sign_texture', defaultSignStyle)
- newDNASign = DNASign('sign')
- newDNASign.setCode(self.getCurrent('sign_texture'))
- newDNASign.setColor(self.getCurrent('sign_color'))
- #newDNASign.setColor(VBase4(0.0, 1.0, 0.0, 1.0))
- #newDNASign.setScale(VBase3(2.0, 1.0, 2.0))
- baseline = DNASignBaseline('baseline')
- baseline.setCode("comic")
- baseline.setColor(VBase4(0.0, 0.0, 0.0, 1.0))
- #baseline.setKern(1.0);
- #baseline.setWiggle(30.0);
- #baseline.setStumble(1.0);
- #baseline.setStomp(10.0);
- #baseline.setWidth(16.0)
- #baseline.setHeight(16.0)
- baseline.setScale(VBase3(0.7, 1.0, 0.7))
- newDNASign.add(baseline)
-
- #graphic = DNASignGraphic('graphic')
- #graphic.setCode("sign_general1")
- #graphic.setColor(VBase4(1.0, 1.0, 0.0, 0.5))
- #graphic.setScale(VBase3(.2, 1.0, .2))
- #graphic.setHpr(VBase3(0.0, 0.0, 90.0))
- #baseline.add(graphic)
-
- DNASetBaselineString(baseline, "Toon Shop")
- return newDNASign
- def createWindows(self):
- newDNAWindows = DNAWindows()
- newDNAWindows.setCode(self.getCurrent('window_texture'))
- newDNAWindows.setWindowCount(self.getCurrent('window_count'))
- newDNAWindows.setColor(self.getCurrent('window_color'))
- return newDNAWindows
- def removeCornice(self, cornice, parent):
- self.setCurrent('cornice_color', cornice.getColor())
- DNARemoveChildOfClass(parent, DNA_CORNICE)
- def removeLandmarkDoor(self, door, parent):
- self.setCurrent('door_color', door.getColor())
- DNARemoveChildOfClass(parent, DNA_DOOR)
- def removeSign(self, sign, parent):
- self.setCurrent('sign_color', sign.getColor())
- DNARemoveChildOfClass(parent, DNA_SIGN)
- def removeDoor(self, door, parent):
- self.setCurrent('door_color', door.getColor())
- DNARemoveChildOfClass(parent, DNA_DOOR)
- def removeWindows(self, windows, parent):
- # And record number of windows
- self.setCurrent('window_color', windows.getColor())
- self.setCurrent('window_count', windows.getWindowCount())
- DNARemoveChildOfClass(parent, DNA_WINDOWS)
- # LEVEL-OBJECT MODIFICATION FUNCTIONS
- def levelHandleMouse3(self):
- # Initialize dna target
- self.DNATarget = None
-
- # If nothing selected, just return
- if not self.selectedNPRoot:
- return
-
- # Next check to see if the selected object is a DNA object
- dnaObject = self.findDNANode(self.selectedNPRoot)
- # Nope, not a DNA object, just return
- if not dnaObject:
- return
-
- # Pick a menu based upon object type
- if DNAClassEqual(dnaObject, DNA_FLAT_BUILDING):
- # FLAT BUILDING OPERATIONS
- menuMode, wallNum = self.getFlatBuildingMode(dnaObject)
- # Check menuMode
- if menuMode == None:
- return
- # Find appropriate target
- wall = self.getWall(dnaObject, wallNum)
- # Record bldg/wall
- self.lastBuilding = dnaObject
- self.lastWall = wall
- if string.find(menuMode,'wall') >= 0:
- self.DNATarget = wall
- self.DNATargetParent = dnaObject
- elif string.find(menuMode,'door') >= 0:
- self.DNATarget = DNAGetChildOfClass(wall, DNA_DOOR)
- self.DNATargetParent = wall
- elif string.find(menuMode, 'window') >= 0:
- self.DNATarget = DNAGetChildOfClass(wall, DNA_WINDOWS)
- self.DNATargetParent = wall
- elif string.find(menuMode,'cornice') >= 0:
- self.DNATarget = DNAGetChildOfClass(wall, DNA_CORNICE)
- self.DNATargetParent = wall
- else:
- self.DNATarget = dnaObject
- elif DNAClassEqual(dnaObject, DNA_PROP):
- # PROP OPERATIONS
- self.DNATarget = dnaObject
- if direct.fControl:
- menuMode = 'prop_color'
- elif direct.fShift:
- menuMode = 'sign_texture'
- self.DNATarget = DNAGetChildOfClass(dnaObject, DNA_SIGN)
- self.DNATargetParent = dnaObject
- else:
- menuMode = 'prop_texture'
- elif DNAClassEqual(dnaObject, DNA_LANDMARK_BUILDING):
- # INSERT HERE
- # LANDMARK BUILDING OPERATIONS
- menuMode = self.getLandmarkBuildingMode(dnaObject)
- if string.find(menuMode, 'door') >= 0:
- self.DNATarget = DNAGetChildOfClass(dnaObject, DNA_DOOR)
- self.DNATargetParent = dnaObject
- elif string.find(menuMode, 'sign') >= 0:
- self.DNATarget = DNAGetChildOfClass(dnaObject, DNA_SIGN)
- self.DNATargetParent = dnaObject
- else:
- self.DNATarget = dnaObject
- elif DNAClassEqual(dnaObject, DNA_STREET):
- # STREET OPERATIONS
- self.DNATarget = dnaObject
- menuMode = 'street_texture'
-
- # No valid menu mode, get the hell out of here!
- if menuMode == None:
- return
-
- # Now spawn apropriate menu task if menu selected
- self.activeMenu = self.getMenu(menuMode)
- # Set initial state
- state = None
- if self.DNATarget:
- if string.find(menuMode,'texture') >= 0:
- state = self.DNATarget.getCode()
- elif string.find(menuMode, 'color') >= 0:
- state = self.DNATarget.getColor()
- self.panel.setCurrentColor(state)
- self.panel.setResetColor(state)
- elif string.find(menuMode, 'orientation') >= 0:
- state = self.DNATarget.getCode()[-2:]
- elif menuMode == 'building_width':
- state = self.DNATarget.getWidth()
- elif menuMode == 'window_count':
- state = self.DNATarget.getWindowCount()
- elif menuMode == 'building_style_all':
- # Extract the building style from the current building
- state = DNAFlatBuildingStyle(building = self.DNATarget)
- elif menuMode == 'baseline_style':
- # Extract the baseline style
- state = DNABaselineStyle(
- baseline = self.panel.currentBaselineDNA)
- elif menuMode == 'wall_style':
- # Extract the wall style from the current wall
- state = DNAWallStyle(wall = self.DNATarget)
- self.activeMenu.setInitialState(state)
-
- # Spawn active menu's task
- self.activeMenu.spawnPieMenuTask()
- def getLandmarkBuildingMode(self, dnaObject):
- # Where are we hitting the building?
- hitPt = self.getWallIntersectionPoint(self.selectedNPRoot)
- if hitPt[2] < 10.0:
- # Do door operations
- if direct.fControl:
- menuMode = 'door_color'
- elif direct.fAlt:
- menuMode = 'door_orientation'
- else:
- menuMode = 'door_texture'
- else:
- # Do sign operations
- if direct.fControl:
- menuMode = 'sign_color'
- elif direct.fAlt:
- menuMode = 'sign_orientation'
- elif direct.fShift:
- menuMode = 'baseline_style'
- else:
- menuMode = 'sign_texture'
- return menuMode
- def getFlatBuildingMode(self, dnaObject):
- # Where are we hitting the building?
- hitPt = self.getWallIntersectionPoint(self.selectedNPRoot)
- wallNum = self.computeWallNum(dnaObject, hitPt)
- if wallNum < 0:
- # Do building related operations
- """
- if direct.fShift:
- menuMode = 'building_type'
- elif direct.fAlt:
- """
- if direct.fAlt:
- menuMode = 'building_width'
- else:
- menuMode = 'building_style_all'
- else:
- # Otherwise, do wall specific operations
- # Figure out where you are hitting on the wall
- wallHeights, offsetList = DNAGetWallHeights(dnaObject)
- # Find a normalized X and Z coordinate
- xPt = hitPt[0]/dnaObject.getWidth()
- # Adjust zPt depending on what wall you are pointing at
- wallHeight = wallHeights[wallNum]
- zPt = (hitPt[2] - offsetList[wallNum])/wallHeight
- # Record current wall height
- self.setCurrent('wall_height', wallHeight)
- # Determine which zone you are pointing at
- if (zPt > 0.8):
- # Do cornice operations
- if direct.fControl:
- menuMode = 'cornice_color'
- elif direct.fAlt:
- menuMode = 'cornice_orientation'
- else:
- menuMode = 'cornice_texture'
- elif ((xPt < 0.3) or (xPt > 0.7)):
- # Do wall operations
- if direct.fControl:
- menuMode = 'wall_color'
- elif direct.fAlt:
- menuMode = 'wall_orientation'
- elif direct.fShift:
- menuMode = 'wall_texture'
- else:
- menuMode = 'wall_style'
- elif (zPt < 0.4):
- # Do door operations
- if direct.fControl:
- menuMode = 'door_color'
- elif direct.fAlt:
- menuMode = 'door_orientation'
- else:
- menuMode = 'door_texture'
- # MRM: Temp for now
- menuMode = 'window_texture'
- else:
- # Do window operations
- if direct.fControl:
- menuMode = 'window_color'
- elif direct.fAlt:
- menuMode = 'window_orientation'
- elif direct.fShift:
- menuMode = 'window_count'
- else:
- menuMode = 'window_texture'
- return menuMode, wallNum
- def levelHandleMouse3Up(self):
- if self.activeMenu:
- self.activeMenu.removePieMenuTask()
- # Update panel color if appropriate
- if self.DNATarget:
- objClass = DNAGetClassType(self.DNATarget)
- if ((objClass.eq(DNA_WALL)) or
- (objClass.eq(DNA_WINDOWS)) or
- (objClass.eq(DNA_DOOR)) or
- (objClass.eq(DNA_CORNICE)) or
- (objClass.eq(DNA_PROP))
- ):
- self.panel.setCurrentColor(self.DNATarget.getColor())
-
- def setDNATargetColor(self, color):
- if self.DNATarget:
- self.DNATarget.setColor(color)
- self.replaceSelected()
-
- def setDNATargetCode(self, type, code):
- if (self.DNATarget != None) and (code != None):
- # Update code
- self.DNATarget.setCode(code)
- elif (self.DNATarget != None) and (code == None):
- # Delete object, record pertinant properties before
- # you delete the object so you can restore them later
- # Remove object
- if (type == 'cornice'):
- self.removeCornice(self.DNATarget, self.DNATargetParent)
- elif (type == 'sign'):
- self.removeSign(self.DNATarget, self.DNATargetParent)
- elif (type == 'landmark_door'):
- self.removeLandmarkDoor(self.DNATarget, self.DNATargetParent)
- elif (type == 'door'):
- self.removeDoor(self.DNATarget, self.DNATargetParent)
- elif (type == 'windows'):
- self.removeWindows(self.DNATarget, self.DNATargetParent)
- # Clear out DNATarget
- self.DNATarget = None
- elif (self.DNATarget == None) and (code != None):
- # Add new object
- if (type == 'cornice'):
- self.DNATarget = self.createCornice()
- elif (type == 'sign'):
- self.DNATarget = self.createSign()
- elif (type == 'landmark_door'):
- self.DNATarget = self.createDoor()
- elif (type == 'door'):
- self.DNATarget = self.createDoor()
- elif (type == 'windows'):
- # Make sure window_count n.e. 0
- if self.getCurrent('window_count') == 0:
- self.setCurrent(
- 'window_count',
- self.getRandomWindowCount())
- # Now create the windows
- self.DNATarget = self.createWindows()
- if self.DNATarget:
- self.DNATargetParent.add(self.DNATarget)
- # Update visible representation
- self.replaceSelected()
-
- def setDNATargetOrientation(self, orientation):
- if (self.DNATarget != None) and (orientation != None):
- oldCode = self.DNATarget.getCode()[:-2]
- self.DNATarget.setCode(oldCode+orientation)
- self.replaceSelected()
-
- def setBuildingStyle(self, style):
- if (self.DNATarget != None) and (style != None):
- self.styleManager.setDNAFlatBuildingStyle(
- self.DNATarget, style,
- width = self.DNATarget.getWidth(),
- name = self.DNATarget.getName())
- # MRM: Need to disable dna store warning
- self.replaceSelected()
- # Re-add replication hooks so we get right kind of copy
- self.addReplicationHooks(self.DNATarget)
-
- def setBuildingType(self, type):
- print 'setBuildingType: ', `type`
-
- def setBuildingWidth(self, width):
- if self.DNATarget:
- self.DNATarget.setWidth(width)
- self.replaceSelected()
-
- def setWindowCount(self, count):
- if (self.DNATarget != None) and (count != 0):
- self.DNATarget.setWindowCount(count)
- elif (self.DNATarget != None) and (count == 0):
- # Remove windows and clear out DNATarget
- self.removeWindows(self.DNATarget, self.DNATargetParent)
- self.DNATarget = None
- elif (self.DNATarget == None) and (count != 0):
- self.DNATarget = self.createWindows()
- self.DNATargetParent.add(self.DNATarget)
- self.replaceSelected()
-
- def setWallStyle(self, style):
- if (self.DNATarget != None) and (style != None):
- self.styleManager.setDNAWallStyle(
- self.DNATarget, style,
- self.DNATarget.getHeight())
- self.replaceSelected()
-
- def setColor(self, nodePath, r,g,b,a):
- """ This is used to set color of dnaNode subparts """
- dnaNode = self.findDNANode(nodePath)
- if dnaNode:
- objClass = DNAGetClassType(dnaNode)
- if ((objClass.eq(DNA_WALL)) or
- (objClass.eq(DNA_WINDOWS)) or
- (objClass.eq(DNA_DOOR)) or
- (objClass.eq(DNA_CORNICE)) or
- (objClass.eq(DNA_PROP)) or
- (objClass.eq(DNA_SIGN)) or
- (objClass.eq(DNA_SIGN_BASELINE)) or
- (objClass.eq(DNA_SIGN_TEXT)) or
- (objClass.eq(DNA_SIGN_GRAPHIC))
- ):
- # Update dna information
- dnaNode.setColor(VBase4(r/255.0, g/255.0, b/255.0, a/255.0))
-
- # SELECTION FUNCTIONS
- def selectedNodePathHook(self, nodePath):
- """
- Hook called upon selection of a node path used to restrict
- selection to DNA Objects. Press control to select any type of
- DNA Object, with no control key pressed, hook selects only
- DNA Root objects
- """
- # Clear out old root variables
- self.selectedDNARoot = None
- self.selectedNPRoot = None
- self.selectedSuitPoint = None
- # Now process newly selected node path
- dnaParent = None
- dnaNode = self.findDNANode(nodePath)
- if direct.fControl:
- # Is the current node a DNA Object?
- if not dnaNode:
- # No it isn't, look for a parent DNA object
- dnaParent = self.findDNAParent(nodePath.getParent())
- else:
- # Is the current node a DNA Root object?
- if nodePath.getName()[-8:] != '_DNARoot':
- # No it isn't, look for a parent DNA Root object
- dnaParent = self.findDNARoot(nodePath.getParent())
- # Do we need to switch selection to a parent object?
- if dnaParent:
- # Yes, deselect currently selected node path
- direct.deselect(nodePath)
- # And select parent
- direct.select(dnaParent, direct.fShift)
- elif dnaNode:
- # We got a valid node path/DNA object, continue
- self.selectedNPRoot = nodePath
- self.selectedDNARoot = dnaNode
- # Reset last landmark
- if DNAClassEqual(dnaNode, DNA_LANDMARK_BUILDING):
- self.lastLandmarkBuildingDNA=dnaNode
- if self.showLandmarkBlockToggleGroup:
- # Toggle old highlighting off:
- self.toggleShowLandmarkBlock()
- # Toggle on the the new highlighting:
- self.toggleShowLandmarkBlock()
- # Reset last Code (for autoPositionGrid)
- if DNAClassEqual(dnaNode, DNA_STREET):
- self.snapList = OBJECT_SNAP_POINTS[dnaNode.getCode()]
- else:
- pointOrCell, type = self.findPointOrCell(nodePath)
- if pointOrCell and (type == 'suitPointMarker'):
- print "Found suit point!", pointOrCell
- self.selectedSuitPoint = pointOrCell
- if pointOrCell and (type == 'battleCellMarker'):
- print "Found battle cell!", pointOrCell
- # Let others know that something new may be selected:
- for i in self.selectedNodePathHookHooks:
- i()
- def deselectedNodePathHook(self, nodePath):
- # Clear out old root variables
- self.selectedDNARoot = None
- self.selectedNPRoot = None
- self.selectedSuitPoint = None
- # Let others know:
- for i in self.deselectedNodePathHookHooks:
- i()
- def findDNAParent(self, nodePath):
- """ Walk up a node path's ancestry looking for its DNA Root """
- # Check to see if current node is a dna object
- if self.findDNANode(nodePath):
- # Its a root!
- return nodePath
- else:
- # If reached the top: fail
- if not nodePath.hasParent():
- return 0
- else:
- # Try parent
- return self.findDNAParent(nodePath.getParent())
- def findDNARoot(self, nodePath):
- """ Walk up a node path's ancestry looking for its DNA Root """
- # Check current node's name for root marker
- if (nodePath.getName()[-8:] == '_DNARoot'):
- # Its a root!
- return nodePath
- else:
- # If reached the top: fail
- if not nodePath.hasParent():
- return None
- else:
- # Try parent
- return self.findDNARoot(nodePath.getParent())
- def findPointOrCell(self, nodePath):
- """
- Walk up a node path's ancestry to see if its a suit point marker
- or a battle cell marker
- """
- # Check current node's name for root marker
- if (nodePath.getName() == 'suitPointMarker'):
- # Its a suit point marker!
- # See if point is in pointDict
- point = self.getSuitPointFromNodePath(nodePath)
- return point, 'suitPointMarker'
- elif (nodePath.getName() == 'battleCellMarker'):
- # Its a battle cell marker
- # See if cell is in cell Dict
- cell = self.getBattleCellFromNodePath(nodePath)
- return cell, 'battleCellMarker'
- else:
- # If reached the top: fail
- if not nodePath.hasParent():
- return None, None
- else:
- # Try parent
- return self.findPointOrCell(nodePath.getParent())
- # MANIPULATION FUNCTIONS
- def keyboardRotateSelected(self, arrowDirection):
- """ Rotate selected objects using arrow keys """
- # Get snap angle
- if direct.fShift:
- oldSnapAngle = direct.grid.snapAngle
- direct.grid.setSnapAngle(1.0)
- snapAngle = direct.grid.snapAngle
- print direct.fShift, snapAngle
- # Compute new angle
- if ((arrowDirection == 'left') or (arrowDirection == 'up')):
- self.setLastAngle(self.getLastAngle() + snapAngle)
- else:
- self.setLastAngle(self.getLastAngle() - snapAngle)
-
- if (self.getLastAngle() < -180.0):
- self.setLastAngle(self.getLastAngle() + 360.0)
- elif (self.getLastAngle() > 180.0):
- self.setLastAngle(self.getLastAngle() - 360.0)
- # Move selected objects
- for selectedNode in direct.selected:
- selectedNode.setHpr(self.getLastAngle(), 0, 0)
- # Snap objects to grid and update DNA if necessary
- self.updateSelectedPose()
- if direct.fShift:
- direct.grid.setSnapAngle(oldSnapAngle)
- def keyboardTranslateSelected(self, arrowDirection):
- gridToCamera = direct.grid.getMat(direct.camera)
- camXAxis = gridToCamera.xformVec(X_AXIS)
- xxDot = camXAxis.dot(X_AXIS)
- xzDot = camXAxis.dot(Z_AXIS)
- # what is the current grid spacing?
- if direct.fShift:
- # If shift, divide grid spacing by 10.0
- oldGridSpacing = direct.grid.gridSpacing
- # Use back door to set grid spacing to avoid grid update
- direct.grid.gridSpacing = direct.grid.gridSpacing/10.0
- deltaMove = direct.grid.gridSpacing
- # Compute the specified delta
- deltaPos = Vec3(0)
- if (abs(xxDot) > abs(xzDot)):
- if (xxDot < 0.0):
- deltaMove = -deltaMove
- # Compute delta
- if (arrowDirection == 'right'):
- deltaPos.setX(deltaPos[0] + deltaMove)
- elif (arrowDirection == 'left'):
- deltaPos.setX(deltaPos[0] - deltaMove)
- elif (arrowDirection == 'up'):
- deltaPos.setY(deltaPos[1] + deltaMove)
- elif (arrowDirection == 'down'):
- deltaPos.setY(deltaPos[1] - deltaMove)
- else:
- if (xzDot < 0.0):
- deltaMove = -deltaMove
- # Compute delta
- if (arrowDirection == 'right'):
- deltaPos.setY(deltaPos[1] - deltaMove)
- elif (arrowDirection == 'left'):
- deltaPos.setY(deltaPos[1] + deltaMove)
- elif (arrowDirection == 'up'):
- deltaPos.setX(deltaPos[0] + deltaMove)
- elif (arrowDirection == 'down'):
- deltaPos.setX(deltaPos[0] - deltaMove)
- # Move selected objects
- for selectedNode in direct.selected:
- # Move it
- selectedNode.setPos(direct.grid,
- selectedNode.getPos(direct.grid) + deltaPos)
- # Snap objects to grid and update DNA if necessary
- self.updateSelectedPose()
- # Restore grid spacing
- if direct.fShift:
- # Use back door to set grid spacing to avoid grid update
- direct.grid.gridSpacing = oldGridSpacing
- def keyboardXformSelected(self, arrowDirection):
- if direct.fControl:
- self.keyboardRotateSelected(arrowDirection)
- else:
- self.keyboardTranslateSelected(arrowDirection)
- # VISIBILITY FUNCTIONS
- def editDNAVisGroups(self):
- visGroups = self.getDNAVisGroups(self.NPToplevel)
- if visGroups:
- self.vgpanel = VisGroupsEditor(self, visGroups)
- else:
- showinfo('Vis Groups Editor','No DNA Vis Groups Found!')
-
- def getDNAVisGroups(self, nodePath):
- """ Find the highest level vis groups in the scene graph """
- dnaNode = self.findDNANode(nodePath)
- if dnaNode:
- if DNAClassEqual(dnaNode, DNA_VIS_GROUP):
- return [[nodePath, dnaNode]]
- childVisGroups = []
- children = nodePath.getChildrenAsList()
- for child in children:
- childVisGroups = (childVisGroups + self.getDNAVisGroups(child))
- return childVisGroups
- def findParentVisGroup(self, nodePath):
- """ Find the containing vis group """
- dnaNode = self.findDNANode(nodePath)
- if dnaNode:
- if DNAClassEqual(dnaNode, DNA_VIS_GROUP):
- return nodePath, dnaNode
- elif nodePath.hasParent():
- return self.findParentVisGroup(nodePath.getParent())
- else:
- return None
-
- def showGrid(self,flag):
- """ toggle direct grid """
- if flag:
- direct.grid.enable()
- else:
- direct.grid.disable()
- # LEVEL MAP/MARKER FUNCTIONS
- def createLevelMaps(self):
- """
- Load up the various neighborhood maps
- """
- # For neighborhood maps
- self.levelMap = hidden.attachNewNode('level-map')
- self.activeMap = None
- self.mapDictionary = {}
- """
- for neighborhood in NEIGHBORHOODS:
- self.createMap(neighborhood)
- """
- def createMap(self, neighborhood):
- map = loader.loadModel('models/level_editor/' + neighborhood +
- '_layout')
- if map:
- map.arc().setTransition(TransparencyTransition(1))
- map.setColor(Vec4(1,1,1,.4))
- self.mapDictionary[neighborhood] = map
- # Make sure this item isn't pickable
- direct.addUnpickable(neighborhood + '_layout')
- def selectMap(self, neighborhood):
- if self.activeMap:
- self.activeMap.reparentTo(hidden)
- if self.mapDictionary.has_key(neighborhood):
- self.activeMap = self.mapDictionary[neighborhood]
- self.activeMap.reparentTo(self.levelMap)
- def toggleMapVis(self, flag):
- if flag:
- self.levelMap.reparentTo(direct.group)
- else:
- self.levelMap.reparentTo(hidden)
- def createInsertionMarker(self):
- self.insertionMarker = LineNodePath(self)
- self.insertionMarker.lineNode.setName('insertionMarker')
- self.insertionMarker.setColor(VBase4(0.785, 0.785, 0.5,1))
- self.insertionMarker.setThickness(1)
- self.insertionMarker.reset()
- self.insertionMarker.moveTo(-75,0,0)
- self.insertionMarker.drawTo(75,0,0)
- self.insertionMarker.moveTo(0,-75,0)
- self.insertionMarker.drawTo(0,75,0)
- self.insertionMarker.moveTo(0,0,-75)
- self.insertionMarker.drawTo(0,0,75)
- self.insertionMarker.create()
- def spawnInsertionMarkerTask(self):
- t = Task.Task(self.insertionMarkerTask)
- taskMgr.spawnTaskNamed(t, 'insertionMarkerTask')
- def insertionMarkerTask(self, state):
- self.insertionMarker.setPosHpr(direct.grid, 0,0,0, 0,0,0)
- # MRM: Why is this necessary?
- self.insertionMarker.setScale(1,1,1)
- return Task.cont
- # UTILITY FUNCTIONS
- def getRandomDictionaryEntry(self,dict):
- numKeys = len(dict)
- if numKeys > 0:
- keys = dict.keys()
- key = keys[randint(0,numKeys - 1)]
- return dict[key]
- else:
- return None
- def getRandomWindowCount(self):
- if ((self.lastWall != None) and (self.lastBuilding != None)):
- h = ROUND_INT(self.lastWall.getHeight())
- w = ROUND_INT(self.lastBuilding.getWidth())
- # Otherwise....
- if w == 5:
- # 5 ft walls can have 1 window
- return 1
- elif h == 10:
- # All other 10 ft high bldgs can have 1 or 2
- return randint(1,2)
- else:
- # All others can have 1 - 4
- return randint(1,4)
- else:
- return 1
- def autoPositionGrid(self):
- taskMgr.removeTasksNamed('autoPositionGrid')
- # Move grid to prepare for placement of next object
- selectedNode = direct.selected.last
- if selectedNode:
- dnaNode = self.findDNANode(selectedNode)
- if dnaNode == None:
- return
- nodeClass = DNAGetClassType(dnaNode)
- deltaPos = Point3(20,0,0)
- deltaHpr = VBase3(0)
- if nodeClass.eq(DNA_FLAT_BUILDING):
- deltaPos.setX(dnaNode.getWidth())
- elif nodeClass.eq(DNA_STREET):
- objectCode = dnaNode.getCode()
- deltas = self.getNextSnapPoint()
- deltaPos.assign(deltas[0])
- deltaHpr.assign(deltas[1])
- elif nodeClass.eq(DNA_LANDMARK_BUILDING):
- objectCode = dnaNode.getCode()
- if objectCode[-2:-1] == 'A':
- deltaPos.setX(25.0)
- elif objectCode[-2:-1] == 'B':
- deltaPos.setX(15.0)
- elif objectCode[-2:-1] == 'C':
- deltaPos.setX(20.0)
- # Position grid for placing next object
- # Eventually we need to setHpr too
- t = direct.grid.lerpPosHpr(
- deltaPos, deltaHpr, 0.25,
- other = selectedNode,
- blendType = 'easeInOut',
- task = 'autoPositionGrid')
- t.deltaPos = deltaPos
- t.deltaHpr = deltaHpr
- t.selectedNode = selectedNode
- t.uponDeath = self.autoPositionCleanup
-
- # Also move the camera
- taskMgr.removeTasksNamed('autoMoveDelay')
- handlesToCam = direct.widget.getPos(direct.camera)
- handlesToCam = handlesToCam * ( direct.dr.near/handlesToCam[1])
- if ((abs(handlesToCam[0]) > (direct.dr.nearWidth * 0.4)) or
- (abs(handlesToCam[2]) > (direct.dr.nearHeight * 0.4))):
- taskMgr.removeTasksNamed('manipulateCamera')
- direct.cameraControl.centerCamIn(0.5)
- def autoPositionCleanup(self,state):
- direct.grid.setPosHpr(state.selectedNode, state.deltaPos,
- state.deltaHpr)
- if direct.grid.getHprSnap():
- # Clean up grid angle
- direct.grid.setH(ROUND_TO(direct.grid.getH(),
- direct.grid.snapAngle))
- def getNextSnapPoint(self):
- """ Pull next pos hpr deltas off of snap list then rotate list """
- if self.snapList:
- deltas = self.snapList[0]
- # Rotate list by one
- self.snapList = self.snapList[1:] + self.snapList[:1]
- return deltas
- else:
- return (ZERO_VEC, ZERO_VEC)
- def getWallIntersectionPoint(self, selectedNode):
- """
- Return point of intersection between building's wall and line from cam
- through mouse.
- """
- # Find mouse point on near plane
- mouseX = direct.dr.mouseX
- mouseY = direct.dr.mouseY
- nearX = (math.tan(deg2Rad(direct.dr.fovH)/2.0) *
- mouseX * direct.dr.near)
- nearZ = (math.tan(deg2Rad(direct.dr.fovV)/2.0) *
- mouseY * direct.dr.near)
- # Initialize points
- mCam2Wall = direct.camera.getMat(selectedNode)
- mouseOrigin = Point3(0)
- mouseOrigin.assign(mCam2Wall.getRow3(3))
- mouseDir = Vec3(0)
- mouseDir.set(nearX, direct.dr.near, nearZ)
- mouseDir.assign(mCam2Wall.xformVec(mouseDir))
- # Calc intersection point
- return planeIntersect(mouseOrigin, mouseDir, ZERO_POINT, NEG_Y_AXIS)
- def getGridSnapIntersectionPoint(self):
- """
- Return point of intersection between ground plane and line from cam
- through mouse. Return false, if nothing selected. Snap to grid.
- """
- return direct.grid.computeSnapPoint(self.getGridIntersectionPoint())
- def getGridIntersectionPoint(self):
- """
- Return point of intersection between ground plane and line from cam
- through mouse. Return false, if nothing selected
- """
- # Find mouse point on near plane
- mouseX = direct.dr.mouseX
- mouseY = direct.dr.mouseY
- nearX = (math.tan(deg2Rad(direct.dr.fovH)/2.0) *
- mouseX * direct.dr.near)
- nearZ = (math.tan(deg2Rad(direct.dr.fovV)/2.0) *
- mouseY * direct.dr.near)
- # Initialize points
- mCam2Grid = direct.camera.getMat(direct.grid)
- mouseOrigin = Point3(0)
- mouseOrigin.assign(mCam2Grid.getRow3(3))
- mouseDir = Vec3(0)
- mouseDir.set(nearX, direct.dr.near, nearZ)
- mouseDir.assign(mCam2Grid.xformVec(mouseDir))
- # Calc intersection point
- return planeIntersect(mouseOrigin, mouseDir, ZERO_POINT, Z_AXIS)
- def jumpToInsertionPoint(self):
- """ Move selected object to insertion point """
- selectedNode = direct.selected.last
- if selectedNode:
- # Check if its a dna node
- dnaNode = self.findDNANode(selectedNode)
- if dnaNode:
- # Place the new node path at the current grid origin
- selectedNode.setPos(direct.grid,0,0,0)
- # Initialize angle to match last object
- selectedNode.setHpr(self.getLastAngle(), 0, 0)
- # Now update DNA pos and hpr to reflect final pose
- dnaNode.setPos(selectedNode.getPos())
- dnaNode.setHpr(selectedNode.getHpr())
- # Update grid to get ready for the next object
- self.autoPositionGrid()
- # STYLE/DNA FILE FUNCTIONS
- def loadSpecifiedDNAFile(self):
- f = Filename(self.styleManager.stylePathPrefix +
- '/alpha/DIRECT/LevelEditor/DNAFiles')
- path = os.path.join(f.toOsSpecific(), self.outputDir)
- if not os.path.isdir(path):
- print 'LevelEditor Warning: Invalid default DNA directory!'
- print 'Using current directory'
- path = '.'
- dnaFilename = askopenfilename(
- defaultextension = '.dna',
- filetypes = (('DNA Files', '*.dna'),('All files', '*')),
- initialdir = path,
- title = 'Load DNA File',
- parent = self.panel.component('hull'))
- if dnaFilename:
- self.loadDNAFromFile(dnaFilename)
- def saveToSpecifiedDNAFile(self):
- f = Filename(self.styleManager.stylePathPrefix +
- '/alpha/DIRECT/LevelEditor/DNAFiles')
- path = os.path.join(f.toOsSpecific(), self.outputDir)
- if not os.path.isdir(path):
- print 'LevelEditor Warning: Invalid DNA save directory!'
- print 'Using current directory'
- path = '.'
- dnaFilename = asksaveasfilename(
- defaultextension = '.dna',
- filetypes = (('DNA Files', '*.dna'),('All files', '*')),
- initialdir = path,
- title = 'Save DNA File as',
- parent = self.panel.component('hull'))
- if dnaFilename:
- self.outputDNA(dnaFilename)
- def loadDNAFromFile(self, filename):
- # Reset level, destroying existing scene/DNA hierarcy
- self.reset(fDeleteToplevel = 1, fCreateToplevel = 0,
- fUpdateExplorer = 0)
- # Now load in new file
- node = loadDNAFile(DNASTORE, filename, CSDefault, 1)
- if node.getNumParents(RenderRelation.getClassType()) == 1:
- # If the node already has a parent arc when it's loaded, we must
- # be using the level editor and we want to preserve that arc.
- newNPToplevel = NodePath()
- newNPToplevel.extendBy(node.getParent(
- RenderRelation.getClassType(), 0))
- newNPToplevel.reparentTo(hidden)
- else:
- # Otherwise, we should create a new arc for the node.
- newNPToplevel = hidden.attachNewNode(node)
- # Make sure the topmost file DNA object gets put under DNARoot
- newDNAToplevel = self.findDNANode(newNPToplevel)
-
- # reset the landmark block number:
- (self.landmarkBlock, needTraverse)=self.findHighestLandmarkBlock(
- newDNAToplevel, newNPToplevel)
- # Update toplevel variables
- if needTraverse:
- self.createToplevel(newDNAToplevel)
- else:
- self.createToplevel(newDNAToplevel, newNPToplevel)
- # Create visible representations of all the paths and battle cells
- self.createSuitPaths()
- self.hideSuitPaths()
- self.createBattleCells()
- self.hideBattleCells()
- # Set the title bar to have the filename to make it easier
- # to remember what file you are working on
- self.panel["title"] = 'Level Editor: ' + os.path.basename(filename)
- self.panel.sceneGraphExplorer.update()
- def outputDNADefaultFile(self):
- f = Filename(self.styleManager.stylePathPrefix +
- '/alpha/DIRECT/LevelEditor/DNAFiles')
- file = os.path.join(f.toOsSpecific(), self.outputDir, self.outputFile)
- self.outputDNA(file)
-
- def outputDNA(self,filename):
- print 'Saving DNA to: ', filename
- binaryFilename = Filename(filename)
- binaryFilename.setBinary()
- self.DNAData.writeDna(binaryFilename, Notify.out(),DNASTORE)
-
- def saveColor(self):
- self.appendColorToColorPaletteFile(self.panel.colorEntry.get())
- def appendColorToColorPaletteFile(self, color):
- obj = self.DNATarget
- if obj:
- classType = DNAGetClassType(obj)
- if classType.eq(DNA_WALL):
- tag = 'wall_color:'
- elif classType.eq(DNA_WINDOWS):
- tag = 'window_color:'
- elif classType.eq(DNA_DOOR):
- tag = 'door_color:'
- elif classType.eq(DNA_CORNICE):
- tag = 'cornice_color:'
- elif classType.eq(DNA_PROP):
- tag = 'prop_color:'
- else:
- return
- # Valid type, add color to file
- filename = self.neighborhood + '_colors.txt'
- fname = Filename(self.styleManager.stylePathPrefix +
- '/alpha/DIRECT/LevelEditor/StyleFiles/' +
- filename)
- f = open(fname.toOsSpecific(), 'a')
- f.write('%s Vec4(%.2f, %.2f, %.2f, 1.0)\n' %
- (tag,
- color[0]/255.0,
- color[1]/255.0,
- color[2]/255.0))
- f.close()
- def saveBaselineStyle(self):
- if self.panel.currentBaselineDNA:
- # Valid baseline, add style to file
- filename = self.neighborhood + '_baseline_styles.txt'
- fname = Filename(self.styleManager.stylePathPrefix +
- '/alpha/DIRECT/LevelEditor/StyleFiles/' +
- filename)
- f = open(fname.toOsSpecific(), 'a')
- # Add a blank line
- f.write('\n')
- # Now output style details to file
- style = DNABaselineStyle(baseline = self.panel.currentBaselineDNA)
- style.output(f)
- # Close the file
- f.close()
- def saveWallStyle(self):
- if self.lastWall:
- # Valid wall, add style to file
- filename = self.neighborhood + '_wall_styles.txt'
- fname = Filename(self.styleManager.stylePathPrefix +
- '/alpha/DIRECT/LevelEditor/StyleFiles/' +
- filename)
- f = open(fname.toOsSpecific(), 'a')
- # Add a blank line
- f.write('\n')
- # Now output style details to file
- style = DNAWallStyle(wall = self.lastWall)
- style.output(f)
- # Close the file
- f.close()
- def saveBuildingStyle(self):
- dnaObject = self.selectedDNARoot
- if dnaObject:
- if DNAClassEqual(dnaObject, DNA_FLAT_BUILDING):
- # Valid wall, add style to file
- filename = self.neighborhood + '_building_styles.txt'
- fname = Filename(self.styleManager.stylePathPrefix +
- '/alpha/DIRECT/LevelEditor/StyleFiles/' +
- filename)
- f = open(fname.toOsSpecific(), 'a')
- # Add a blank line
- f.write('\n')
- # Now output style details to file
- style = DNAFlatBuildingStyle(building = dnaObject)
- style.output(f)
- # Close the file
- f.close()
- return
- print 'Must select building before saving building style'
- # GET/SET
- # DNA Object elements
- def getWall(self, dnaFlatBuilding, wallNum):
- wallCount = 0
- for i in range(dnaFlatBuilding.getNumChildren()):
- child = dnaFlatBuilding.at(i)
- if DNAClassEqual(child, DNA_WALL):
- if wallCount == wallNum:
- return child
- wallCount = wallCount + 1
- # Not found
- return None
- def computeWallNum(self, aDNAFlatBuilding, hitPt):
- """
- Given a hitPt, return wall number if cursor is over building
- Return -1 if cursor is outside of building
- """
- xPt = hitPt[0]
- zPt = hitPt[2]
- # Left or right of building
- if ((xPt < 0) or (xPt > aDNAFlatBuilding.getWidth())):
- return -1
- # Below the building
- if zPt < 0:
- return -1
- # Above z = 0 and within wall width, check height of walls
- heightList, offsetList = DNAGetWallHeights(aDNAFlatBuilding)
- wallNum = 0
- for i in range(len(heightList)):
- # Compute top of wall segment
- top = offsetList[i] + heightList[i]
- if zPt < top:
- return wallNum
- wallNum = wallNum + 1
- return -1
- def getWindowCount(self, dnaWall):
- windowCount = 0
- for i in range(dnaWall.getNumChildren()):
- child = dnaWall.at(i)
- if DNAClassEqual(child, DNA_WINDOWS):
- windowCount = windowCount + 1
- # Not found
- return windowCount
- # Style manager edit mode
- def setEditMode(self, neighborhood):
- self.neighborhood = neighborhood
- self.neighborhoodCode = NEIGHBORHOOD_CODES[self.neighborhood]
- self.outputFile = neighborhood + '_working.dna'
- if neighborhood == 'toontown_central':
- self.outputDir = 'ToontownCentral'
- elif neighborhood == 'donalds_dock':
- self.outputDir = 'DonaldsDock'
- elif neighborhood == 'minnies_melody_land':
- self.outputDir = 'MinniesMelodyLand'
- elif neighborhood == 'the_burrrgh':
- self.outputDir = 'TheBurrrgh'
- elif neighborhood == 'daisys_garden':
- self.outputDir = 'DaisysGarden'
- elif neighborhood == 'donalds_dreamland':
- self.outputDir = 'DonaldsDreamland'
- self.panel.editMenu.selectitem(neighborhood)
- self.styleManager.setEditMode(neighborhood)
- self.panel.updateHeightList(self.getCurrent('building_height'))
- self.selectMap(neighborhood)
-
- def getEditMode(self):
- return self.styleManager.getEditMode()
-
- # Level Style Attributes
- def __getitem__(self,attribute):
- """ Return top level entry in attribute dictionary """
- return self.styleManager.attributeDictionary[attribute]
-
- def getAttribute(self, attribute):
- """ Return specified attribute for current neighborhood """
- return self.styleManager.getAttribute(attribute)
- def hasAttribute(self, attribute):
- """ Return specified attribute for current neighborhood """
- return self.styleManager.hasAttribute(attribute)
- def getCurrent(self, attribute):
- """ Return neighborhood's current selection for specified attribute """
- return self.getAttribute(attribute).getCurrent()
-
- def setCurrent(self, attribute, newCurrent):
- """ Set neighborhood's current selection for specified attribute """
- self.getAttribute(attribute).setCurrent(newCurrent, fEvent = 0)
-
- def getMenu(self, attribute):
- """ Return neighborhood's Pie Menu object for specified attribute """
- return self.getAttribute(attribute).getMenu()
-
- def getDict(self, attribute):
- """ Return neighborhood's Dictionary for specified attribute """
- return self.getAttribute(attribute).getDict()
-
- def getList(self, attribute):
- """ Return neighborhood's List for specified attribute """
- return self.getAttribute(attribute).getList()
-
- # DNA variables
- def getDNAData(self):
- return self.DNAData
-
- def getDNAToplevel(self):
- return self.DNAToplevel
-
- def getDNAParent(self):
- return self.DNAParent
-
- def getDNATarget(self):
- return self.DNATarget
-
- # Node Path variables
- def getNPToplevel(self):
- return self.NPToplevel
-
- def getNPParent(self):
- return self.NPParent
-
- # Count of groups added to level
- def setGroupNum(self,num):
- self.groupNum = num
-
- def getGroupNum(self):
- return self.groupNum
-
- # Angle of last object added to level
- def setLastAngle(self, angle):
- self.lastAngle = angle
-
- def getLastAngle(self):
- return self.lastAngle
- def drawSuitEdge(self, edge, parent):
- # Draw a line from start to end
- edgeLine = LineNodePath(parent)
- edgeLine.lineNode.setName('suitEdge')
- edgeLine.setColor(VBase4(0.0, 0.0, 0.5 ,1))
- edgeLine.setThickness(1)
- edgeLine.reset()
- # We need to draw the arrow relative to the parent, but the
- # point positions are relative to the NPToplevel. So get the
- # start and end positions relative to the parent, then draw
- # the arrow using those points
- tempNode = self.NPToplevel.attachNewNode('tempNode')
- mat = self.NPToplevel.getMat(parent)
- relStartPos = Point3(mat.xformPoint(edge.getStartPoint().getPos()))
- relEndPos = Point3(mat.xformPoint(edge.getEndPoint().getPos()))
- # Compute offset: a vector rotated 90 degrees clockwise
- offset = Vec3(relEndPos - relStartPos)
- offset.normalize()
- offset *= 0.1
- a = offset[0]
- offset.setX(offset[1])
- offset.setY(-1 * a)
- # Just to get it above the street
- offset.setZ(0.05)
- # Add offset to start and end to help differentiate lines
- relStartPos += offset
- relEndPos += offset
- # Draw arrow
- edgeLine.drawArrow(relStartPos,
- relEndPos,
- 15, # arrow angle
- 1) # arrow length
- edgeLine.create()
- # Adjust color of highlighted lines
- if edge in self.visitedEdges:
- NodePath.setColor(edgeLine,1,0,0,1)
- # Clean up:
- tempNode.removeNode()
- return edgeLine
- def drawSuitPoint(self, suitPoint, pos, type, parent):
- marker = self.suitPointMarker.copyTo(parent)
- marker.setName("suitPointMarker")
- marker.setPos(pos)
- if (type == DNASuitPoint.STREETPOINT):
- marker.setColor(0,0,0.6)
- marker.setScale(0.4)
- elif (type == DNASuitPoint.FRONTDOORPOINT):
- marker.setColor(0,0,1)
- marker.setScale(0.5)
- elif (type == DNASuitPoint.SIDEDOORPOINT):
- marker.setColor(0,0.2,0.4)
- marker.setScale(0.5)
- # Highlight if necessary
- if suitPoint in self.visitedPoints:
- marker.setColor(1,0,0,1)
- return marker
- def placeSuitPoint(self):
- v = self.getGridSnapIntersectionPoint()
- # get the absolute pos relative to the top level.
- # That is what gets stored in the point
- mat = direct.grid.getMat(self.NPToplevel)
- absPos = Point3(mat.xformPoint(v))
- print 'Suit point: ' + `absPos`
- # Store the point in the DNA. If this point is already in there,
- # it returns the existing point
- suitPoint = DNASTORE.storeSuitPoint(self.currentSuitPointType, absPos)
- if not self.pointDict.has_key(suitPoint):
- marker = self.drawSuitPoint(suitPoint,
- absPos, self.currentSuitPointType,
- self.suitPointToplevel)
- self.pointDict[suitPoint] = marker
- self.currentSuitPointIndex = suitPoint.getIndex()
- if self.startSuitPoint:
- self.endSuitPoint = suitPoint
- # Make a new dna edge
- if DNAClassEqual(self.DNAParent, DNA_VIS_GROUP):
- zoneId = self.DNAParent.getName()
- suitEdge = DNASuitEdge(
- self.startSuitPoint, self.endSuitPoint, zoneId)
- DNASTORE.storeSuitEdge(suitEdge)
- # Add edge to the current vis group so it can be written out
- self.DNAParent.addSuitEdge(suitEdge)
- # Draw a line to represent the edge
- edgeLine = self.drawSuitEdge(suitEdge, self.NPParent)
- # Store the line in a dict so we can hide/show them
- self.edgeDict[suitEdge] = edgeLine
- # Store the edge on each point in case we move the point
- # we can update the edge
- for point in [self.startSuitPoint, self.endSuitPoint]:
- if self.point2edgeDict.has_key(point):
- self.point2edgeDict[point].append(suitEdge)
- else:
- self.point2edgeDict[point] = [suitEdge]
-
- print 'Added dnaSuitEdge to zone: ' + zoneId
- else:
- print 'Error: DNAParent is not a dnaVisGroup. Did not add edge'
- # Reset
- self.startSuitPoint = None
- self.endSuitPoint = None
- else:
- # First point, store it
- self.startSuitPoint = suitPoint
- def highlightConnected(self, nodePath = None, fReversePath = 0):
- if nodePath == None:
- nodePath = direct.selected.last
- if nodePath:
- suitPoint = self.findPointOrCell(nodePath)[0]
- if suitPoint:
- self.clearPathHighlights()
- self.highlightConnectedRec(suitPoint, fReversePath)
- def highlightConnectedRec(self, suitPoint, fReversePath):
- nodePath = self.pointDict.get(suitPoint, None)
- if nodePath:
- # highlight marker
- nodePath.setColor(1,0,0,1)
- # Add point to visited points
- self.visitedPoints.append(suitPoint)
- # highlight connected edges
- for edge in self.point2edgeDict[suitPoint]:
- if ((fReversePath or (suitPoint == edge.getStartPoint())) and
- (edge not in self.visitedEdges)):
- edgeLine = self.edgeDict[edge]
- # Call node path not LineNodePath setColor
- NodePath.setColor(edgeLine,1,0,0,1)
- # Add edge to visited edges
- self.visitedEdges.append(edge)
- # Color components connected to the edge
- if fReversePath:
- startPoint = edge.getStartPoint()
- if startPoint not in self.visitedPoints:
- self.highlightConnectedRec(startPoint,
- fReversePath)
- endPoint = edge.getEndPoint()
- type = endPoint.getPointType()
- if ((endPoint not in self.visitedPoints) and
- (fReversePath or (type == DNASuitPoint.STREETPOINT))):
- self.highlightConnectedRec(endPoint,
- fReversePath)
- def clearPathHighlights(self):
- for point in self.pointDict.keys():
- type = point.getPointType()
- marker = self.pointDict[point]
- if (type == DNASuitPoint.STREETPOINT):
- marker.setColor(0,0,0.6)
- elif (type == DNASuitPoint.FRONTDOORPOINT):
- marker.setColor(0,0,1)
- elif (type == DNASuitPoint.SIDEDOORPOINT):
- marker.setColor(0,0.2,0.4)
- for edge in self.edgeDict.values():
- edge.clearColor()
- self.visitedPoints = []
- self.visitedEdges = []
- def drawBattleCell(self, cell, parent):
- marker = self.battleCellMarker.copyTo(parent)
- # Greenish
- marker.setColor(0.25,0.75,0.25,0.5)
- marker.setTransparency(1)
- marker.setPos(cell.getPos())
- # scale to radius which is width/2
- marker.setScale(cell.getWidth()/2.0,
- cell.getHeight()/2.0,
- 1)
- return marker
- def placeBattleCell(self):
- # Store the battle cell in the current vis group
- if not DNAClassEqual(self.DNAParent, DNA_VIS_GROUP):
- print 'Error: DNAParent is not a dnaVisGroup. Did not add battle cell'
- return
- v = self.getGridSnapIntersectionPoint()
- mat = direct.grid.getMat(self.NPParent)
- absPos = Point3(mat.xformPoint(v))
- if (self.currentBattleCellType == '20w 20l'):
- cell = DNABattleCell(20, 20, absPos)
- elif (self.currentBattleCellType == '20w 30l'):
- cell = DNABattleCell(20, 30, absPos)
- elif (self.currentBattleCellType == '30w 20l'):
- cell = DNABattleCell(30, 20, absPos)
- elif (self.currentBattleCellType == '30w 30l'):
- cell = DNABattleCell(30, 30, absPos)
- # Store the battle cell in the storage
- DNASTORE.storeBattleCell(cell)
- # Draw the battle cell
- marker = self.drawBattleCell(cell, self.NPParent)
- # Keep a handy dict of the visible markers
- self.cellDict[cell] = marker
- # Store the battle cell in the current vis group
- self.DNAParent.addBattleCell(cell)
- def createSuitPaths(self):
- # Points
- numPoints = DNASTORE.getNumSuitPoints()
- for i in range(numPoints):
- point = DNASTORE.getSuitPointAtIndex(i)
- marker = self.drawSuitPoint(point,
- point.getPos(), point.getPointType(),
- self.suitPointToplevel)
- self.pointDict[point] = marker
- # Edges
- visGroups = self.getDNAVisGroups(self.NPToplevel)
- for visGroup in visGroups:
- np = visGroup[0]
- dnaVisGroup = visGroup[1]
- numSuitEdges = dnaVisGroup.getNumSuitEdges()
- for i in range(numSuitEdges):
- edge = dnaVisGroup.getSuitEdge(i)
- edgeLine = self.drawSuitEdge(edge, np)
- self.edgeDict[edge] = edgeLine
- # Store the edge on each point in case we move the point
- # we can update the edge
- for point in [edge.getStartPoint(), edge.getEndPoint()]:
- if self.point2edgeDict.has_key(point):
- self.point2edgeDict[point].append(edge)
- else:
- self.point2edgeDict[point] = [edge]
- def getSuitPointFromNodePath(self, nodePath):
- """
- Given a node path, attempt to find the point,nodePath pair
- in the pointDict. If it is there, return the point. If we
- cannot find it, return None.
- TODO: a reverse lookup pointDict would speed this up quite a bit
- """
- for point, marker in self.pointDict.items():
- if marker.eq(nodePath):
- return point
- return None
- def resetPathMarkers(self):
- for edge, edgeLine in self.edgeDict.items():
- if not edgeLine.isEmpty():
- edgeLine.reset()
- edgeLine.removeNode()
- self.edgeDict = {}
- for point, marker in self.pointDict.items():
- if not marker.isEmpty():
- marker.removeNode()
- self.pointDict = {}
-
- def hideSuitPaths(self):
- for edge, edgeLine in self.edgeDict.items():
- edgeLine.hide()
- for point, marker in self.pointDict.items():
- marker.hide()
- def showSuitPaths(self):
- for edge, edgeLine in self.edgeDict.items():
- edgeLine.show()
- for point, marker in self.pointDict.items():
- marker.show()
- def createBattleCells(self):
- # Edges
- visGroups = self.getDNAVisGroups(self.NPToplevel)
- for visGroup in visGroups:
- np = visGroup[0]
- dnaVisGroup = visGroup[1]
- numCells = dnaVisGroup.getNumBattleCells()
- for i in range(numCells):
- cell = dnaVisGroup.getBattleCell(i)
- marker = self.drawBattleCell(cell, np)
- self.cellDict[cell] = marker
- def resetBattleCellMarkers(self):
- for cell, marker in self.cellDict.items():
- if not marker.isEmpty():
- marker.remove()
- self.cellDict = {}
- def hideBattleCells(self):
- for cell, marker in self.cellDict.items():
- marker.hide()
- def showBattleCells(self):
- for cell, marker in self.cellDict.items():
- marker.show()
-
- def getBattleCellFromNodePath(self, nodePath):
- """
- Given a node path, attempt to find the battle cell, nodePath pair
- in the cellDict. If it is there, return the cell. If we
- cannot find it, return None.
- TODO: a reverse lookup cellDict would speed this up quite a bit
- """
- for cell, marker in self.cellDict.items():
- if marker.eq(nodePath):
- return cell
- return None
- def toggleZoneColors(self):
- if self.panel.zoneColor.get():
- self.colorZones()
- else:
- self.clearZoneColors()
- def colorZones(self):
- # Give each zone a random color to see them better
- visGroups = self.getDNAVisGroups(self.NPToplevel)
- for visGroup in visGroups:
- np = visGroup[0]
- np.setColor(0.5 + random()/2.0,
- 0.5 + random()/2.0,
- 0.5 + random()/2.0)
- def clearZoneColors(self):
- # Clear random colors
- visGroups = self.getDNAVisGroups(self.NPToplevel)
- for visGroup in visGroups:
- np = visGroup[0]
- np.clearColor()
-
- def getBlockFromName(self, name):
- block=name[2:name.find(':')]
- return block
-
- def addToLandmarkBlock(self):
- dnaRoot=self.selectedDNARoot
- if dnaRoot and self.lastLandmarkBuildingDNA:
- if DNAClassEqual(dnaRoot, DNA_FLAT_BUILDING):
- n=dnaRoot.getName()
- n=n[n.find(':'):]
- block=self.lastLandmarkBuildingDNA.getName()
- block=block[2:block.find(':')]
- dnaRoot.setName('tb'+block+n)
- self.replaceSelected()
- # If we're highlighting the landmark blocks:
- if self.showLandmarkBlockToggleGroup:
- # then highlight this one:
- np=self.selectedNPRoot
- self.showLandmarkBlockToggleGroup.append(np)
- np.setColor(1,0,0,1)
- elif self.selectedSuitPoint and self.lastLandmarkBuildingDNA:
- block=self.lastLandmarkBuildingDNA.getName()
- block=block[2:block.find(':')]
- print ("associate point with building: " + str(block))
- self.selectedSuitPoint.setLandmarkBuildingIndex(int(block))
- def findHighestLandmarkBlock(self, dnaRoot, npRoot):
- npc=npRoot.findAllMatches("**/*:toon_landmark_*")
- highest=0
- for i in range(npc.getNumPaths()):
- path=npc.getPath(i)
- block=path.getName()
- block=int(block[2:block.find(':')])
- if (block > highest):
- highest=block
- # Make a list of flat building names, outside of the
- # recursive function:
- self.flatNames=['random'] + BUILDING_TYPES
- self.flatNames=map(lambda n: n+'_DNARoot', self.flatNames)
- # Search/recurse the dna:
- newHighest=self.convertToLandmarkBlocks(highest, dnaRoot)
- # Get rid of the list of flat building names:
- del self.flatNames
-
- needToTraverse = (highest!=newHighest)
- return (newHighest, needToTraverse)
- def convertToLandmarkBlocks(self, block, dnaRoot):
- """
- Find all the buildings without landmark blocks and
- assign them one.
- """
- for i in range(dnaRoot.getNumChildren()):
- child = dnaRoot.at(i)
- if DNAClassEqual(child, DNA_LANDMARK_BUILDING):
- # Landmark buildings:
- name=child.getName()
- if name.find('toon_landmark_')==0:
- block=block+1
- child.setName('tb'+str(block)+':'+name)
- elif DNAClassEqual(child, DNA_FLAT_BUILDING):
- # Flat buildings:
- name=child.getName()
- if (name in self.flatNames):
- child.setName('tb0:'+name)
- else:
- block = self.convertToLandmarkBlocks(block, child)
- return block
- def revertLandmarkBlock(self, block):
- """
- un-block flat buildings (set them to block zero).
- """
- npc=self.NPToplevel.findAllMatches("**/tb"+block+":*_DNARoot")
- for i in range(npc.getNumPaths()):
- nodePath=npc.getPath(i)
- name=nodePath.getName()
- if name[name.find(':'):][:15] != ':toon_landmark_':
- name='tb0'+name[name.find(':'):]
- dna=self.findDNANode(nodePath)
- dna.setName(name)
- nodePath=self.replace(nodePath, dna)
- # If we're highlighting the landmark blocks:
- if self.showLandmarkBlockToggleGroup:
- # then highlight this one:
- self.showLandmarkBlockToggleGroup.append(nodePath)
- nodePath.setColor(0,1,0,1)
-
- def landmarkBlockRemove(self, dna, nodePath):
- if dna:
- name=dna.getName()
- # Get the underscore index within the name:
- usIndex=name.find(':')
- if name[usIndex:][:15] == ':toon_landmark_':
- block=name[2:usIndex]
- self.lastLandmarkBuildingDNA=None
- self.revertLandmarkBlock(block)
-
- def toggleShowLandmarkBlock(self):
- dna=self.lastLandmarkBuildingDNA
- if dna:
- if not self.showLandmarkBlockToggleGroup:
- group=[]
- block=dna.getName()
- block=block[2:block.find(':')]
- # Get current landmark buildings:
- npc=self.NPToplevel.findAllMatches("**/tb"+block+":*_DNARoot")
- for i in range(npc.getNumPaths()):
- nodePath=npc.getPath(i)
- group.append(nodePath)
- nodePath.setColor(1,0,0,1)
- # Get block zero buildings (i.e. non-blocked):
- npc=self.NPToplevel.findAllMatches("**/tb0:*_DNARoot")
- for i in range(npc.getNumPaths()):
- nodePath=npc.getPath(i)
- group.append(nodePath)
- nodePath.setColor(0,1,0,1)
- # Get the suit point for this lb
- for point, marker in self.pointDict.items():
- if (point.getPointType() == DNASuitPoint.FRONTDOORPOINT):
- lbIndex = point.getLandmarkBuildingIndex()
- if (lbIndex == int(block)):
- marker.setColor(1,0,0,1)
- marker.setScale(1.0)
- # There should only be one, so break now
- elif (lbIndex == -1):
- # This point belongs to no block
- marker.setColor(0,1,0,1)
-
- self.showLandmarkBlockToggleGroup=group
- else:
- for i in self.showLandmarkBlockToggleGroup:
- i.clearColor()
- for point, marker in self.pointDict.items():
- if (point.getPointType() == DNASuitPoint.FRONTDOORPOINT):
- marker.setColor(0,0,1,1)
- marker.setScale(0.5)
- self.showLandmarkBlockToggleGroup=None
-
- def pdbBreak(self):
- pdb.set_trace()
- class LevelStyleManager:
- """Class which reads in style files and manages class variables"""
- def __init__(self):
- # Used to locate the alpha mount on windows (i.e. on what drive)
- self.stylePathPrefix = base.config.GetString('style-path-prefix', '')
- # The main dictionary holding all attribute objects
- self.attributeDictionary = {}
- # Create the style samples
- self.createBaselineStyleAttributes()
- self.createWallStyleAttributes()
- self.createBuildingStyleAttributes()
- self.createColorAttributes()
- self.createDNAAttributes()
- self.createMiscAttributes()
- # BASELINE STYLE FUNCTIONS
- def createBaselineStyleAttributes(self):
- """
- Create a baselineStyle entry in the attribute dictionary
- This will be a dictionary of style attributes, one per neighborhood
- """
- # First create an empty dictionary
- dict = self.attributeDictionary['baseline_style'] = {}
- # Create a attribute object for each neighborhood
- for neighborhood in NEIGHBORHOODS:
- attribute = LevelAttribute('baseline_style')
- attribute.setDict(
- # Create a baseline style dictionary for each neighborhood
- self.createBaselineStyleDictionary(neighborhood))
- # Using this dictionary, create style pie menus
- attribute.setMenu(
- self.createBaselineStyleMenu(neighborhood, attribute.getDict()))
- dict[neighborhood] = attribute
-
- def createBaselineStyleDictionary(self, neighborhood):
- """
- Create a dictionary of baseline styles for a neighborhood
- """
- filename = neighborhood + '_baseline_styles.txt'
- print 'Loading baseline styles from: ' + filename
- styleData = self.getStyleFileData(filename)
- return self.initializeBaselineStyleDictionary(styleData, neighborhood)
-
- def initializeBaselineStyleDictionary(self, styleData, neighborhood):
- """
- Fill in the baseline style dictionary with data from the style file
- """
- styleDictionary = {}
- styleCount = 0
- code = NEIGHBORHOOD_CODES[neighborhood]
- while styleData:
- l = styleData[0]
- if l == 'baselineStyle':
- # Start of new style, strip off first line then extract style
- style, styleData = self.extractBaselineStyle(styleData)
- style.name = code + '_baseline_style_' + `styleCount`
- # Store style in dictionary
- styleDictionary[style.name] = style
- styleCount = styleCount + 1
- # Move to next line
- styleData = styleData[1:]
- return styleDictionary
- def extractBaselineStyle(self, styleData):
- """
- Pull out one style from a list of style data. Will keep
- processing data until endBaselineStyle of end of data is reached.
- Returns a baseline style and remaining styleData.
- """
- # Create default style
- style = DNABaselineStyle()
- # Strip off first line
- styleData = styleData[1:]
- while styleData:
- l = styleData[0]
- if l == 'endBaselineStyle':
- # End of style found, break out of while loop
- # Note, endBaselineStyle line is *not* stripped off
- return style, styleData
- else:
- pair = map(string.strip, l.split(':'))
- if style.__dict__.has_key(pair[0]):
- pair_0 = pair[0]
- # Convert some numerical values
- if (pair_0 == 'color'
- or pair_0 == 'kern'
- or pair_0 == 'wiggle'
- or pair_0 == 'stumble'
- or pair_0 == 'stomp'
- or pair_0 == 'curve'
- or pair_0 == 'x'
- or pair_0 == 'z'
- or pair_0 == 'scaleX'
- or pair_0 == 'scaleZ'
- or pair_0 == 'roll'):
- style[pair_0] = eval(pair[1])
- else:
- style[pair_0] = pair[1]
- else:
- print 'extractBaselineStyle: Invalid Key'
- print pair[0]
- styleData = styleData[1:]
- # No end of style found, return style data as is
- return style, None
-
- def createBaselineStyleMenu(self, neighborhood, dictionary):
- """
- Create a baseline style pie menu
- """
- numItems = len(dictionary)
- newStyleMenu = hidden.attachNewNode(neighborhood + '_style_menu')
- radius = 0.7
- angle = deg2Rad(360.0/numItems)
- keys = dictionary.keys()
- keys.sort()
- styles = map(lambda x, d = dictionary: d[x], keys)
- sf = 0.1
- aspectRatio = (direct.dr.width/float(direct.dr.height))
- for i in range(numItems):
- # Get the node
- node = self.createBaselineStyleSample(styles[i])
- bounds = node.getBounds()
- center = bounds.getCenter()
- center = center * sf
- # Reposition it
- node.setPos((radius * math.cos(i * angle)) - center[0],
- 0.0,
- ((radius * aspectRatio * math.sin(i * angle)) -
- center[2]))
- # Scale it
- node.setScale(sf)
- # Add it to the styleMenu
- node.reparentTo(newStyleMenu)
- # Scale the whole shebang down by 0.5
- newStyleMenu.setScale(0.5)
- # Create and return a pie menu
- return PieMenu(newStyleMenu, styles)
-
- def createBaselineStyleSample(self, baselineStyle):
- """
- Create a style sample using the DNA info in the style
- """
- baseline = DNASignBaseline()
- # Set some example text:
- DNASetBaselineString(baseline, "Example Text")
- baselineStyle.copyTo(baseline)
- return baseline.traverse(hidden, DNASTORE, 1)
- # WALL STYLE FUNCTIONS
- def createWallStyleAttributes(self):
- """
- Create a wallStyle entry in the attribute dictionary
- This will be a dictionary of style attributes, one per neighborhood
- """
- # First create an empty dictionary
- dict = self.attributeDictionary['wall_style'] = {}
- # Create a attribute object for each neighborhood
- for neighborhood in NEIGHBORHOODS:
- attribute = LevelAttribute('wall_style')
- attribute.setDict(
- # Create a wall style dictionary for each neighborhood
- self.createWallStyleDictionary(neighborhood))
- # Using this dictionary, create color pie menus
- attribute.setMenu(
- self.createWallStyleMenu(neighborhood, attribute.getDict()))
- dict[neighborhood] = attribute
-
- def createWallStyleDictionary(self, neighborhood):
- """
- Create a dictionary of wall styles for a neighborhood
- """
- filename = neighborhood + '_wall_styles.txt'
- print 'Loading wall styles from: ' + filename
- styleData = self.getStyleFileData(filename)
- return self.initializeWallStyleDictionary(styleData, neighborhood)
-
- def initializeWallStyleDictionary(self, styleData, neighborhood):
- """
- Fill in the wall style dictionary with data from the style file
- """
- styleDictionary = {}
- styleCount = 0
- code = NEIGHBORHOOD_CODES[neighborhood]
- while styleData:
- l = styleData[0]
- if l == 'wallStyle':
- # Start of new style, strip off first line then extract style
- style, styleData = self.extractWallStyle(styleData)
- style.name = code + '_wall_style_' + `styleCount`
- # Store style in dictionary
- styleDictionary[style.name] = style
- styleCount = styleCount + 1
- # Move to next line
- styleData = styleData[1:]
- return styleDictionary
- def extractWallStyle(self, styleData):
- """
- Pull out one style from a list of style data. Will keep
- processing data until endWallStyle of end of data is reached.
- Returns a wall style and remaining styleData.
- """
- # Create default style
- style = DNAWallStyle()
- # Strip off first line
- styleData = styleData[1:]
- while styleData:
- l = styleData[0]
- if l == 'endWallStyle':
- # End of style found, break out of while loop
- # Note, endWallStyle line is *not* stripped off
- return style, styleData
- else:
- pair = map(string.strip, l.split(':'))
- if style.__dict__.has_key(pair[0]):
- # Convert colors and count strings to numerical values
- if ((string.find(pair[0],'_color') >= 0) or
- (string.find(pair[0],'_count') >= 0)):
- style[pair[0]] = eval(pair[1])
- else:
- style[pair[0]] = pair[1]
- else:
- print 'getStyleDictionaryFromStyleData: Invalid Key'
- print pair[0]
- styleData = styleData[1:]
- # No end of style found, return style data as is
- return style, None
-
- def createWallStyleMenu(self, neighborhood, dictionary):
- """
- Create a wall style pie menu
- """
- numItems = len(dictionary)
- newStyleMenu = hidden.attachNewNode(neighborhood + '_style_menu')
- radius = 0.7
- angle = deg2Rad(360.0/numItems)
- keys = dictionary.keys()
- keys.sort()
- styles = map(lambda x, d = dictionary: d[x], keys)
- sf = 0.03
- aspectRatio = (direct.dr.width/float(direct.dr.height))
- for i in range(numItems):
- # Get the node
- node = self.createWallStyleSample(styles[i])
- bounds = node.getBounds()
- center = bounds.getCenter()
- center = center * sf
- # Reposition it
- node.setPos((radius * math.cos(i * angle)) - center[0],
- 0.0,
- ((radius * aspectRatio * math.sin(i * angle)) -
- center[2]))
- # Scale it
- node.setScale(sf)
- # Add it to the styleMenu
- node.reparentTo(newStyleMenu)
- # Scale the whole shebang down by 0.5
- newStyleMenu.setScale(0.5)
- # Create and return a pie menu
- return PieMenu(newStyleMenu, styles)
-
- def createWallStyleSample(self, wallStyle):
- """
- Create a style sample using the DNA info in the style
- """
- bldg = DNAFlatBuilding()
- bldgStyle = DNAFlatBuildingStyle(styleList = [(wallStyle, 10.0)])
- self.setDNAFlatBuildingStyle(bldg, bldgStyle, width = 12.0,
- name = 'wall_style_sample')
- return bldg.traverse(hidden, DNASTORE, 1)
-
- # BUILDING STYLE FUNCTIONS
- def createBuildingStyleAttributes(self):
- """
- Create a buildingStyle entry in the attribute dictionary
- This will be a dictionary of style attributes, one per neighborhood
- This information is sorted and stored by num walls, building height,
- and building type (e.g. 10_20, or 10_10_10).
- """
- # First create an attribute which holds one dictionary per
- # neighborhood which stores all of the styles for each neighborhood.
- styleDict = self.attributeDictionary['building_style_all'] = {}
- # Keep track of all building types
- typeDict = {}
- masterTypeList = []
- for neighborhood in NEIGHBORHOODS:
- attribute = LevelAttribute('building_style_all')
- # Create a building style dictionary for each neighborhood
- attribute.setDict(
- self.createBuildingStyleDictionary(neighborhood))
- # Using this dictionary, create building style pie menus
- attribute.setMenu(
- self.createBuildingStyleMenu(neighborhood,
- attribute.getDict()))
- # Store attribute in dictionary keyed by neighborhood
- styleDict[neighborhood] = attribute
- # Generate a list of building types for this neighborhood
- # and a list of building types for all neighborhoods,
- # to be used in creating attribute dicts below
- typeList = typeDict[neighborhood] = []
- for style in attribute.getList():
- heightType = string.strip(string.split(style.name, ':')[1])
- if heightType not in typeList:
- typeList.append(heightType)
- if heightType not in masterTypeList:
- masterTypeList.append(heightType)
- # Now sort styles according to the building type and number of walls
- # in the building style. Each of these attributes is also sorted by
- # neighborhood
- for i in masterTypeList:
- typeKey = i + '_styles'
- self.attributeDictionary[typeKey] = {}
- for i in NUM_WALLS:
- numWallKey = `i` + '_wall_styles'
- self.attributeDictionary[numWallKey] = {}
- # Also sort height lists according to total height of the building
- for i in BUILDING_HEIGHTS:
- heightKey = `i` + '_ft_wall_heights'
- self.attributeDictionary[heightKey] = {}
- # Now distribute data for each neighborhood
- for neighborhood in NEIGHBORHOODS:
- # Create temp dicts to accumulate styles and heights for that
- # neighborhood
- typeAttributes = {}
- numWallsAttributes = {}
- heightAttributes = {}
- # Store atributes for the different categories
- # Building type
- for i in typeDict[neighborhood]:
- typeAttrName = neighborhood + '_' + i + '_styles'
- typeAttributes[i] = LevelAttribute(typeAttrName)
- # Number of walls
- for i in NUM_WALLS:
- styleAttrName = neighborhood + '_' + `i` + '_wall_styles'
- numWallsAttributes[i] = LevelAttribute(styleAttrName)
- # Building height
- for i in BUILDING_HEIGHTS:
- heightAttrName = neighborhood + '_' + `i` + '_ft_wall_heights'
- heightAttributes[i] = LevelAttribute(heightAttrName)
- # Sort through the styles and store in separate lists
- for style in styleDict[neighborhood].getList():
- # Put in code for number of walls into building styles
- heightType = string.strip(string.split(style.name, ':')[1])
- heightList = map(string.atof, string.split(heightType, '_'))
- numWalls = len(heightList)
- # This one stores styles sorted by type
- typeAttributes[heightType].add(style)
- # This one stores styles sorted by number of walls
- numWallsAttributes[numWalls].add(style)
- # A record of all the unique height lists
- height = calcHeight(heightList)
- if heightList not in heightAttributes[height].getList():
- heightAttributes[height].add(heightList)
- # Now store these sorted style and height attributes
- # in the appropriate top-level attribute dictionary
- for i in typeDict[neighborhood]:
- # Styles
- typeKey = i + '_styles'
- self.attributeDictionary[typeKey][neighborhood] = (
- typeAttributes[i])
- for i in NUM_WALLS:
- # Styles
- numWallKey = `i` + '_wall_styles'
- self.attributeDictionary[numWallKey][neighborhood] = (
- numWallsAttributes[i])
- for i in BUILDING_HEIGHTS:
- # Heights
- heightKey = `i` + '_ft_wall_heights'
- self.attributeDictionary[heightKey][neighborhood] = (
- heightAttributes[i])
-
- def createBuildingStyleDictionary(self, neighborhood):
- """
- Create a dictionary of wall styles for a neighborhood
- """
- filename = neighborhood + '_building_styles.txt'
- print 'Loading building styles from: ' + filename
- styleData = self.getStyleFileData(filename)
- return self.initializeBuildingStyleDictionary(styleData, neighborhood)
- def initializeBuildingStyleDictionary(self, styleData, neighborhood):
- """
- Fill in the building style dictionary with data from the style file
- """
- # Create a dictionary of all building styles, this will later be
- # split out into a separate dictionary for each building type
- # e.g. 20, 10-10, 10-20....
- bldgStyleDictionary = {}
- styleCount = 0
- code = NEIGHBORHOOD_CODES[neighborhood]
- while styleData:
- # Pull out first line
- l = styleData[0]
- if l[:13] == 'buildingStyle':
- # Start with empty style list
- bldgStyle = DNAFlatBuildingStyle(styleList = [])
- # Extract height information found at end of line
- heightCode = string.strip(string.split(l, ':')[1])
- heightList = map(string.atof, string.split(heightCode, '_'))
- # Construct name for building style. Tack on height code
- # to be used later to split styles by heightCode
- bldgStyle.name = (
- code + '_building_style_' + `styleCount` +
- ':' + heightCode)
- # Increment counter
- styleCount = styleCount + 1
- # Reset wall counter to zero
- wallCount = 0
-
- elif l == 'endBuildingStyle':
- # Done, add new style to dictionary
- bldgStyleDictionary[bldgStyle.name] = bldgStyle
-
- elif l[:9] == 'wallStyle':
- # Beginning of next wall style
- wallStyle, styleData = self.extractWallStyle(styleData)
- wallStyle.name = bldgStyle.name + '_wall_' + `wallCount`
- try:
- height = heightList[wallCount]
- except IndexError:
- height = 10.0
- # Add wall style to building style
- bldgStyle.add(wallStyle, height)
- # Increment wall counter
- wallCount = wallCount + 1
- # Move to next line
- styleData = styleData[1:]
- return bldgStyleDictionary
-
- def createBuildingStyleMenu(self, neighborhood, dictionary):
- """
- Create a wall style pie menu
- """
- numItems = len(dictionary)
- newStyleMenu = hidden.attachNewNode(neighborhood + '_style_menu')
- radius = 0.7
- angle = deg2Rad(360.0/numItems)
- keys = dictionary.keys()
- keys.sort()
- styles = map(lambda x, d = dictionary: d[x], keys)
- sf = 0.02
- aspectRatio = (direct.dr.width/float(direct.dr.height))
- for i in range(numItems):
- # Get the node
- node = self.createBuildingStyleSample(styles[i])
- bounds = node.getBounds()
- center = bounds.getCenter()
- center = center * sf
- # Reposition it
- node.setPos((radius * math.cos(i * angle)) - center[0],
- 0.0,
- ((radius * aspectRatio * math.sin(i * angle)) -
- center[2]))
- # Scale it
- node.setScale(sf)
- # Add it to the styleMenu
- node.reparentTo(newStyleMenu)
- # Scale the whole shebang down by 0.5
- newStyleMenu.setScale(0.5)
- # Create and return a pie menu
- return PieMenu(newStyleMenu, styles)
-
- def createBuildingStyleSample(self, bldgStyle):
- """
- Create a style sample using the DNA info in the style
- """
- bldg = DNAFlatBuilding()
- self.setDNAFlatBuildingStyle(bldg, bldgStyle, width = 10.0,
- name = 'building_style_sample')
- return bldg.traverse(hidden, DNASTORE, 1)
-
- def setDNAFlatBuildingStyle(self, fb, bldgStyle, width = 10.0,
- heightList = None, name = 'building'):
- """ Set DNAFlatBuilding style. """
- # Remove flat building's children
- DNARemoveChildren(fb)
- # Update the name
- fb.setName(name)
- # Create the walls
- styleList = bldgStyle.styleList
- # Height list not specified, use styles default heights
- if not heightList:
- heightList = bldgStyle.heightList
- for i in range(len(styleList)):
- wallStyle = styleList[i]
- # Get Style
- if not wallStyle:
- # If set to None use default style
- wallStyle = DNAWallStyle()
- # Try to get height
- try:
- wallHeight = heightList[i]
- except IndexError:
- wallHeight = 10.0
- # Create wall accordingly
- wall = DNAWall()
- self.setDNAWallStyle(wall, wallStyle, wallHeight,
- width = width)
- # Add it to building DNA
- fb.add(wall)
- # Set the buildings width
- fb.setWidth(width)
- def setDNAWallStyle(self, wall, style, height = 10.0, width = None):
- """ Set DNAWall to input style. """
- # Remove wall's children
- DNARemoveChildren(wall)
- # Update wall attributes
- wall.setCode(style['wall_texture'])
- wall.setColor(style['wall_color'])
- wall.setHeight(height)
- # Add windows if necessary
- if style['window_texture']:
- windows = DNAWindows()
- windowCount = style['window_count']
- if width:
- if (width < 15.0):
- windowCount = min(1, windowCount)
- windows.setWindowCount(windowCount)
- # Set window's attributes
- windows.setCode(style['window_texture'])
- windows.setColor(style['window_color'])
- # Add windows to the wall
- wall.add(windows)
- # Add a window awning if necessary
- if style['window_awning_texture']:
- awning = DNAProp()
- # Update awning's attributes
- awning.setCode(style['window_awning_texture'])
- awning.setColor(style['window_awning_color'])
- # Add awning to window
- windows.add(awning)
- # Add a door if necessary
- if style['door_texture']:
- door = DNADoor()
- # Set the door's attributes
- door.setCode(style['door_texture'])
- door.setColor(style['door_color'])
- # Add door to wall
- wall.add(door)
- # Add a door awning if necessary
- if style['door_awning_texture']:
- awning = DNAProp()
- awning.setCode(style['door_awning_texture'])
- awning.setColor(style['door_awning_color'])
- door.add(awning)
- # And a cornice if necessary
- if style['cornice_texture']:
- cornice = DNACornice()
- # Set the cornice's attributes
- cornice.setCode(style['cornice_texture'])
- cornice.setColor(style['cornice_color'])
- # Add cornice to wall
- wall.add(cornice)
- def printFlatBuildingStyle(self, building):
- for i in range(building.getNumChildren()):
- child = building.at(i)
- if DNAClassEqual(child, DNA_WALL):
- self.printWallStyle(child)
-
- def printWallStyle(self, wall):
- print 'wall_texture: ' + wall.getCode()
- color = wall.getColor()
- print ('wall_color: Vec4(%.3f, %.3f, %.3f, 1.0)' %
- (color[0], color[1], color[2]))
- for i in range(wall.getNumChildren()):
- child = wall.at(i)
- if DNAClassEqual(child, DNA_WINDOWS):
- print 'window_texture: ' + child.getCode()
- color = child.getColor()
- print ('window_color: Vec4(%.3f, %.3f, %.3f, 1.0)' %
- (color[0], color[1], color[2]))
- # MRM: Check for awnings here
- elif DNAClassEqual(child, DNA_DOOR):
- print 'door_texture: ' + child.getCode()
- color = child.getColor()
- print ('door_color: Vec4(%.3f, %.3f, %.3f, 1.0)' %
- (color[0], color[1], color[2]))
- # MRM: Check for awnings here
- elif DNAClassEqual(child, DNA_CORNICE):
- print 'cornice_texture: ' + child.getCode()
- color = child.getColor()
- print ('cornice_color: Vec4(%.3f, %.3f, %.3f, 1.0)' %
- (color[0], color[1], color[2]))
- # COLOR PALETTE FUNCTIONS
- def createColorAttributes(self):
- # First compile color information for each neighborhood
- colorDictionary = {}
- colorMenuDictionary = {}
- for neighborhood in NEIGHBORHOODS:
- colorDictionary[neighborhood] = (
- # Create a wall style dictionary for each neighborhood
- self.createColorDictionary(neighborhood))
- # Using this dictionary, create color pie menus
- colorMenuDictionary[neighborhood] = (
- self.createColorMenus(
- neighborhood, colorDictionary[neighborhood]))
- # Now store this info in the appropriate place in the attribute dict
- for colorType in COLOR_TYPES:
- neighborhoodDict = self.attributeDictionary[colorType] = {}
- for neighborhood in NEIGHBORHOODS:
- attribute = LevelAttribute(colorType)
- dict = {}
- # Add colors to attribute dictionary
- colorList = colorDictionary[neighborhood][colorType]
- for i in range(len(colorList)):
- dict[i] = colorList[i]
- attribute.setDict(dict)
- attribute.setMenu(
- colorMenuDictionary[neighborhood][colorType])
- neighborhoodDict[neighborhood] = attribute
-
- def createColorDictionary(self, neighborhood):
- filename = neighborhood + '_colors.txt'
- print 'Loading Color Palettes from: ' + filename
- colorData = self.getStyleFileData(filename)
- return self.getColorDictionary(colorData)
-
- def getColorDictionary(self, colorData):
- # Initialze neighborhod color dictionary
- dict = {}
- for colorType in COLOR_TYPES:
- dict[colorType] = DEFAULT_COLORS[:]
- # Add color information to appropriate sub-list
- for line in colorData:
- pair = map(string.strip, line.split(':'))
- key = pair[0]
- if dict.has_key(key):
- dict[key].append(eval(pair[1]))
- else:
- print 'LevelStyleManager.getColorDictionary key not found'
- return dict
-
- def createColorMenus(self, neighborhood, dictionary):
- menuDict = {}
- keys = dictionary.keys()
- for key in keys:
- menuDict[key] = (
- self.createColorMenu(neighborhood + key, dictionary[key]))
- return menuDict
-
- def createColorMenu(self, menuName, colorList, radius = 0.7, sf = 2.0):
- # Create color chips for each color
- numItems = len(colorList)
- # Attach it to hidden for now
- newColorMenu = hidden.attachNewNode(menuName + 'Menu')
- # Compute the angle per item
- angle = deg2Rad(360.0/float(numItems))
- aspectRatio = (direct.dr.width / float(direct.dr.height))
- # Attach the color chips to the new menu and adjust sizes
- for i in range (numItems):
- # Create a text node--just a card, really--of the right color.
- tn = TextNode()
- tn.freeze()
- tn.setFont(getDefaultFont())
- tn.setTransform(Mat4.scaleMat(0.07, 0.07, 0.07 * aspectRatio))
- tn.setCardColor(colorList[i])
- tn.setCardActual(0, 1.1111, 0, 0.8333)
- tn.setText(' ')
- tn.thaw()
- # Reposition it
- card = tn.getCardTransformed()
- center = (card[1] - card[0], card[3] - card[2])
- node = newColorMenu.attachNewNode(tn)
- node.setScale(sf)
- node.setPos(radius * math.cos(i * angle) - center[0], 0.0,
- ((radius * aspectRatio * math.sin(i * angle)) -
- center[1]))
- # Scale the whole shebang down by 0.5
- newColorMenu.setScale(0.5)
- # Create and return resulting pie menu
- return PieMenu(newColorMenu, colorList)
-
- # DNA ATTRIBUTES
- def createDNAAttributes(self):
- # Create the DNA Attribute entries
- # Most objects are oriented with graphical menu items
- # Street and props aren't oiented and use text menus
- for dnaType in DNA_TYPES:
- # Create a dictionary of dna types
- dict = {}
- if ((dnaType == 'street') or (dnaType == 'prop') or
- (dnaType == 'toon_landmark')):
- dnaList = self.getCatalogCodes(dnaType)
- elif (dnaType == 'sign'):
- dnaList = [''] + self.getCatalogCodes(dnaType)
- else:
- dnaList = [None] + self.getCatalogCodesSuffix(dnaType, '_ur')
- # Add dnaCodes to attribute dictionary
- for i in range(len(dnaList)):
- dict[i] = dnaList[i]
- # Create a LevelAttribute
- attribute = LevelAttribute(dnaType + '_texture')
- attribute.setDict(dict)
- # Prepend None to allow option of no item
- if ((dnaType == 'street') or (dnaType == 'prop') or
- (dnaType == 'toon_landmark')):
- attribute.setMenu(self.createTextPieMenu(dnaType, dnaList))
- elif (dnaType == 'wall'):
- attribute.setMenu(self.createDNAPieMenu(dnaType, dnaList,
- sf = 0.25))
- elif (dnaType == 'sign'):
- attribute.setMenu(self.createDNAPieMenu(dnaType, dnaList,
- sf = 0.05))
- elif (dnaType == 'door'):
- attribute.setMenu(self.createDNAPieMenu(dnaType, dnaList,
- sf = 0.035))
- elif (dnaType == 'cornice'):
- attribute.setMenu(self.createDNAPieMenu(dnaType, dnaList,
- sf = 0.5))
- elif (dnaType == 'window'):
- attribute.setMenu(self.createDNAPieMenu(dnaType, dnaList,
- sf = 0.125))
- else:
- print 'unknown attribute'
- # Add it to the attributeDictionary
- self.attributeDictionary[dnaType + '_texture'] = attribute
-
- def createDNAPieMenu(self, dnaType, dnaList, radius = 0.7, sf = 1.0):
- # Get the currently available window options
- numItems = len(dnaList)
- # Create a top level node to hold the menu
- newMenu = hidden.attachNewNode(dnaType + 'Menu')
- # Compute angle increment per item
- angle = deg2Rad(360.0/numItems)
- aspectRatio = direct.dr.width /float(direct.dr.height)
- # Add items
- for i in range(0, numItems):
- if dnaList[i]:
- # Get the node
- node = DNASTORE.findNode(dnaList[i])
- else:
- node = None
- if node:
- # Add it to the window menu
- path = node.instanceTo(newMenu)
- # Place menu nodes in a circle, offset each in X and Z
- # by half node width/height
- bounds = path.getBounds()
- center = bounds.getCenter()
- center = center * sf
- path.setPos((radius * math.cos(i * angle)) - center[0],
- 0.0,
- ((radius * aspectRatio * math.sin(i * angle)) -
- center[2]))
- path.setScale(sf)
- # Scale the whole shebang down by 0.5
- newMenu.setScale(0.5)
- # Create and return a pie menu
- return PieMenu(newMenu, dnaList)
- def createTextPieMenu(self, dnaType, textList, radius = 0.7, sf = 1.0):
- numItems = len(textList)
- # Create top level node for new menu
- newMenu = hidden.attachNewNode(dnaType + 'Menu')
- # Compute angle per item
- angle = deg2Rad(360.0/numItems)
- aspectRatio = direct.dr.width/float(direct.dr.height)
- # Add items
- for i in range (numItems):
- # Create text node for each item
- if (textList[i] != None):
- tn = TextNode()
- tn.freeze()
- tn.setFont(getDefaultFont())
- tn.setTransform(Mat4.scaleMat(0.07, 0.07, 0.07 * aspectRatio))
- tn.setTextColor(0, 0, 0, 1)
- tn.setCardColor(1, 1, 1, 1)
- tn.setCardAsMargin(0.1, 0.1, 0.1, 0.1)
- tn.setText(str(textList[i]))
- tn.thaw()
- # Reposition it
- card = tn.getCardTransformed()
- center = (card[1] - card[0], card[3] - card[2])
- node = newMenu.attachNewNode(tn)
- node.setScale(sf)
- node.setPos(radius * math.cos(i * angle) - center[0], 0.0,
- ((radius * aspectRatio * math.sin(i * angle)) -
- center[1]))
- # Scale the whole shebang down by 0.5
- newMenu.setScale(0.5)
- # Create and return a pie menu
- return PieMenu(newMenu, textList)
- # MISCELLANEOUS MENUS
- def createMiscAttributes(self):
- # Num windows menu
- self.createMiscAttribute('window_count',[0,1,2,3,4])
- # Building width menu
- self.createMiscAttribute('building_width',[5,10,15,15.6,20,20.7,25])
- # Building types
- self.createMiscAttribute('building_type', BUILDING_TYPES)
- # Building heights
- self.createMiscAttribute('building_height', [10,20,25,30])
- # MRM: Need offset on these menus
- # Wall orientation menu
- self.createMiscAttribute('wall_orientation', ['ur','ul','dl','dr'])
- # Wall height menu
- self.createMiscAttribute('wall_height', [10, 20])
- # Window orientation menu
- self.createMiscAttribute('window_orientation', ['ur','ul',None,None])
- # Sign orientation menu
- self.createMiscAttribute('sign_orientation', ['ur','ul',None,None])
- # Door orientation menu
- self.createMiscAttribute('door_orientation', ['ur','ul',None,None])
- # Cornice orientation menu
- self.createMiscAttribute('cornice_orientation', ['ur','ul',None,None])
-
- def createMiscAttribute(self, miscType, miscList, sf = 3.0):
- # Create a dictionary from miscList
- dict = {}
- # Add items to attribute dictionary
- for i in range(len(miscList)):
- dict[i] = miscList[i]
- # Create the miscellaneous Attribute entries
- attribute = LevelAttribute(miscType)
- attribute.setDict(dict)
- # Now create a pie menu
- attribute.setMenu(self.createTextPieMenu(miscType, miscList,
- sf = sf))
- # Add it to the attributeDictionary
- self.attributeDictionary[miscType] = attribute
- # GENERAL FUNCTIONS
- def getStyleFileData(self, filename):
- """
- Open the specified file and strip out unwanted whitespace and
- empty lines. Return file as list, one file line per element.
- """
- fname = Filename(self.stylePathPrefix +
- '/alpha/DIRECT/LevelEditor/StyleFiles/' +
- filename)
- f = open(fname.toOsSpecific(), 'r')
- rawData = f.readlines()
- f.close()
- styleData = []
- for line in rawData:
- l = string.strip(line)
- if l:
- styleData.append(l)
- return styleData
- # UTILITY FUNCTIONS
- def getAttribute(self, attribute):
- """ Return specified attribute for current neighborhood """
- levelAttribute = self.attributeDictionary[attribute]
- # Get attribute for current neighborhood
- if (type(levelAttribute) == types.DictionaryType):
- levelAttribute = levelAttribute[self.getEditMode()]
- return levelAttribute
- # UTILITY FUNCTIONS
- def hasAttribute(self, attribute):
- """ Return specified attribute for current neighborhood """
- if not self.attributeDictionary.has_key(attribute):
- return 0
- else:
- levelAttribute = self.attributeDictionary[attribute]
- # Get attribute for current neighborhood
- if (type(levelAttribute) == types.DictionaryType):
- editMode = self.getEditMode()
- return levelAttribute.has_key(editMode)
- else:
- return 1
- def getCatalogCode(self, category, i):
- return DNASTORE.getCatalogCode(category, i)
-
- def getCatalogCodes(self, category):
- numCodes = DNASTORE.getNumCatalogCodes(category)
- codes = []
- for i in range(numCodes):
- codes.append(DNASTORE.getCatalogCode(category, i))
- return codes
- def getCatalogCodesSuffix(self, category, suffix):
- codes = self.getCatalogCodes(category)
- orientedCodes = []
- for code in codes:
- if code[-3:] == suffix:
- orientedCodes.append(code)
- return orientedCodes
- def setEditMode(self, mode):
- """Set current neighborhood editing mode"""
- self._editMode = mode
-
- def getEditMode(self):
- """Get current neighborhood editing mode"""
- return self._editMode
- class LevelAttribute:
- """Class which encapsulates a pie menu and a set of items"""
- def __init__(self, name):
- # Record name
- self.name = name
- # Pie menu used to pick an option
- self._menu = None
- # Dictionary of available options
- self._dict = {}
- self._list = []
- self.count = 0
- # Currently selected option
- self._current = None
- def setCurrent(self, newValue, fEvent = 1):
- self._current = newValue
- # Send event if specified
- if fEvent:
- messenger.send('select_' + self.name, [self._current])
- def setMenu(self,menu):
- self._menu = menu
- self._menu.action = self.setCurrent
- def setDict(self,dict):
- self._dict = dict
- # Create a list from the dictionary
- self._list = dict.values()
- # Update count
- self.count = len(self._list)
- # Initialize current to first item
- if (len(self._list) > 0):
- self._current = self._list[0]
- def setList(self,list):
- self._list = list
- # Create a dictionary from the list
- self._dict = {}
- self.count = 0
- for item in list:
- self._dict[self.count] = item
- self.count += 1
- # Initialize current to first item
- if (self.count > 0):
- self._current = self._list[0]
- def add(self,item):
- self._dict[self.count] = item
- self._list.append(item)
- self.count += 1
- def getCurrent(self):
- return self._current
- def getMenu(self):
- return self._menu
- def getDict(self):
- return self._dict
- def getList(self):
- return self._list
- def getCount(self):
- return self.count
- class DNAFlatBuildingStyle:
- """Class to hold attributes of a building style"""
- def __init__(self, building = None, styleList = None, name = 'bldg_style'):
- self.name = name
- if building:
- # Passed in a building
- self.copy(building)
- elif styleList != None:
- # Passed in a list of style-height pairs
- self.styleList = []
- self.heightList = []
- self.numWalls = 0
- for pair in styleList:
- self.add(pair[0], pair[1])
- else:
- # Use default style/height
- self.styleList = [DNAWallStyle()]
- self.heightList = [10]
- self.numWalls = 1
- def add(self, style, height):
- self.styleList.append(style)
- self.heightList.append(height)
- self.numWalls += 1
-
- def copy(self, building):
- self.styleList = []
- self.heightList = DNAGetWallHeights(building)[0]
- self.numWalls = 0
- for i in range(building.getNumChildren()):
- child = building.at(i)
- if DNAClassEqual(child, DNA_WALL):
- wallStyle = DNAWallStyle(wall = child)
- self.styleList.append(wallStyle)
- self.numWalls += 1
- def output(self, file = sys.stdout):
- file.write('buildingStyle: %s\n' % createHeightCode(self.heightList))
- for style in self.styleList:
- style.output(file)
- file.write('endBuildingStyle\n')
- def createHeightCode(heightList):
- def joinHeights(h1,h2):
- return '%s_%s' % (h1, h2)
- hl = map(ROUND_INT, heightList)
- if len(hl) == 1:
- return `hl[0]`
- return reduce(joinHeights, hl)
- def calcHeight(heightList):
- height = 0
- for h in heightList:
- height = height + h
- return int(height)
- class DNABaselineStyle:
- """Class to hold attributes of a baseline style (wiggle, colors, etc)"""
- def __init__(self, baseline = None, name = 'baseline_style'):
- # First initialize everything
- self.name = name
- self.code = None # i.e. font
- self.kern = None
- self.wiggle = None
- self.stumble = None
- self.stomp = None
- self.curve = None
- self.x = None
- self.z = None
- self.scaleX = 1.0
- self.scaleZ = 1.0
- self.roll = None
- self.flags = None
- self.color = Vec4(1.0)
- # Then copy the specifics for the baseline if input
- if baseline:
- self.copy(baseline)
- def copy(self, baseline):
- self.code = baseline.getCode()
- self.kern = baseline.getKern()
- self.wiggle = baseline.getWiggle()
- self.stumble = baseline.getStumble()
- self.stomp = baseline.getStomp()
- width=baseline.getWidth()
- if width:
- self.curve = 1.0/width
- else:
- self.curve = 0.0
- pos = baseline.getPos()
- self.x = pos[0]
- self.z = pos[2]
- scale = baseline.getScale()
- self.scaleX = scale[0]
- self.scaleZ = scale[2]
- hpr = baseline.getHpr()
- self.roll = hpr[2]
- self.flags = baseline.getFlags()
- self.color = baseline.getColor()
- def copyTo(self, baseline):
- if self.code != None:
- baseline.setCode(self.code)
- if self.kern != None:
- baseline.setKern(self.kern)
- if self.wiggle != None:
- baseline.setWiggle(self.wiggle)
- if self.stumble != None:
- baseline.setStumble(self.stumble)
- if self.stomp != None:
- baseline.setStomp(self.stomp)
- if self.curve != None:
- diameter=0.0
- if self.curve:
- diameter=1.0/self.curve
- baseline.setWidth(diameter)
- baseline.setHeight(diameter)
- if (self.x != None) or (self.z != None):
- pos=baseline.getPos()
- if self.x != None:
- pos=Vec3(self.x, pos[1], pos[2])
- if self.z != None:
- pos=Vec3(pos[0], pos[1], self.z)
- baseline.setPos(pos)
- if self.roll != None:
- baseline.setHpr(Vec3(0.0, 0.0, self.roll))
- if (self.scaleX != None) or (self.scaleZ != None):
- scale=baseline.getScale()
- if self.scaleX != None:
- scale=Vec3(self.scaleX, scale[1], scale[2])
- if self.scaleZ != None:
- scale=Vec3(scale[0], scale[1], self.scaleZ)
- baseline.setScale(scale)
- if self.flags != None:
- baseline.setFlags(self.flags)
- if self.color != None:
- baseline.setColor(self.color)
- def output(self, file = sys.stdout):
- """ Output style description to a file """
- file.write('baselineStyle\n')
- if self.name != None:
- file.write('name: %s\n' % self.name)
- if self.code != None:
- file.write('code: %s\n' % self.code)
- if self.kern != None:
- file.write('kern: %s\n' % self.kern)
- if self.wiggle != None:
- file.write('wiggle: %s\n' % self.wiggle)
- if self.stumble != None:
- file.write('stumble: %s\n' % self.stumble)
- if self.stomp != None:
- file.write('stomp: %s\n' % self.stomp)
- if self.curve != None:
- file.write('curve: %s\n' % self.curve)
- if self.x != None:
- file.write('x: %s\n' % self.x)
- if self.z != None:
- file.write('z: %s\n' % self.z)
- if self.scaleX != None:
- file.write('scaleX: %s\n' % self.scaleX)
- if self.scaleZ != None:
- file.write('scaleZ: %s\n' % self.scaleZ)
- if self.roll != None:
- file.write('roll: %s\n' % self.roll)
- if self.flags != None:
- file.write('flags: %s\n' % self.flags)
- if self.color != None:
- file.write('color: Vec4(%.2f, %.2f, %.2f, 1.0)\n'
- % (self.color[0], self.color[1], self.color[2]))
- file.write('endBaselineStyle\n')
- # Convience functions to facilitate class use
- def __setitem__(self, index, item):
- self.__dict__[index] = item
-
- def __getitem__(self, index):
- return self.__dict__[index]
-
- def __repr__(self):
- return(
- 'name: %s\n' % self.name +
- 'code: %s\n' % self.code +
- 'kern: %s\n' % self.kern +
- 'wiggle: %s\n' % self.wiggle +
- 'stumble: %s\n' % self.stumble +
- 'stomp: %s\n' % self.stomp +
- 'curve: %s\n' % self.curve +
- 'x: %s\n' % self.x +
- 'z: %s\n' % self.z +
- 'scaleX: %s\n' % self.scaleX +
- 'scaleZ: %s\n' % self.scaleZ +
- 'roll: %s\n' % self.roll +
- 'flags: %s\n' % self.flags +
- 'color: %s\n' % self.color
- )
- class DNAWallStyle:
- """Class to hold attributes of a wall style (textures, colors, etc)"""
- def __init__(self, wall = None, name = 'wall_style'):
- # First initialize everything
- self.name = name
- self.wall_texture = 'wall_md_blank_ur'
- self.wall_color = Vec4(1.0)
- self.window_count = 2
- self.window_texture = None
- self.window_color = Vec4(1.0)
- self.window_awning_texture = None
- self.window_awning_color = Vec4(1.0)
- self.door_texture = None
- self.door_color = Vec4(1.0)
- self.door_awning_texture = None
- self.door_awning_color = Vec4(1.0)
- self.cornice_texture = None
- self.cornice_color = Vec4(1.0)
- # Then copy the specifics for the wall if input
- if wall:
- self.copy(wall)
- def copy(self, wall):
- self.wall_texture = wall.getCode()
- self.wall_color = wall.getColor()
- for i in range(wall.getNumChildren()):
- child = wall.at(i)
- if DNAClassEqual(child, DNA_WINDOWS):
- self.window_count = child.getWindowCount()
- self.window_texture = child.getCode()
- self.window_color = child.getColor()
- # MRM: Check for awnings here
- elif DNAClassEqual(child, DNA_DOOR):
- self.door_texture = child.getCode()
- self.door_color = child.getColor()
- # MRM: Check for awnings here
- elif DNAClassEqual(child, DNA_CORNICE):
- self.cornice_texture = child.getCode()
- self.cornice_color = child.getColor()
- def output(self, file = sys.stdout):
- """ Output style description to a file """
- def writeAttributes(f, type, s = self):
- color = s[type + '_color']
- f.write('%s_texture: %s\n' % (type, s[type + '_texture']))
- f.write('%s_color: Vec4(%.2f, %.2f, %.2f, 1.0)\n' %
- (type, color[0], color[1], color[2]))
- file.write('wallStyle\n')
- writeAttributes(file, 'wall')
- if self['window_texture']:
- writeAttributes(file, 'window')
- file.write('window_count: %s\n' % self['window_count'])
- if self['window_awning_texture']:
- writeAttributes(file, 'window_awning')
- if self['door_texture']:
- writeAttributes(file, 'door')
- if self['door_awning_texture']:
- writeAttributes(file, 'door_awning')
- if self['cornice_texture']:
- writeAttributes(file, 'cornice')
- file.write('endWallStyle\n')
- # Convience functions to facilitate class use
- def __setitem__(self, index, item):
- self.__dict__[index] = item
-
- def __getitem__(self, index):
- return self.__dict__[index]
-
- def __repr__(self):
- return(
- 'Name: %s\n' % self.name +
- 'Wall Texture: %s\n' % self.wall_texture +
- 'Wall Color: %s\n' % self.wall_color +
- 'Window Texture: %s\n' % self.window_texture +
- 'Window Color: %s\n' % self.window_color +
- 'Window Awning Texture: %s\n' % self.window_awning_texture +
- 'Window Awning Color: %s\n' % self.window_awning_color +
- 'Door Texture: %s\n' % self.door_texture +
- 'Door Color: %s\n' % self.door_color +
- 'Door Awning Texture: %s\n' % self.door_awning_texture +
- 'Door Awning Color: %s\n' % self.door_awning_color +
- 'Cornice Texture: %s\n' % self.cornice_texture +
- 'Cornice Color: %s\n' % self.cornice_color
- )
- class OldLevelEditor(NodePath, PandaObject):
- pass
- class LevelEditorPanel(Pmw.MegaToplevel):
- def __init__(self, levelEditor, parent = None, **kw):
- INITOPT = Pmw.INITOPT
- optiondefs = (
- ('title', 'Toontown Level Editor', None),
- )
- self.defineoptions(kw, optiondefs)
- Pmw.MegaToplevel.__init__(self, parent, title = self['title'])
- self.levelEditor = levelEditor
- self.styleManager = self.levelEditor.styleManager
- self.fUpdateSelected = 1
- # Handle to the toplevels hull
- hull = self.component('hull')
- hull.geometry('400x550')
-
- balloon = self.balloon = Pmw.Balloon(hull)
- # Start with balloon help disabled
- self.balloon.configure(state = 'none')
-
- menuFrame = Frame(hull, relief = GROOVE, bd = 2)
- menuFrame.pack(fill = X)
- menuBar = Pmw.MenuBar(menuFrame, hotkeys = 1, balloon = balloon)
- menuBar.pack(side = LEFT, expand = 1, fill = X)
- menuBar.addmenu('Level Editor', 'Level Editor Operations')
- menuBar.addmenuitem('Level Editor', 'command',
- 'Load DNA from specified file',
- label = 'Load DNA...',
- command = self.levelEditor.loadSpecifiedDNAFile)
- menuBar.addmenuitem('Level Editor', 'command',
- 'Save DNA data to specified file',
- label = 'Save DNA As...',
- command = self.levelEditor.saveToSpecifiedDNAFile)
- menuBar.addmenuitem('Level Editor', 'command',
- 'Save DNA File',
- label = 'Save DNA',
- command = self.levelEditor.outputDNADefaultFile)
- menuBar.addmenuitem('Level Editor', 'command',
- 'Edit Visibility Groups',
- label = 'Edit Vis Groups',
- command = self.levelEditor.editDNAVisGroups)
- menuBar.addmenuitem('Level Editor', 'command',
- 'Reset level',
- label = 'Reset level',
- command = self.levelEditor.reset)
- menuBar.addmenuitem('Level Editor', 'command',
- 'Exit Level Editor Panel',
- label = 'Exit',
- command = self.levelEditor.destroy)
- menuBar.addmenu('Style', 'Style Operations')
- menuBar.addmenuitem('Style', 'command',
- "Save Selected Object's Color",
- label = 'Save Color',
- command = self.levelEditor.saveColor)
- menuBar.addmenuitem('Style', 'command',
- "Save Selected Baseline's Style",
- label = 'Save Baseline Style',
- command = self.levelEditor.saveBaselineStyle)
- menuBar.addmenuitem('Style', 'command',
- "Save Selected Wall's Style",
- label = 'Save Wall Style',
- command = self.levelEditor.saveWallStyle)
- menuBar.addmenuitem('Style', 'command',
- "Save Selected Buildings's Style",
- label = 'Save Bldg Style',
- command = self.levelEditor.saveBuildingStyle)
- menuBar.addmenuitem('Style', 'command',
- 'Reload Color Palettes',
- label = 'Reload Colors',
- command = self.styleManager.createColorAttributes)
- menuBar.addmenuitem('Style', 'command',
- 'Reload Baseline Style Palettes',
- label = 'Reload Baseline Styles',
- command = self.styleManager.createBaselineStyleAttributes)
- menuBar.addmenuitem('Style', 'command',
- 'Reload Wall Style Palettes',
- label = 'Reload Wall Styles',
- command = self.styleManager.createWallStyleAttributes)
- menuBar.addmenuitem('Style', 'command',
- 'Reload Building Style Palettes',
- label = 'Reload Bldg Styles',
- command = self.styleManager.createBuildingStyleAttributes)
- menuBar.addmenu('Help', 'Level Editor Help Operations')
- self.toggleBalloonVar = IntVar()
- self.toggleBalloonVar.set(0)
- menuBar.addmenuitem('Help', 'checkbutton',
- 'Toggle balloon help',
- label = 'Balloon Help',
- variable = self.toggleBalloonVar,
- command = self.toggleBalloon)
- self.editMenu = Pmw.ComboBox(
- menuFrame, labelpos = W,
- label_text = 'Edit Mode:', entry_width = 18,
- selectioncommand = self.levelEditor.setEditMode, history = 0,
- scrolledlist_items = NEIGHBORHOODS)
- self.editMenu.selectitem(NEIGHBORHOODS[0])
- self.editMenu.pack(side = LEFT, expand = 0)
-
- # Create the notebook pages
- self.notebook = Pmw.NoteBook(hull)
- self.notebook.pack(fill = BOTH, expand = 1)
- streetsPage = self.notebook.add('Streets')
- toonBuildingsPage = self.notebook.add('Toon Bldgs')
- landmarkBuildingsPage = self.notebook.add('Landmark Bldgs')
- # suitBuildingsPage = self.notebook.add('Suit Buildings')
- propsPage = self.notebook.add('Props')
- signPage = self.notebook.add('Signs')
- suitPathPage = self.notebook.add('Paths')
- battleCellPage = self.notebook.add('Cells')
- sceneGraphPage = self.notebook.add('SceneGraph')
- self.notebook['raisecommand'] = self.updateInfo
- # STREETS
- Label(streetsPage, text = 'Streets',
- font=('MSSansSerif', 14, 'bold')).pack(expand = 0)
- self.addStreetButton = Button(
- streetsPage,
- text = 'ADD STREET',
- command = self.addStreet)
- self.addStreetButton.pack(fill = X, padx = 20, pady = 10)
- self.streetSelector = Pmw.ComboBox(
- streetsPage,
- dropdown = 0,
- listheight = 200,
- labelpos = W,
- label_text = 'Street type:',
- label_width = 12,
- label_anchor = W,
- entry_width = 30,
- selectioncommand = self.setStreetModuleType,
- scrolledlist_items = map(lambda s: s[7:],
- self.styleManager.getCatalogCodes(
- 'street'))
- )
- self.streetModuleType = self.styleManager.getCatalogCode('street',0)
- self.streetSelector.selectitem(self.streetModuleType[7:])
- self.streetSelector.pack(expand = 1, fill = BOTH)
- # TOON BUILDINGS
- Label(toonBuildingsPage, text = 'Toon Buildings',
- font=('MSSansSerif', 14, 'bold')).pack(expand = 0)
- self.addToonBuildingButton = Button(
- toonBuildingsPage,
- text = 'ADD TOON BUILDING',
- command = self.addFlatBuilding)
- self.addToonBuildingButton.pack(fill = X, padx = 20, pady = 10)
- self.toonBuildingSelector = Pmw.ComboBox(
- toonBuildingsPage,
- dropdown = 0,
- listheight = 200,
- labelpos = W,
- label_width = 12,
- label_anchor = W,
- label_text = 'Bldg type:',
- entry_width = 30,
- selectioncommand = self.setFlatBuildingType,
- scrolledlist_items = (['random'] + BUILDING_TYPES)
- )
- bf = Frame(toonBuildingsPage)
- Label(bf, text = 'Building Height:').pack(side = LEFT, expand = 0)
- self.heightMode = IntVar()
- self.heightMode.set(20)
- self.tenFootButton = Radiobutton(
- bf,
- text = '10 ft',
- value = 10,
- variable = self.heightMode,
- command = self.setFlatBuildingHeight)
- self.tenFootButton.pack(side = LEFT, expand = 1, fill = X)
- self.twentyFootButton = Radiobutton(
- bf,
- text = '20 ft',
- value = 20,
- variable = self.heightMode,
- command = self.setFlatBuildingHeight)
- self.twentyFootButton.pack(side = LEFT, expand = 1, fill = X)
- self.twentyFiveFootButton = Radiobutton(
- bf,
- text = '25 ft',
- value = 25,
- variable = self.heightMode,
- command = self.setFlatBuildingHeight)
- self.twentyFiveFootButton.pack(side = LEFT, expand = 1, fill = X)
- self.thirtyFootButton = Radiobutton(
- bf,
- text = '30 ft',
- value = 30,
- variable = self.heightMode,
- command = self.setFlatBuildingHeight)
- self.thirtyFootButton.pack(side = LEFT, expand = 1, fill = X)
- bf.pack(fill = X)
-
- self.toonBuildingType = 'random'
- self.toonBuildingSelector.selectitem(self.toonBuildingType)
- self.toonBuildingSelector.pack(expand = 1, fill = BOTH)
-
- # LANDMARK BUILDINGS
- Label(landmarkBuildingsPage, text = 'Landmark Buildings',
- font=('MSSansSerif', 14, 'bold')).pack(expand = 0)
- self.addLandmarkBuildingButton = Button(
- landmarkBuildingsPage,
- text = 'ADD LANDMARK BUILDING',
- command = self.addLandmark)
- self.addLandmarkBuildingButton.pack(fill = X, padx = 20, pady = 10)
- self.landmarkBuildingSelector = Pmw.ComboBox(
- landmarkBuildingsPage,
- dropdown = 0,
- listheight = 200,
- labelpos = W,
- label_width = 12,
- label_anchor = W,
- label_text = 'Bldg type:',
- entry_width = 30,
- selectioncommand = self.setLandmarkType,
- scrolledlist_items = map(lambda s: s[14:],
- self.styleManager.getCatalogCodes(
- 'toon_landmark'))
- )
- self.landmarkType = self.styleManager.getCatalogCode(
- 'toon_landmark',0)
- self.landmarkBuildingSelector.selectitem(
- self.styleManager.getCatalogCode('toon_landmark',0)[14:])
- self.landmarkBuildingSelector.pack(expand = 1, fill = BOTH)
-
- # SIGNS
- Label(signPage, text = 'Signs',
- font=('MSSansSerif', 14, 'bold')).pack(expand = 0)
- self.currentSignDNA=None
- self.currentBaselineDNA=None
- self.levelEditor.selectedNodePathHookHooks.append(self.updateSignPage)
- gridFrame = Frame(signPage)
- signSelectedFrame = Frame(gridFrame)
- self.currentBaselineIndex=0
- self.baselineMenu = Pmw.ComboBox(
- signSelectedFrame,
- labelpos = W,
- label_text = 'Selected:', entry_width = 24,
- selectioncommand = self.selectSignBaseline,
- history = 0, # unique = 0,
- scrolledlist_items = ['<the sign>'])
- self.baselineMenu.selectitem(self.currentBaselineIndex)
- self.baselineMenu.pack(side = LEFT, expand = 1, fill = X)
- self.baselineAddButton = Button(
- signSelectedFrame,
- text="Add Baseline", command=self.addBaseline)
- self.baselineAddButton.pack(side = LEFT, expand = 1, fill = X)
- self.baselineDeleteButton = Button(
- signSelectedFrame,
- text="Del", command=self.deleteSignItem)
- self.baselineDeleteButton.pack(side = LEFT, expand = 1, fill = X)
- signSelectedFrame.grid(row=0, column=0, columnspan=6)
- self.baselineString=StringVar()
- self.baselineString.trace("wu", self.signBaselineTrace)
- self.baselineTextBox = Entry(
- gridFrame, width = 24,
- textvariable=self.baselineString)
- self.baselineTextBox.grid(row=1, column=0, columnspan=3)
- fontList = [""]+self.styleManager.getCatalogCodes('font')
- self.fontMenu = Pmw.ComboBox(
- gridFrame, labelpos = W,
- label_text = 'Font:', entry_width = 12,
- selectioncommand = self.setSignBaslineFont, history = 0,
- scrolledlist_items = fontList)
- self.fontMenu.selectitem(0)
- self.fontMenu.grid(row=1, column=3, columnspan=3)
- graphicList = self.styleManager.getCatalogCodes('graphic')
- self.graphicMenu = Pmw.ComboBox(
- gridFrame, labelpos = W,
- label_text = 'Add Graphic:', entry_width = 24,
- selectioncommand = self.addSignGraphic, history = 0,
- scrolledlist_items = graphicList)
- self.graphicMenu.selectitem(0)
- self.graphicMenu.grid(row=2, column=0, columnspan=4)
- signButtonFrame = Frame(gridFrame)
-
- self.bigFirstLetterIntVar = IntVar()
- self.bigFirstLetterCheckbutton = Checkbutton(
- signButtonFrame,
- text = 'Big First Letter',
- variable=self.bigFirstLetterIntVar, command=self.setBigFirstLetter)
- self.bigFirstLetterCheckbutton.pack(
- side = LEFT, expand = 1, fill = X)
- self.allCapsIntVar = IntVar()
- self.allCapsCheckbutton = Checkbutton(
- signButtonFrame,
- text = 'All Caps',
- variable=self.allCapsIntVar, command=self.setAllCaps)
- self.allCapsCheckbutton.pack(side = LEFT, expand = 1, fill = X)
- self.dropShadowIntVar = IntVar()
- self.dropShadowCheckbutton = Checkbutton(
- signButtonFrame,
- text = 'Drop Shadow',
- variable=self.dropShadowIntVar, command=self.setDropShadow)
- self.dropShadowCheckbutton.pack(side = LEFT, expand = 1, fill = X)
-
- signButtonFrame.grid(row=3, column=0, columnspan=6)
- self.addKernFloater = Floater.Floater(
- gridFrame,
- text='Kern',
- maxVelocity=1.0,
- command=self.setSignBaselineKern)
- self.addKernFloater.grid(row=4, column=0, rowspan=2, columnspan=3)
- self.addWiggleFloater = Floater.Floater(
- gridFrame,
- text='Wiggle',
- maxVelocity=10.0,
- command=self.setSignBaselineWiggle)
- self.addWiggleFloater.grid(row=6, column=0, rowspan=2, columnspan=3)
- self.addStumbleFloater = Floater.Floater(
- gridFrame,
- text='Stumble',
- maxVelocity=1.0,
- command=self.setSignBaselineStumble)
- self.addStumbleFloater.grid(row=8, column=0, rowspan=2, columnspan=3)
- self.addStompFloater = Floater.Floater(
- gridFrame,
- text='Stomp',
- maxVelocity=1.0,
- command=self.setSignBaselineStomp)
- self.addStompFloater.grid(row=10, column=0, rowspan=2, columnspan=3)
- self.addCurveFloater = Floater.Floater(
- gridFrame,
- text='Curve',
- maxVelocity = 1.0,
- command=self.setSignBaselineCurve)
- self.addCurveFloater.grid(row=12, column=0, rowspan=2, columnspan=3)
- self.addXFloater = Floater.Floater(
- gridFrame,
- text='X',
- maxVelocity=1.0,
- command=self.setDNATargetX)
- self.addXFloater.grid(row=4, column=3, rowspan=2, columnspan=3)
- self.addZFloater = Floater.Floater(
- gridFrame,
- text='Z',
- maxVelocity=1.0,
- command=self.setDNATargetZ)
- self.addZFloater.grid(row=6, column=3, rowspan=2, columnspan=3)
- self.addScaleXFloater = Floater.Floater(
- gridFrame,
- text='Scale X',
- maxVelocity=1.0,
- command=self.setDNATargetScaleX)
- self.addScaleXFloater.grid(row=8, column=3, rowspan=2, columnspan=3)
- self.addScaleZFloater = Floater.Floater(
- gridFrame,
- text='Scale Z',
- maxVelocity=1.0,
- command=self.setDNATargetScaleZ)
- self.addScaleZFloater.grid(row=10, column=3, rowspan=2, columnspan=3)
- self.addRollFloater = Floater.Floater(
- gridFrame,
- text='Roll',
- maxVelocity=10.0,
- command=self.setDNATargetRoll)
- self.addRollFloater.grid(row=12, column=3, rowspan=2, columnspan=3)
- gridFrame.pack(fill=BOTH)
- # PROPS
- Label(propsPage, text = 'Props',
- font=('MSSansSerif', 14, 'bold')).pack(expand = 0)
- self.addPropsButton = Button(
- propsPage,
- text = 'ADD PROP',
- command = self.addProp)
- self.addPropsButton.pack(fill = X, padx = 20, pady = 10)
- self.propSelector = Pmw.ComboBox(
- propsPage,
- dropdown = 0,
- listheight = 200,
- labelpos = W,
- label_width = 12,
- label_anchor = W,
- label_text = 'Prop type:',
- entry_width = 30,
- selectioncommand = self.setPropType,
- scrolledlist_items = self.styleManager.getCatalogCodes('prop')
- )
- self.propType = self.styleManager.getCatalogCode('prop',0)
- self.propSelector.selectitem(
- self.styleManager.getCatalogCode('prop',0))
- self.propSelector.pack(expand = 1, fill = BOTH)
- # SUIT PATHS
- Label(suitPathPage, text = 'Suit Paths',
- font=('MSSansSerif', 14, 'bold')).pack(expand = 0)
- spButtons = Frame(suitPathPage)
- self.fPaths = IntVar()
- self.fPaths.set(0)
- self.pathButton = Checkbutton(spButtons,
- text = 'Show Paths',
- width = 6,
- variable = self.fPaths,
- command = self.toggleSuitPaths)
- self.pathButton.pack(side = LEFT, expand = 1, fill = X)
- self.zoneColor = IntVar()
- self.zoneColor.set(0)
- self.colorZoneButton1 = Checkbutton(
- spButtons,
- text = 'Color Zones', width = 6,
- variable = self.zoneColor,
- command = self.levelEditor.toggleZoneColors)
- self.colorZoneButton1.pack(side = LEFT, expand = 1, fill = X)
- spButtons.pack(fill = X)
- spButtons = Frame(suitPathPage)
- Label(spButtons, text = 'Highlight:').pack(side = LEFT, fill = X)
- self.highlightConnectedButton = Button(
- spButtons,
- text = 'Forward',
- width = 6,
- command = self.levelEditor.highlightConnected)
- self.highlightConnectedButton.pack(side = LEFT, expand = 1, fill = X)
- self.highlightConnectedButton2 = Button(
- spButtons,
- text = 'Connected',
- width = 6,
- command = lambda s = self: s.levelEditor.highlightConnected(fReversePath = 1))
- self.highlightConnectedButton2.pack(side = LEFT, expand = 1, fill = X)
- self.clearHighlightButton = Button(
- spButtons,
- text = 'Clear',
- width = 6,
- command = self.levelEditor.clearPathHighlights)
- self.clearHighlightButton.pack(side = LEFT, expand = 1, fill = X)
- spButtons.pack(fill = X, pady = 4)
-
- self.suitPointSelector = Pmw.ComboBox(
- suitPathPage,
- dropdown = 0,
- listheight = 200,
- labelpos = W,
- label_text = 'Point type:',
- label_width = 12,
- label_anchor = W,
- entry_width = 30,
- selectioncommand = self.setSuitPointType,
- scrolledlist_items = ['street', 'front door', 'side door']
- )
- self.suitPointSelector.selectitem('street')
- self.suitPointSelector.pack(expand = 1, fill = BOTH)
- # BATTLE CELLS
- Label(battleCellPage, text = 'Battle Cells',
- font=('MSSansSerif', 14, 'bold')).pack(expand = 0)
- bcButtons = Frame(battleCellPage)
- self.fCells = IntVar()
- self.fCells.set(0)
- self.cellButton = Checkbutton(bcButtons,
- text = 'Show Cells',
- width = 6,
- variable = self.fCells,
- command = self.toggleBattleCells)
- self.cellButton.pack(side = LEFT, expand = 1, fill = X)
- self.colorZoneButton2 = Checkbutton(
- bcButtons,
- text = 'Color Zones', width = 6,
- variable = self.zoneColor,
- command = self.levelEditor.toggleZoneColors)
- self.colorZoneButton2.pack(side = LEFT, expand = 1, fill = X)
- bcButtons.pack(fill = X)
- self.battleCellSelector = Pmw.ComboBox(
- battleCellPage,
- dropdown = 0,
- listheight = 200,
- labelpos = W,
- label_text = 'Cell type:',
- label_width = 12,
- label_anchor = W,
- entry_width = 30,
- selectioncommand = self.setBattleCellType,
- scrolledlist_items = ['20w 20l', '20w 30l', '30w 20l', '30w 30l']
- )
- self.battleCellSelector.selectitem('20w 20l')
- self.battleCellSelector.pack(expand = 1, fill = BOTH)
- # SCENE GRAPH EXPLORER
- Label(sceneGraphPage, text = 'Level Scene Graph',
- font=('MSSansSerif', 14, 'bold')).pack(expand = 0)
- self.sceneGraphExplorer = SceneGraphExplorer(
- parent = sceneGraphPage,
- nodePath = self.levelEditor,
- menuItems = ['Add Group', 'Add Vis Group'])
- self.sceneGraphExplorer.pack(expand = 1, fill = BOTH)
- # Compact down notebook
- self.notebook.setnaturalsize()
- self.colorEntry = VectorWidgets.ColorEntry(
- hull, text = 'Select Color',
- command = self.updateSelectedObjColor)
- self.colorEntry.menu.add_command(
- label = 'Save Color', command = self.levelEditor.saveColor)
- self.colorEntry.pack(fill = X)
- buttonFrame = Frame(hull)
- self.fMapVis = IntVar()
- self.fMapVis.set(0)
- self.mapSnapButton = Checkbutton(buttonFrame,
- text = 'Map Vis',
- width = 6,
- variable = self.fMapVis,
- command = self.toggleMapVis)
- #self.mapSnapButton.pack(side = LEFT, expand = 1, fill = X)
- self.fXyzSnap = IntVar()
- self.fXyzSnap.set(1)
- self.xyzSnapButton = Checkbutton(buttonFrame,
- text = 'XyzSnap',
- width = 6,
- variable = self.fXyzSnap,
- command = self.toggleXyzSnap)
- self.xyzSnapButton.pack(side = LEFT, expand = 1, fill = X)
- self.fHprSnap = IntVar()
- self.fHprSnap.set(1)
- self.hprSnapButton = Checkbutton(buttonFrame,
- text = 'HprSnap',
- width = 6,
- variable = self.fHprSnap,
- command = self.toggleHprSnap)
- self.hprSnapButton.pack(side = LEFT, expand = 1, fill = X)
- def toggleWidgetHandles(s = self):
- if s.fPlaneSnap.get():
- direct.widget.disableHandles(['x-ring', 'x-disc',
- 'y-ring', 'y-disc',
- 'z-post'])
- else:
- direct.widget.enableHandles('all')
- self.fPlaneSnap = IntVar()
- self.fPlaneSnap.set(1)
- self.planeSnapButton = Checkbutton(buttonFrame,
- text = 'PlaneSnap',
- width = 6,
- variable = self.fPlaneSnap,
- command = toggleWidgetHandles)
- self.planeSnapButton.pack(side = LEFT, expand = 1, fill = X)
- self.fGrid = IntVar()
- self.fGrid.set(0)
- direct.gridButton = Checkbutton(buttonFrame,
- text = 'Show Grid',
- width = 6,
- variable = self.fGrid,
- command = self.toggleGrid)
- direct.gridButton.pack(side = LEFT, expand = 1, fill = X)
- buttonFrame.pack(fill = X)
- buttonFrame4 = Frame(hull)
- self.driveMode = IntVar()
- self.driveMode.set(1)
- self.directModeButton = Radiobutton(
- buttonFrame4,
- text = 'DIRECT Fly',
- value = 1,
- variable = self.driveMode,
- command = self.levelEditor.useDirectFly)
- self.directModeButton.pack(side = LEFT, fill = X, expand = 1)
- self.driveModeButton = Radiobutton(
- buttonFrame4,
- text = 'Drive',
- value = 0,
- variable = self.driveMode,
- command = self.levelEditor.useDriveMode)
- self.driveModeButton.pack(side = LEFT, fill = X, expand = 1)
-
- self.fColl = IntVar()
- self.fColl.set(1)
- direct.collButton = Checkbutton(
- buttonFrame4,
- text = 'Collide',
- variable = self.fColl,
- command = self.levelEditor.toggleCollisions)
- direct.collButton.pack(side = LEFT, expand = 1, fill = X)
- self.fVis = IntVar()
- self.fVis.set(1)
- direct.visButton = Checkbutton(
- buttonFrame4,
- text = 'Visibility',
- variable = self.fVis,
- command = self.levelEditor.toggleVisibility)
- direct.visButton.pack(side = LEFT, expand = 1, fill = X)
- self.fVisZones = IntVar()
- self.fVisZones.set(visualizeZones)
- direct.visZonesButton = Checkbutton(
- buttonFrame4,
- text = 'Show Zones',
- variable = self.fVisZones)
- direct.visZonesButton.pack(side = LEFT, expand = 1, fill = X)
- buttonFrame4.pack(fill = X, padx = 5)
-
- # Make sure input variables processed
- self.initialiseoptions(LevelEditorPanel)
- def updateInfo(self, page):
- if page == 'Signs':
- self.updateSignPage()
-
- def toggleGrid(self):
- if self.fGrid.get():
- direct.grid.enable()
- else:
- direct.grid.disable()
- def toggleSuitPaths(self):
- if self.fPaths.get():
- self.levelEditor.showSuitPaths()
- else:
- self.levelEditor.hideSuitPaths()
- def toggleBattleCells(self):
- if self.fCells.get():
- self.levelEditor.showBattleCells()
- else:
- self.levelEditor.hideBattleCells()
- def toggleXyzSnap(self):
- direct.grid.setXyzSnap(self.fXyzSnap.get())
- def toggleHprSnap(self):
- direct.grid.setHprSnap(self.fXyzSnap.get())
-
- def toggleMapVis(self):
- self.levelEditor.toggleMapVis(self.fMapVis.get())
- def setStreetModuleType(self,name):
- self.streetModuleType = 'street_' + name
- self.levelEditor.setCurrent('street_texture', self.streetModuleType)
- def addStreet(self):
- self.levelEditor.addStreet(self.streetModuleType)
- def setFlatBuildingType(self,name):
- self.toonBuildingType = name
- self.levelEditor.setCurrent('building_type', self.toonBuildingType)
-
- def setFlatBuildingHeight(self):
- height = self.heightMode.get()
- self.levelEditor.setCurrent('building_height', height)
- self.updateHeightList(height)
- def updateHeightList(self, height):
- # Update combo box
- heightList = self.levelEditor.getList(`height` + '_ft_wall_heights')
- self.toonBuildingSelector.setlist(
- ['random'] + map(createHeightCode,heightList))
- self.toonBuildingSelector.selectitem(0)
- self.toonBuildingSelector.invoke()
-
- def addFlatBuilding(self):
- self.levelEditor.addFlatBuilding(self.toonBuildingType)
- def setLandmarkType(self,name):
- self.landmarkType = 'toon_landmark_' + name
- self.levelEditor.setCurrent('toon_landmark_texture', self.landmarkType)
- def signPanelSync(self):
- self.baselineMenu.delete(1, END)
- sign=self.findSignFromDNARoot()
- if not sign:
- return
- baselineList = DNAGetChildren(sign, DNA_SIGN_BASELINE)
- for baseline in baselineList:
- s=DNAGetBaselineString(baseline)
- self.baselineMenu.insert(END, s)
- self.baselineMenu.selectitem(0)
- self.selectSignBaseline(0)
-
- def updateSignPage(self):
- if (self.notebook.getcurselection() == 'Signs'):
- sign=self.findSignFromDNARoot()
- # Only update if it's not the current sign:
- if (self.currentSignDNA != sign):
- self.currentSignDNA = sign
- self.signPanelSync()
- def findSignFromDNARoot(self):
- dnaRoot=self.levelEditor.selectedDNARoot
- if not dnaRoot:
- return
- objClass=DNAGetClassType(dnaRoot)
- if (objClass.eq(DNA_LANDMARK_BUILDING)
- or objClass.eq(DNA_PROP)):
- target=DNAGetChildRecursive(dnaRoot, DNA_SIGN)
- return target
-
- def selectSignBaseline(self, val):
- if not self.currentSignDNA:
- return
- # Temporarily undefine DNATarget (this will speed
- # up setting the values, because the callbacks won't
- # call self.levelEditor.replaceSelected() with each
- # setting):
- self.levelEditor.DNATarget=None
- self.currentBaselineDNA=None
- target=None
- index=self.currentBaselineIndex=int((self.baselineMenu.curselection())[0])
- if (index==0):
- target=self.currentSignDNA
- # Unset some ui elements:
- self.baselineString.set('')
- self.fontMenu.selectitem(0)
- self.addCurveFloater.set(0)
- self.addKernFloater.set(0)
- self.addWiggleFloater.set(0)
- self.addStumbleFloater.set(0)
- self.addStompFloater.set(0)
- self.bigFirstLetterIntVar.set(0)
- self.allCapsIntVar.set(0)
- self.dropShadowIntVar.set(0)
- else:
- target=DNAGetChild(self.currentSignDNA, DNA_SIGN_BASELINE, index-1)
- if target:
- # Update panel info:
- self.baselineString.set(DNAGetBaselineString(target))
- self.fontMenu.selectitem(target.getCode())
- self.addCurveFloater.set(target.getWidth())
- self.addKernFloater.set(target.getKern())
- self.addWiggleFloater.set(target.getWiggle())
- self.addStumbleFloater.set(target.getStumble())
- self.addStompFloater.set(target.getStomp())
- flags=target.getFlags()
- self.bigFirstLetterIntVar.set('b' in flags)
- self.allCapsIntVar.set('c' in flags)
- self.dropShadowIntVar.set('d' in flags)
- self.currentBaselineDNA=target
- if target:
- pos=target.getPos()
- self.addXFloater.set(pos[0])
- self.addZFloater.set(pos[2])
- scale=target.getScale()
- self.addScaleXFloater.set(scale[0])
- self.addScaleZFloater.set(scale[2])
- hpr=target.getHpr()
- self.addRollFloater.set(hpr[2])
- self.levelEditor.DNATarget=target
- def deleteSignItem(self):
- """Delete the selected sign or sign baseline"""
- if (self.currentBaselineDNA):
- # Remove the baseline:
- assert(int((self.baselineMenu.curselection())[0]) == self.currentBaselineIndex)
- DNARemoveChildOfClass(self.currentSignDNA, DNA_SIGN_BASELINE,
- self.currentBaselineIndex-1)
- self.baselineMenu.delete(self.currentBaselineIndex)
- self.baselineMenu.selectitem(0)
- self.currentBaselineIndex=0
- self.currentBaselineDNA=None
- self.selectSignBaseline(0)
- self.levelEditor.replaceSelected()
- elif (self.currentSignDNA):
- # Remove the sign:
- assert(int((self.baselineMenu.curselection())[0]) == 0)
- le = self.levelEditor
- le.removeSign(le.DNATarget, le.DNATargetParent)
- self.currentBaselineDNA=None
- self.currentSignDNA=None
- self.levelEditor.replaceSelected()
- def signBaselineTrace(self, a, b, mode):
- #print self, a, b, mode, self.baselineString.get()
- baseline=self.currentBaselineDNA
- if baseline:
- s=self.baselineString.get()
- self.setBaselineString(s)
- def addSignGraphic(self, code):
- """
- Create a new baseline with a graphic and
- add it to the current sign
- """
- sign=self.findSignFromDNARoot()
- if sign:
- graphic=DNASignGraphic()
- graphic.setCode(code)
- baseline=DNASignBaseline()
- baseline.add(graphic)
- sign.add(baseline)
- # Show the UI to the new baseline:
- self.levelEditor.DNATarget=baseline
- self.baselineMenu.insert(END, '['+code+']')
- current=self.baselineMenu.size()-1
- self.baselineMenu.selectitem(current)
- self.selectSignBaseline(current)
- self.levelEditor.replaceSelected()
- def addBaseline(self):
- sign=self.findSignFromDNARoot()
- if sign:
- baseline=DNASignBaseline()
- text="Zoo"
- DNASetBaselineString(baseline, text)
- sign.add(baseline)
- # Show the UI to the new baseline:
- self.levelEditor.DNATarget=baseline
- self.baselineMenu.insert(END, text)
- current=self.baselineMenu.size()-1
- self.baselineMenu.selectitem(current)
- self.selectSignBaseline(current)
- self.levelEditor.replaceSelected()
-
- def addBaselineItem(self):
- pass
-
- def selectSignBaselineItem(self, val):
- baseline=self.currentBaselineDNA
- if baseline:
- baseline.setCode(val)
- self.levelEditor.replaceSelected()
- def setSignBaselineStyle(self, val):
- baseline=self.currentBaselineDNA
- if baseline == None:
- print "\n\nbaseline == None"
- return #skyler: This isn't working yet.
- # As a workaround, select the baseline from the tk panel.
- # Try to find the first baseline in the sign:
- sign=self.findSignFromDNARoot()
- if sign:
- self.currentSignDNA = sign
- baseline=DNAGetChild(sign, DNA_SIGN_BASELINE)
- if baseline and val:
- self.levelEditor.DNATarget=baseline
- self.currentBaselineDNA=baseline
- settings=val
- self.levelEditor.replaceSelectedEnabled=0
-
- # Don't set string: self.baselineString.set('')
- if settings['curve'] != None:
- self.addCurveFloater.set(settings['curve'])
- if settings['kern'] != None:
- self.addKernFloater.set(settings['kern'])
- if settings['wiggle'] != None:
- self.addWiggleFloater.set(settings['wiggle'])
- if settings['stumble'] != None:
- self.addStumbleFloater.set(settings['stumble'])
- if settings['stomp'] != None:
- self.addStompFloater.set(settings['stomp'])
- flags=settings['flags']
- if flags != None:
- self.bigFirstLetterIntVar.set('b' in flags)
- self.setBigFirstLetter();
-
- self.allCapsIntVar.set('c' in flags)
- self.setAllCaps()
-
- self.dropShadowIntVar.set('d' in flags)
- self.setDropShadow()
- code = settings['code']
- if code != None:
- self.fontMenu.selectitem(code)
- self.setSignBaslineFont(code)
-
- if settings['x'] != None:
- self.addXFloater.set(settings['x'])
- if settings['z'] != None:
- self.addZFloater.set(settings['z'])
- if settings['scaleX'] != None:
- self.addScaleXFloater.set(settings['scaleX'])
- if settings['scaleZ'] != None:
- self.addScaleZFloater.set(settings['scaleZ'])
- if settings['roll'] != None:
- self.addRollFloater.set(settings['roll'])
-
- color = settings['color']
- if color != None:
- #self.updateSelectedObjColor(settings['color'])
- self.setCurrentColor(color)
- self.setResetColor(color)
- baseline.setColor(color)
- self.levelEditor.replaceSelectedEnabled=1
- self.levelEditor.replaceSelected()
-
- def setBaselineString(self, val):
- baseline=self.currentBaselineDNA
- if baseline:
- DNASetBaselineString(baseline, val);
- self.baselineMenu.delete(self.currentBaselineIndex)
- self.baselineMenu.insert(self.currentBaselineIndex, val)
- self.baselineMenu.selectitem(self.currentBaselineIndex)
- self.levelEditor.replaceSelected()
- def adjustBaselineFlag(self, newValue, flagChar):
- baseline=self.currentBaselineDNA
- if baseline:
- flags=baseline.getFlags()
- if newValue:
- if not flagChar in flags:
- # Add the flag:
- baseline.setFlags(flags+flagChar)
- elif flagChar in flags:
- # Remove the flag:
- flags=string.join(flags.split(flagChar), '')
- baseline.setFlags(flags)
- self.levelEditor.replaceSelected()
-
- def setBigFirstLetter(self):
- self.adjustBaselineFlag(self.bigFirstLetterIntVar.get(), 'b')
-
- def setAllCaps(self):
- self.adjustBaselineFlag(self.allCapsIntVar.get(), 'c')
-
- def setDropShadow(self):
- self.adjustBaselineFlag(self.dropShadowIntVar.get(), 'd')
-
- def setSignBaslineFont(self, val):
- target=self.levelEditor.DNATarget
- if target and (DNAGetClassType(target).eq(DNA_SIGN_BASELINE)
- or DNAGetClassType(target).eq(DNA_SIGN_TEXT)):
- target.setCode(val)
- self.levelEditor.replaceSelected()
- def setSignBaselineCurve(self, val):
- baseline=self.currentBaselineDNA
- if baseline:
- try:
- val=1.0/val
- except ZeroDivisionError:
- val=0
- baseline.setWidth(val)
- baseline.setHeight(val)
- self.levelEditor.replaceSelected()
- def setSignBaselineKern(self, val):
- baseline=self.currentBaselineDNA
- if baseline:
- baseline.setKern(val)
- self.levelEditor.replaceSelected()
- def setSignBaselineWiggle(self, val):
- baseline=self.currentBaselineDNA
- if baseline:
- baseline.setWiggle(val)
- self.levelEditor.replaceSelected()
- def setSignBaselineStumble(self, val):
- baseline=self.currentBaselineDNA
- if baseline:
- baseline.setStumble(val)
- self.levelEditor.replaceSelected()
- def setSignBaselineStomp(self, val):
- baseline=self.currentBaselineDNA
- if baseline:
- baseline.setStomp(val)
- self.levelEditor.replaceSelected()
- def setDNATargetX(self, val):
- target=self.levelEditor.DNATarget
- if target:
- pos=target.getPos()
- pos=VBase3(val, pos[1], pos[2])
- target.setPos(pos)
- self.levelEditor.replaceSelected()
- def setDNATargetZ(self, val):
- target=self.levelEditor.DNATarget
- if target:
- pos=target.getPos()
- pos=VBase3(pos[0], pos[1], val)
- target.setPos(pos)
- self.levelEditor.replaceSelected()
- def setDNATargetScaleX(self, val):
- target=self.levelEditor.DNATarget
- if target:
- scale=target.getScale()
- scale=VBase3(val, scale[1], scale[2])
- target.setScale(scale)
- self.levelEditor.replaceSelected()
- def setDNATargetScaleZ(self, val):
- target=self.levelEditor.DNATarget
- if target:
- scale=target.getScale()
- scale=VBase3(scale[0], scale[1], val)
- target.setScale(scale)
- self.levelEditor.replaceSelected()
- def setDNATargetRoll(self, val):
- target=self.levelEditor.DNATarget
- if target:
- hpr=target.getHpr()
- hpr=VBase3(hpr[0], hpr[1], val)
- target.setHpr(hpr)
- self.levelEditor.replaceSelected()
- def addLandmark(self):
- self.levelEditor.addLandmark(self.landmarkType)
- def setPropType(self,name):
- self.propType = name
- self.levelEditor.setCurrent('prop_texture', self.propType)
-
- def addProp(self):
- self.levelEditor.addProp(self.propType)
- def updateSelectedWallWidth(self, strVal):
- self.levelEditor.updateSelectedWallWidth(string.atof(strVal))
- def setCurrentColor(self, colorVec, fUpdate = 0):
- # Turn on/off update of selected before updating entry
- self.fUpdateSelected = fUpdate
- self.colorEntry.set([int(colorVec[0] * 255.0),
- int(colorVec[1] * 255.0),
- int(colorVec[2] * 255.0),
- 255])
-
- def setResetColor(self, colorVec):
- self.colorEntry['resetValue'] = (
- [int(colorVec[0] * 255.0),
- int(colorVec[1] * 255.0),
- int(colorVec[2] * 255.0),
- 255])
- def setSuitPointType(self,name):
- if (name == "street"):
- self.levelEditor.currentSuitPointType = DNASuitPoint.STREETPOINT
- elif (name == "front door"):
- self.levelEditor.currentSuitPointType = DNASuitPoint.FRONTDOORPOINT
- elif (name == "side door"):
- self.levelEditor.currentSuitPointType = DNASuitPoint.SIDEDOORPOINT
- print self.levelEditor.currentSuitPointType
- def setBattleCellType(self,name):
- self.levelEditor.currentBattleCellType = name
- def updateSelectedObjColor(self, color):
- try:
- obj = self.levelEditor.DNATarget
- if self.fUpdateSelected and (obj != None):
- objClass = DNAGetClassType(obj)
- if ((objClass.eq(DNA_WALL)) or
- (objClass.eq(DNA_WINDOWS)) or
- (objClass.eq(DNA_DOOR)) or
- (objClass.eq(DNA_CORNICE)) or
- (objClass.eq(DNA_PROP)) or
- (objClass.eq(DNA_SIGN)) or
- (objClass.eq(DNA_SIGN_BASELINE)) or
- (objClass.eq(DNA_SIGN_TEXT)) or
- (objClass.eq(DNA_SIGN_GRAPHIC))
- ):
- self.levelEditor.setDNATargetColor(
- VBase4((color[0]/255.0),
- (color[1]/255.0),
- (color[2]/255.0),
- 1.0))
- except AttributeError:
- pass
- # Default is to update selected
- self.fUpdateSelected = 1
- def toggleBalloon(self):
- if self.toggleBalloonVar.get():
- self.balloon.configure(state = 'balloon')
- else:
- self.balloon.configure(state = 'none')
- class VisGroupsEditor(Pmw.MegaToplevel):
- def __init__(self, levelEditor, visGroups = ['None'],
- parent = None, **kw):
- INITOPT = Pmw.INITOPT
- optiondefs = (
- ('title', 'Visability Groups Editor', None),
- )
- self.defineoptions(kw, optiondefs)
- Pmw.MegaToplevel.__init__(self, parent, title = self['title'])
- self.levelEditor = levelEditor
- self.visGroups = visGroups
- self.visGroupNames = map(lambda pair: pair[1].getName(),
- self.visGroups)
- # Initialize dictionary of visibility relationships
- self.visDict = {}
- # Group we are currently setting visGroups for
- self.target = None
- # Flag to enable/disable toggleVisGroup command
- self.fCommand = 1
- # Handle to the toplevels hull
- hull = self.component('hull')
- balloon = self.balloon = Pmw.Balloon(hull)
- # Start with balloon help disabled
- self.balloon.configure(state = 'none')
-
- menuFrame = Frame(hull, relief = GROOVE, bd = 2)
- menuFrame.pack(fill = X, expand = 1)
- menuBar = Pmw.MenuBar(menuFrame, hotkeys = 1, balloon = balloon)
- menuBar.pack(side = LEFT, expand = 1, fill = X)
- menuBar.addmenu('Vis Groups Editor',
- 'Visability Groups Editor Operations')
- menuBar.addmenuitem('Vis Groups Editor', 'command',
- 'Exit Visability Groups Editor',
- label = 'Exit',
- command = self.preDestroy)
- menuBar.addmenu('Help', 'Visability Groups Editor Help Operations')
- self.toggleBalloonVar = IntVar()
- self.toggleBalloonVar.set(0)
- menuBar.addmenuitem('Help', 'checkbutton',
- 'Toggle balloon help',
- label = 'Balloon Help',
- variable = self.toggleBalloonVar,
- command = self.toggleBalloon)
- # Create a combo box to choose target vis group
- self.targetSelector = Pmw.ComboBox(
- hull, labelpos = W, label_text = 'Target Vis Group:',
- entry_width = 12, selectioncommand = self.selectVisGroup,
- scrolledlist_items = self.visGroupNames)
- self.targetSelector.selectitem(self.visGroupNames[0])
- self.targetSelector.pack(expand = 1, fill = X)
- # Scrolled frame to hold radio selector
- sf = Pmw.ScrolledFrame(hull, horizflex = 'elastic',
- usehullsize = 1, hull_width = 200,
- hull_height = 400)
- frame = sf.interior()
- sf.pack(padx=5, pady=3, fill = BOTH, expand = 1)
- # Add vis groups selector
- self.selected = Pmw.RadioSelect(frame, selectmode=MULTIPLE,
- orient = VERTICAL,
- pady = 0,
- command = self.toggleVisGroup)
- for groupInfo in self.visGroups:
- nodePath = groupInfo[0]
- group = groupInfo[1]
- name = group.getName()
- self.selected.add(name, width = 12)
- # Assemble list of groups visible from this group
- visible = []
- for i in range(group.getNumVisibles()):
- visible.append(group.getVisibleName(i))
- visible.sort()
- self.visDict[name] = [nodePath, group, visible]
- # Pack the widget
- self.selected.pack(expand = 1, fill = X)
- # And make sure scrolled frame is happy
- sf.reposition()
- buttonFrame = Frame(hull)
- buttonFrame.pack(fill=X, expand = 1)
- self.showMode = IntVar()
- self.showMode.set(0)
- self.showAllButton = Radiobutton(buttonFrame, text = 'Show All',
- value = 0, indicatoron = 1,
- variable = self.showMode,
- command = self.refreshVisibility)
- self.showAllButton.pack(side = LEFT, fill = X, expand = 1)
- self.showActiveButton = Radiobutton(buttonFrame, text = 'Show Target',
- value = 1, indicatoron = 1,
- variable = self.showMode,
- command = self.refreshVisibility)
- self.showActiveButton.pack(side = LEFT, fill = X, expand = 1)
- # Make sure input variables processed
- self.initialiseoptions(VisGroupsEditor)
-
- # Switch to current target's list
- self.selectVisGroup(self.visGroupNames[0])
- def selectVisGroup(self, target):
- print 'Setting vis options for group:', target
- # Record current target
- oldTarget = self.target
- # Record new target
- self.target = target
- # Deselect buttons from old target (first deactivating command)
- self.fCommand = 0
- if oldTarget:
- visList = self.visDict[oldTarget][2]
- for group in visList:
- self.selected.invoke(self.selected.index(group))
- # Now set buttons to reflect state of new target
- visList = self.visDict[target][2]
- for group in visList:
- self.selected.invoke(self.selected.index(group))
- # Reactivate command
- self.fCommand = 1
- # Update scene
- self.refreshVisibility()
- def toggleVisGroup(self, groupName, state):
- if self.fCommand:
- targetInfo = self.visDict[self.target]
- target = targetInfo[1]
- visList = targetInfo[2]
- groupNP = self.visDict[groupName][0]
- group = self.visDict[groupName][1]
- # MRM: Add change in visibility here
- # Show all vs. show active
- if state == 1:
- print 'Vis Group:', self.target, 'adding group:', groupName
- if groupName not in visList:
- visList.append(groupName)
- target.addVisible(groupName)
- # Update vis and color
- groupNP.show()
- groupNP.setColor(1,0,0,1)
- else:
- print 'Vis Group:', self.target, 'removing group:', groupName
- if groupName in visList:
- visList.remove(groupName)
- target.removeVisible(groupName)
- # Update vis and color
- if self.showMode.get() == 1:
- groupNP.hide()
- groupNP.clearColor()
- def refreshVisibility(self):
- # Get current visibility list for target
- targetInfo = self.visDict[self.target]
- visList = targetInfo[2]
- for key in self.visDict.keys():
- groupNP = self.visDict[key][0]
- if key in visList:
- groupNP.show()
- if key == self.target:
- groupNP.setColor(0,1,0,1)
- else:
- groupNP.setColor(1,0,0,1)
- else:
- if self.showMode.get() == 0:
- groupNP.show()
- else:
- groupNP.hide()
- groupNP.clearColor()
- def preDestroy(self):
- # First clear level editor variable
- self.levelEditor.vgpanel = None
- self.destroy()
- def toggleBalloon(self):
- if self.toggleBalloonVar.get():
- self.balloon.configure(state = 'balloon')
- else:
- self.balloon.configure(state = 'none')
-
- l = LevelEditor()
- run()
|