WorldEditorView.cpp 442 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485104861048710488104891049010491104921049310494104951049610497104981049910500105011050210503105041050510506105071050810509105101051110512105131051410515105161051710518105191052010521105221052310524105251052610527105281052910530105311053210533105341053510536105371053810539105401054110542105431054410545105461054710548105491055010551105521055310554105551055610557105581055910560105611056210563105641056510566105671056810569105701057110572105731057410575105761057710578105791058010581105821058310584105851058610587105881058910590105911059210593105941059510596105971059810599106001060110602106031060410605106061060710608106091061010611106121061310614106151061610617106181061910620106211062210623106241062510626106271062810629106301063110632106331063410635106361063710638106391064010641106421064310644106451064610647106481064910650106511065210653106541065510656106571065810659106601066110662106631066410665106661066710668106691067010671106721067310674106751067610677106781067910680106811068210683106841068510686106871068810689106901069110692106931069410695106961069710698106991070010701107021070310704107051070610707107081070910710107111071210713107141071510716107171071810719107201072110722107231072410725107261072710728107291073010731107321073310734107351073610737107381073910740107411074210743107441074510746107471074810749107501075110752107531075410755107561075710758107591076010761107621076310764107651076610767107681076910770107711077210773107741077510776107771077810779107801078110782107831078410785107861078710788107891079010791107921079310794107951079610797107981079910800108011080210803108041080510806108071080810809108101081110812108131081410815108161081710818108191082010821108221082310824108251082610827108281082910830108311083210833108341083510836108371083810839108401084110842108431084410845108461084710848108491085010851108521085310854108551085610857108581085910860108611086210863108641086510866108671086810869108701087110872108731087410875108761087710878108791088010881108821088310884108851088610887108881088910890108911089210893108941089510896108971089810899109001090110902109031090410905109061090710908109091091010911109121091310914109151091610917109181091910920109211092210923109241092510926109271092810929109301093110932109331093410935109361093710938109391094010941109421094310944109451094610947109481094910950109511095210953109541095510956109571095810959109601096110962109631096410965109661096710968109691097010971109721097310974109751097610977109781097910980109811098210983109841098510986109871098810989109901099110992109931099410995109961099710998109991100011001110021100311004110051100611007110081100911010110111101211013110141101511016110171101811019110201102111022110231102411025110261102711028110291103011031110321103311034110351103611037110381103911040110411104211043110441104511046110471104811049110501105111052110531105411055110561105711058110591106011061110621106311064110651106611067110681106911070110711107211073110741107511076110771107811079110801108111082110831108411085110861108711088110891109011091110921109311094110951109611097110981109911100111011110211103111041110511106111071110811109111101111111112111131111411115111161111711118111191112011121111221112311124111251112611127111281112911130111311113211133111341113511136111371113811139111401114111142111431114411145111461114711148111491115011151111521115311154111551115611157111581115911160111611116211163111641116511166111671116811169111701117111172111731117411175111761117711178111791118011181111821118311184111851118611187111881118911190111911119211193111941119511196111971119811199112001120111202112031120411205112061120711208112091121011211112121121311214112151121611217112181121911220112211122211223112241122511226112271122811229112301123111232112331123411235112361123711238112391124011241112421124311244112451124611247112481124911250112511125211253112541125511256112571125811259112601126111262112631126411265112661126711268112691127011271112721127311274112751127611277112781127911280112811128211283112841128511286112871128811289112901129111292112931129411295112961129711298112991130011301113021130311304113051130611307113081130911310113111131211313113141131511316113171131811319113201132111322113231132411325113261132711328113291133011331113321133311334113351133611337113381133911340113411134211343113441134511346113471134811349113501135111352113531135411355113561135711358113591136011361113621136311364113651136611367113681136911370113711137211373113741137511376113771137811379113801138111382113831138411385113861138711388113891139011391113921139311394113951139611397113981139911400114011140211403114041140511406114071140811409114101141111412114131141411415114161141711418114191142011421114221142311424114251142611427114281142911430114311143211433114341143511436114371143811439114401144111442114431144411445114461144711448114491145011451114521145311454114551145611457114581145911460114611146211463114641146511466114671146811469114701147111472114731147411475114761147711478114791148011481114821148311484114851148611487114881148911490114911149211493114941149511496114971149811499115001150111502115031150411505115061150711508115091151011511115121151311514115151151611517115181151911520115211152211523115241152511526115271152811529115301153111532115331153411535115361153711538115391154011541115421154311544115451154611547115481154911550115511155211553115541155511556115571155811559115601156111562115631156411565115661156711568115691157011571115721157311574115751157611577115781157911580115811158211583115841158511586115871158811589115901159111592115931159411595115961159711598115991160011601116021160311604116051160611607116081160911610116111161211613116141161511616116171161811619116201162111622116231162411625116261162711628116291163011631116321163311634116351163611637116381163911640116411164211643116441164511646116471164811649116501165111652116531165411655116561165711658116591166011661116621166311664116651166611667116681166911670116711167211673116741167511676116771167811679116801168111682116831168411685116861168711688116891169011691116921169311694116951169611697116981169911700117011170211703117041170511706117071170811709117101171111712117131171411715117161171711718117191172011721117221172311724117251172611727117281172911730117311173211733117341173511736117371173811739117401174111742117431174411745117461174711748117491175011751117521175311754117551175611757117581175911760117611176211763117641176511766117671176811769117701177111772117731177411775117761177711778117791178011781117821178311784117851178611787117881178911790117911179211793117941179511796117971179811799118001180111802118031180411805118061180711808118091181011811118121181311814118151181611817118181181911820118211182211823118241182511826118271182811829118301183111832118331183411835118361183711838118391184011841118421184311844118451184611847118481184911850118511185211853118541185511856118571185811859118601186111862118631186411865118661186711868118691187011871118721187311874118751187611877118781187911880118811188211883118841188511886118871188811889118901189111892118931189411895118961189711898118991190011901119021190311904119051190611907119081190911910119111191211913119141191511916119171191811919119201192111922119231192411925119261192711928119291193011931119321193311934119351193611937119381193911940119411194211943119441194511946119471194811949119501195111952119531195411955119561195711958119591196011961119621196311964119651196611967119681196911970119711197211973119741197511976119771197811979119801198111982119831198411985119861198711988119891199011991119921199311994119951199611997119981199912000120011200212003120041200512006120071200812009120101201112012120131201412015120161201712018120191202012021120221202312024120251202612027120281202912030120311203212033120341203512036120371203812039120401204112042120431204412045120461204712048120491205012051120521205312054120551205612057120581205912060120611206212063120641206512066120671206812069120701207112072120731207412075120761207712078120791208012081120821208312084120851208612087120881208912090120911209212093120941209512096120971209812099121001210112102121031210412105121061210712108121091211012111121121211312114121151211612117121181211912120121211212212123121241212512126121271212812129121301213112132121331213412135121361213712138121391214012141121421214312144121451214612147121481214912150121511215212153121541215512156121571215812159121601216112162121631216412165121661216712168121691217012171121721217312174121751217612177121781217912180121811218212183121841218512186121871218812189121901219112192121931219412195121961219712198121991220012201122021220312204122051220612207122081220912210122111221212213122141221512216122171221812219122201222112222122231222412225122261222712228122291223012231122321223312234122351223612237122381223912240122411224212243122441224512246122471224812249122501225112252122531225412255122561225712258122591226012261122621226312264122651226612267122681226912270122711227212273122741227512276122771227812279122801228112282122831228412285122861228712288122891229012291122921229312294122951229612297122981229912300123011230212303123041230512306123071230812309123101231112312123131231412315123161231712318123191232012321123221232312324123251232612327123281232912330123311233212333123341233512336123371233812339123401234112342123431234412345123461234712348123491235012351123521235312354123551235612357123581235912360123611236212363123641236512366123671236812369123701237112372123731237412375123761237712378123791238012381123821238312384123851238612387123881238912390123911239212393123941239512396123971239812399124001240112402124031240412405124061240712408124091241012411124121241312414124151241612417124181241912420124211242212423124241242512426124271242812429124301243112432124331243412435124361243712438124391244012441124421244312444124451244612447124481244912450124511245212453124541245512456124571245812459124601246112462124631246412465124661246712468124691247012471124721247312474124751247612477124781247912480124811248212483124841248512486124871248812489124901249112492124931249412495124961249712498124991250012501125021250312504125051250612507125081250912510125111251212513125141251512516125171251812519125201252112522125231252412525125261252712528125291253012531125321253312534125351253612537125381253912540125411254212543125441254512546125471254812549125501255112552125531255412555125561255712558125591256012561125621256312564125651256612567125681256912570125711257212573125741257512576125771257812579125801258112582125831258412585125861258712588125891259012591125921259312594125951259612597125981259912600126011260212603126041260512606126071260812609126101261112612126131261412615126161261712618126191262012621126221262312624126251262612627126281262912630126311263212633126341263512636126371263812639126401264112642126431264412645126461264712648126491265012651126521265312654126551265612657126581265912660126611266212663126641266512666126671266812669126701267112672126731267412675126761267712678126791268012681126821268312684126851268612687126881268912690126911269212693126941269512696126971269812699127001270112702127031270412705127061270712708127091271012711127121271312714127151271612717127181271912720127211272212723127241272512726127271272812729127301273112732127331273412735127361273712738127391274012741127421274312744127451274612747127481274912750127511275212753127541275512756127571275812759127601276112762127631276412765127661276712768127691277012771127721277312774127751277612777127781277912780127811278212783127841278512786127871278812789127901279112792127931279412795127961279712798127991280012801128021280312804128051280612807128081280912810128111281212813128141281512816128171281812819128201282112822128231282412825128261282712828128291283012831128321283312834128351283612837128381283912840128411284212843128441284512846128471284812849128501285112852128531285412855128561285712858128591286012861128621286312864128651286612867128681286912870128711287212873128741287512876128771287812879128801288112882128831288412885128861288712888128891289012891128921289312894128951289612897128981289912900129011290212903129041290512906129071290812909129101291112912129131291412915129161291712918129191292012921129221292312924129251292612927129281292912930129311293212933129341293512936129371293812939129401294112942129431294412945129461294712948129491295012951129521295312954129551295612957129581295912960129611296212963129641296512966129671296812969129701297112972129731297412975129761297712978129791298012981129821298312984129851298612987129881298912990129911299212993129941299512996129971299812999130001300113002130031300413005130061300713008130091301013011130121301313014130151301613017130181301913020130211302213023130241302513026130271302813029130301303113032130331303413035130361303713038130391304013041130421304313044130451304613047130481304913050130511305213053130541305513056130571305813059130601306113062130631306413065130661306713068130691307013071130721307313074130751307613077130781307913080130811308213083130841308513086130871308813089130901309113092130931309413095130961309713098130991310013101131021310313104131051310613107131081310913110131111311213113131141311513116131171311813119131201312113122131231312413125131261312713128131291313013131131321313313134131351313613137131381313913140131411314213143131441314513146131471314813149131501315113152131531315413155131561315713158131591316013161131621316313164131651316613167131681316913170131711317213173131741317513176131771317813179131801318113182131831318413185131861318713188131891319013191131921319313194131951319613197131981319913200132011320213203132041320513206132071320813209132101321113212132131321413215132161321713218132191322013221132221322313224132251322613227132281322913230132311323213233132341323513236132371323813239132401324113242132431324413245132461324713248132491325013251132521325313254132551325613257132581325913260132611326213263132641326513266132671326813269132701327113272132731327413275132761327713278132791328013281132821328313284132851328613287132881328913290132911329213293132941329513296132971329813299133001330113302133031330413305133061330713308133091331013311133121331313314133151331613317133181331913320133211332213323133241332513326133271332813329133301333113332133331333413335133361333713338133391334013341133421334313344133451334613347133481334913350133511335213353133541335513356133571335813359133601336113362133631336413365133661336713368133691337013371133721337313374133751337613377133781337913380133811338213383133841338513386133871338813389133901339113392133931339413395133961339713398133991340013401134021340313404134051340613407134081340913410134111341213413134141341513416134171341813419134201342113422134231342413425134261342713428134291343013431134321343313434134351343613437134381343913440134411344213443134441344513446134471344813449134501345113452134531345413455134561345713458134591346013461134621346313464134651346613467134681346913470134711347213473134741347513476134771347813479134801348113482134831348413485134861348713488134891349013491134921349313494134951349613497134981349913500135011350213503135041350513506135071350813509135101351113512135131351413515135161351713518135191352013521135221352313524135251352613527135281352913530135311353213533135341353513536135371353813539135401354113542135431354413545135461354713548135491355013551135521355313554135551355613557135581355913560135611356213563135641356513566135671356813569135701357113572135731357413575135761357713578135791358013581135821358313584135851358613587135881358913590135911359213593135941359513596135971359813599136001360113602136031360413605136061360713608136091361013611136121361313614136151361613617136181361913620136211362213623136241362513626136271362813629136301363113632136331363413635136361363713638136391364013641136421364313644136451364613647136481364913650136511365213653136541365513656136571365813659136601366113662136631366413665136661366713668136691367013671136721367313674136751367613677136781367913680136811368213683136841368513686136871368813689136901369113692136931369413695136961369713698136991370013701137021370313704137051370613707137081370913710137111371213713137141371513716137171371813719137201372113722137231372413725
  1. /* Copyright (c) 2002-2012 Croteam Ltd.
  2. This program is free software; you can redistribute it and/or modify
  3. it under the terms of version 2 of the GNU General Public License as published by
  4. the Free Software Foundation
  5. This program is distributed in the hope that it will be useful,
  6. but WITHOUT ANY WARRANTY; without even the implied warranty of
  7. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  8. GNU General Public License for more details.
  9. You should have received a copy of the GNU General Public License along
  10. with this program; if not, write to the Free Software Foundation, Inc.,
  11. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
  12. // WorldEditorView.cpp : implementation of the CWorldEditorView class
  13. //
  14. #include "stdafx.h"
  15. #include "WorldEditor.h"
  16. #include <Engine/Base/Profiling.h>
  17. #include <Engine/Base/Statistics.h>
  18. #include <Engine/Templates/Stock_CTextureData.h>
  19. #include <Engine/Terrain/TerrainEditing.h>
  20. #include <Engine/Terrain/TerrainMisc.h>
  21. #ifdef _DEBUG
  22. #undef new
  23. #define new DEBUG_NEW
  24. #undef THIS_FILE
  25. static char THIS_FILE[] = __FILE__;
  26. #endif
  27. CTimerValue _tvLastTerrainBrushingApplied;
  28. static INDEX aiForCreationOfSizingVertices[14][6] =
  29. {
  30. {0,0,2,2,5,5},
  31. {1,1,2,2,5,5},
  32. {1,1,2,2,4,4},
  33. {0,0,2,2,4,4},
  34. {0,0,3,3,5,5},
  35. {1,1,3,3,5,5},
  36. {1,1,3,3,4,4},
  37. {0,0,3,3,4,4},
  38. {0,1,2,3,5,5},
  39. {1,1,2,3,4,5},
  40. {0,1,2,3,4,4},
  41. {0,0,2,3,4,5},
  42. {0,1,2,2,4,5},
  43. {0,1,3,3,4,5},
  44. };
  45. static INDEX aiForAllowedSizing[14][6] =
  46. {
  47. {1,0,1,0,0,1},
  48. {0,1,1,0,0,1},
  49. {0,1,1,0,1,0},
  50. {1,0,1,0,1,0},
  51. {1,0,0,1,0,1},
  52. {0,1,0,1,0,1},
  53. {0,1,0,1,1,0},
  54. {1,0,0,1,1,0},
  55. {0,0,0,0,0,1},
  56. {0,1,0,0,0,0},
  57. {0,0,0,0,1,0},
  58. {1,0,0,0,0,0},
  59. {0,0,1,0,0,0},
  60. {0,0,0,1,0,0},
  61. };
  62. /////////////////////////////////////////////////////////////////////////////
  63. // CWorldEditorView
  64. IMPLEMENT_DYNCREATE(CWorldEditorView, CView)
  65. BEGIN_MESSAGE_MAP(CWorldEditorView, CView)
  66. //{{AFX_MSG_MAP(CWorldEditorView)
  67. ON_WM_CREATE()
  68. ON_WM_SIZE()
  69. ON_WM_KILLFOCUS()
  70. ON_WM_LBUTTONDOWN()
  71. ON_WM_KEYDOWN()
  72. ON_WM_KEYUP()
  73. ON_WM_MOUSEMOVE()
  74. ON_WM_RBUTTONDOWN()
  75. ON_WM_LBUTTONUP()
  76. ON_WM_RBUTTONUP()
  77. ON_WM_DROPFILES()
  78. ON_COMMAND(ID_ISOMETRIC_FRONT, OnIsometricFront)
  79. ON_COMMAND(ID_ISOMETRIC_BACK, OnIsometricBack)
  80. ON_COMMAND(ID_ISOMETRIC_BOTTOM, OnIsometricBottom)
  81. ON_COMMAND(ID_ISOMETRIC_LEFT, OnIsometricLeft)
  82. ON_COMMAND(ID_ISOMETRIC_RIGHT, OnIsometricRight)
  83. ON_COMMAND(ID_ISOMETRIC_TOP, OnIsometricTop)
  84. ON_COMMAND(ID_PERSPECTIVE, OnPerspective)
  85. ON_COMMAND(ID_ZOOM_LESS, OnZoomLess)
  86. ON_COMMAND(ID_ZOOM_MORE, OnZoomMore)
  87. ON_COMMAND(ID_MOVE_DOWN, OnMoveDown)
  88. ON_COMMAND(ID_MOVE_UP, OnMoveUp)
  89. ON_WM_LBUTTONDBLCLK()
  90. ON_COMMAND(ID_MEASUREMENT_TAPE, OnMeasurementTape)
  91. ON_UPDATE_COMMAND_UI(ID_MEASUREMENT_TAPE, OnUpdateMeasurementTape)
  92. ON_COMMAND(ID_CIRCLE_MODES, OnCircleModes)
  93. ON_UPDATE_COMMAND_UI(ID_CIRCLE_MODES, OnUpdateCircleModes)
  94. ON_COMMAND(ID_DESELECT_ALL, OnDeselectAll)
  95. ON_COMMAND(ID_DELETE_ENTITIES, OnDeleteEntities)
  96. ON_UPDATE_COMMAND_UI(ID_DELETE_ENTITIES, OnUpdateDeleteEntities)
  97. ON_WM_SETCURSOR()
  98. ON_COMMAND(ID_TAKE_SS, OnTakeSs)
  99. ON_UPDATE_COMMAND_UI(ID_ENTITY_MODE, OnUpdateEntityMode)
  100. ON_COMMAND(ID_SECTOR_MODE, OnSectorMode)
  101. ON_UPDATE_COMMAND_UI(ID_SECTOR_MODE, OnUpdateSectorMode)
  102. ON_COMMAND(ID_POLYGON_MODE, OnPolygonMode)
  103. ON_UPDATE_COMMAND_UI(ID_POLYGON_MODE, OnUpdatePolygonMode)
  104. ON_COMMAND(ID_EDIT_PASTE, OnEditPaste)
  105. ON_COMMAND(ID_EDIT_COPY, OnEditCopy)
  106. ON_COMMAND(ID_CLONE_CSG, OnCloneCSG)
  107. ON_UPDATE_COMMAND_UI(ID_CLONE_CSG, OnUpdateCloneCsg)
  108. ON_COMMAND(ID_MEASURE_ON, OnMeasureOn)
  109. ON_UPDATE_COMMAND_UI(ID_MEASURE_ON, OnUpdateMeasureOn)
  110. ON_COMMAND(ID_RESET_VIEWER, OnResetViewer)
  111. ON_COMMAND(ID_COPY_TEXTURE, OnCopyTexture)
  112. ON_COMMAND(ID_PASTE_TEXTURE, OnPasteTexture)
  113. ON_COMMAND(ID_CENTER_ENTITY, OnCenterEntity)
  114. ON_COMMAND(ID_FUNCTION, OnFunction)
  115. ON_UPDATE_COMMAND_UI(ID_CENTER_ENTITY, OnUpdateCenterEntity)
  116. ON_COMMAND(ID_DROP_MARKER, OnDropMarker)
  117. ON_UPDATE_COMMAND_UI(ID_DROP_MARKER, OnUpdateDropMarker)
  118. ON_COMMAND(ID_TEST_CONNECTIONS, OnTestConnections)
  119. ON_UPDATE_COMMAND_UI(ID_TEST_CONNECTIONS, OnUpdateTestConnections)
  120. ON_COMMAND(ID_ALIGN_VOLUME, OnAlignVolume)
  121. ON_UPDATE_COMMAND_UI(ID_ALIGN_VOLUME, OnUpdateAlignVolume)
  122. ON_COMMAND(ID_CURRENT_VIEW_PROPERTIES, OnCurrentViewProperties)
  123. ON_COMMAND(ID_DELETE_MIP, OnDeleteMip)
  124. ON_UPDATE_COMMAND_UI(ID_DELETE_MIP, OnUpdateDeleteMip)
  125. ON_COMMAND(ID_PREVIOUS_MIP_BRUSH, OnPreviousMipBrush)
  126. ON_UPDATE_COMMAND_UI(ID_PREVIOUS_MIP_BRUSH, OnUpdatePreviousMipBrush)
  127. ON_COMMAND(ID_NEXT_MIP_BRUSH, OnNextMipBrush)
  128. ON_UPDATE_COMMAND_UI(ID_NEXT_MIP_BRUSH, OnUpdateNextMipBrush)
  129. ON_COMMAND(ID_CROSSROAD_FOR_C, OnCrossroadForC)
  130. ON_COMMAND(ID_CHOOSE_COLOR, OnChooseColor)
  131. ON_UPDATE_COMMAND_UI(ID_CHOOSE_COLOR, OnUpdateChooseColor)
  132. ON_COMMAND(ID_MENU_COPY_MAPPING, OnMenuCopyMapping)
  133. ON_COMMAND(ID_MENU_PASTE_MAPPING, OnMenuPasteMapping)
  134. ON_COMMAND(ID_SET_AS_CSG_TARGET, OnSetAsCsgTarget)
  135. ON_COMMAND(ID_KEY_PASTE, OnKeyPaste)
  136. ON_WM_RBUTTONDBLCLK()
  137. ON_COMMAND(ID_SELECT_BY_TEXTURE_ADJACENT, OnSelectByTextureAdjacent)
  138. ON_COMMAND(ID_SELECT_BY_TEXTURE_IN_SECTOR, OnSelectByTextureInSector)
  139. ON_COMMAND(ID_SELECT_BY_COLOR_IN_SECTOR, OnSelectByColorInSector)
  140. ON_COMMAND(ID_CONUS_PRIMITIVE, OnConusPrimitive)
  141. ON_COMMAND(ID_TORUS_PRIMITIVE, OnTorusPrimitive)
  142. ON_COMMAND(ID_TERRAIN_PRIMITIVE, OnTerrainPrimitive)
  143. ON_COMMAND(ID_SPHERE_PRIMITIVE, OnSpherePrimitive)
  144. ON_COMMAND(ID_STAIRCASE_PRIMITIVE, OnStaircasePrimitive)
  145. ON_UPDATE_COMMAND_UI(ID_CONUS_PRIMITIVE, OnUpdateConusPrimitive)
  146. ON_UPDATE_COMMAND_UI(ID_SPHERE_PRIMITIVE, OnUpdateSpherePrimitive)
  147. ON_UPDATE_COMMAND_UI(ID_TERRAIN_PRIMITIVE, OnUpdateTerrainPrimitive)
  148. ON_UPDATE_COMMAND_UI(ID_TORUS_PRIMITIVE, OnUpdateTorusPrimitive)
  149. ON_UPDATE_COMMAND_UI(ID_STAIRCASE_PRIMITIVE, OnUpdateStaircasePrimitive)
  150. ON_COMMAND(ID_POPUP_CONUS, OnPopupConus)
  151. ON_COMMAND(ID_POPUP_SPHERE, OnPopupSphere)
  152. ON_COMMAND(ID_POPUP_STAIRS, OnPopupStairs)
  153. ON_COMMAND(ID_POPUP_TERRAIN, OnPopupTerrain)
  154. ON_COMMAND(ID_POPUP_TORUS, OnPopupTorus)
  155. ON_UPDATE_COMMAND_UI(ID_MOVE_DOWN, OnUpdateMoveDown)
  156. ON_UPDATE_COMMAND_UI(ID_MOVE_UP, OnUpdateMoveUp)
  157. ON_COMMAND(ID_SELECT_LIGHTS, OnSelectLights)
  158. ON_COMMAND(ID_DISCARD_SHADOWS, OnDiscardShadows)
  159. ON_COMMAND(ID_COPY_SECTOR_AMBIENT, OnCopySectorAmbient)
  160. ON_COMMAND(ID_PASTE_SECTOR_AMBIENT, OnPasteSectorAmbient)
  161. ON_COMMAND(ID_SELECT_ALL_POLYGONS, OnSelectAllPolygons)
  162. ON_COMMAND(ID_COPY_SECTORS, OnCopySectors)
  163. ON_COMMAND(ID_DELETE_SECTORS, OnDeleteSectors)
  164. ON_COMMAND(ID_PASTE_SECTORS, OnPasteSectors)
  165. ON_COMMAND(ID_CENTER_BCG_VIEWER, OnCenterBcgViewer)
  166. ON_COMMAND(ID_MENU_PASTE_AS_PROJECTED_MAPPING, OnMenuPasteAsProjectedMapping)
  167. ON_COMMAND(ID_KEY_PASTE_AS_PROJECTED, OnKeyPasteAsProjected)
  168. ON_COMMAND(ID_SELECT_ALL_ENTITIES, OnSelectAllEntitiesInSectors)
  169. ON_COMMAND(ID_SELECT_ALL_SECTORS, OnSelectAllSectors)
  170. ON_COMMAND(ID_LAST_PRIMITIVE, OnLastPrimitive)
  171. ON_UPDATE_COMMAND_UI(ID_LAST_PRIMITIVE, OnUpdateLastPrimitive)
  172. ON_COMMAND(ID_CLONE_TO_MORE_PRECISE_MIP, OnCloneToMorePreciseMip)
  173. ON_COMMAND(ID_CLONE_TO_ROUGHER_MIP_LEVEL, OnCloneToRougherMipLevel)
  174. ON_COMMAND(ID_CREATE_EMPTY_MORE_PRECISE_MIP, OnCreateEmptyMorePreciseMip)
  175. ON_COMMAND(ID_CREATE_EMPTY_ROUGHER_MIP, OnCreateEmptyRougherMip)
  176. ON_UPDATE_COMMAND_UI(ID_CLONE_TO_MORE_PRECISE_MIP, OnUpdateCloneToMorePreciseMip)
  177. ON_UPDATE_COMMAND_UI(ID_CLONE_TO_ROUGHER_MIP_LEVEL, OnUpdateCloneToRougherMipLevel)
  178. ON_UPDATE_COMMAND_UI(ID_CREATE_EMPTY_MORE_PRECISE_MIP, OnUpdateCreateEmptyMorePreciseMip)
  179. ON_UPDATE_COMMAND_UI(ID_CREATE_EMPTY_ROUGHER_MIP, OnUpdateCreateEmptyRougherMip)
  180. ON_COMMAND(ID_EDIT_PASTE_ALTERNATIVE, OnEditPasteAlternative)
  181. ON_COMMAND(ID_SELECT_ALL_ENTITIES_IN_WORLD, OnSelectAllEntitiesInWorld)
  182. ON_UPDATE_COMMAND_UI(ID_EDIT_PASTE_ALTERNATIVE, OnUpdateEditPasteAlternative)
  183. ON_COMMAND(ID_ENTITY_MODE, OnEntityMode)
  184. ON_COMMAND(ID_FIND_TEXTURE, OnFindTexture)
  185. ON_COMMAND(ID_SELECT_SECTORS_WITH_SAME_NAME, OnSelectSectorsWithSameName)
  186. ON_COMMAND(ID_SELECT_SECTORS_ARROUND_ENTITY, OnSelectSectorsArroundEntity)
  187. ON_COMMAND(ID_SELECT_SECTORS_ARROUND_ENTITY_ON_CONTEXT, OnSelectSectorsArroundEntityOnContext)
  188. ON_COMMAND(ID_INSERT_VERTEX, OnInsertVertex)
  189. ON_COMMAND(ID_DELETE_VERTEX, OnDeleteVertex)
  190. ON_COMMAND(ID_SAVE_PICTURES_FOR_ENVIRONMENT, OnSavePicturesForEnvironment)
  191. ON_UPDATE_COMMAND_UI(ID_SAVE_PICTURES_FOR_ENVIRONMENT, OnUpdateSavePicturesForEnvironment)
  192. ON_WM_ERASEBKGND()
  193. ON_COMMAND(ID_CSG_SELECT_SECTOR, OnCsgSelectSector)
  194. ON_COMMAND(ID_MENU_ALIGN_MAPPING_U, OnMenuAlignMappingU)
  195. ON_COMMAND(ID_MENU_ALIGN_MAPPING_V, OnMenuAlignMappingV)
  196. ON_WM_DESTROY()
  197. ON_COMMAND(ID_FALL_DOWN, OnFallDown)
  198. ON_COMMAND(ID_PREVIOUS, OnPrevious)
  199. ON_COMMAND(ID_NEXT, OnNext)
  200. ON_UPDATE_COMMAND_UI(ID_PREVIOUS, OnUpdatePrevious)
  201. ON_UPDATE_COMMAND_UI(ID_NEXT, OnUpdateNext)
  202. ON_COMMAND(ID_REMOVE_UNUSED_TEXTURES, OnRemoveUnusedTextures)
  203. ON_COMMAND(ID_ROTATE, OnRotate)
  204. ON_COMMAND(ID_ROTATE_BACK, OnRotateBack)
  205. ON_COMMAND(ID_SELECT_VISIBLE_SECTORS, OnSelectVisibleSectors)
  206. ON_COMMAND(ID_EDIT_COPY_ALTERNATIVE, OnEditCopyAlternative)
  207. ON_COMMAND(ID_ROTATE_LEFT, OnRotateLeft)
  208. ON_COMMAND(ID_ROTATE_RIGHT, OnRotateRight)
  209. ON_COMMAND(ID_ROTATE_UP, OnRotateUp)
  210. ON_COMMAND(ID_ROTATE_DOWN, OnRotateDown)
  211. ON_COMMAND(ID_SELECT_WHO_TARGETS, OnSelectWhoTargets)
  212. ON_COMMAND(ID_SELECT_INVALIDTRIS, OnSelectInvalidTris)
  213. ON_COMMAND(ID_TEST_CONNECTIONS_BACK, OnTestConnectionsBack)
  214. ON_UPDATE_COMMAND_UI(ID_TEST_CONNECTIONS_BACK, OnUpdateTestConnectionsBack)
  215. ON_WM_MOUSEWHEEL()
  216. ON_COMMAND(ID_SELECT_SECTORS_OTHER_SIDE, OnSelectSectorsOtherSide)
  217. ON_COMMAND(ID_SELECT_LINKS_TO_SECTOR, OnSelectLinksToSector)
  218. ON_COMMAND(ID_REMAIN_SELECTEDBY_ORIENTATION, OnRemainSelectedByOrientation)
  219. ON_COMMAND(ID_DESELECT_BY_ORIENTATION, OnDeselectByOrientation)
  220. ON_COMMAND(ID_VERTEX_MODE, OnVertexMode)
  221. ON_COMMAND(ID_REOPTIMIZE_BRUSHES, OnReoptimizeBrushes)
  222. ON_COMMAND(ID_MERGE_VERTICES, OnMergeVertices)
  223. ON_COMMAND(ID_EXPORT_DISPLACE_MAP, OnExportDisplaceMap)
  224. ON_COMMAND(ID_CUT_MODE, OnCutMode)
  225. ON_UPDATE_COMMAND_UI(ID_CUT_MODE, OnUpdateCutMode)
  226. ON_COMMAND(ID_SELECT_ALL_TARGETS, OnSelectAllTargets)
  227. ON_COMMAND(ID_SELECT_ALL_TARGETS_ON_CONTEXT, OnSelectAllTargetsOnContext)
  228. ON_COMMAND(ID_SELECT_CLONES, OnSelectClones)
  229. ON_COMMAND(ID_SELECT_CLONES_ON_CONTEXT, OnSelectClonesOnContext)
  230. ON_UPDATE_COMMAND_UI(ID_SELECT_CLONES, OnUpdateSelectClones)
  231. ON_COMMAND(ID_SELECT_ALL_VERTICES, OnSelectAllVertices)
  232. ON_COMMAND(ID_SELECT_OF_SAME_CLASS, OnSelectOfSameClass)
  233. ON_COMMAND(ID_SELECT_OF_SAME_CLASS_ON_CONTEXT, OnSelectOfSameClassOnContext)
  234. ON_COMMAND(ID_ALTERNATIVE_MOVING_MODE, OnAlternativeMovingMode)
  235. ON_COMMAND(ID_RE_TRIPLE, OnReTriple)
  236. ON_COMMAND(ID_SELECT_WHO_TARGETS_ON_CONTEXT, OnSelectWhoTargetsOnContext)
  237. ON_COMMAND(ID_CLEAR_ALL_TARGETS, OnClearAllTargets)
  238. ON_COMMAND(ID_SELECT_CSG_TARGET, OnSelectCsgTarget)
  239. ON_UPDATE_COMMAND_UI(ID_SELECT_CSG_TARGET, OnUpdateSelectCsgTarget)
  240. ON_COMMAND(ID_REMAIN_SELECTEDBY_ORIENTATION_SINGLE, OnRemainSelectedbyOrientationSingle)
  241. ON_UPDATE_COMMAND_UI(ID_RE_TRIPLE, OnUpdateReTriple)
  242. ON_COMMAND(ID_TRIANGULARIZE_POLYGON, OnTriangularizePolygon)
  243. ON_COMMAND(ID_ENTITY_CONTEXT_HELP, OnEntityContextHelp)
  244. ON_COMMAND(ID_POPUP_AUTO_FIT_MAPPING, OnPopupAutoFitMapping)
  245. ON_COMMAND(ID_TRIANGULARIZE_SELECTION, OnTriangularizeSelection)
  246. ON_UPDATE_COMMAND_UI(ID_TRIANGULARIZE_SELECTION, OnUpdateTriangularizeSelection)
  247. ON_COMMAND(ID_POPUP_AUTO_FIT_MAPPING_SMALL, OnPopupAutoFitMappingSmall)
  248. ON_COMMAND(ID_POPUP_AUTO_FIT_MAPPING_BOTH, OnPopupAutoFitMappingBoth)
  249. ON_COMMAND(ID_RESET_MAPPING_OFFSET, OnResetMappingOffset)
  250. ON_COMMAND(ID_RESET_MAPPING_ROTATION, OnResetMappingRotation)
  251. ON_COMMAND(ID_RESET_MAPPING_STRETCH, OnResetMappingStretch)
  252. ON_COMMAND(ID_CROSSROAD_FOR_L, OnCrossroadForL)
  253. ON_COMMAND(ID_SELECT_USING_TARGET_TREE, OnSelectUsingTargetTree)
  254. ON_COMMAND(ID_TARGET_TREE, OnTargetTree)
  255. ON_UPDATE_COMMAND_UI(ID_TARGET_TREE, OnUpdateTargetTree)
  256. ON_COMMAND(ID_SWAP_LAYERS_12, OnSwapLayers12)
  257. ON_COMMAND(ID_SWAP_LAYERS_23, OnSwapLayers23)
  258. ON_COMMAND(ID_SELECT_DESCENDANTS, OnSelectDescendants)
  259. ON_COMMAND(ID_CROSSROAD_FOR_CTRL_F, OnCrossroadForCtrlF)
  260. ON_COMMAND(ID_ROTATE_TO_TARGET_CENTER, OnRotateToTargetCenter)
  261. ON_COMMAND(ID_ROTATE_TO_TARGET_ORIGIN, OnRotateToTargetOrigin)
  262. ON_COMMAND(ID_COPY_ORIENTATION, OnCopyOrientation)
  263. ON_COMMAND(ID_COPY_PLACEMENT, OnCopyPlacement)
  264. ON_COMMAND(ID_COPY_POSITION, OnCopyPosition)
  265. ON_COMMAND(ID_PASTE_ORIENTATION, OnPasteOrientation)
  266. ON_COMMAND(ID_PASTE_PLACEMENT, OnPastePlacement)
  267. ON_COMMAND(ID_PASTE_POSITION, OnPastePosition)
  268. ON_COMMAND(ID_ALIGN_B, OnAlignB)
  269. ON_COMMAND(ID_ALIGN_H, OnAlignH)
  270. ON_COMMAND(ID_ALIGN_P, OnAlignP)
  271. ON_COMMAND(ID_ALIGN_X, OnAlignX)
  272. ON_COMMAND(ID_ALIGN_Y, OnAlignY)
  273. ON_COMMAND(ID_ALIGN_Z, OnAlignZ)
  274. ON_COMMAND(ID_AUTOTEXTURIZE_MIPS, OnAutotexturizeMips)
  275. ON_UPDATE_COMMAND_UI(ID_AUTOTEXTURIZE_MIPS, OnUpdateAutotexturizeMips)
  276. ON_COMMAND(ID_RANDOM_OFFSET_U, OnRandomOffsetU)
  277. ON_COMMAND(ID_RANDOM_OFFSET_V, OnRandomOffsetV)
  278. ON_COMMAND(ID_STRETCH_RELATIVE_OFFSET, OnStretchRelativeOffset)
  279. ON_COMMAND(ID_DESELECT_HIDDEN, OnDeselectHidden)
  280. ON_COMMAND(ID_SELECT_HIDDEN, OnSelectHidden)
  281. ON_COMMAND(ID_SECTORS_TO_BRUSH, OnSectorsToBrush)
  282. ON_COMMAND(ID_POLYGONS_TO_BRUSH, OnPolygonsToBrush)
  283. ON_COMMAND(ID_CLONE_POLYGONS, OnClonePolygons)
  284. ON_COMMAND(ID_DELETE_POLYGONS, OnDeletePolygons)
  285. ON_COMMAND(ID_KEY_U, OnKeyU)
  286. ON_COMMAND(ID_KEY_D, OnKeyD)
  287. ON_COMMAND(ID_FLIP_POLYGON, OnFlipPolygon)
  288. ON_COMMAND(ID_TERRAIN_MODE, OnTerrainMode)
  289. ON_UPDATE_COMMAND_UI(ID_TERRAIN_MODE, OnUpdateTerrainMode)
  290. ON_COMMAND(ID_KEY_M, OnKeyM)
  291. ON_COMMAND(ID_KEY_BACKSLASH, OnKeyBackslash)
  292. ON_COMMAND(ID_SELECT_BRUSH, OnSelectBrush)
  293. ON_COMMAND(ID_SELECT_TERRAIN, OnSelectTerrain)
  294. ON_COMMAND(ID_ALTITUDE_EDIT_MODE, OnAltitudeEditMode)
  295. ON_COMMAND(ID_LAYER_TEXTURE_EDIT_MODE, OnLayerTextureEditMode)
  296. ON_COMMAND(ID_TBRUSH_ALTITUDE, OnTbrushAltitude)
  297. ON_COMMAND(ID_TBRUSH_EQUILAZE, OnTbrushEquilaze)
  298. ON_COMMAND(ID_TBRUSH_ERASE, OnTbrushErase)
  299. ON_COMMAND(ID_TBRUSH_NOISE, OnTbrushNoise)
  300. ON_COMMAND(ID_TBRUSH_SMOOTH, OnTbrushSmooth)
  301. ON_COMMAND(ID_OPTIMIZE_TERRAIN, OnOptimizeTerrain)
  302. ON_COMMAND(ID_RECALCULATE_TERRAIN_SHADOWS, OnRecalculateTerrainShadows)
  303. ON_COMMAND(ID_VIEW_HEIGHTMAP, OnViewHeightmap)
  304. ON_COMMAND(ID_IMPORT_HEIGHTMAP, OnImportHeightmap)
  305. ON_COMMAND(ID_EXPORT_HEIGHTMAP, OnExportHeightmap)
  306. ON_COMMAND(ID_IMPORT_HEIGHTMAP16, OnImportHeightmap16)
  307. ON_COMMAND(ID_EXPORT_HEIGHTMAP16, OnExportHeightmap16)
  308. ON_COMMAND(ID_SELECT_LAYER, OnSelectLayer)
  309. ON_COMMAND(ID_PICK_LAYER, OnPickLayer)
  310. ON_COMMAND(ID_KEY_O, OnKeyO)
  311. ON_UPDATE_COMMAND_UI(ID_KEY_O, OnUpdateKeyO)
  312. ON_COMMAND(ID_POSTERIZE, OnPosterize)
  313. ON_COMMAND(ID_EQUILIZE, OnFlatten)
  314. ON_COMMAND(ID_APPLY_FILTER, OnApplyFilter)
  315. ON_COMMAND(ID_TE_SMOOTH, OnTeSmooth)
  316. ON_COMMAND(ID_EDIT_TERRAIN_PREFS, OnEditTerrainPrefs)
  317. ON_UPDATE_COMMAND_UI(ID_EDIT_TERRAIN_PREFS, OnUpdateEditTerrainPrefs)
  318. ON_COMMAND(ID_KEY_CTRL_SHIFT_E, OnKeyCtrlShiftE)
  319. ON_COMMAND(ID_KEY_CTRL_SHIFT_G, OnKeyCtrlShiftG)
  320. ON_UPDATE_COMMAND_UI(ID_KEY_CTRL_SHIFT_G, OnUpdateKeyCtrlShiftG)
  321. ON_COMMAND(ID_TERRAIN_LAYER_OPTIONS, OnTerrainLayerOptions)
  322. ON_UPDATE_COMMAND_UI(ID_TERRAIN_LAYER_OPTIONS, OnUpdateTerrainLayerOptions)
  323. ON_COMMAND(ID_KEY_CTRL_SHIFT_K, OnKeyCtrlShiftK)
  324. ON_COMMAND(ID_APPLY_CONTINOUS_NOISE, OnApplyContinousNoise)
  325. ON_COMMAND(ID_APPLY_MINIMUM, OnApplyMinimum)
  326. ON_COMMAND(ID_APPLY_MAXIMUM, OnApplyMaximum)
  327. ON_COMMAND(ID_APPLY_FLATTEN, OnApplyFlatten)
  328. ON_COMMAND(ID_APPLY_POSTERIZE, OnApplyPosterize)
  329. ON_COMMAND(ID_OPTIMIZE_LAYERS, OnOptimizeLayers)
  330. ON_COMMAND(ID_TBRUSH_CONTINOUS_NOISE, OnTbrushContinousNoise)
  331. ON_COMMAND(ID_TBRUSH_FILTER, OnTbrushFilter)
  332. ON_COMMAND(ID_TBRUSH_FLATTEN, OnTbrushFlatten)
  333. ON_COMMAND(ID_TBRUSH_MAXIMUM, OnTbrushMaximum)
  334. ON_COMMAND(ID_TBRUSH_MINIMUM, OnTbrushMinimum)
  335. ON_COMMAND(ID_TBRUSH_POSTERIZE, OnTbrushPosterize)
  336. ON_COMMAND(ID_TERRAIN_PROPERTIES, OnTerrainProperties)
  337. //}}AFX_MSG_MAP
  338. ON_COMMAND_RANGE(ID_BUFFER01, ID_BUFFER10, OnKeyBuffer)
  339. ON_COMMAND_RANGE(ID_EDIT_BUFFER01, ID_EDIT_BUFFER10, OnKeyEditBuffer)
  340. END_MESSAGE_MAP()
  341. /////////////////////////////////////////////////////////////////////////////
  342. // CWorldEditorView construction/destruction
  343. CWorldEditorView::CWorldEditorView()
  344. {
  345. m_iaInputAction = IA_NONE;
  346. m_iaLastInputAction=IA_NONE;
  347. m_pbpoTranslationPlane = NULL;
  348. m_vpViewPrefs = theApp.m_vpViewPrefs[ 0];
  349. m_ptProjectionType = CSlaveViewer::PT_PERSPECTIVE;
  350. m_pdpDrawPort = NULL;
  351. m_pvpViewPort = NULL;
  352. m_fGridInMeters = 10.0f;
  353. m_pbpoRightClickedPolygon = NULL;
  354. m_penEntityHitOnContext = NULL;
  355. m_iDragVertice = -1;
  356. m_iDragEdge = -1;
  357. _pselbvxtSelectOnRender = NULL;
  358. _pselenSelectOnRender = NULL;
  359. m_bRequestVtxClickSelect = FALSE;
  360. m_bRequestVtxLassoSelect = FALSE;
  361. m_bRequestEntityLassoSelect = FALSE;
  362. m_strTest="";
  363. }
  364. CWorldEditorView::~CWorldEditorView()
  365. {
  366. }
  367. BOOL CWorldEditorView::PreCreateWindow(CREATESTRUCT& cs)
  368. {
  369. // TODO: Modify the Window class or styles here by modifying
  370. // the CREATESTRUCT cs
  371. return CView::PreCreateWindow(cs);
  372. }
  373. static void GetToolTipText(void *pView, char *pToolTipText)
  374. {
  375. CWorldEditorView *pWorldEditorView = (CWorldEditorView *) pView;
  376. pWorldEditorView->GetToolTipText( pToolTipText);
  377. }
  378. /////////////////////////////////////////////////////////////////////////////
  379. // CWorldEditorView drawing
  380. void CWorldEditorView::RenderBackdropTexture(CDrawPort *pDP,
  381. FLOAT3D v0, FLOAT3D v1, FLOAT3D v2, FLOAT3D v3,
  382. CTextureObject &to)
  383. {
  384. if( to.GetData() == NULL) return;
  385. CWorldEditorDoc* pDoc = GetDocument();
  386. FLOAT3D v0p, v1p, v2p, v3p;
  387. // create a slave viewer
  388. CSlaveViewer svViewer(GetChildFrame()->m_mvViewer, m_ptProjectionType, pDoc->m_plGrid, pDP);
  389. // create a projection for slave viewer
  390. CAnyProjection3D prProjection;
  391. svViewer.MakeProjection(prProjection);
  392. prProjection->Prepare();
  393. // project current base vertice and convert y coordinate from mathemathical representation
  394. // into screen representation
  395. prProjection->ProjectCoordinate( v0, v0p); v0p(2) = pDP->GetHeight() - v0p(2);
  396. prProjection->ProjectCoordinate( v1, v1p); v1p(2) = pDP->GetHeight() - v1p(2);
  397. prProjection->ProjectCoordinate( v2, v2p); v2p(2) = pDP->GetHeight() - v2p(2);
  398. prProjection->ProjectCoordinate( v3, v3p); v3p(2) = pDP->GetHeight() - v3p(2);
  399. FLOATaabbox3D box;
  400. box |= v0p;
  401. box |= v1p;
  402. box |= v2p;
  403. box |= v3p;
  404. if( (box.Size()(1) > 2) && (box.Size()(2) > 2) )
  405. {
  406. // create rectangle for backdrop picture
  407. PIXaabbox2D rectPict;
  408. rectPict = PIXaabbox2D( PIX2D((SLONG)box.Min()(1), (SLONG)box.Min()(2)),
  409. PIX2D((SLONG)box.Max()(1), (SLONG)box.Max()(2)) );
  410. pDP->PutTexture( &to, rectPict);
  411. }
  412. }
  413. BOOL _bCursorMoved=FALSE;
  414. void CWorldEditorView::RenderView( CDrawPort *pDP)
  415. {
  416. CWorldEditorDoc* pDoc = GetDocument();
  417. ASSERT_VALID(pDoc);
  418. CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
  419. CChildFrame *pChild = GetChildFrame();
  420. BOOL bCSGOn = pDoc->m_pwoSecondLayer != NULL;
  421. BOOL bAlt = (GetKeyState( VK_MENU)&0x8000) != 0;
  422. BOOL bSpace = (GetKeyState( VK_SPACE)&0x8000) != 0;
  423. BOOL bCtrl = (GetKeyState( VK_CONTROL)&0x8000) != 0;
  424. // create a slave viewer
  425. CSlaveViewer svViewer(GetChildFrame()->m_mvViewer, m_ptProjectionType,
  426. pDoc->m_plGrid, pDP);
  427. // copy view's world rendering preferences to global world rendering preferences
  428. _wrpWorldRenderPrefs = m_vpViewPrefs.m_wrpWorldRenderPrefs;
  429. _wrpWorldRenderPrefs.SetTextureLayerOn( theApp.m_bTexture1, 0);
  430. _wrpWorldRenderPrefs.SetTextureLayerOn( theApp.m_bTexture2, 1);
  431. _wrpWorldRenderPrefs.SetTextureLayerOn( theApp.m_bTexture3, 2);
  432. // set shadow type from child frame
  433. _wrpWorldRenderPrefs.SetShadowsType( GetChildFrame()->m_stShadowType);
  434. // copy view's model rendering preferences to global model rendering preferences
  435. _mrpModelRenderPrefs = m_vpViewPrefs.m_mrpModelRenderPrefs;
  436. // copy auto mip modeling flag from child frame
  437. _wrpWorldRenderPrefs.SetAutoMipBrushingOn( GetChildFrame()->m_bAutoMipBrushingOn);
  438. // and manual mip factor
  439. _wrpWorldRenderPrefs.SetManualMipBrushingFactor( GetChildFrame()->m_fManualMipBrushingFactor);
  440. // view visibility tweaking
  441. _wrpWorldRenderPrefs.SetVisTweaksOn(GetChildFrame()->m_bShowVisibilityTweaks);
  442. _wrpWorldRenderPrefs.DisableVisTweaks(GetChildFrame()->m_bDisableVisibilityTweaks);
  443. _pselbscVisTweaks=&pDoc->m_selSectorSelection;
  444. _wrpWorldRenderPrefs.SetSelectedEntityModel( theApp.m_pEntityMarkerModelObject);
  445. _wrpWorldRenderPrefs.SetSelectedPortalModel( theApp.m_pPortalMarkerModelObject);
  446. _wrpWorldRenderPrefs.SetEmptyBrushModel( theApp.m_pEmptyBrushModelObject);
  447. // if we are using automatic rendering range
  448. if( m_vpViewPrefs.m_bAutoRenderingRange)
  449. {
  450. // set rendering range of 1.5 x viewer's target distance
  451. FLOAT fTargetDistance = svViewer.GetTargetDistance();
  452. // we have to take second layer distance in considiration also
  453. FLOAT fMinimumRenderRange = fTargetDistance;
  454. // if second layer's world exists
  455. if( pDoc->m_pwoSecondLayer != NULL)
  456. {
  457. CPlacement3D plViewer = GetChildFrame()->m_mvViewer.GetViewerPlacement();
  458. // calculate viewer-layer distance
  459. FLOAT fViewerLayerDistance =
  460. (plViewer.pl_PositionVector - pDoc->m_plSecondLayer.pl_PositionVector).Length();
  461. // if current minimum rendering range is smaller than one that viewer-layer
  462. // distance would request
  463. if( fMinimumRenderRange < fViewerLayerDistance )
  464. {
  465. fMinimumRenderRange = fViewerLayerDistance;
  466. }
  467. }
  468. // don't allow minimum rendering range to drop below 1.5 m
  469. if( fMinimumRenderRange < 1.5f)
  470. {
  471. fMinimumRenderRange = 1.5f;
  472. }
  473. _wrpWorldRenderPrefs.SetMinimumRenderRange( fMinimumRenderRange * 1.5f);
  474. }
  475. // we are using fixed rendering range
  476. else
  477. {
  478. // set global rendering range from fixed one remembered in prefs
  479. _wrpWorldRenderPrefs.SetMinimumRenderRange( m_vpViewPrefs.m_fRenderingRange);
  480. }
  481. // set visibility of link lines
  482. _wrpWorldRenderPrefs.SetShowTargetsOn(pChild->m_bShowTargets);
  483. // set visibility of entity names
  484. _wrpWorldRenderPrefs.SetShowEntityNamesOn(pChild->m_bShowEntityNames);
  485. // find out if z buffer clearing should occure
  486. BOOL bClearZBuffer = FALSE;
  487. BOOL bClearScreen = TRUE;
  488. // get world and model polygon fill flags
  489. BOOL bModelPolygonFilling =
  490. (_mrpModelRenderPrefs.GetRenderType() & RT_TEXTURE_MASK) != RT_NO_POLYGON_FILL;
  491. // find out if any of isometric projection modes is currently on
  492. BOOL bPerspectiveOn = m_ptProjectionType == CSlaveViewer::PT_PERSPECTIVE;
  493. BOOL bPolygonFillOn = _wrpWorldRenderPrefs.GetPolygonsFillType() != CWorldRenderPrefs::FT_NONE;
  494. // if something requires clearing of z-buffer
  495. if( bPolygonFillOn ||
  496. pDoc->m_bOrientationIcons ||
  497. ((!bCSGOn && bPerspectiveOn) && GetChildFrame()->m_bSceneRenderingTime) ||
  498. m_vpViewPrefs.m_bMeasurementTape ||
  499. theApp.m_bMeasureModeOn || theApp.m_bCutModeOn)
  500. {
  501. bClearZBuffer = TRUE;
  502. }
  503. // if we will render models using polygon fill, we must clear z-buffer
  504. if( bModelPolygonFilling)
  505. {
  506. bClearZBuffer = TRUE;
  507. }
  508. // if rendering will fill whole screen along with z-buffer
  509. if( bPolygonFillOn && bPerspectiveOn)
  510. {
  511. bClearZBuffer = FALSE;
  512. bClearScreen = FALSE;
  513. }
  514. COLOR colBcgFill=m_vpViewPrefs.m_PaperColor;
  515. if(_wrpWorldRenderPrefs.IsBackgroundTextureOn())
  516. {
  517. bClearScreen = TRUE;
  518. colBcgFill=pDoc->m_woWorld.wo_colBackground;
  519. }
  520. // set selected entity model
  521. _wrpWorldRenderPrefs.SetSelectedEntityModel( theApp.m_pEntityMarkerModelObject);
  522. // set selected portal model
  523. _wrpWorldRenderPrefs.SetSelectedPortalModel( theApp.m_pPortalMarkerModelObject);
  524. // set empty brush model
  525. _wrpWorldRenderPrefs.SetEmptyBrushModel( theApp.m_pEmptyBrushModelObject);
  526. switch( pDoc->GetEditingMode())
  527. {
  528. case POLYGON_MODE:
  529. {
  530. _wrpWorldRenderPrefs.SetSelectionType( CWorldRenderPrefs::ST_POLYGONS);
  531. break;
  532. }
  533. case SECTOR_MODE:
  534. {
  535. _wrpWorldRenderPrefs.SetSelectionType( CWorldRenderPrefs::ST_SECTORS);
  536. break;
  537. }
  538. case ENTITY_MODE:
  539. {
  540. _wrpWorldRenderPrefs.SetSelectionType( CWorldRenderPrefs::ST_ENTITIES);
  541. break;
  542. }
  543. case VERTEX_MODE:
  544. {
  545. _wrpWorldRenderPrefs.SetSelectionType( CWorldRenderPrefs::ST_VERTICES);
  546. break;
  547. }
  548. case TERRAIN_MODE:
  549. {
  550. _wrpWorldRenderPrefs.SetSelectionType( CWorldRenderPrefs::ST_NONE);
  551. break;
  552. }
  553. case CSG_MODE:
  554. {
  555. _wrpWorldRenderPrefs.SetSelectionType( CWorldRenderPrefs::ST_NONE);
  556. break;
  557. }
  558. default: { FatalError("Unknown editing mode."); break;};
  559. }
  560. // if selection shouldn't be rendered and we are not in vertex mode (selection should always be rendered)
  561. if( !GetChildFrame()->m_bSelectionVisible && (pDoc->GetEditingMode()!= VERTEX_MODE) )
  562. {
  563. _wrpWorldRenderPrefs.SetSelectionType( CWorldRenderPrefs::ST_NONE);
  564. }
  565. // create a projection for slave viewer
  566. CAnyProjection3D prProjection;
  567. svViewer.MakeProjection(prProjection);
  568. // set object placement
  569. prProjection->ObjectPlacementL() = pDoc->m_plGrid;
  570. if( !bPerspectiveOn && !_wrpWorldRenderPrefs.wrp_bApplyFarClipPlaneInIsometricProjection)
  571. {
  572. prProjection->FarClipDistanceL() = -1;
  573. }
  574. else
  575. {
  576. prProjection->FarClipDistanceL() = _wrpWorldRenderPrefs.wrp_fFarClipPlane;
  577. }
  578. // prepare the projection
  579. prProjection->Prepare();
  580. // if screen clearance is required
  581. if( bClearScreen)
  582. {
  583. try
  584. {
  585. m_toBcgPicture.SetData_t(CTString(m_vpViewPrefs.m_achrBcgPicture));
  586. }
  587. // if failed
  588. catch (char *strError)
  589. {
  590. (void) strError;
  591. }
  592. if( m_toBcgPicture.GetData() != NULL)
  593. {
  594. // fill background with bcg picture
  595. PIXaabbox2D screenBox;
  596. screenBox = PIXaabbox2D( PIX2D(0,0), PIX2D(pDP->GetWidth(), pDP->GetHeight()) );
  597. pDP->PutTexture( &m_toBcgPicture, screenBox);
  598. }
  599. else
  600. {
  601. // clear background using current color form rendering preferences
  602. pDP->Fill(colBcgFill | CT_OPAQUE);
  603. }
  604. if( pDoc->m_woWorld.wo_strBackdropUp != "" && GetChildFrame()->m_bRenderViewPictures)
  605. {
  606. FLOAT3D v0 = FLOAT3D(pDoc->m_woWorld.wo_fUpCX-pDoc->m_woWorld.wo_fUpW/2.0f, 0.0f,
  607. pDoc->m_woWorld.wo_fUpCZ-pDoc->m_woWorld.wo_fUpL/2.0f);
  608. FLOAT3D v1 = FLOAT3D(pDoc->m_woWorld.wo_fUpCX+pDoc->m_woWorld.wo_fUpW/2.0f, 0.0f,
  609. pDoc->m_woWorld.wo_fUpCZ-pDoc->m_woWorld.wo_fUpL/2.0f);
  610. FLOAT3D v2 = FLOAT3D(pDoc->m_woWorld.wo_fUpCX+pDoc->m_woWorld.wo_fUpW/2.0f, 0.0f,
  611. pDoc->m_woWorld.wo_fUpCZ+pDoc->m_woWorld.wo_fUpL/2.0f);
  612. FLOAT3D v3 = FLOAT3D(pDoc->m_woWorld.wo_fUpCX-pDoc->m_woWorld.wo_fUpW/2.0f, 0.0f,
  613. pDoc->m_woWorld.wo_fUpCZ+pDoc->m_woWorld.wo_fUpL/2.0f);
  614. RenderBackdropTexture( pDP, v0, v1, v2, v3, pDoc->m_toBackdropUp);
  615. }
  616. if( pDoc->m_woWorld.wo_strBackdropFt != "" && GetChildFrame()->m_bRenderViewPictures)
  617. {
  618. FLOAT3D v0 = FLOAT3D(pDoc->m_woWorld.wo_fFtCX-pDoc->m_woWorld.wo_fFtW/2.0f,
  619. pDoc->m_woWorld.wo_fFtCY-pDoc->m_woWorld.wo_fFtH/2.0f, 0.0f);
  620. FLOAT3D v1 = FLOAT3D(pDoc->m_woWorld.wo_fFtCX+pDoc->m_woWorld.wo_fFtW/2.0f,
  621. pDoc->m_woWorld.wo_fFtCY-pDoc->m_woWorld.wo_fFtH/2.0f, 0.0f);
  622. FLOAT3D v2 = FLOAT3D(pDoc->m_woWorld.wo_fFtCX+pDoc->m_woWorld.wo_fFtW/2.0f,
  623. pDoc->m_woWorld.wo_fFtCY+pDoc->m_woWorld.wo_fFtH/2.0f, 0.0f);
  624. FLOAT3D v3 = FLOAT3D(pDoc->m_woWorld.wo_fFtCX-pDoc->m_woWorld.wo_fFtW/2.0f,
  625. pDoc->m_woWorld.wo_fFtCY+pDoc->m_woWorld.wo_fFtH/2.0f, 0.0f);
  626. RenderBackdropTexture( pDP, v0, v1, v2, v3, pDoc->m_toBackdropFt);
  627. }
  628. if( pDoc->m_woWorld.wo_strBackdropRt != "" && GetChildFrame()->m_bRenderViewPictures)
  629. {
  630. FLOAT3D v0 = FLOAT3D(0.0f, pDoc->m_woWorld.wo_fRtCY-pDoc->m_woWorld.wo_fRtH/2.0f,
  631. pDoc->m_woWorld.wo_fRtCZ-pDoc->m_woWorld.wo_fRtL/2.0f);
  632. FLOAT3D v1 = FLOAT3D(0.0f, pDoc->m_woWorld.wo_fRtCY+pDoc->m_woWorld.wo_fRtH/2.0f,
  633. pDoc->m_woWorld.wo_fRtCZ-pDoc->m_woWorld.wo_fRtL/2.0f);
  634. FLOAT3D v2 = FLOAT3D(0.0f, pDoc->m_woWorld.wo_fRtCY+pDoc->m_woWorld.wo_fRtH/2.0f,
  635. pDoc->m_woWorld.wo_fRtCZ+pDoc->m_woWorld.wo_fRtL/2.0f);
  636. FLOAT3D v3 = FLOAT3D(0.0f, pDoc->m_woWorld.wo_fRtCY-pDoc->m_woWorld.wo_fRtH/2.0f,
  637. pDoc->m_woWorld.wo_fRtCZ+pDoc->m_woWorld.wo_fRtL/2.0f);
  638. RenderBackdropTexture( pDP, v0, v1, v2, v3, pDoc->m_toBackdropRt);
  639. }
  640. // if object should me rendered as backdrop
  641. if( GetChildFrame()->m_bRenderViewPictures)
  642. {
  643. CObject3D &ob = pDoc->m_o3dBackdropObject;
  644. FOREACHINDYNAMICARRAY(ob.ob_aoscSectors, CObjectSector, itosc)
  645. {
  646. FOREACHINDYNAMICARRAY(itosc->osc_aoedEdges, CObjectEdge, itoe)
  647. {
  648. FLOAT3D vtx0 = DOUBLEtoFLOAT(*itoe->oed_Vertex0);
  649. FLOAT3D vtx1 = DOUBLEtoFLOAT(*itoe->oed_Vertex1);
  650. prProjection->PreClip( vtx0, vtx0);
  651. prProjection->PreClip( vtx1, vtx1);
  652. prProjection->ClipLine(vtx0, vtx1);
  653. // apply perspective
  654. FLOAT3D vtx0p, vtx1p;
  655. prProjection->PostClip( vtx0, vtx0p);
  656. prProjection->PostClip( vtx1, vtx1p);
  657. // draw one line of bounding box
  658. pDP->DrawLine( (PIX)vtx0p(1), (PIX)vtx0p(2), (PIX)vtx1p(1), (PIX)vtx1p(2),
  659. C_dGRAY|CT_OPAQUE);
  660. }
  661. }
  662. }
  663. }
  664. // if z-buffer clearance is required
  665. if( bClearZBuffer)
  666. {
  667. // erase z-buffer
  668. pDP->FillZBuffer(ZBUF_BACK);
  669. }
  670. FLOAT3D fGridOrigin;
  671. // project grid origin
  672. prProjection->ProjectCoordinate( FLOAT3D( 0.0f, 0.0f, 0.0f), fGridOrigin);
  673. // convert y coordinate form mathematical form info screen space
  674. fGridOrigin(2) = pDP->GetHeight() - fGridOrigin(2);
  675. // calculate grid in pixels but there must be bigger than given minimal size
  676. #define SMALLEST_ALLOWED_GRID_IN_PIXELS 30
  677. // get zoom factor
  678. FLOAT fZoom = svViewer.GetZoomFactor();
  679. // declare decadic grid in meters
  680. FLOAT afDecadicGridInMeters[] = {0.25f,0.50f,1.0f,2.5f,5.0f,10.0f,25.0f,50.0f,100.0f,
  681. 250.0f,500.0f,1000.0f,10000.0f,100000.0f};
  682. FLOAT afBinaryGridInMeters[] = {0.25f,0.50f,1.0f,2.0f,4.0f,8.0f,16.0f,32.0f,64.0f,128.0f,256.0f,
  683. 512.0f,1024.0f,2048.0f,4096.0f,8192.0f,16384.0f,32768.0f,65536.0f};
  684. // select max grid value
  685. if( theApp.m_bDecadicGrid)
  686. {
  687. m_fGridInMeters = afDecadicGridInMeters[ sizeof( afDecadicGridInMeters)/sizeof(FLOAT)-1];
  688. }
  689. else
  690. {
  691. m_fGridInMeters = afBinaryGridInMeters[ sizeof( afBinaryGridInMeters)/sizeof(FLOAT)-1];
  692. }
  693. // ptr to curently active grid table
  694. FLOAT *pafGridInMeters;
  695. INDEX ctTableMembers;
  696. // select active table
  697. if( theApp.m_bDecadicGrid)
  698. {
  699. pafGridInMeters = afDecadicGridInMeters;
  700. ctTableMembers = sizeof( afDecadicGridInMeters)/sizeof(FLOAT);
  701. }
  702. else
  703. {
  704. pafGridInMeters = afBinaryGridInMeters;
  705. ctTableMembers = sizeof( afBinaryGridInMeters)/sizeof(FLOAT);
  706. }
  707. // for all members in precalculated grid in meters array
  708. for( INDEX i=0; i<ctTableMembers; i++)
  709. {
  710. // calculate grid steep
  711. m_fpixGridSteep = fZoom * pafGridInMeters[ i];
  712. // is it bigger than smallest allowed grid size in pixels
  713. if( m_fpixGridSteep >= SMALLEST_ALLOWED_GRID_IN_PIXELS)
  714. {
  715. m_fGridInMeters = pafGridInMeters[ i];
  716. break;
  717. }
  718. }
  719. // we have calculated wanted grid in pixels, value is stored in pixGridSteep
  720. // if grid on, draw it
  721. if( GetChildFrame()->m_bGridOn && !bPerspectiveOn && !bPolygonFillOn)
  722. {
  723. // get grid's origin projected point
  724. FLOAT fGridOriginX = fGridOrigin(1);
  725. FLOAT fGridOriginY = fGridOrigin(2);
  726. // calculate starting coordinates of left-up grid line
  727. FLOAT fGridX = fGridOriginX - (m_fpixGridSteep * (int)(fGridOriginX / m_fpixGridSteep));
  728. FLOAT fGridY = fGridOriginY - (m_fpixGridSteep * (int)(fGridOriginY / m_fpixGridSteep));
  729. // remember these start grid values so they can be used for measurement
  730. m_fGridX = fGridX;
  731. m_fGridY = fGridY;
  732. // style of grid line
  733. ULONG ulLineStyle;
  734. // loop all vertical grid lines
  735. #define LINE_EPSILON 0.05f
  736. FOREVER
  737. {
  738. // does this grid lines touch origin point
  739. if( Abs(fGridX - fGridOriginX) < LINE_EPSILON )
  740. {
  741. // if so, draw full line
  742. ulLineStyle = _FULL_;
  743. }
  744. else
  745. {
  746. // does not, draw point line
  747. ulLineStyle = _POINT_;
  748. }
  749. // draw one vertical grid line
  750. pDP->DrawLine( (int) fGridX, 0, (int) fGridX, pDP->GetHeight()-1,
  751. m_vpViewPrefs.m_GridColor|CT_OPAQUE, ulLineStyle);
  752. // move to next grid line
  753. fGridX += m_fpixGridSteep;
  754. // is coordinate passed draw port's width
  755. if( fGridX > pDP->GetWidth())
  756. {
  757. // if so, vertical grid is drawn, stop endless loop
  758. break;
  759. }
  760. }
  761. // loop all horizontal grid lines
  762. FOREVER
  763. {
  764. // does this grid lines touch origin point
  765. if( Abs(fGridY - fGridOriginY) < LINE_EPSILON )
  766. {
  767. // if so, draw full line
  768. ulLineStyle = _FULL_;
  769. }
  770. else
  771. {
  772. // does not, draw point line
  773. ulLineStyle = _POINT_;
  774. }
  775. // draw one vertical grid line
  776. pDP->DrawLine( 0, (int) fGridY, pDP->GetWidth()-1, (int) fGridY,
  777. m_vpViewPrefs.m_GridColor|CT_OPAQUE, ulLineStyle);
  778. // move to next grid line
  779. fGridY += m_fpixGridSteep;
  780. // is coordinate passed draw port's height
  781. if( fGridY > pDP->GetHeight())
  782. {
  783. // if so, vertical grid is drawn, stop endless loop
  784. break;
  785. }
  786. }
  787. }
  788. // if we should draw measurement tape
  789. if( m_vpViewPrefs.m_bMeasurementTape && !bPerspectiveOn)
  790. {
  791. // define tape in meters for decadic grid type
  792. FLOAT afDecadicTapeInMeters[] =
  793. { 0.01f, 0.1f, 1.0f, 10.0f, 100.0f, 1000.0f, 10000.0f, 100000.0f};
  794. CTString astrDecadicTapeInMeters[] =
  795. { "1 mm", "1 cm", "1 m", "10 m", "100 m", "1 km", "10 km", "100 km"};
  796. // define tape in meters for binary grid type
  797. FLOAT afBinaryTapeInMeters[] =
  798. { 1.0f/64, 1.0f/8, 1.0f, 8.0f, 64.0f, 256.0f, 1024.0f, 4096.0f, 16484.0f, 65536.0f};
  799. CTString astrBinaryTapeInMeters[] =
  800. { "1/64 m", "1/8 m", "1 m", "8 m", "64 m", "256 m", "1024 m", "4096 m", "16384 m", "65536 m"};
  801. CTString *pastrTapeInMetersTable;
  802. FLOAT *pafTapeInMetersTable;
  803. INDEX ctTableMembers;
  804. // select active table
  805. if( theApp.m_bDecadicGrid)
  806. {
  807. pafTapeInMetersTable = afDecadicTapeInMeters;
  808. pastrTapeInMetersTable = astrDecadicTapeInMeters;
  809. ctTableMembers = sizeof( afDecadicTapeInMeters)/sizeof(FLOAT);
  810. }
  811. else
  812. {
  813. pafTapeInMetersTable = afBinaryTapeInMeters;
  814. pastrTapeInMetersTable = astrBinaryTapeInMeters;
  815. ctTableMembers = sizeof( afBinaryTapeInMeters)/sizeof(FLOAT);
  816. }
  817. // here we will calculate our tape lenght in meters
  818. FLOAT fTapeLenMeters;
  819. // here we will calculate our tape lenght in pixels
  820. PIX pixTapeLen;
  821. // here we will place appropriate text saying tape's lenght in meters
  822. CTString strTapeLen;
  823. // for all possible dimensions of measurement tape
  824. for( INDEX i=ctTableMembers-1; i>=0; i--)
  825. {
  826. // get tape len in meters
  827. fTapeLenMeters = pafTapeInMetersTable[ i];
  828. // get appropriate descriptive string
  829. strTapeLen = pastrTapeInMetersTable[ i];
  830. // calculate tape in pixels
  831. pixTapeLen = (PIX)(fZoom * fTapeLenMeters);
  832. // is it smaller than 75% of draw port's width
  833. if( pixTapeLen <= pDP->GetWidth()*3/4)
  834. {
  835. // it is, we found our tape dimension
  836. break;
  837. }
  838. }
  839. // calculate tape position on screen
  840. PIX x = (PIX) ( pDP->GetWidth() * 0.05f); // x starts at 5% of draw port's width
  841. PIX y = (PIX) ( pDP->GetHeight()* 0.95f); // y starts at 95% of draw port's height
  842. // draw tape's left end, little vertical line
  843. pDP->DrawLine( x, y-2, x, y+2, C_BLACK|CT_OPAQUE);
  844. // draw tape's main, horizontal little
  845. pDP->DrawLine( x, y, x+pixTapeLen, y, C_BLACK|CT_OPAQUE);
  846. // draw tape's right end, little vertical line
  847. pDP->DrawLine( x+pixTapeLen, y-2, x+pixTapeLen, y+2, C_BLACK|CT_OPAQUE);
  848. // type appropriate text, lenght in meters
  849. pDP->SetFont( theApp.m_pfntSystem);
  850. pDP->SetTextAspect( 1.0f);
  851. pDP->SetTextScaling( 1.0f);
  852. pDP->PutText( strTapeLen, x, y-16);
  853. }
  854. // we are not rendering scene over already rendered scene (used for CSG layer)
  855. pDP->SetOverlappedRendering(FALSE);
  856. // print grid size (or no grid)
  857. char strPaneText[ 128];
  858. sprintf( strPaneText, "Grid: %g m", m_fGridInMeters);
  859. pMainFrame->m_wndStatusBar.SetPaneText( GRID_PANE, CString(strPaneText), TRUE);
  860. // create renderer and render world
  861. CEntity *penOnlySelected = NULL;
  862. if( pDoc->m_selEntitySelection.Count() == 1)
  863. {
  864. pDoc->m_selEntitySelection.Lock();
  865. penOnlySelected = &pDoc->m_selEntitySelection[0];
  866. pDoc->m_selEntitySelection.Unlock();
  867. }
  868. // request vertex selecting from renderer
  869. if( m_bRequestVtxClickSelect)
  870. {
  871. _bSelectAlternative = m_bOnSelectVertexShiftDown;
  872. _pselbvxtSelectOnRender = &pDoc->m_selVertexSelection;
  873. }
  874. if( m_bRequestVtxLassoSelect)
  875. {
  876. _bSelectAlternative = m_bOnSelectVertexAltDown;
  877. _pselbvxtSelectOnRender = &pDoc->m_selVertexSelection;
  878. _pavpixSelectLasso = &m_avpixLaso;
  879. }
  880. if( m_bRequestEntityLassoSelect)
  881. {
  882. _bSelectAlternative = m_bOnSelectEntityAltDown;
  883. _pselenSelectOnRender = &pDoc->m_selEntitySelection;
  884. _pavpixSelectLasso = &m_avpixLaso;
  885. }
  886. if(pDoc->GetEditingMode()==TERRAIN_MODE &&
  887. theApp.m_penLastTerrainHit==GetTerrainEntity() &&
  888. !_pInput->IsInputEnabled())
  889. {
  890. RenderAndApplyTerrainEditBrush(theApp.m_vLastTerrainHit);
  891. }
  892. if( GetChildFrame()->m_bViewFromEntity &&
  893. (penOnlySelected != NULL) &&
  894. !(penOnlySelected->GetFlags()&ENF_ANCHORED) &&
  895. bPerspectiveOn )
  896. {
  897. // create a projection for slave viewer
  898. CAnyProjection3D prProjection;
  899. svViewer.MakeProjection(prProjection);
  900. prProjection->ViewerPlacementL() = penOnlySelected->GetPlacement();
  901. prProjection->Prepare();
  902. ::RenderView(pDoc->m_woWorld, *penOnlySelected, prProjection, *pDP);
  903. }
  904. else
  905. {
  906. // create renderer and render world
  907. ::RenderView(pDoc->m_woWorld, *(CEntity*) NULL, prProjection, *pDP);
  908. }
  909. // don't allow further laso select tests
  910. if( m_bRequestVtxLassoSelect || m_bRequestEntityLassoSelect)
  911. {
  912. m_avpixLaso.Clear();
  913. }
  914. _pselbvxtSelectOnRender = NULL;
  915. _pselenSelectOnRender = NULL;
  916. m_bRequestVtxClickSelect = FALSE;
  917. m_bRequestVtxLassoSelect = FALSE;
  918. m_bRequestEntityLassoSelect = FALSE;
  919. _pavpixSelectLasso = NULL;
  920. INDEX ctLasoPts = m_avpixLaso.Count();
  921. if(((m_iaInputAction == IA_SELECT_LASSO_BRUSH_VERTEX) ||
  922. (m_iaInputAction == IA_SELECT_LASSO_ENTITY)) && (ctLasoPts>1) )
  923. {
  924. for( INDEX iKnot=0; iKnot<ctLasoPts-1; iKnot++)
  925. {
  926. PIX x0 = m_avpixLaso[iKnot](1);
  927. PIX x1 = m_avpixLaso[iKnot+1](1);
  928. PIX y0 = m_avpixLaso[iKnot](2);
  929. PIX y1 = m_avpixLaso[iKnot+1](2);
  930. pDP->DrawLine(x0, y0, x1, y1, m_vpViewPrefs.m_GridColor|CT_OPAQUE);
  931. }
  932. }
  933. prProjection->DepthBufferNearL() = 0.0f;
  934. prProjection->DepthBufferFarL() = 0.9f;
  935. prProjection->Prepare();
  936. BeginModelRenderingView(prProjection, pDP);
  937. // if we have entity mode active, at least one entity selected and edititng property of
  938. // edit range type, and perspective is not on, render entities using rendering range model
  939. CPropertyID *ppidProperty = pMainFrame->m_PropertyComboBar.GetSelectedProperty();
  940. if( (pDoc->GetEditingMode() == ENTITY_MODE) &&
  941. (pDoc->m_selEntitySelection.Count() != 0) &&
  942. (ppidProperty != NULL) &&
  943. ( (ppidProperty->pid_eptType == CEntityProperty::EPT_ANGLE3D) ||
  944. (ppidProperty->pid_eptType == CEntityProperty::EPT_RANGE) ||
  945. (ppidProperty->pid_eptType == CEntityProperty::EPT_FLOATAABBOX3D && !bPerspectiveOn)) )
  946. {
  947. // for all selected entities
  948. FOREACHINDYNAMICCONTAINER(pDoc->m_selEntitySelection, CEntity, iten)
  949. {
  950. // obtain property ptr
  951. CEntityProperty *penpProperty = iten->PropertyForName( ppidProperty->pid_strName);
  952. // if this entity is just selected, it may not have range property but that was not
  953. // noticed (it will be during first on idle), so skip it
  954. if( penpProperty==NULL)
  955. {
  956. continue;
  957. }
  958. // if we are in perspective and entity property is marked not to be visible in perspective view
  959. if( (penpProperty->ep_ulFlags & EPROPF_HIDEINPERSPECTIVE) && bPerspectiveOn)
  960. {
  961. continue;
  962. }
  963. // this model we will render
  964. CModelObject *pModelObject;
  965. // this render model structure will be rendered
  966. CRenderModel rmRenderModel;
  967. // if we are editing range property
  968. if( ppidProperty->pid_eptType == CEntityProperty::EPT_RANGE)
  969. {
  970. // get editing range
  971. FLOAT fRange = ENTITYPROPERTY( &*iten, penpProperty->ep_slOffset, FLOAT);
  972. // set collision box's stretch factor
  973. theApp.m_pRangeSphereModelObject->mo_Stretch = FLOAT3D( fRange, fRange, fRange);
  974. // set texture rendering mode and phong shading
  975. //_mrpModelRenderPrefs.SetRenderType( RT_TEXTURE|RT_SHADING_PHONG);
  976. // copy range model's placement from entity
  977. rmRenderModel.SetObjectPlacement(iten->GetPlacement());
  978. // set range sphere model for rendering
  979. pModelObject = theApp.m_pRangeSphereModelObject;
  980. }
  981. // if we are editing angle3D property
  982. else if( ppidProperty->pid_eptType == CEntityProperty::EPT_ANGLE3D)
  983. {
  984. // get editting bounding box
  985. ANGLE3D aAngle = ENTITYPROPERTY( &*iten, penpProperty->ep_slOffset, ANGLE3D);
  986. rmRenderModel.SetObjectPlacement(
  987. CPlacement3D(iten->GetPlacement().pl_PositionVector, aAngle));
  988. // set angle3d vector's stretch factor
  989. FLOATaabbox3D box;
  990. iten->GetSize(box);
  991. FLOAT fStretch = box.Size().Length();
  992. theApp.m_pAngle3DModelObject->mo_Stretch = FLOAT3D( fStretch, fStretch, fStretch);
  993. // set angle3d model for rendering
  994. pModelObject = theApp.m_pAngle3DModelObject;
  995. }
  996. else
  997. {
  998. // get editting bounding box
  999. FLOATaabbox3D bbox = ENTITYPROPERTY( &*iten, penpProperty->ep_slOffset, FLOATaabbox3D);
  1000. // reset orientation (axes alligned bounding box !!!)
  1001. rmRenderModel.SetObjectPlacement(
  1002. CPlacement3D(iten->GetPlacement().pl_PositionVector + bbox.Min(),
  1003. ANGLE3D( 0, 0, 0)));
  1004. // set collision box's stretch factor
  1005. theApp.m_pBoundingBoxModelObject->mo_Stretch = bbox.Size();
  1006. // render black wire frame allways
  1007. _mrpModelRenderPrefs.SetWire( TRUE);
  1008. _mrpModelRenderPrefs.SetInkColor( C_BLACK);
  1009. // set bounding box model for rendering
  1010. pModelObject = theApp.m_pBoundingBoxModelObject;
  1011. }
  1012. // set light placement
  1013. rmRenderModel.rm_vLightDirection = FLOAT3D(1.0f, -1.0f, 1.0f);
  1014. // set color of light
  1015. rmRenderModel.rm_colLight= C_WHITE;
  1016. rmRenderModel.rm_colAmbient = C_GRAY;
  1017. // render range sphere model
  1018. pModelObject->SetupModelRendering(rmRenderModel);
  1019. pModelObject->RenderModel(rmRenderModel);
  1020. }
  1021. }
  1022. // if we should render volume box model
  1023. if( pDoc->m_bBrowseEntitiesMode)
  1024. {
  1025. // this model we will render
  1026. CModelObject *pModelObject;
  1027. // this render model structure will be rendered
  1028. CRenderModel rmRenderModel;
  1029. // create bbox from requested volume
  1030. FLOATaabbox3D bboxVolume( pDoc->m_vCreateBoxVertice0, pDoc->m_vCreateBoxVertice1);
  1031. // position it inside box
  1032. rmRenderModel.SetObjectPlacement(CPlacement3D(bboxVolume.Min(), ANGLE3D( 0, 0, 0)));
  1033. // set collision box's stretch factor
  1034. theApp.m_pBoundingBoxModelObject->mo_Stretch = bboxVolume.Size();
  1035. // render black wire frame allways
  1036. _mrpModelRenderPrefs.SetWire( TRUE);
  1037. _mrpModelRenderPrefs.SetHiddenLines( TRUE);
  1038. _mrpModelRenderPrefs.SetInkColor( C_BLACK);
  1039. // set bounding box model for rendering
  1040. pModelObject = theApp.m_pBoundingBoxModelObject;
  1041. // set light placement
  1042. rmRenderModel.rm_vLightDirection = FLOAT3D(1.0f, -1.0f, 1.0f);
  1043. // set color of light
  1044. rmRenderModel.rm_colLight= C_WHITE;
  1045. rmRenderModel.rm_colAmbient = C_GRAY;
  1046. // render bounding volume model
  1047. pModelObject->SetupModelRendering(rmRenderModel);
  1048. pModelObject->RenderModel(rmRenderModel);
  1049. }
  1050. EndModelRenderingView();
  1051. // if we should draw orientation icon, do it now because latter we may
  1052. // have problems due to automatic InitRenderer (in that case we would try
  1053. // to render icons on second layer's DrawPort, last locked, but it is allready
  1054. // destructed)
  1055. if( pDoc->m_bOrientationIcons)
  1056. {
  1057. #define XS 10
  1058. #define YS 16
  1059. #define DX 32
  1060. #define DY 32
  1061. PIXaabbox2D boxScreen(PIX2D(XS, YS), PIX2D(XS+DX, YS+DY));
  1062. // choose view's orientation icon index
  1063. INDEX iIcon = 0;
  1064. CTString strView="None";
  1065. CTString strU="?";
  1066. CTString strV="?";
  1067. switch( m_ptProjectionType)
  1068. {
  1069. case CSlaveViewer::PT_PERSPECTIVE: { iIcon = 0; strView="persp"; strU=""; strV=""; break;}
  1070. case CSlaveViewer::PT_ISOMETRIC_FRONT: { iIcon = 5; strView="front"; strU="x"; strV="y"; break;}
  1071. case CSlaveViewer::PT_ISOMETRIC_RIGHT: { iIcon = 3; strView="right"; strU="-z"; strV="y"; break;}
  1072. case CSlaveViewer::PT_ISOMETRIC_TOP: { iIcon = 1; strView="top"; strU="x"; strV="-z"; break;}
  1073. case CSlaveViewer::PT_ISOMETRIC_BACK: { iIcon = 6; strView="back"; strU="-x"; strV="y"; break;}
  1074. case CSlaveViewer::PT_ISOMETRIC_LEFT: { iIcon = 4; strView="left"; strU="z"; strV="y"; break;}
  1075. case CSlaveViewer::PT_ISOMETRIC_BOTTOM: { iIcon = 2; strView="bottom"; strU="x"; strV="z"; break;}
  1076. }
  1077. MEXaabbox2D boxTexture(MEX2D(iIcon*DX, 0), MEX2D((iIcon+1)*DX, DY));
  1078. // render icon
  1079. CTextureObject toIcon;
  1080. toIcon.SetData( theApp.m_pViewIconsTD);
  1081. pDP->PutTexture(&toIcon, boxScreen, boxTexture);
  1082. PIX2D pixCenter=PIX2D( pDP->GetWidth()*0.03f, pDP->GetHeight()*0.97f);
  1083. DrawAxis( pixCenter, 40, C_BLUE|CT_OPAQUE, C_RED|CT_OPAQUE, strU, strV);
  1084. pDP->SetFont( _pfdConsoleFont);
  1085. pDP->SetTextAspect( 1.0f);
  1086. pDP->SetTextScaling( 1.0f);
  1087. pDP->PutTextCXY( strView, XS+DX/2, YS/2, C_RED|CT_OPAQUE);
  1088. }
  1089. pDP->BlendScreen();
  1090. // if second layer's world exists
  1091. if( pDoc->m_pwoSecondLayer != NULL)
  1092. {
  1093. // prepare second layer's projection ...
  1094. // get viewer placement from first layer
  1095. CPlacement3D plVirtualViewer = prProjection->ViewerPlacementR();
  1096. // transform it to the system of the second layer
  1097. plVirtualViewer.AbsoluteToRelative(pDoc->m_plSecondLayer);
  1098. // use it in projection for second layer
  1099. CAnyProjection3D prProjectionSecondLayer;
  1100. prProjectionSecondLayer = prProjection;
  1101. prProjectionSecondLayer->ViewerPlacementL() = plVirtualViewer;
  1102. prProjectionSecondLayer->Prepare();
  1103. // if we will not use any kind of polygon filling
  1104. if( !bPolygonFillOn)
  1105. {
  1106. // render scene directly into primary draw port
  1107. ::RenderView( *pDoc->m_pwoSecondLayer, *(CEntity*) NULL,
  1108. prProjectionSecondLayer, *pDP);
  1109. }
  1110. // if filling, create drawport for second layer and create picture using CopyViaZBuffer
  1111. else
  1112. {
  1113. // disable shadow rendering on world in second layer
  1114. _wrpWorldRenderPrefs.SetShadowsType( CWorldRenderPrefs::SHT_NONE);
  1115. // set that we will rendering scene over allready rendered scene
  1116. pDP->SetOverlappedRendering(TRUE);
  1117. // render second layer's scene over already rendered scene using filled z-buffer
  1118. ::RenderView( *pDoc->m_pwoSecondLayer, *(CEntity*) NULL, prProjectionSecondLayer, *pDP);
  1119. }
  1120. // if we are in triangularisation primitive mode
  1121. if( (pDoc->m_bPrimitiveMode) &&
  1122. (theApp.m_vfpCurrent.vfp_ttTriangularisationType != TT_NONE) )
  1123. {
  1124. theApp.m_vfpCurrent.vfp_o3dPrimitive.ob_aoscSectors.Lock();
  1125. CDynamicArray<CObjectVertex> &aVtx = theApp.m_vfpCurrent.vfp_o3dPrimitive.ob_aoscSectors[0].osc_aovxVertices;
  1126. theApp.m_vfpCurrent.vfp_o3dPrimitive.ob_aoscSectors.Unlock();
  1127. aVtx.Lock();
  1128. // render all selected vertices as boxes
  1129. for( INDEX iVtx=0; iVtx<aVtx.Count(); iVtx++)
  1130. {
  1131. if( aVtx[ iVtx].ovx_ulFlags & OVXF_SELECTED)
  1132. {
  1133. FLOAT3D vProjected;
  1134. // project vertice
  1135. prProjectionSecondLayer->ProjectCoordinate( DOUBLEtoFLOAT(aVtx[ iVtx]), vProjected);
  1136. // convert y coordinate from mathemathical representation into screen one
  1137. vProjected(2) = pDP->GetHeight() - vProjected(2);
  1138. pDP->Fill( (SLONG)vProjected(1)-3, (SLONG)vProjected(2)-3, 6, 6, C_BLACK|CT_OPAQUE);
  1139. }
  1140. }
  1141. aVtx.Unlock();
  1142. }
  1143. }
  1144. // if cut mode on, this isn't perspective view, and cut line modification has been performed on this view
  1145. if( theApp.m_bCutModeOn && !bPerspectiveOn && ( pDoc->m_pCutLineView == this))
  1146. {
  1147. // render cut line
  1148. FLOAT3D v0 = pDoc->m_vCutLineStart;
  1149. FLOAT3D v1 = pDoc->m_vCutLineEnd;
  1150. FLOAT3D vp0;
  1151. FLOAT3D vp1;
  1152. // create a projection for current viewer
  1153. CAnyProjection3D prProjection;
  1154. svViewer.MakeProjection(prProjection);
  1155. prProjection->Prepare();
  1156. prProjection->ProjectCoordinate( v0, vp0);
  1157. prProjection->ProjectCoordinate( v1, vp1);
  1158. // convert y coordinates into view space
  1159. vp0(2) = pDP->GetHeight()-vp0(2);
  1160. vp1(2) = pDP->GetHeight()-vp1(2);
  1161. PIX x1 = (PIX)vp0(1);
  1162. PIX y1 = (PIX)vp0(2);
  1163. PIX x2 = (PIX)vp1(1);
  1164. PIX y2 = (PIX)vp1(2);
  1165. // spread cut line (using parametric line representation) to edges of the draw port
  1166. FLOAT dx = x2-x1;
  1167. FLOAT dy = y2-y1;
  1168. FLOAT fT[4];
  1169. fT[0] = (0-x1)/dx;
  1170. fT[1] = (pDP->GetWidth()-x1)/dx;
  1171. fT[2] = (0-y1)/dy;
  1172. fT[3] = (pDP->GetHeight()-y1)/dy;
  1173. // find smallest T greater than 0 and biggest T less than 0
  1174. FLOAT fMaxNegT = -9999999.0f;
  1175. FLOAT fMinPosT = 9999999.0f;
  1176. for( INDEX iT=0; iT<4; iT++)
  1177. {
  1178. if(fT[iT]>1)
  1179. {
  1180. if(fT[iT]<fMinPosT)
  1181. {
  1182. fMinPosT = fT[iT];
  1183. }
  1184. }
  1185. else if(fT[iT]<0)
  1186. {
  1187. if(fT[iT]>fMaxNegT)
  1188. {
  1189. fMaxNegT = fT[iT];
  1190. }
  1191. }
  1192. }
  1193. // calculate border coordinates for found two T values
  1194. PIX xb1 = (PIX) x1+dx*fMaxNegT;
  1195. PIX xb2 = (PIX) x1+dx*fMinPosT;
  1196. PIX yb1 = (PIX) y1+dy*fMaxNegT;
  1197. PIX yb2 = (PIX) y1+dy*fMinPosT;
  1198. // draw cut line
  1199. COLOR colCutBorderLine = C_RED|CT_OPAQUE;
  1200. pDP->DrawLine( xb1, yb1, xb2, yb2, colCutBorderLine, _TY124_);
  1201. // draw control point lines
  1202. COLOR colControl = C_BLACK|CT_OPAQUE;
  1203. pDP->DrawLine( x1-3, y1-3, x1+3, y1+3, colControl);
  1204. pDP->DrawLine( x1+3, y1-3, x1-3, y1+3, colControl);
  1205. pDP->DrawLine( x2-3, y2-3, x2+3, y2+3, colControl);
  1206. pDP->DrawLine( x2+3, y2-3, x2-3, y2+3, colControl);
  1207. }
  1208. // if measure mode on
  1209. if( m_iaInputAction == IA_MEASURING)
  1210. {
  1211. // calculate placement for mouse down
  1212. CPlacement3D plMouseDown;
  1213. // obtain information about where mouse pointed into the world in the moment of mouse down
  1214. CCastRay crRayHit = GetMouseHitInformation( m_ptMouseDown);
  1215. plMouseDown.pl_PositionVector = crRayHit.cr_vHit;
  1216. pDoc->SnapToGrid( plMouseDown, m_fGridInMeters/GRID_DISCRETE_VALUES);
  1217. // calculate placement for current mouse position
  1218. CPlacement3D plCurrentMousePos;
  1219. // obtain information about where mouse points into the world right now
  1220. crRayHit = GetMouseHitInformation( m_ptMouse);
  1221. plCurrentMousePos.pl_PositionVector = crRayHit.cr_vHit;
  1222. // snap to grid curent mouse placement
  1223. pDoc->SnapToGrid( plCurrentMousePos, m_fGridInMeters/GRID_DISCRETE_VALUES);
  1224. // construct bbox containing both points
  1225. FLOATaabbox3D bbox( plMouseDown.pl_PositionVector);
  1226. bbox |= FLOATaabbox3D( plCurrentMousePos.pl_PositionVector);
  1227. FLOAT3D vCenter = plMouseDown.pl_PositionVector;
  1228. FLOAT3D vUp = plMouseDown.pl_PositionVector;
  1229. FLOAT3D vRight = plMouseDown.pl_PositionVector;
  1230. FLOAT3D vForward = plMouseDown.pl_PositionVector;
  1231. vUp(2) = plCurrentMousePos.pl_PositionVector(2);
  1232. vRight(1) = plCurrentMousePos.pl_PositionVector(1);
  1233. vForward(3) = plCurrentMousePos.pl_PositionVector(3);
  1234. // prepare font
  1235. pDP->SetFont( theApp.m_pfntSystem);
  1236. pDP->SetTextAspect( 1.0f);
  1237. pDP->SetTextScaling( 1.0f);
  1238. CTString strText;
  1239. strText.PrintF( "%g", bbox.Size()(1));
  1240. DrawArrowAndTypeText( *prProjection, vCenter, vRight, C_BLUE|CT_OPAQUE, strText);
  1241. strText.PrintF( "%g", bbox.Size()(2));
  1242. DrawArrowAndTypeText( *prProjection, vCenter, vUp, C_BLUE|CT_OPAQUE, strText);
  1243. strText.PrintF( "%g", bbox.Size()(3));
  1244. DrawArrowAndTypeText( *prProjection, vCenter, vForward, C_BLUE|CT_OPAQUE, strText);
  1245. // in orto projections, draw diagonal line
  1246. if( m_ptProjectionType != CSlaveViewer::PT_PERSPECTIVE)
  1247. {
  1248. //strText.PrintF( "%g", bbox.Size().Length());
  1249. DrawArrowAndTypeText( *prProjection,
  1250. plMouseDown.pl_PositionVector,
  1251. plCurrentMousePos.pl_PositionVector, C_lGRAY|CT_OPAQUE, "");
  1252. }
  1253. m_strMeasuring.PrintF( "Distance: %g", bbox.Size().Length());
  1254. }
  1255. // test string
  1256. if( m_strTest!="")
  1257. {
  1258. pDP->SetFont( theApp.m_pfntSystem);
  1259. pDP->SetTextScaling( 1.0f);
  1260. pDP->SetTextAspect( 1.0f);
  1261. pDP->PutText( m_strTest, 32, 32);
  1262. }
  1263. }
  1264. static TIME tmSwapBuffers = 0;
  1265. extern BOOL _bInOnDraw = FALSE;
  1266. void CWorldEditorView::OnDraw(CDC* pDC)
  1267. {
  1268. // skip if already drawing
  1269. if( _bInOnDraw) return;
  1270. _bInOnDraw = TRUE;
  1271. // get some view variables
  1272. CWorldEditorDoc* pDoc = GetDocument();
  1273. BOOL bCSGOn = pDoc->m_pwoSecondLayer != NULL;
  1274. BOOL bPerspectiveOn = m_ptProjectionType == CSlaveViewer::PT_PERSPECTIVE;
  1275. CDrawPort *pdpValidDrawPort = GetDrawPort();
  1276. CViewPort *pvpValidViewPort = GetViewPort();
  1277. // if there is a valid drawport, and the drawport can be locked
  1278. if( pdpValidDrawPort!=NULL && pdpValidDrawPort->Lock())
  1279. {
  1280. // variable to recive start time
  1281. CTimerValue tvStart = _pTimer->GetHighPrecisionTimer();
  1282. // render view
  1283. RenderView( pdpValidDrawPort);
  1284. // obtain stop time
  1285. CTimerValue tvStop = _pTimer->GetHighPrecisionTimer();
  1286. // number telling how many miliseconds passed
  1287. TIME tmDelta = (tvStop-tvStart).GetSeconds() +tmSwapBuffers;
  1288. // mark that view has been changed
  1289. m_chViewChanged.MarkChanged();
  1290. // if we can and should print any kind of frame rate descriptive message
  1291. if( !bCSGOn && bPerspectiveOn && GetChildFrame()->m_bSceneRenderingTime)
  1292. {
  1293. // prepare string about things that impact to currently rendered picture
  1294. CTString strFPS, strReport;
  1295. STAT_Report(strReport);
  1296. STAT_Reset();
  1297. // adjust and set font
  1298. pdpValidDrawPort->SetFont( _pfdConsoleFont);
  1299. pdpValidDrawPort->SetTextScaling( 1.0f);
  1300. // put filter
  1301. PIX pixDPHeight = pdpValidDrawPort->GetHeight();
  1302. pdpValidDrawPort->Fill( 0,0, 150,pixDPHeight, C_BLACK|128, C_BLACK|0, C_BLACK|192, C_BLACK|0);
  1303. // printout statistics
  1304. strFPS.PrintF( " %3.0f FPS (%2.0f ms)\n----------------\n", 1.0f/tmDelta, tmDelta*1000.0f);
  1305. pdpValidDrawPort->PutText( strFPS, 0, 5, C_lCYAN|CT_OPAQUE);
  1306. pdpValidDrawPort->PutText( strReport, 4, 30, C_GREEN|CT_OPAQUE);
  1307. }
  1308. // unlock the drawport
  1309. pdpValidDrawPort->Unlock();
  1310. // swap if there is a valid viewport
  1311. if( pvpValidViewPort!=NULL) {
  1312. tvStart = _pTimer->GetHighPrecisionTimer();
  1313. pvpValidViewPort->SwapBuffers();
  1314. tvStop = _pTimer->GetHighPrecisionTimer();
  1315. tmSwapBuffers = (tvStop-tvStart).GetSeconds();
  1316. }
  1317. }
  1318. // all done
  1319. _bInOnDraw = FALSE;
  1320. }
  1321. /////////////////////////////////////////////////////////////////////////////
  1322. // CWorldEditorView diagnostics
  1323. #ifdef _DEBUG
  1324. void CWorldEditorView::AssertValid() const
  1325. {
  1326. CView::AssertValid();
  1327. }
  1328. void CWorldEditorView::Dump(CDumpContext& dc) const
  1329. {
  1330. CView::Dump(dc);
  1331. }
  1332. CWorldEditorDoc* CWorldEditorView::GetDocument() // non-debug version is inline
  1333. {
  1334. ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CWorldEditorDoc)));
  1335. return (CWorldEditorDoc*)m_pDocument;
  1336. }
  1337. #endif //_DEBUG
  1338. /////////////////////////////////////////////////////////////////////////////
  1339. // CWorldEditorView message handlers
  1340. void CWorldEditorView::OnInitialUpdate()
  1341. {
  1342. CView::OnInitialUpdate();
  1343. // allow file drop
  1344. DragAcceptFiles();
  1345. // at this time, m_hWnd is valid, so we do canvas initialization here
  1346. _pGfx->CreateWindowCanvas(m_hWnd, &m_pvpViewPort, &m_pdpDrawPort);
  1347. // get active view
  1348. CWorldEditorView *pWorldEditorView = theApp.GetActiveView();
  1349. if( (pWorldEditorView != NULL) && (pWorldEditorView != this)
  1350. && (theApp.m_Preferences.ap_CopyExistingWindowPrefs) )
  1351. {
  1352. m_IsWinBcgTexture = pWorldEditorView->m_IsWinBcgTexture;
  1353. m_fnWinBcgTexture = pWorldEditorView->m_fnWinBcgTexture;
  1354. m_SelectionColor = pWorldEditorView->m_SelectionColor;
  1355. m_PaperColor = pWorldEditorView->m_PaperColor;
  1356. m_InkColor = pWorldEditorView->m_InkColor;
  1357. CChildFrame *pcfThis = GetChildFrame();
  1358. CChildFrame *pcfOld = pWorldEditorView->GetChildFrame();
  1359. if( pcfThis != pcfOld)
  1360. {
  1361. pcfThis->m_mvViewer = pcfOld->m_mvViewer;
  1362. }
  1363. }
  1364. else
  1365. {
  1366. m_IsWinBcgTexture = FALSE;
  1367. m_SelectionColor = theApp.m_Preferences.ap_DefaultSelectionColor;
  1368. m_PaperColor = theApp.m_Preferences.ap_DefaultPaperColor;
  1369. m_InkColor = theApp.m_Preferences.ap_DefaultInkColor;
  1370. }
  1371. if( theApp.m_Preferences.ap_SetDefaultColors)
  1372. {
  1373. m_SelectionColor = CLRF_CLR( theApp.m_Preferences.ap_DefaultSelectionColor);
  1374. m_PaperColor = CLRF_CLR( theApp.m_Preferences.ap_DefaultPaperColor);
  1375. m_InkColor = CLRF_CLR( theApp.m_Preferences.ap_DefaultInkColor);
  1376. }
  1377. }
  1378. void CWorldEditorView::OnSize(UINT nType, int cx, int cy)
  1379. {
  1380. CView::OnSize(nType, cx, cy);
  1381. // if we are not in game mode and changing of display mode is not on
  1382. if( !theApp.m_bChangeDisplayModeInProgress)
  1383. { // and window canvas is valid
  1384. if( m_pvpViewPort!=NULL)
  1385. { // resize it
  1386. m_pvpViewPort->Resize();
  1387. }
  1388. }
  1389. }
  1390. int CWorldEditorView::OnCreate(LPCREATESTRUCT lpCreateStruct)
  1391. {
  1392. if (CView::OnCreate(lpCreateStruct) == -1)
  1393. return -1;
  1394. // register drop target
  1395. m_DropTarget.Register(this);
  1396. return 0;
  1397. }
  1398. /*
  1399. * Get the pointer to the main frame object of this application
  1400. */
  1401. CMainFrame *CWorldEditorView::GetMainFrame()
  1402. {
  1403. // get the MDIChildFrame of this window
  1404. CChildFrame *pfrChild = (CChildFrame *)this->GetParentFrame();
  1405. ASSERT(pfrChild!=NULL);
  1406. // get the MDIFrameWnd
  1407. CMainFrame *pfrMain = (CMainFrame *)pfrChild->GetParentFrame();
  1408. ASSERT(pfrMain!=NULL);
  1409. return pfrMain;
  1410. }
  1411. void CWorldEditorView::OnKillFocus(CWnd* pNewWnd)
  1412. {
  1413. m_iaInputAction = IA_NONE;
  1414. // discard laso selection
  1415. m_avpixLaso.Clear();
  1416. CView::OnKillFocus(pNewWnd);
  1417. }
  1418. void CWorldEditorView::OnActivateView(BOOL bActivate,
  1419. CView* pActivateView, CView* pDeactiveView)
  1420. {
  1421. // if new view's document is not same as last activated document and if document is
  1422. // beiing activated
  1423. if( (pActivateView != NULL) &&
  1424. (pActivateView->GetDocument() != theApp.GetLastActivatedDocument()) &&
  1425. (bActivate) &&
  1426. (pActivateView->GetDocument() != NULL) )
  1427. {
  1428. // mark that we are in crossing fase of switching documents if anybody searches for
  1429. // document, he will get NULL
  1430. theApp.m_bDocumentChangeOn = TRUE;
  1431. // force OnIdle so info and combos will adjust to situation when doc = NULL
  1432. theApp.OnIdle( 0);
  1433. // finish crossing fase, continue "normal" behaviour
  1434. theApp.m_bDocumentChangeOn = FALSE;
  1435. }
  1436. // mark that new document will be activated
  1437. theApp.ActivateDocument(GetDocument());
  1438. CView::OnActivateView(bActivate, pActivateView, pDeactiveView);
  1439. }
  1440. BOOL MyChooseColor( COLORREF &clrNewColor, CWnd &wndOwner)
  1441. {
  1442. COLORREF MyCustColors[ 16];
  1443. CHOOSECOLOR ccInit;
  1444. ASSERT( &wndOwner != NULL);
  1445. MyCustColors[ 0] = CLRF_CLR(C_BLACK);
  1446. MyCustColors[ 1] = CLRF_CLR(C_WHITE);
  1447. MyCustColors[ 2] = CLRF_CLR(C_dGRAY);
  1448. MyCustColors[ 3] = CLRF_CLR(C_GRAY);
  1449. MyCustColors[ 4] = CLRF_CLR(C_lGRAY);
  1450. MyCustColors[ 5] = CLRF_CLR(C_dRED);
  1451. MyCustColors[ 6] = CLRF_CLR(C_dGREEN);
  1452. MyCustColors[ 7] = CLRF_CLR(C_dBLUE);
  1453. MyCustColors[ 8] = CLRF_CLR(C_dCYAN);
  1454. MyCustColors[ 9] = CLRF_CLR(C_dMAGENTA);
  1455. MyCustColors[10] = CLRF_CLR(C_dYELLOW);
  1456. MyCustColors[11] = CLRF_CLR(C_dORANGE);
  1457. MyCustColors[12] = CLRF_CLR(C_dBROWN);
  1458. MyCustColors[13] = CLRF_CLR(C_dPINK);
  1459. MyCustColors[14] = CLRF_CLR(C_lORANGE);
  1460. MyCustColors[15] = CLRF_CLR(C_lBROWN);
  1461. memset(&ccInit, 0, sizeof(CHOOSECOLOR));
  1462. ccInit.lStructSize = sizeof(CHOOSECOLOR);
  1463. ccInit.Flags = CC_RGBINIT | CC_FULLOPEN;
  1464. ccInit.rgbResult = clrNewColor;
  1465. ccInit.lpCustColors = &MyCustColors[ 0];
  1466. ccInit.hwndOwner = wndOwner.m_hWnd;
  1467. if( !ChooseColor( &ccInit))
  1468. return FALSE;
  1469. clrNewColor = ccInit.rgbResult;
  1470. return TRUE;
  1471. }
  1472. // Returns eather perspective view's or manual mip factor
  1473. FLOAT CWorldEditorView::GetCurrentlyActiveMipFactor(void)
  1474. {
  1475. // get document
  1476. CWorldEditorDoc* pDoc = GetDocument();
  1477. CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
  1478. CEntity *penBrush = pMainFrame->m_CSGDesitnationCombo.GetSelectedBrushEntity();
  1479. // get draw port
  1480. CDrawPort *pdpValidDrawPort = GetDrawPort();
  1481. if((GetChildFrame()->m_bAutoMipBrushingOn) &&
  1482. (penBrush != NULL) &&
  1483. (pdpValidDrawPort != NULL) )
  1484. {
  1485. // get entity's brush
  1486. CBrush3D *pbrBrush = penBrush->GetBrush();
  1487. // create a slave viewer
  1488. CSlaveViewer svViewer( GetChildFrame()->m_mvViewer, CSlaveViewer::PT_PERSPECTIVE,
  1489. pDoc->m_plGrid, pdpValidDrawPort);
  1490. // create a projection for slave viewer
  1491. CAnyProjection3D prProjection;
  1492. svViewer.MakeProjection(prProjection);
  1493. prProjection->ObjectPlacementL() = penBrush->GetPlacement();
  1494. // prepare the projection
  1495. prProjection->Prepare();
  1496. // return mip factor for entity in perspective projection
  1497. return( -prProjection->pr_TranslationVector(3));
  1498. }
  1499. else
  1500. {
  1501. return (GetChildFrame()->m_fManualMipBrushingFactor);
  1502. }
  1503. }
  1504. void CWorldEditorView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
  1505. {
  1506. // find window under mouse pointer
  1507. CWorldEditorDoc* pDoc = GetDocument();
  1508. pDoc->SetStatusLineModeInfoMessage();
  1509. POINT point;
  1510. GetCursorPos(&point);
  1511. HWND hwndUnderMouse = ::WindowFromPoint( point);
  1512. // if not this one (use parent because gfx-API child is over the window)
  1513. if (m_hWnd != ::GetParent(hwndUnderMouse)) {
  1514. // ignore the key
  1515. return;
  1516. }
  1517. CView::OnKeyDown( nChar, nRepCnt, nFlags);
  1518. BOOL bShift = (GetKeyState(VK_SHIFT) &0x8000) != 0;
  1519. BOOL bCtrl = (GetKeyState(VK_CONTROL)&0x8000) != 0;
  1520. BOOL bAlt = (GetKeyState(VK_MENU) &0x8000) != 0;
  1521. BOOL bSpace = (GetKeyState( VK_SPACE)&0x8000) != 0;
  1522. BOOL bLMB = (GetKeyState( VK_LBUTTON)&0x8000) != 0;
  1523. if(bLMB && !bAlt && (pDoc->GetEditingMode()==TERRAIN_MODE) && !bSpace)
  1524. {
  1525. if( bCtrl) m_iaInputAction=IA_TERRAIN_EDITING_CTRL_LMB;
  1526. else m_iaInputAction=IA_TERRAIN_EDITING_LMB;
  1527. }
  1528. // tool tips are on when you press I
  1529. if( (GetKeyState('I')&0x80) && !(bShift|bCtrl|bAlt)) {
  1530. CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
  1531. // if info doesn't yet exist
  1532. if( pMainFrame->m_pwndToolTip == NULL)
  1533. { // force it
  1534. theApp.m_cttToolTips.ManualOn( m_ptMouse.x, m_ptMouse.y, &::GetToolTipText, this);
  1535. }
  1536. }
  1537. // call parent's key pressed function
  1538. GetChildFrame()->KeyPressed( nChar, nRepCnt, nFlags);
  1539. }
  1540. void CWorldEditorView::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)
  1541. {
  1542. CWorldEditorDoc* pDoc = GetDocument();
  1543. pDoc->SetStatusLineModeInfoMessage();
  1544. // if we are in mip mode for setting, set new brush switch factor
  1545. if( m_iaInputAction == IA_MIP_SETTING)
  1546. {
  1547. SetMipBrushFactor();
  1548. }
  1549. BOOL bCtrl = (GetKeyState(VK_CONTROL)&0x8000) != 0;
  1550. BOOL bSpace = (GetKeyState( VK_SPACE)&0x8000) != 0;
  1551. BOOL bLMB = (GetKeyState( VK_LBUTTON)&0x8000) != 0;
  1552. BOOL bAlt = (GetKeyState( VK_MENU)&0x8000) != 0;
  1553. if(bLMB && !bAlt && (pDoc->GetEditingMode()==TERRAIN_MODE) && !bSpace)
  1554. {
  1555. if( bCtrl) m_iaInputAction=IA_TERRAIN_EDITING_CTRL_LMB;
  1556. else m_iaInputAction=IA_TERRAIN_EDITING_LMB;
  1557. _tvLastTerrainBrushingApplied=_pTimer->GetHighPrecisionTimer();
  1558. }
  1559. // shut down tool tips
  1560. theApp.m_cttToolTips.ManualOff();
  1561. CView::OnKeyUp(nChar, nRepCnt, nFlags);
  1562. }
  1563. void CWorldEditorView::SetMipBrushFactor(void)
  1564. {
  1565. // remember current time as time when last mip brushing option has been used
  1566. _fLastMipBrushingOptionUsed = _pTimer->GetRealTimeTick();
  1567. CChildFrame *pChild = GetChildFrame();
  1568. // set auto mip brushing mode on
  1569. pChild->m_bAutoMipBrushingOn = TRUE;
  1570. // get auto mip factor
  1571. FLOAT fCurrentMipFactor = GetCurrentlyActiveMipFactor();
  1572. pChild->m_bAutoMipBrushingOn = pChild->m_bLastAutoMipBrushingOn;
  1573. // set auto mip brushing mode as it was before mip setting started
  1574. ASSERT( m_pbmToSetMipSwitch != NULL);
  1575. // set new mip switch factor
  1576. m_pbmToSetMipSwitch->SetMipDistance( fCurrentMipFactor-0.01f);
  1577. // switch back to auto mip brushing mode
  1578. GetChildFrame()->m_bAutoMipBrushingOn = TRUE;
  1579. // get document
  1580. CWorldEditorDoc* pDoc = GetDocument();
  1581. // document has changed
  1582. pDoc->SetModifiedFlag();
  1583. // update all views
  1584. pDoc->UpdateAllViews( NULL);
  1585. m_iaInputAction = IA_NONE;
  1586. }
  1587. void CWorldEditorView::StartMouseInput( CPoint point)
  1588. {
  1589. CWorldEditorDoc* pDoc = GetDocument();
  1590. BOOL bCSGOn = pDoc->m_pwoSecondLayer != NULL;
  1591. pDoc->UpdateAllViews(NULL);
  1592. // reset offseted placement
  1593. m_plMouseOffset.pl_PositionVector = FLOAT3D(0.0f, 0.0f, 0.0f);
  1594. m_plMouseOffset.pl_OrientationAngle = ANGLE3D(0, 0, 0);
  1595. // if there is CSG operation active
  1596. if( bCSGOn)
  1597. {
  1598. // copy original layer's placement because we need to perform "continous moving"
  1599. m_plMouseMove = pDoc->m_plSecondLayer;
  1600. }
  1601. // otherwise if we are in entity mode and there is at least 1 entity selected
  1602. else if( pDoc->GetEditingMode() == ENTITY_MODE)
  1603. {
  1604. if(pDoc->m_selEntitySelection.Count()==0)
  1605. {
  1606. pDoc->m_aSelectedEntityPlacements.Clear();
  1607. }
  1608. else
  1609. {
  1610. FLOATaabbox3D box;
  1611. CPlacement3D plEntityCenter;
  1612. plEntityCenter = CPlacement3D( FLOAT3D(0.0f,0.0f,0.0f), ANGLE3D(0,0,0));
  1613. {FOREACHINDYNAMICCONTAINER(pDoc->m_selEntitySelection, CEntity, iten)
  1614. {
  1615. // accumulate positions
  1616. box |= iten->GetPlacement().pl_PositionVector;
  1617. //plEntityCenter.pl_OrientationAngle += iten->GetPlacement().pl_OrientationAngle;
  1618. }}
  1619. plEntityCenter.pl_PositionVector = box.Center();
  1620. plEntityCenter.pl_PositionVector(2) = box.Min()(2);
  1621. // calculate average rotation
  1622. //plEntityCenter.pl_OrientationAngle /= (ANGLE)pDoc->m_selEntitySelection.Count();
  1623. // remember
  1624. pDoc->m_aSelectedEntityPlacements.Clear();
  1625. pDoc->m_aSelectedEntityPlacements.New(pDoc->m_selEntitySelection.Count());
  1626. INDEX ienCurrent = 0;
  1627. {FOREACHINDYNAMICCONTAINER(pDoc->m_selEntitySelection, CEntity, iten)
  1628. {
  1629. CPlacement3D plRelative = iten->GetPlacement();
  1630. plRelative.AbsoluteToRelativeSmooth(plEntityCenter);
  1631. pDoc->m_aSelectedEntityPlacements[ ienCurrent] = plRelative;
  1632. ienCurrent++;
  1633. }}
  1634. // copy it's placement for continous moving
  1635. m_plMouseMove = plEntityCenter;
  1636. }
  1637. }
  1638. else if( pDoc->GetEditingMode() == VERTEX_MODE)
  1639. {
  1640. pDoc->m_avStartDragVertices.Clear();
  1641. INDEX ctDragVertices = pDoc->m_selVertexSelection.Count();
  1642. if( ctDragVertices != 0)
  1643. {
  1644. // remember coordinates of vertices for dragging
  1645. pDoc->m_avStartDragVertices.New(ctDragVertices);
  1646. INDEX iVtx = 0;
  1647. {FOREACHINDYNAMICCONTAINER( pDoc->m_selVertexSelection, CBrushVertex, itbvx)
  1648. {
  1649. pDoc->m_avStartDragVertices[ iVtx] = FLOATtoDOUBLE( itbvx->bvx_vAbsolute);
  1650. iVtx++;
  1651. }}
  1652. }
  1653. }
  1654. // copy mouse point to both point for calculating relative (from last mouse position) and
  1655. // absolute (from mouse down position) distances
  1656. m_ptMouse = point;
  1657. }
  1658. void CWorldEditorView::StopMouseInput(void)
  1659. {
  1660. // update all views when current view stopped modifying
  1661. CWorldEditorDoc* pDoc = GetDocument();
  1662. pDoc->UpdateAllViews( NULL);
  1663. }
  1664. // obtain information about what was hitted with mouse
  1665. CCastRay CWorldEditorView::GetMouseHitInformation( CPoint point,
  1666. BOOL bHitPortals /* = FALSE */,
  1667. BOOL bHitModels /* = TRUE */,
  1668. BOOL bHitFields /* = FALSE */,
  1669. CEntity *penSourceEntity /* = NULL */,
  1670. BOOL bHitBrushes /* = TRUE */)
  1671. {
  1672. CWorldEditorDoc* pDoc = GetDocument();
  1673. // get draw port
  1674. CDrawPort *pdpValidDrawPort = GetDrawPort();
  1675. // if it is not valid
  1676. if( pdpValidDrawPort == NULL)
  1677. {
  1678. // return dummy result
  1679. return CCastRay( NULL, CPlacement3D(FLOAT3D(0.0f,0.0f,0.0f), ANGLE3D(0,0,0)) );
  1680. }
  1681. // obtain viewer placement
  1682. CPlacement3D plViewer = GetChildFrame()->m_mvViewer.GetViewerPlacement();
  1683. // create a slave viewer
  1684. CSlaveViewer svViewer( GetChildFrame()->m_mvViewer, m_ptProjectionType,
  1685. pDoc->m_plGrid, pdpValidDrawPort);
  1686. // now we will try to obtain where mouse poonts to in the base world
  1687. // create a projection for current viewer
  1688. CAnyProjection3D prProjection;
  1689. svViewer.MakeProjection(prProjection);
  1690. prProjection->Prepare();
  1691. // make the ray from viewer point through the mouse point, in current projection
  1692. CPlacement3D plRay;
  1693. prProjection->RayThroughPoint(FLOAT3D((float)point.x,
  1694. pdpValidDrawPort->GetHeight()-(float)point.y, 0.0f), plRay);
  1695. // construct cast ray for base world
  1696. CCastRay crBaseWorldCastResult( penSourceEntity, plRay);
  1697. // set portal "transparency" or "hitability" for hit beam
  1698. crBaseWorldCastResult.cr_bHitPortals = bHitPortals;
  1699. // set hitability for models
  1700. if( (m_vpViewPrefs.m_mrpModelRenderPrefs.GetRenderType() & RT_TEXTURE) && bHitModels)
  1701. {
  1702. crBaseWorldCastResult.cr_ttHitModels = CCastRay::TT_FULL;
  1703. }
  1704. else
  1705. {
  1706. crBaseWorldCastResult.cr_ttHitModels = CCastRay::TT_NONE;
  1707. }
  1708. crBaseWorldCastResult.cr_bHitFields = bHitFields;
  1709. crBaseWorldCastResult.cr_bHitBrushes = bHitBrushes;
  1710. // cast ray, go for hit data
  1711. pDoc->m_woWorld.CastRay( crBaseWorldCastResult);
  1712. // if second layer's world exist
  1713. if( pDoc->m_pwoSecondLayer != NULL)
  1714. {
  1715. // prepare second layer's projection ...
  1716. // get viewer placement from first layer
  1717. CPlacement3D plVirtualViewer = prProjection->ViewerPlacementR();
  1718. // transform it to the system of the second layer
  1719. plVirtualViewer.AbsoluteToRelative(pDoc->m_plSecondLayer);
  1720. // use it in projection for second layer
  1721. CAnyProjection3D prProjectionSecondLayer;
  1722. prProjectionSecondLayer = prProjection;
  1723. prProjectionSecondLayer->ViewerPlacementL() = plVirtualViewer;
  1724. prProjectionSecondLayer->Prepare();
  1725. // calculate valid ray for second layer
  1726. CPlacement3D plLayerRay;
  1727. prProjectionSecondLayer->RayThroughPoint(FLOAT3D((float)point.x,
  1728. pdpValidDrawPort->GetHeight()-(float)point.y, 0.0f), plLayerRay);
  1729. // construct cast ray for second layer's world
  1730. CCastRay crLayerWorldCastResult( penSourceEntity, plLayerRay);
  1731. // set portal "transparency" or "hitability" for hit beam
  1732. crLayerWorldCastResult.cr_bHitPortals = bHitPortals;
  1733. // set hitability for models
  1734. if( m_vpViewPrefs.m_mrpModelRenderPrefs.GetRenderType() & RT_TEXTURE)
  1735. {
  1736. crLayerWorldCastResult.cr_ttHitModels = CCastRay::TT_SIMPLE;
  1737. }
  1738. else
  1739. {
  1740. crLayerWorldCastResult.cr_ttHitModels = CCastRay::TT_NONE;
  1741. }
  1742. // cast ray, go for hit data
  1743. pDoc->m_pwoSecondLayer->CastRay( crLayerWorldCastResult);
  1744. // if any kind of entity on second layer was hitted
  1745. if( crLayerWorldCastResult.cr_penHit != NULL)
  1746. {
  1747. // calculate distance beetween viewer and hited point in layer's world
  1748. FLOAT fSecondLayerHitDistance =
  1749. (crLayerWorldCastResult.cr_vHit - plVirtualViewer.pl_PositionVector).Length();
  1750. // transform hited coordinate back to absolute space
  1751. CPlacement3D plHitPlacement = plLayerRay;
  1752. plHitPlacement.pl_PositionVector = crLayerWorldCastResult.cr_vHit;
  1753. plHitPlacement.RelativeToAbsolute( pDoc->m_plSecondLayer);
  1754. // and set it as hited point
  1755. crLayerWorldCastResult.cr_vHit = plHitPlacement.pl_PositionVector;
  1756. // if ray didn't hit anything on base world
  1757. if( crBaseWorldCastResult.cr_penHit == NULL)
  1758. {
  1759. // valid result is one received from second layer ray hit
  1760. return crLayerWorldCastResult;
  1761. }
  1762. // calculate distance beetween viewer and base world's hit point
  1763. FLOAT fBaseWorldHitDistance =
  1764. (crBaseWorldCastResult.cr_vHit - plViewer.pl_PositionVector).Length();
  1765. // if base world's hit point is closer than second layer's hit point
  1766. if( Abs(fBaseWorldHitDistance) < Abs(fSecondLayerHitDistance))
  1767. {
  1768. // base world's hit result is valid result
  1769. return crBaseWorldCastResult;
  1770. }
  1771. // otherwise
  1772. else
  1773. {
  1774. // second layer's world hit result is valid result
  1775. return crLayerWorldCastResult;
  1776. }
  1777. }
  1778. }
  1779. if( crBaseWorldCastResult.cr_penHit == NULL)
  1780. {
  1781. // placement equals ray placement
  1782. CPlacement3D plPlacementInFront = plRay;
  1783. // calculate position somewhere in front of viewer
  1784. plPlacementInFront.Translate_OwnSystem( FLOAT3D( 0.0f, 0.0f, -10.0f));
  1785. // copy result coordinate into cast object
  1786. crBaseWorldCastResult.cr_vHit = plPlacementInFront.pl_PositionVector;
  1787. }
  1788. return crBaseWorldCastResult;
  1789. }
  1790. FLOAT3D CWorldEditorView::GetMouseHitOnPlane( CPoint point, const FLOATplane3D &plPlane)
  1791. {
  1792. CWorldEditorDoc* pDoc = GetDocument();
  1793. // get draw port
  1794. CDrawPort *pdpValidDrawPort = GetDrawPort();
  1795. // if it is not valid
  1796. if( pdpValidDrawPort == NULL)
  1797. {
  1798. // return dummy result
  1799. return FLOAT3D(0.0f,0.0f,0.0f);
  1800. }
  1801. // obtain viewer placement
  1802. CPlacement3D plViewer = GetChildFrame()->m_mvViewer.GetViewerPlacement();
  1803. // create a slave viewer
  1804. CSlaveViewer svViewer( GetChildFrame()->m_mvViewer, m_ptProjectionType,
  1805. pDoc->m_plGrid, pdpValidDrawPort);
  1806. // now we will try to obtain where mouse poonts to in the base world
  1807. // create a projection for current viewer
  1808. CAnyProjection3D prProjection;
  1809. svViewer.MakeProjection(prProjection);
  1810. prProjection->Prepare();
  1811. // make the ray from viewer point through the mouse point, in current projection
  1812. CPlacement3D plRay;
  1813. prProjection->RayThroughPoint(FLOAT3D((float)point.x,
  1814. pdpValidDrawPort->GetHeight()-(float)point.y, 0.0f), plRay);
  1815. // get two points on the line
  1816. FLOAT3D v0 = plRay.pl_PositionVector;
  1817. FLOAT3D v1;
  1818. AnglesToDirectionVector(plRay.pl_OrientationAngle, v1);
  1819. v1*=100.0f; // to increase precision on large scales
  1820. v1+=v0;
  1821. // find intersection of line and plane
  1822. FLOAT f0 = plPlane.PointDistance(v0);
  1823. FLOAT f1 = plPlane.PointDistance(v1);
  1824. FLOAT fFraction = f0/(f0-f1);
  1825. return v0+(v1-v0)*fFraction;
  1826. }
  1827. void CWorldEditorView::MarkClosestVtxAndEdgeOnPrimitiveBase(CPoint point)
  1828. {
  1829. // get draw port
  1830. CDrawPort *pdpValidDrawPort = GetDrawPort();
  1831. // if it is not valid
  1832. if( pdpValidDrawPort == NULL) return;
  1833. CWorldEditorDoc* pDoc = GetDocument();
  1834. // create a slave viewer
  1835. CSlaveViewer svViewer( GetChildFrame()->m_mvViewer, m_ptProjectionType,
  1836. pDoc->m_plGrid, pdpValidDrawPort);
  1837. // create a projection for current viewer
  1838. CAnyProjection3D prProjection;
  1839. svViewer.MakeProjection(prProjection);
  1840. // prepare the projection
  1841. prProjection->Prepare();
  1842. // make the ray from viewer point through the mouse point, in current projection
  1843. CPlacement3D plRay;
  1844. prProjection->RayThroughPoint(FLOAT3D((float)point.x,
  1845. pdpValidDrawPort->GetHeight()-(float)point.y, 0.0f), plRay);
  1846. // transform ray to the system of the second layer
  1847. plRay.AbsoluteToRelative(pDoc->m_plSecondLayer);
  1848. m_vMouseDownSecondLayer = plRay.pl_PositionVector;
  1849. // prepare second layer's projection ...
  1850. // get viewer placement from first layer
  1851. CPlacement3D plVirtualViewer = prProjection->ViewerPlacementR();
  1852. // transform it to the system of the second layer
  1853. plVirtualViewer.AbsoluteToRelative(pDoc->m_plSecondLayer);
  1854. // use it in projection for second layer
  1855. CAnyProjection3D prProjectionSecondLayer;
  1856. prProjectionSecondLayer = prProjection;
  1857. prProjectionSecondLayer->ViewerPlacementL() = plVirtualViewer;
  1858. prProjectionSecondLayer->Prepare();
  1859. // get number of vertices for base polygon
  1860. INDEX vtxCt = theApp.m_vfpCurrent.vfp_avVerticesOnBaseOfPrimitive.Count();
  1861. // set distance of closest vertice to a hudge distance
  1862. FLOAT fMinVertexDistance = 999999.9f;
  1863. m_iDragVertice = -1;
  1864. FLOAT fMinEdgeDistance = 999999.9f;
  1865. m_iDragEdge = -1;
  1866. // now we will project base vertices onto screen and try
  1867. // to find closest vertice to mouse for moving vertices on the base
  1868. for( INDEX iVtx=0; iVtx<vtxCt; iVtx++)
  1869. {
  1870. INDEX iNext = (iVtx+1)%vtxCt;
  1871. FLOAT3D vProjectedVtx1, vProjectedVtx2;
  1872. // project vertices
  1873. prProjectionSecondLayer->ProjectCoordinate(
  1874. DOUBLEtoFLOAT(theApp.m_vfpCurrent.vfp_avVerticesOnBaseOfPrimitive[ iVtx]), vProjectedVtx1);
  1875. prProjectionSecondLayer->ProjectCoordinate(
  1876. DOUBLEtoFLOAT(theApp.m_vfpCurrent.vfp_avVerticesOnBaseOfPrimitive[ iNext]), vProjectedVtx2);
  1877. // convert y coordinate from mathemathical representation into screen one
  1878. vProjectedVtx1(2) = pdpValidDrawPort->GetHeight() - vProjectedVtx1(2);
  1879. vProjectedVtx2(2) = pdpValidDrawPort->GetHeight() - vProjectedVtx2(2);
  1880. vProjectedVtx1(3) = 0.0f;
  1881. vProjectedVtx2(3) = 0.0f;
  1882. // calculate distance to mouse
  1883. FLOAT fDVtx1 = ( FLOAT3D((FLOAT)point.x, (FLOAT)point.y, 0.0f) - vProjectedVtx1).Length();
  1884. FLOAT fDVtx2 = ( FLOAT3D((FLOAT)point.x, (FLOAT)point.y, 0.0f) - vProjectedVtx2).Length();
  1885. FLOAT fEdgeLen = ( vProjectedVtx1 - vProjectedVtx2).Length();
  1886. FLOAT s = (fDVtx1+fDVtx2+fEdgeLen)/2.0f;
  1887. FLOAT fArea = FLOAT(sqrt( FLOATtoDOUBLE( s*(s-fDVtx1)*(s-fDVtx2)*(s-fEdgeLen))));
  1888. FLOAT fDEdge = 2.0f*fArea/fEdgeLen;
  1889. // if distance of edge is smaller than last remembered and both edges are smaller than
  1890. // edges of triangle
  1891. if( (fDEdge < fMinEdgeDistance) && (fEdgeLen > fDVtx1) && (fEdgeLen > fDVtx2) )
  1892. {
  1893. fMinEdgeDistance = fDEdge;
  1894. m_iDragEdge = iVtx;
  1895. }
  1896. // if distance of first vertex is smaller than last remembered
  1897. if( fDVtx1 < fMinVertexDistance)
  1898. {
  1899. fMinVertexDistance = fDVtx1;
  1900. m_iDragVertice = iVtx;
  1901. }
  1902. }
  1903. // when we found closest vertice, remember its current position
  1904. m_vStartDragVertice = theApp.m_vfpCurrent.vfp_avVerticesOnBaseOfPrimitive[ m_iDragVertice];
  1905. if( m_iDragEdge != -1)
  1906. {
  1907. INDEX iEdgeEnd = (m_iDragEdge+1)%vtxCt;
  1908. m_vStartDragEdge =
  1909. (theApp.m_vfpCurrent.vfp_avVerticesOnBaseOfPrimitive[ m_iDragEdge]+
  1910. theApp.m_vfpCurrent.vfp_avVerticesOnBaseOfPrimitive[ iEdgeEnd])/2.0f;
  1911. }
  1912. }
  1913. void CWorldEditorView::MarkClosestVtxOnPrimitive( BOOL bToggleSelection)
  1914. {
  1915. // get draw port
  1916. CDrawPort *pdpValidDrawPort = GetDrawPort();
  1917. // if it is not valid
  1918. if( pdpValidDrawPort == NULL) return;
  1919. CWorldEditorDoc* pDoc = GetDocument();
  1920. // create a slave viewer
  1921. CSlaveViewer svViewer( GetChildFrame()->m_mvViewer, m_ptProjectionType,
  1922. pDoc->m_plGrid, pdpValidDrawPort);
  1923. // create a projection for current viewer
  1924. CAnyProjection3D prProjection;
  1925. svViewer.MakeProjection(prProjection);
  1926. // prepare the projection
  1927. prProjection->Prepare();
  1928. // prepare second layer's projection ...
  1929. // get viewer placement from first layer
  1930. CPlacement3D plVirtualViewer = prProjection->ViewerPlacementR();
  1931. // transform it to the system of the second layer
  1932. plVirtualViewer.AbsoluteToRelative(pDoc->m_plSecondLayer);
  1933. // use it in projection for second layer
  1934. CAnyProjection3D prProjectionSecondLayer;
  1935. prProjectionSecondLayer = prProjection;
  1936. prProjectionSecondLayer->ViewerPlacementL() = plVirtualViewer;
  1937. prProjectionSecondLayer->Prepare();
  1938. theApp.m_vfpCurrent.vfp_o3dPrimitive.ob_aoscSectors.Lock();
  1939. CDynamicArray<CObjectVertex> &aVtx = theApp.m_vfpCurrent.vfp_o3dPrimitive.ob_aoscSectors[0].osc_aovxVertices;
  1940. theApp.m_vfpCurrent.vfp_o3dPrimitive.ob_aoscSectors.Unlock();
  1941. aVtx.Lock();
  1942. // set distance of closest vertice to a hudge distance
  1943. FLOAT fMinVertexDistance = 999999.9f;
  1944. FLOAT fMinVertexDistanceZ = 999999.9f;
  1945. INDEX iClosest = -1;
  1946. BOOL bHasSelection = FALSE;
  1947. // now we will project base vertices onto screen and try
  1948. // to find closest vertice to mouse for moving vertices on the base
  1949. for( INDEX iVtx=0; iVtx<aVtx.Count(); iVtx++)
  1950. {
  1951. if( (aVtx[ iVtx].ovx_ulFlags & OVXF_SELECTED) && !bHasSelection)
  1952. {
  1953. bHasSelection = TRUE;
  1954. m_vStartDragO3DVertice = aVtx[ iVtx];
  1955. }
  1956. aVtx[ iVtx].ovx_ulFlags &= ~OVXF_CLOSEST;
  1957. FLOAT3D vProjected;
  1958. // project current base vertice
  1959. prProjectionSecondLayer->ProjectCoordinate( DOUBLEtoFLOAT(aVtx[ iVtx]), vProjected);
  1960. // convert y coordinate from mathemathical representation into screen one
  1961. vProjected(2) = pdpValidDrawPort->GetHeight() - vProjected(2);
  1962. // calculate distance to mouse point
  1963. FLOAT fDX = (FLOAT)m_ptMouse.x-vProjected(1);
  1964. FLOAT fDY = (FLOAT)m_ptMouse.y-vProjected(2);
  1965. FLOAT fDistance = (FLOAT)sqrt(fDX*fDX+fDY*fDY);
  1966. FLOAT fDistanceZ = -vProjected(3);
  1967. // if this distance is smaller than last remembered
  1968. if( (fDistance < fMinVertexDistance-0.5) ||
  1969. ((fDistance<fMinVertexDistance+0.5) && fDistanceZ<fMinVertexDistanceZ) )
  1970. {
  1971. // set this one as smallest
  1972. fMinVertexDistance = fDistance;
  1973. fMinVertexDistanceZ = fDistanceZ;
  1974. // remember its index
  1975. iClosest = iVtx;
  1976. }
  1977. }
  1978. aVtx[ iClosest].ovx_ulFlags |= OVXF_CLOSEST;
  1979. if( bToggleSelection)
  1980. {
  1981. aVtx[ iClosest].ovx_ulFlags ^= OVXF_SELECTED;
  1982. }
  1983. if( !bHasSelection)
  1984. {
  1985. m_vStartDragO3DVertice = aVtx[ iClosest];
  1986. }
  1987. aVtx.Unlock();
  1988. }
  1989. POINT CWorldEditorView::Get2DCoordinateFrom3D( FLOAT3D vPoint)
  1990. {
  1991. CDrawPort *pDP = m_pdpDrawPort;
  1992. CWorldEditorDoc* pDoc = GetDocument();
  1993. CAnyProjection3D prProjection;
  1994. // create a slave viewer
  1995. CSlaveViewer svViewer( GetChildFrame()->m_mvViewer, m_ptProjectionType, pDoc->m_plGrid, pDP);
  1996. svViewer.MakeProjection(prProjection);
  1997. prProjection->Prepare();
  1998. FLOAT3D vResult;
  1999. prProjection->ProjectCoordinate( vPoint, vResult);
  2000. POINT ptResult;
  2001. ptResult.x = (LONG) vResult(1);
  2002. ptResult.y = pDP->GetHeight()-(LONG) vResult(2);
  2003. return ptResult;
  2004. }
  2005. FLOAT3D CWorldEditorView::Get3DCoordinateFrom2D( POINT &pt)
  2006. {
  2007. CDrawPort *pDP = m_pdpDrawPort;
  2008. // convert coordinate
  2009. PIX pixX = pt.x;
  2010. PIX pixY = pt.y;
  2011. CWorldEditorDoc* pDoc = GetDocument();
  2012. CAnyProjection3D prProjection;
  2013. // create a slave viewer
  2014. CSlaveViewer svViewer( GetChildFrame()->m_mvViewer, m_ptProjectionType, pDoc->m_plGrid, pDP);
  2015. svViewer.MakeProjection(prProjection);
  2016. prProjection->Prepare();
  2017. // make the ray from viewer point through the mouse point, in current projection
  2018. CPlacement3D plRay;
  2019. prProjection->RayThroughPoint(FLOAT3D((float)pixX, pDP->GetHeight()-(float)pixY, 0.0f), plRay);
  2020. // snap to grid entity's placement
  2021. pDoc->SnapToGrid( plRay, m_fGridInMeters/GRID_DISCRETE_VALUES);
  2022. // get viewer's direction vector
  2023. FLOAT3D vDirection;
  2024. AnglesToDirectionVector( plRay.pl_OrientationAngle, vDirection);
  2025. FLOAT3D vResult;
  2026. vResult = plRay.pl_PositionVector + vDirection;
  2027. // snap result
  2028. SnapVector( vResult);
  2029. return vResult;
  2030. }
  2031. void CWorldEditorView::SnapVector(FLOAT3D &vToSnap)
  2032. {
  2033. CWorldEditorDoc* pDoc = GetDocument();
  2034. if( pDoc->m_bAutoSnap)
  2035. {
  2036. Snap(vToSnap(1), m_fGridInMeters/GRID_DISCRETE_VALUES);
  2037. Snap(vToSnap(2), m_fGridInMeters/GRID_DISCRETE_VALUES);
  2038. Snap(vToSnap(3), m_fGridInMeters/GRID_DISCRETE_VALUES);
  2039. }
  2040. else
  2041. {
  2042. Snap(vToSnap(1), SNAP_DOUBLE_CM);
  2043. Snap(vToSnap(2), SNAP_DOUBLE_CM);
  2044. Snap(vToSnap(3), SNAP_DOUBLE_CM);
  2045. }
  2046. }
  2047. void CWorldEditorView::SnapVector(DOUBLE3D &vToSnap)
  2048. {
  2049. CWorldEditorDoc* pDoc = GetDocument();
  2050. FLOAT3D vTemp = DOUBLEtoFLOAT(vToSnap);
  2051. if( pDoc->m_bAutoSnap)
  2052. {
  2053. Snap(vTemp(1), m_fGridInMeters/GRID_DISCRETE_VALUES);
  2054. Snap(vTemp(2), m_fGridInMeters/GRID_DISCRETE_VALUES);
  2055. Snap(vTemp(3), m_fGridInMeters/GRID_DISCRETE_VALUES);
  2056. }
  2057. else
  2058. {
  2059. Snap(vTemp(1), SNAP_DOUBLE_CM);
  2060. Snap(vTemp(2), SNAP_DOUBLE_CM);
  2061. Snap(vTemp(3), SNAP_DOUBLE_CM);
  2062. }
  2063. vToSnap = FLOATtoDOUBLE(vTemp);
  2064. }
  2065. FLOAT GetDistance( POINT &pt1, POINT &pt2)
  2066. {
  2067. FLOAT2D vpt1, vpt2;
  2068. vpt1(1) = pt1.x;
  2069. vpt1(2) = pt1.y;
  2070. vpt2(1) = pt2.x;
  2071. vpt2(2) = pt2.y;
  2072. FLOAT2D vDistance = vpt1-vpt2;
  2073. return vDistance.Length();
  2074. }
  2075. void CWorldEditorView::RenderAndApplyTerrainEditBrush(FLOAT3D vHit)
  2076. {
  2077. CWorldEditorDoc* pDoc = GetDocument();
  2078. CTerrain *ptrTerrain=GetTerrain();
  2079. if( ptrTerrain!=NULL)
  2080. {
  2081. CTString strBrushFile;
  2082. INDEX iBrush=INDEX(theApp.m_fCurrentTerrainBrush);
  2083. strBrushFile.PrintF("Textures\\Editor\\TerrainBrush%02d.tex", iBrush);
  2084. try
  2085. {
  2086. CTextureData *ptdBrush=_pTextureStock->Obtain_t(strBrushFile);
  2087. ptdBrush->Force(TEX_STATIC);
  2088. FLOAT fStrengthRatio=theApp.m_fTerrainBrushPressure/1024.0f;
  2089. FLOAT fUncompensatedStrength=(pow(1.0f+theApp.m_fTerrainBrushPressure/1024.0f*16.0f,2)-1.0f)/64.0f;
  2090. COLOR colSelection=C_WHITE|CT_OPAQUE;
  2091. ETerrainEdit teTool=TE_NONE;
  2092. SelectionFill sf;
  2093. // heightmap mode
  2094. if( theApp.m_iTerrainEditMode==TEM_HEIGHTMAP)
  2095. {
  2096. colSelection=C_ORANGE|CT_OPAQUE;
  2097. switch(INDEX(theApp.m_iTerrainBrushMode))
  2098. {
  2099. case TBM_PAINT : teTool=TE_BRUSH_ALTITUDE_PAINT ; break;
  2100. case TBM_SMOOTH : teTool=TE_BRUSH_ALTITUDE_SMOOTH ; break;
  2101. case TBM_FILTER : teTool=TE_BRUSH_ALTITUDE_FILTER ; break;
  2102. case TBM_MINIMUM : teTool=TE_BRUSH_ALTITUDE_MINIMUM ; break;
  2103. case TBM_MAXIMUM : teTool=TE_BRUSH_ALTITUDE_MAXIMUM ; break;
  2104. case TBM_FLATTEN : teTool=TE_BRUSH_ALTITUDE_FLATTEN ; break;
  2105. case TBM_POSTERIZE : teTool=TE_BRUSH_ALTITUDE_POSTERIZE; break;
  2106. case TBM_RND_NOISE : teTool=TE_BRUSH_ALTITUDE_RND_NOISE; break;
  2107. case TBM_CONTINOUS_NOISE: teTool=TE_BRUSH_ALTITUDE_CONTINOUS_NOISE; break;
  2108. case TBM_ERASE : teTool=TE_BRUSH_EDGE_ERASE ; break;
  2109. }
  2110. }
  2111. // texture layer mode
  2112. else
  2113. {
  2114. colSelection=C_GREEN|CT_OPAQUE;
  2115. teTool=TE_BRUSH_LAYER_PAINT;
  2116. CTerrainLayer *ptlLayer=GetLayer();
  2117. if(ptlLayer==NULL) return;
  2118. if( ptlLayer->tl_ltType==LT_TILE)
  2119. {
  2120. teTool=TE_TILE_PAINT;
  2121. }
  2122. else
  2123. {
  2124. switch(INDEX(theApp.m_iTerrainBrushMode))
  2125. {
  2126. case TBM_PAINT : teTool=TE_BRUSH_LAYER_PAINT ; break;
  2127. case TBM_SMOOTH : teTool=TE_BRUSH_LAYER_SMOOTH ; break;
  2128. case TBM_FILTER : teTool=TE_BRUSH_LAYER_FILTER ; break;
  2129. case TBM_RND_NOISE : teTool=TE_BRUSH_LAYER_RND_NOISE; break;
  2130. case TBM_CONTINOUS_NOISE: teTool=TE_BRUSH_LAYER_CONTINOUS_NOISE; break;
  2131. case TBM_ERASE : teTool=TE_BRUSH_EDGE_ERASE ; break;
  2132. }
  2133. }
  2134. }
  2135. // no cursor if selection is hidden
  2136. if(!GetChildFrame()->m_bSelectionVisible) colSelection&=0xFFFFFF00;
  2137. if( m_iaInputAction==IA_TERRAIN_EDITING_LMB || m_iaInputAction==IA_TERRAIN_EDITING_CTRL_LMB)
  2138. {
  2139. // if we pressed mouse down (terrain edit start)
  2140. if(m_iaInputAction!=m_iaLastInputAction)
  2141. {
  2142. TerrainEditBegin();
  2143. }
  2144. CTimerValue tvNow=_pTimer->GetHighPrecisionTimer();
  2145. // get difference to time when last mip brushing option has been used
  2146. FLOAT fSecondsPassed=(tvNow-_tvLastTerrainBrushingApplied).GetSeconds();
  2147. _tvLastTerrainBrushingApplied=_pTimer->GetHighPrecisionTimer();
  2148. // apply time passed factor, so terrain editing wouldn't depend upon frame rate
  2149. fSecondsPassed=Clamp(fSecondsPassed,0.0f,1.0f);
  2150. FLOAT fCompensatedStrength=fUncompensatedStrength*fSecondsPassed/(1.0f/50.0f);
  2151. if( m_iaInputAction==IA_TERRAIN_EDITING_CTRL_LMB) fCompensatedStrength=-fCompensatedStrength;
  2152. // apply terrain editing
  2153. EditTerrain(ptdBrush, vHit, fCompensatedStrength, teTool);
  2154. }
  2155. // if we stopped editing
  2156. else if( m_iaLastInputAction==IA_TERRAIN_EDITING_LMB || m_iaLastInputAction==IA_TERRAIN_EDITING_CTRL_LMB)
  2157. {
  2158. TerrainEditEnd();
  2159. }
  2160. m_iaLastInputAction=m_iaInputAction;
  2161. // render terrain editing cursor
  2162. Rect rect;
  2163. Point pt=Calculate2dHitPoint(ptrTerrain, vHit);
  2164. rect.rc_iLeft=pt.pt_iX-ptdBrush->GetPixWidth()/2;
  2165. rect.rc_iRight=pt.pt_iX+(ptdBrush->GetPixWidth()-ptdBrush->GetPixWidth()/2);
  2166. rect.rc_iTop=pt.pt_iY-ptdBrush->GetPixHeight()/2;
  2167. rect.rc_iBottom=pt.pt_iY+(ptdBrush->GetPixHeight()-ptdBrush->GetPixHeight()/2);
  2168. if(GetChildFrame()->m_bSelectionVisible)
  2169. {
  2170. sf=(SelectionFill) theApp.m_Preferences.ap_iTerrainSelectionVisible;
  2171. }
  2172. else
  2173. {
  2174. sf=(SelectionFill) theApp.m_Preferences.ap_iTerrainSelectionHidden;
  2175. }
  2176. if(sf!=3)
  2177. {
  2178. ShowSelection(ptrTerrain, rect, ptdBrush, colSelection, 0.25f+fStrengthRatio*0.75f, sf);
  2179. }
  2180. }
  2181. catch( char *strError)
  2182. {
  2183. (void) strError;
  2184. }
  2185. }
  2186. }
  2187. void CWorldEditorView::OnLButtonDown(UINT nFlags, CPoint point)
  2188. {
  2189. m_iaInputAction = IA_NONE;
  2190. CDrawPort *pdpValidDrawPort = GetDrawPort();
  2191. if( pdpValidDrawPort == NULL) return;
  2192. m_pbpoTranslationPlane = NULL;
  2193. CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
  2194. CWorldEditorDoc* pDoc = GetDocument();
  2195. ASSERT_VALID(pDoc);
  2196. // key statuses
  2197. BOOL bAlt = (GetKeyState( VK_MENU)&0x8000) != 0;
  2198. BOOL bSpace = (GetKeyState( ' ') & 128) != 0;
  2199. BOOL bCtrl = nFlags & MK_CONTROL;
  2200. BOOL bShift = nFlags & MK_SHIFT;
  2201. BOOL bRMB = nFlags & MK_RBUTTON;
  2202. BOOL bCSGOn = pDoc->m_pwoSecondLayer != NULL;
  2203. BOOL bHitModels = (pDoc->GetEditingMode() == ENTITY_MODE) || bSpace;
  2204. BOOL bHitFields = (pDoc->GetEditingMode() == ENTITY_MODE) || bSpace;
  2205. BOOL bHitBrushes = (pDoc->GetEditingMode() != TERRAIN_MODE) || bSpace;
  2206. // obtain information about where mouse points into the world
  2207. CCastRay crRayHit = GetMouseHitInformation( point, FALSE, bHitModels, bHitFields, NULL, bHitBrushes);
  2208. m_vHitOnMouseDown = crRayHit.cr_vHit;
  2209. theApp.m_vLastTerrainHit=crRayHit.cr_vHit;
  2210. m_ptMouseDown = point;
  2211. m_VFPMouseDown = theApp.m_vfpCurrent;
  2212. CSlaveViewer svViewer( GetChildFrame()->m_mvViewer, m_ptProjectionType,
  2213. pDoc->m_plGrid, pdpValidDrawPort);
  2214. CAnyProjection3D prProjection;
  2215. svViewer.MakeProjection(prProjection);
  2216. prProjection->Prepare();
  2217. // space+ctrl+lmb zoomes in 2x
  2218. if( bSpace && bCtrl)
  2219. {
  2220. if( bRMB) return;
  2221. // set new target
  2222. GetChildFrame()->m_mvViewer.SetTargetPlacement( crRayHit.cr_vHit);
  2223. // move mouse to center of screen
  2224. CPoint ptCenter = CPoint( m_pdpDrawPort->GetWidth()/2, m_pdpDrawPort->GetHeight()/2);
  2225. ClientToScreen( &ptCenter);
  2226. SetCursorPos(ptCenter.x, ptCenter.y);
  2227. OnZoomMore();
  2228. pDoc->UpdateAllViews( NULL);
  2229. m_ptMouseDown = ptCenter;
  2230. return;
  2231. }
  2232. // space+lmb is used for viewer and CSG layer movement in floor plane,+rmb rotates
  2233. else if( bSpace)
  2234. {
  2235. if( bRMB) m_iaInputAction = IA_ROTATING_VIEWER;
  2236. else m_iaInputAction = IA_MOVING_VIEWER_IN_FLOOR_PLANE;
  2237. StartMouseInput( point);
  2238. }
  2239. // in measure mode, only viewer moving is enabled
  2240. else if( theApp.m_bMeasureModeOn)
  2241. {
  2242. m_iaInputAction = IA_MEASURING;
  2243. }
  2244. // in cut mode, only viewer moving is enabled
  2245. else if( theApp.m_bCutModeOn)
  2246. {
  2247. // project 3D control points
  2248. POINT ptStart = Get2DCoordinateFrom3D( pDoc->m_vCutLineStart);
  2249. POINT ptEnd = Get2DCoordinateFrom3D( pDoc->m_vCutLineEnd);
  2250. // calculate distances
  2251. FLOAT fDStart = GetDistance( ptStart, point);
  2252. FLOAT fDEnd = GetDistance( ptEnd, point);
  2253. FLOAT fAllowedDistance = 32.0f;
  2254. // if we clicked near coontrol point
  2255. if( fDStart < fAllowedDistance)
  2256. {
  2257. m_iaInputAction = IA_MOVING_CUT_LINE_START;
  2258. pDoc->m_vControlLineDragStart = pDoc->m_vCutLineStart;
  2259. }
  2260. else if( fDEnd < fAllowedDistance)
  2261. {
  2262. m_iaInputAction = IA_MOVING_CUT_LINE_END;
  2263. pDoc->m_vControlLineDragStart = pDoc->m_vCutLineEnd;
  2264. }
  2265. else
  2266. {
  2267. m_iaInputAction = IA_CUT_MODE;
  2268. pDoc->m_pCutLineView = this;
  2269. pDoc->m_vCutLineStart = Get3DCoordinateFrom2D( point);
  2270. pDoc->m_vCutLineEnd = pDoc->m_vCutLineStart;
  2271. }
  2272. pDoc->UpdateAllViews( this);
  2273. }
  2274. // test for mouse operations used while primitive CSG is on
  2275. else if( bCSGOn)
  2276. {
  2277. if( bCtrl && bAlt)
  2278. {
  2279. SetAsCsgTarget(crRayHit.cr_penHit);
  2280. }
  2281. if( bCtrl && !bShift)
  2282. {
  2283. if( bRMB) m_iaInputAction = IA_ROTATING_SECOND_LAYER;
  2284. else m_iaInputAction = IA_MOVING_SECOND_LAYER_IN_FLOOR_PLANE;
  2285. }
  2286. else if( pDoc->m_bPrimitiveMode)
  2287. {
  2288. // in triangularisation primitive mode
  2289. if( theApp.m_vfpCurrent.vfp_ttTriangularisationType != TT_NONE)
  2290. {
  2291. // select vertices on primitive
  2292. MarkClosestVtxOnPrimitive( bShift);
  2293. // and start dragging them
  2294. if( !bShift) m_iaInputAction = IA_DRAG_VERTEX_ON_PRIMITIVE;
  2295. }
  2296. // shift+lmb inserts vertex on primitive base
  2297. else if( !bCtrl && bShift)
  2298. {
  2299. // find and remember vertex on primitive base for draging
  2300. MarkClosestVtxAndEdgeOnPrimitiveBase( point);
  2301. if(m_iDragEdge != -1)
  2302. {
  2303. pDoc->InsertPrimitiveVertex( m_iDragEdge, m_vMouseDownSecondLayer);
  2304. }
  2305. }
  2306. // lmb is used for dragging vertices on base of primitive
  2307. else
  2308. {
  2309. // ctrl+shift+lmb stretches primitive
  2310. if( bCtrl && bShift) m_iaInputAction = IA_STRETCHING_PRIMITIVE;
  2311. else m_iaInputAction = IA_DRAG_VERTEX_ON_PRIMITIVE_BASE;
  2312. // ------ Find closest vertice on base of primitive and remember its position
  2313. // prepare second layer's projection ...
  2314. // get viewer placement from first layer
  2315. CPlacement3D plVirtualViewer = prProjection->ViewerPlacementR();
  2316. // transform it to the system of the second layer
  2317. plVirtualViewer.AbsoluteToRelative(pDoc->m_plSecondLayer);
  2318. // use it in projection for second layer
  2319. CAnyProjection3D prProjectionSecondLayer;
  2320. prProjectionSecondLayer = prProjection;
  2321. prProjectionSecondLayer->ViewerPlacementL() = plVirtualViewer;
  2322. prProjectionSecondLayer->Prepare();
  2323. // find and remember vertex on primitive base for draging
  2324. MarkClosestVtxAndEdgeOnPrimitiveBase( point);
  2325. m_iSizeControlVertice = -1;
  2326. FLOAT fMinDistance = 9999999.9f;
  2327. // prepare array with vertices used as control points for sizing box arround primitive
  2328. FLOAT3D avtxSizeControlVertices[ 14];
  2329. // table of min x, max x, miny, ...
  2330. FLOAT afCoordinates[ 6];
  2331. afCoordinates[0] = theApp.m_vfpCurrent.vfp_fXMin;
  2332. afCoordinates[1] = theApp.m_vfpCurrent.vfp_fXMax;
  2333. afCoordinates[2] = theApp.m_vfpCurrent.vfp_fYMin;
  2334. afCoordinates[3] = theApp.m_vfpCurrent.vfp_fYMax;
  2335. afCoordinates[4] = theApp.m_vfpCurrent.vfp_fZMin;
  2336. afCoordinates[5] = theApp.m_vfpCurrent.vfp_fZMax;
  2337. // create control points using table with indices into afCoordinates table
  2338. for( INDEX iVtx=0;iVtx<14;iVtx++)
  2339. {
  2340. avtxSizeControlVertices[iVtx](1) =
  2341. (afCoordinates[aiForCreationOfSizingVertices[iVtx][0]]+
  2342. afCoordinates[aiForCreationOfSizingVertices[iVtx][1]])/2;
  2343. avtxSizeControlVertices[iVtx](2) =
  2344. (afCoordinates[aiForCreationOfSizingVertices[iVtx][2]]+
  2345. afCoordinates[aiForCreationOfSizingVertices[iVtx][3]])/2;
  2346. avtxSizeControlVertices[iVtx](3) =
  2347. (afCoordinates[aiForCreationOfSizingVertices[iVtx][4]]+
  2348. afCoordinates[aiForCreationOfSizingVertices[iVtx][5]])/2;
  2349. }
  2350. // now we will project size control vertices and try to find closest one to mouse
  2351. for( INDEX iControlVtx=0; iControlVtx<14; iControlVtx++)
  2352. {
  2353. FLOAT3D vProjectedCoordinate;
  2354. // project current control vertex
  2355. prProjectionSecondLayer->ProjectCoordinate(
  2356. avtxSizeControlVertices[iControlVtx], vProjectedCoordinate);
  2357. // convert y coordinate from mathemathical representation into screen one
  2358. vProjectedCoordinate(2) = pdpValidDrawPort->GetHeight() - vProjectedCoordinate(2);
  2359. FLOAT fDX = vProjectedCoordinate(1)-point.x;
  2360. FLOAT fDY = vProjectedCoordinate(2)-point.y;
  2361. // calculate distance to mouse point
  2362. FLOAT fDistance = fDX*fDX+fDY*fDY;
  2363. // if this distance is smaller than last remembered
  2364. if( fDistance < fMinDistance)
  2365. {
  2366. // set this one as smallest
  2367. fMinDistance = fDistance;
  2368. // and remember its indice as souch
  2369. m_iSizeControlVertice = iControlVtx;
  2370. }
  2371. }
  2372. }
  2373. }
  2374. // reset relative placement (m_plMouseOffset)
  2375. StartMouseInput( point);
  2376. }
  2377. // if only Alt key is pressed, we are not in vertex nor entity mode, we want to save thumbnail
  2378. else if( bAlt && !bCtrl && !bShift && !bSpace &&
  2379. (pDoc->GetEditingMode() != VERTEX_MODE) &&
  2380. (pDoc->GetEditingMode() != ENTITY_MODE))
  2381. {
  2382. // if document is modified
  2383. if( pDoc->IsModified() )
  2384. {
  2385. // report error
  2386. AfxMessageBox(L"You must save your document before you can perform drag.");
  2387. }
  2388. else
  2389. {
  2390. CTFileName fnDocument = CTString(CStringA(pDoc->GetPathName()));
  2391. // save the thumbnail
  2392. pDoc->SaveThumbnail();
  2393. // try to
  2394. try
  2395. {
  2396. // remove application path
  2397. fnDocument.RemoveApplicationPath_t();
  2398. // create drag and drop object
  2399. HGLOBAL hglobal = CreateHDrop( fnDocument);
  2400. m_DataSource.CacheGlobalData( CF_HDROP, hglobal);
  2401. m_DataSource.DoDragDrop( DROPEFFECT_COPY);
  2402. }
  2403. // if failed
  2404. catch (char *strError)
  2405. {
  2406. // report error
  2407. AfxMessageBox(CString(strError));
  2408. }
  2409. }
  2410. }
  2411. // else if we are in entity mode
  2412. else if( pDoc->GetEditingMode() == ENTITY_MODE)
  2413. {
  2414. // if ctrl pressed, we want to move or rotate entity selection
  2415. if( bCtrl && !bShift && !bAlt)
  2416. {
  2417. if( bRMB) m_iaInputAction = IA_ROTATING_ENTITY_SELECTION;
  2418. else m_iaInputAction = IA_MOVING_ENTITY_SELECTION_IN_FLOOR_PLANE;
  2419. StartMouseInput( point);
  2420. }
  2421. // if we are in browsing entities mode (or select by volume)
  2422. else if( (pDoc->m_bBrowseEntitiesMode) &&
  2423. (m_ptProjectionType != CSlaveViewer::PT_PERSPECTIVE) )
  2424. {
  2425. m_iaInputAction = IA_SIZING_SELECT_BY_VOLUME_BOX;
  2426. // ------ Find closest vertice of volume box
  2427. // create a slave viewer
  2428. CSlaveViewer svViewer( GetChildFrame()->m_mvViewer, m_ptProjectionType,
  2429. pDoc->m_plGrid, pdpValidDrawPort);
  2430. // create a projection for current viewer
  2431. CAnyProjection3D prProjection;
  2432. svViewer.MakeProjection(prProjection);
  2433. // prepare the projection
  2434. prProjection->Prepare();
  2435. // set distance of closest vertice to a hudge distance
  2436. FLOAT fMinVertexDistance = 999999.9f;
  2437. pDoc->m_iVolumeBoxDragVertice = 0;
  2438. // now we will project volume box's vertices onto screen and find closest one to mouse
  2439. for( INDEX iVtx=0; iVtx<8; iVtx++)
  2440. {
  2441. FLOAT3D vProjectedCoordinate;
  2442. // project current base vertice
  2443. prProjection->ProjectCoordinate( pDoc->m_avVolumeBoxVertice[iVtx], vProjectedCoordinate);
  2444. // convert y coordinate from mathemathical representation into screen one
  2445. vProjectedCoordinate(2) = pdpValidDrawPort->GetHeight() - vProjectedCoordinate(2);
  2446. // reset on screen "z" coordinate
  2447. vProjectedCoordinate(3) = 0.0f;
  2448. // calculate distance to mouse point
  2449. FLOAT fDistance =
  2450. ( FLOAT3D((FLOAT)point.x, (FLOAT)point.y, 0.0f) - vProjectedCoordinate ).Length();
  2451. // if this distance is smaller than last remembered
  2452. if( fDistance < fMinVertexDistance)
  2453. {
  2454. // set this one as smallest
  2455. fMinVertexDistance = fDistance;
  2456. // and remember its indice as souch
  2457. pDoc->m_iVolumeBoxDragVertice = iVtx;
  2458. }
  2459. }
  2460. // when we found closest vertice, remember its current position
  2461. pDoc->m_vVolumeBoxStartDragVertice = pDoc->m_avVolumeBoxVertice[ pDoc->m_iVolumeBoxDragVertice];
  2462. // reset relative placement (m_plMouseOffset)
  2463. StartMouseInput( point);
  2464. }
  2465. // ctrl+shift+lmb is used to edit range and angle3d properties
  2466. else if( bCtrl && bShift)
  2467. {
  2468. if( pDoc->m_selEntitySelection.Count() != 0)
  2469. {
  2470. // get selected property
  2471. CPropertyID *ppid = pMainFrame->m_PropertyComboBar.GetSelectedProperty();
  2472. // if property is of range or angle3d type
  2473. if( (ppid != NULL) && (ppid->pid_eptType == CEntityProperty::EPT_RANGE) )
  2474. {
  2475. m_iaInputAction = IA_CHANGING_RANGE_PROPERTY;
  2476. }
  2477. if( (ppid != NULL) && (ppid->pid_eptType == CEntityProperty::EPT_ANGLE3D) )
  2478. {
  2479. m_iaInputAction = IA_CHANGING_ANGLE3D_PROPERTY;
  2480. }
  2481. }
  2482. }
  2483. // Alt+Ctrl+LMB requests that clicked entity becomes target to selected entity
  2484. else if( bAlt && bCtrl && (crRayHit.cr_penHit != NULL))
  2485. {
  2486. if( pDoc->m_selEntitySelection.Count() == 0)
  2487. {
  2488. SetAsCsgTarget(crRayHit.cr_penHit);
  2489. }
  2490. else
  2491. {
  2492. // get selected property
  2493. CPropertyID *ppid = pMainFrame->m_PropertyComboBar.GetSelectedProperty();
  2494. if( (ppid == NULL) ||
  2495. !((ppid->pid_eptType == CEntityProperty::EPT_ENTITYPTR) ||
  2496. (ppid->pid_eptType == CEntityProperty::EPT_PARENT)) ) return;
  2497. BOOL bParentProperty = ppid->pid_eptType == CEntityProperty::EPT_PARENT;
  2498. // for each of the selected entities
  2499. FOREACHINDYNAMICCONTAINER(pDoc->m_selEntitySelection, CEntity, iten)
  2500. {
  2501. if( bParentProperty)
  2502. {
  2503. iten->SetParent( crRayHit.cr_penHit);
  2504. }
  2505. else if (crRayHit.cr_penHit->IsTargetable())
  2506. {
  2507. // obtain entity class ptr
  2508. CDLLEntityClass *pdecDLLClass = iten->GetClass()->ec_pdecDLLClass;
  2509. // for all classes in hierarchy of this entity
  2510. for(;
  2511. pdecDLLClass!=NULL;
  2512. pdecDLLClass = pdecDLLClass->dec_pdecBase) {
  2513. // for all properties
  2514. for(INDEX iProperty=0; iProperty<pdecDLLClass->dec_ctProperties; iProperty++) {
  2515. CEntityProperty &epProperty = pdecDLLClass->dec_aepProperties[iProperty];
  2516. if( (ppid->pid_strName == epProperty.ep_strName) &&
  2517. (ppid->pid_eptType == epProperty.ep_eptType) )
  2518. {
  2519. // discard old entity settings
  2520. iten->End();
  2521. // set clicked entity as one that selected entity points to
  2522. ENTITYPROPERTY( &*iten, epProperty.ep_slOffset, CEntityPointer) = crRayHit.cr_penHit;
  2523. // apply new entity settings
  2524. iten->Initialize();
  2525. }
  2526. }
  2527. }
  2528. }
  2529. }
  2530. // update edit range control (by updating parent dialog)
  2531. pMainFrame->m_PropertyComboBar.UpdateData( FALSE);
  2532. // mark that selections have been changed
  2533. pDoc->m_chSelections.MarkChanged();
  2534. }
  2535. }
  2536. // we want to select entities
  2537. else
  2538. {
  2539. m_iaInputAction = IA_SELECTING_ENTITIES;
  2540. m_bOnSelectEntityShiftDown = bShift;
  2541. m_bOnSelectEntityAltDown = bAlt;
  2542. }
  2543. }
  2544. // else if we are in sector mode
  2545. else if( pDoc->GetEditingMode() == SECTOR_MODE)
  2546. {
  2547. m_iaInputAction = IA_SELECTING_SECTORS;
  2548. ToggleHittedSector( crRayHit);
  2549. }
  2550. // if we are in polygon mode
  2551. else if( pDoc->GetEditingMode() == POLYGON_MODE)
  2552. {
  2553. // Alt+Ctrl+LMB requests that clicked polygon sizes its texture
  2554. if( bAlt && bCtrl && !bShift)
  2555. {
  2556. MultiplyMappingOnPolygon( 0.5f);
  2557. }
  2558. else if( bAlt && bCtrl && bShift)
  2559. {
  2560. OnRemainSelectedByOrientation(FALSE);
  2561. }
  2562. if( bAlt && bShift)
  2563. {
  2564. OnRemainSelectedByOrientation(TRUE);
  2565. }
  2566. // if we hit polygon
  2567. else if( (crRayHit.cr_penHit != NULL) &&
  2568. (crRayHit.cr_pbpoBrushPolygon != NULL) )
  2569. {
  2570. // if we want to change polygon mapping
  2571. if( bCtrl && !bShift)
  2572. {
  2573. if( bRMB) m_iaInputAction = IA_ROTATING_POLYGON_MAPPING;
  2574. else m_iaInputAction = IA_MOVING_POLYGON_MAPPING;
  2575. StartMouseInput( point);
  2576. // remember hitted point
  2577. m_f3dRotationOrigin = crRayHit.cr_vHit;
  2578. m_plMouseMove.pl_PositionVector = crRayHit.cr_vHit;
  2579. m_plMouseMove.pl_OrientationAngle = ANGLE3D( 0, 0, 0);
  2580. m_pbpoTranslationPlane = crRayHit.cr_pbpoBrushPolygon;
  2581. m_plTranslationPlane = crRayHit.cr_pbpoBrushPolygon->bpo_pbplPlane->bpl_plAbsolute;
  2582. }
  2583. // select or deselect hitted polygon
  2584. else if( !bCtrl)
  2585. {
  2586. m_iaInputAction = IA_SELECTING_POLYGONS;
  2587. ToggleHittedPolygon( crRayHit);
  2588. }
  2589. }
  2590. }
  2591. // if we are in vertex mode
  2592. else if( pDoc->GetEditingMode() == VERTEX_MODE)
  2593. {
  2594. // Ctrl+Alt is used to add vertex
  2595. if( bCtrl && bAlt)
  2596. {
  2597. CBrushPolygon *pbpo = crRayHit.cr_pbpoBrushPolygon;
  2598. if( (crRayHit.cr_penHit != NULL) && (pbpo != NULL) )
  2599. {
  2600. pDoc->m_selPolygonSelection.Clear();
  2601. pDoc->m_selVertexSelection.Clear();
  2602. pbpo->bpo_pbscSector->TriangularizePolygon( pbpo);
  2603. pDoc->m_chSelections.MarkChanged();
  2604. // cast ray again to hit newly created triangle
  2605. CCastRay crRayHit = GetMouseHitInformation( point, FALSE, bHitModels, bHitFields);
  2606. CBrushPolygon *pbpo = crRayHit.cr_pbpoBrushPolygon;
  2607. if( (crRayHit.cr_penHit != NULL) && (pbpo != NULL) )
  2608. {
  2609. pDoc->m_selPolygonSelection.Select( *pbpo);
  2610. pbpo->bpo_pbscSector->InsertVertexIntoTriangle( pDoc->m_selPolygonSelection, crRayHit.cr_vHit);
  2611. }
  2612. }
  2613. }
  2614. // Ctrl is used for rotating or moving vertices
  2615. else if( bCtrl)
  2616. {
  2617. if( bShift)
  2618. {
  2619. m_iaInputAction = IA_STRETCH_BRUSH_VERTEX;
  2620. }
  2621. else if( bRMB)
  2622. {
  2623. m_iaInputAction = IA_ROTATE_BRUSH_VERTEX;
  2624. }
  2625. else
  2626. {
  2627. m_iaInputAction = IA_DRAG_BRUSH_VERTEX_IN_FLOOR_PLANE;
  2628. }
  2629. // clear polygon selection because some of the old polygons could disappear
  2630. pDoc->m_selPolygonSelection.Clear();
  2631. pDoc->m_woWorld.TriangularizeForVertices( pDoc->m_selVertexSelection);
  2632. StartMouseInput( point);
  2633. }
  2634. else
  2635. {
  2636. m_avpixLaso.Clear();
  2637. m_iaInputAction = IA_SELECT_SINGLE_BRUSH_VERTEX;
  2638. _vpixSelectNearPoint(1) = point.x;
  2639. _vpixSelectNearPoint(2) = point.y;
  2640. m_bOnSelectVertexShiftDown = bShift;
  2641. m_bOnSelectVertexAltDown = bAlt;
  2642. }
  2643. }
  2644. else if( pDoc->GetEditingMode() == TERRAIN_MODE)
  2645. {
  2646. if(crRayHit.cr_penHit!=NULL && crRayHit.cr_penHit==GetTerrainEntity())
  2647. {
  2648. _bCursorMoved=FALSE;
  2649. if( bAlt && bCtrl)
  2650. {
  2651. OnPickLayer();
  2652. }
  2653. else if( !bAlt && bCtrl)
  2654. {
  2655. m_iaInputAction = IA_TERRAIN_EDITING_CTRL_LMB;
  2656. _tvLastTerrainBrushingApplied=_pTimer->GetHighPrecisionTimer();
  2657. }
  2658. else if( !bAlt)
  2659. {
  2660. m_iaInputAction = IA_TERRAIN_EDITING_LMB;
  2661. _tvLastTerrainBrushingApplied=_pTimer->GetHighPrecisionTimer();
  2662. }
  2663. }
  2664. else
  2665. {
  2666. // if terrain entity hit
  2667. if(crRayHit.cr_penHit!=NULL && crRayHit.cr_penHit->GetRenderType()==CEntity::RT_TERRAIN)
  2668. {
  2669. pDoc->m_ptrSelectedTerrain=crRayHit.cr_penHit->GetTerrain();
  2670. theApp.m_ctTerrainPage.MarkChanged();
  2671. }
  2672. }
  2673. }
  2674. CView::OnLButtonDown(nFlags, point);
  2675. }
  2676. void SelectLayerCommand(INDEX iSelectedLayer)
  2677. {
  2678. SelectLayer(iSelectedLayer);
  2679. theApp.m_ctTerrainPageCanvas.MarkChanged();
  2680. CWorldEditorDoc* pDoc = theApp.GetActiveDocument();
  2681. if(pDoc!=NULL)
  2682. {
  2683. pDoc->m_chSelections.MarkChanged();
  2684. }
  2685. }
  2686. void CWorldEditorView::InvokeSelectLayerCombo(void)
  2687. {
  2688. CPoint pt=m_ptMouse;
  2689. CCastRay crRayHit=GetMouseHitInformation( pt);
  2690. if( (crRayHit.cr_penHit==NULL) || (crRayHit.cr_penHit->GetRenderType()!=CEntity::RT_TERRAIN) ) return;
  2691. CCustomComboWnd *pCombo=new CCustomComboWnd;
  2692. CTerrain *ptrTerrain=crRayHit.cr_penHit->GetTerrain();
  2693. if(ptrTerrain==NULL) return;
  2694. INDEX ctLayers=ptrTerrain->tr_atlLayers.Count();
  2695. for(INDEX iLayer=ctLayers-1; iLayer>=0; iLayer--)
  2696. {
  2697. CTString strLayerName;
  2698. UBYTE ubPower=GetValueFromMask(ptrTerrain, iLayer, crRayHit.cr_vHit);
  2699. strLayerName.PrintF("Layer %d (%d%%)", iLayer+1, INDEX(ubPower/255.0f*100.0f));
  2700. if(ubPower>0)
  2701. {
  2702. INDEX iAddedAs=pCombo->InsertItem( strLayerName);
  2703. pCombo->SetItemValue( iAddedAs, iLayer);
  2704. }
  2705. if(ubPower==255) break;
  2706. }
  2707. GetCursorPos( &pt);
  2708. pCombo->Initialize(NULL, SelectLayerCommand, pt.x-8, pt.y-8, TRUE);
  2709. }
  2710. void CWorldEditorView::OnRButtonDown(UINT nFlags, CPoint point)
  2711. {
  2712. if( m_iaInputAction != IA_MIP_SETTING) m_iaInputAction = IA_NONE;
  2713. CWorldEditorDoc* pDoc = GetDocument();
  2714. ASSERT_VALID(pDoc);
  2715. CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
  2716. BOOL bShift = nFlags & MK_SHIFT;
  2717. BOOL bCtrl = nFlags & MK_CONTROL;
  2718. BOOL bLMB = nFlags & MK_LBUTTON;
  2719. BOOL bCSGOn = pDoc->m_pwoSecondLayer != NULL;
  2720. BOOL bAlt = (GetKeyState( VK_MENU)&0x8000) != 0;
  2721. BOOL bSpace = (GetKeyState( VK_SPACE)&0x8000) != 0;
  2722. BOOL bCaps = (GetKeyState( VK_CAPITAL)&0x0001) != 0;
  2723. BOOL bHitModels = (pDoc->GetEditingMode() == ENTITY_MODE) || bSpace;
  2724. BOOL bHitFields = (pDoc->GetEditingMode() == ENTITY_MODE) || bSpace;
  2725. StartMouseInput( point);
  2726. // remember point in the view
  2727. m_ptMouseDown = point;
  2728. // remember values for primitive
  2729. m_VFPMouseDown = theApp.m_vfpCurrent;
  2730. // if nothing of below is activated, call popup menu
  2731. if( !bShift && !bAlt && !bCtrl && !bSpace && !bLMB)
  2732. {
  2733. CallPopupMenu( point);
  2734. }
  2735. // space+ctrl+lmb zoomes out 2x
  2736. else if( bSpace && bCtrl)
  2737. {
  2738. if( bLMB) return;
  2739. OnZoomLess();
  2740. return;
  2741. }
  2742. else if( bSpace && bLMB)
  2743. {
  2744. m_iaInputAction = IA_ROTATING_VIEWER;
  2745. }
  2746. // we have viewer movement in view plane
  2747. else if( bSpace && !bShift)
  2748. {
  2749. if( bSpace) m_iaInputAction = IA_MOVING_VIEWER_IN_VIEW_PLANE;
  2750. StartMouseInput( point);
  2751. }
  2752. // second layer movements
  2753. else if( bCSGOn)
  2754. {
  2755. // if ctrl+rmb pressed, we want to move second layer in view plane
  2756. if( bCtrl && !bShift)
  2757. {
  2758. if( bLMB) m_iaInputAction = IA_ROTATING_SECOND_LAYER;
  2759. else m_iaInputAction = IA_MOVING_SECOND_LAYER_IN_VIEW_PLANE;
  2760. StartMouseInput( point);
  2761. }
  2762. // test for mouse operations used while primitive CSG is on
  2763. else if( pDoc->m_bPrimitiveMode)
  2764. {
  2765. // ctrl+shift+rmb sheares primitive
  2766. if( bCtrl && bShift)
  2767. {
  2768. if( m_ptProjectionType != CSlaveViewer::PT_PERSPECTIVE)
  2769. m_iaInputAction = IA_SHEARING_PRIMITIVE;
  2770. }
  2771. // shift+rmb in deletes vertex on base of primitive
  2772. else if( bShift && !bCtrl && !bLMB && !bSpace)
  2773. {
  2774. MarkClosestVtxAndEdgeOnPrimitiveBase( point);
  2775. if( m_iDragVertice != -1) pDoc->DeletePrimitiveVertex( m_iDragVertice);
  2776. }
  2777. }
  2778. }
  2779. else if( pDoc->GetEditingMode() == POLYGON_MODE)
  2780. {
  2781. // measure and cut modes disable all functions
  2782. if( theApp.m_bMeasureModeOn || theApp.m_bCutModeOn)
  2783. {
  2784. }
  2785. if( bAlt && bShift)
  2786. {
  2787. OnDeselectByOrientation();
  2788. }
  2789. // alt+ctrl+rmb sizes polygon's texture
  2790. else if( bAlt && bCtrl)
  2791. {
  2792. MultiplyMappingOnPolygon( 2.0f);
  2793. }
  2794. else if( bCtrl && bLMB)
  2795. {
  2796. m_iaInputAction = IA_ROTATING_POLYGON_MAPPING;
  2797. }
  2798. // shift turns on portal testing
  2799. else if( bShift && !bCtrl)
  2800. {
  2801. m_iaInputAction = IA_SELECTING_POLYGONS;
  2802. // cast ray but ask if test for portal hits
  2803. CCastRay crRayHit = GetMouseHitInformation( point, TRUE, FALSE);
  2804. ToggleHittedPolygon( crRayHit);
  2805. }
  2806. }
  2807. else if( pDoc->GetEditingMode() == SECTOR_MODE)
  2808. {
  2809. // shift turns on portal testing
  2810. if( bShift)
  2811. {
  2812. m_iaInputAction = IA_SELECTING_SECTORS;
  2813. // cast ray but ask if test for portal hits
  2814. CCastRay crRayHit = GetMouseHitInformation( point, TRUE, FALSE);
  2815. ToggleHittedSector( crRayHit);
  2816. }
  2817. }
  2818. else if(pDoc->GetEditingMode() == ENTITY_MODE)
  2819. {
  2820. CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
  2821. CEntity *penBrush = pMainFrame->m_CSGDesitnationCombo.GetSelectedBrushEntity();
  2822. // if we should start mip setting mode
  2823. if( bShift && bCtrl && !bAlt && (penBrush != NULL) )
  2824. {
  2825. if( m_iaInputAction == IA_MIP_SETTING) return;
  2826. // get entity's brush
  2827. CBrush3D *pbrBrush = penBrush->GetBrush();
  2828. if( pbrBrush != NULL)
  2829. {
  2830. CChildFrame *pChild = GetChildFrame();
  2831. // set auto mip brushing mode as it was before mip setting started
  2832. pChild->m_bLastAutoMipBrushingOn = pChild->m_bAutoMipBrushingOn;
  2833. // get curently active mip factor
  2834. FLOAT fCurrentMipFactor = GetCurrentlyActiveMipFactor();
  2835. // get the mip brush for current factor
  2836. m_pbmToSetMipSwitch = pbrBrush->GetBrushMipByDistance(fCurrentMipFactor);
  2837. // if we are in automatic mip brushing mode
  2838. if( (GetChildFrame()->m_bAutoMipBrushingOn) && (m_pbmToSetMipSwitch != NULL) )
  2839. {
  2840. // set manual mip factor so current mip brush would be visible
  2841. GetChildFrame()->m_fManualMipBrushingFactor = fCurrentMipFactor;
  2842. // set manual mip brushing mode
  2843. GetChildFrame()->m_bAutoMipBrushingOn = FALSE;
  2844. m_iaInputAction = IA_MIP_SETTING;
  2845. }
  2846. else
  2847. {
  2848. m_iaInputAction = IA_NONE;
  2849. }
  2850. }
  2851. else
  2852. {
  2853. m_iaInputAction = IA_NONE;
  2854. }
  2855. }
  2856. // Alt+Ctrl+RMB sets clicked entity as target on first available free target ptr slot
  2857. else if( bAlt && bCtrl && !bShift && (pDoc->m_selEntitySelection.Count() != 0))
  2858. {
  2859. // obtain information about where mouse points into the world
  2860. CCastRay crRayHit = GetMouseHitInformation( point, FALSE, bHitModels, bHitFields);
  2861. if(crRayHit.cr_penHit != NULL)
  2862. {
  2863. // get first empty selected property
  2864. pMainFrame->m_PropertyComboBar.SetFirstValidEmptyTargetProperty( crRayHit.cr_penHit);
  2865. }
  2866. }
  2867. // if ctrl+rmb pressed, we want to move entity selection in view plane
  2868. else if( bCtrl && !bShift && !bAlt)
  2869. {
  2870. if( bLMB) m_iaInputAction = IA_ROTATING_ENTITY_SELECTION;
  2871. else m_iaInputAction = IA_MOVING_ENTITY_SELECTION_IN_VIEW_PLANE;
  2872. StartMouseInput( point);
  2873. }
  2874. else if( bShift && bSpace && !GetChildFrame()->m_bAutoMipBrushingOn)
  2875. {
  2876. m_iaInputAction = IA_MANUAL_MIP_SWITCH_FACTOR_CHANGING;
  2877. }
  2878. else if( bShift && bAlt)
  2879. {
  2880. // obtain information about where mouse points into the world
  2881. CCastRay crRayHit = GetMouseHitInformation( point, FALSE, bHitModels, bHitFields);
  2882. ShowLinkTree(crRayHit.cr_penHit, TRUE, bCaps);
  2883. }
  2884. else if( bShift)
  2885. {
  2886. // obtain information about where mouse points into the world
  2887. CCastRay crRayHit = GetMouseHitInformation( point, FALSE, bHitModels, bHitFields);
  2888. ShowLinkTree(crRayHit.cr_penHit, FALSE, bCaps);
  2889. }
  2890. }
  2891. // if we are in vertex mode
  2892. else if( pDoc->GetEditingMode() == VERTEX_MODE)
  2893. {
  2894. if( bCtrl)
  2895. {
  2896. if( bLMB)
  2897. {
  2898. m_iaInputAction = IA_ROTATE_BRUSH_VERTEX;
  2899. }
  2900. else
  2901. {
  2902. m_iaInputAction = IA_DRAG_BRUSH_VERTEX_IN_VIEW_PLANE;
  2903. }
  2904. // clear polygon selection because some of the old polygons could disappear
  2905. pDoc->m_selPolygonSelection.Clear();
  2906. pDoc->m_woWorld.TriangularizeForVertices( pDoc->m_selVertexSelection);
  2907. StartMouseInput( point);
  2908. }
  2909. if( bShift)
  2910. {
  2911. if(pDoc->m_selVertexSelection.Count()==3)
  2912. {
  2913. pDoc->m_woWorld.CreatePolygon(pDoc->m_selVertexSelection);
  2914. pDoc->ClearSelections();
  2915. }
  2916. }
  2917. }
  2918. // if we are in terrain mode
  2919. else if( pDoc->GetEditingMode() == TERRAIN_MODE)
  2920. {
  2921. InvokeSelectLayerCombo();
  2922. }
  2923. CView::OnRButtonDown(nFlags, point);
  2924. }
  2925. void CWorldEditorView::OnLButtonUp(UINT nFlags, CPoint point)
  2926. {
  2927. CWorldEditorDoc* pDoc = GetDocument();
  2928. CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
  2929. BOOL bShift = nFlags & MK_SHIFT;
  2930. BOOL bSpace = (GetKeyState( VK_SPACE)&0x8000) != 0;
  2931. BOOL bCtrl = (GetKeyState( VK_CONTROL)&0x8000) != 0;
  2932. BOOL bCSGOn = pDoc->m_pwoSecondLayer != NULL;
  2933. StopMouseInput();
  2934. // if measure mode on
  2935. if( theApp.m_bMeasureModeOn)
  2936. {
  2937. Invalidate( FALSE);
  2938. }
  2939. // if we are in browse by volume mode and lmb released, refresh first selected volume
  2940. if( pDoc->m_bBrowseEntitiesMode && !bSpace && !bCtrl)
  2941. {
  2942. pDoc->SelectEntitiesByVolumeBox();
  2943. }
  2944. if( pDoc->GetEditingMode() == ENTITY_MODE)
  2945. {
  2946. if( m_iaInputAction == IA_SELECTING_ENTITIES)
  2947. {
  2948. // obtain information about where mouse points into the world
  2949. CCastRay crRayHit = GetMouseHitInformation( point, FALSE, TRUE, TRUE);
  2950. // if we hit some entity
  2951. if( crRayHit.cr_penHit != NULL)
  2952. {
  2953. // if shift is not pressed
  2954. if( !bShift)
  2955. {
  2956. BOOL bWasSelected = crRayHit.cr_penHit->IsSelected( ENF_SELECTED);
  2957. // deselect all selected entities
  2958. INDEX ctSelectedBefore = pDoc->m_selEntitySelection.Count();
  2959. pDoc->m_selEntitySelection.Clear();
  2960. // if entity was not selected before
  2961. if( !((ctSelectedBefore == 1) && bWasSelected))
  2962. {
  2963. // select it
  2964. pDoc->m_selEntitySelection.Select( *crRayHit.cr_penHit);
  2965. }
  2966. }
  2967. else
  2968. {
  2969. // if entity is not yet selected
  2970. if( !crRayHit.cr_penHit->IsSelected( ENF_SELECTED))
  2971. {
  2972. // select it
  2973. pDoc->m_selEntitySelection.Select( *crRayHit.cr_penHit);
  2974. }
  2975. // otherwise deselect it
  2976. else
  2977. {
  2978. pDoc->m_selEntitySelection.Deselect( *crRayHit.cr_penHit);
  2979. }
  2980. }
  2981. }
  2982. // mark that selections have been changed
  2983. pDoc->m_chSelections.MarkChanged();
  2984. // and refresh property combo manualy calling on idle
  2985. pMainFrame->m_PropertyComboBar.m_PropertyComboBox.OnIdle( 0);
  2986. // update all views
  2987. pDoc->UpdateAllViews( this);
  2988. }
  2989. else if( m_iaInputAction == IA_SELECT_LASSO_ENTITY)
  2990. {
  2991. m_bRequestEntityLassoSelect = TRUE;
  2992. pDoc->m_chSelections.MarkChanged();
  2993. Invalidate( FALSE);
  2994. }
  2995. }
  2996. if( pDoc->GetEditingMode() == VERTEX_MODE)
  2997. {
  2998. if( m_iaInputAction == IA_SELECT_SINGLE_BRUSH_VERTEX)
  2999. {
  3000. m_bRequestVtxClickSelect = TRUE;
  3001. pDoc->m_chSelections.MarkChanged();
  3002. Invalidate( FALSE);
  3003. }
  3004. else if( m_iaInputAction == IA_SELECT_LASSO_BRUSH_VERTEX)
  3005. {
  3006. m_bRequestVtxLassoSelect = TRUE;
  3007. pDoc->m_chSelections.MarkChanged();
  3008. Invalidate( FALSE);
  3009. }
  3010. else if(
  3011. (m_iaInputAction == IA_DRAG_BRUSH_VERTEX_IN_FLOOR_PLANE) ||
  3012. (m_iaInputAction == IA_DRAG_BRUSH_VERTEX_IN_VIEW_PLANE) ||
  3013. (m_iaInputAction == IA_STRETCH_BRUSH_VERTEX) ||
  3014. (m_iaInputAction == IA_ROTATE_BRUSH_VERTEX) )
  3015. {
  3016. pDoc->m_woWorld.UpdateSectorsAfterVertexChange( pDoc->m_selVertexSelection);
  3017. }
  3018. }
  3019. m_iaInputAction = IA_NONE;
  3020. CView::OnLButtonUp(nFlags, point);
  3021. }
  3022. void CWorldEditorView::OnRButtonUp(UINT nFlags, CPoint point)
  3023. {
  3024. CWorldEditorDoc* pDoc = GetDocument();
  3025. if( m_iaInputAction == IA_MIP_SETTING)
  3026. {
  3027. SetMipBrushFactor();
  3028. }
  3029. else if(
  3030. (m_iaInputAction == IA_DRAG_BRUSH_VERTEX_IN_FLOOR_PLANE) ||
  3031. (m_iaInputAction == IA_DRAG_BRUSH_VERTEX_IN_VIEW_PLANE) ||
  3032. (m_iaInputAction == IA_STRETCH_BRUSH_VERTEX) ||
  3033. (m_iaInputAction == IA_ROTATE_BRUSH_VERTEX) )
  3034. {
  3035. pDoc->m_woWorld.UpdateSectorsAfterVertexChange( pDoc->m_selVertexSelection);
  3036. }
  3037. m_iaInputAction = IA_NONE;
  3038. StopMouseInput();
  3039. CView::OnRButtonUp(nFlags, point);
  3040. }
  3041. // select all descendents of selected entity
  3042. void SelectDescendents( CEntitySelection &selEntity, CEntity &enParent)
  3043. {
  3044. FOREACHINLIST( CEntity, en_lnInParent, enParent.en_lhChildren, itenChild)
  3045. {
  3046. SelectDescendents( selEntity, *itenChild);
  3047. }
  3048. if( !enParent.IsSelected( ENF_SELECTED))
  3049. {
  3050. selEntity.Select( enParent);
  3051. }
  3052. }
  3053. void CWorldEditorView::OnLButtonDblClk(UINT nFlags, CPoint point)
  3054. {
  3055. m_iaInputAction = IA_NONE;
  3056. CWorldEditorDoc* pDoc = GetDocument();
  3057. BOOL bSpace = (GetKeyState( ' ') & 128) != 0;
  3058. BOOL bAlt = (GetKeyState( VK_MENU)&0x8000) != 0;
  3059. BOOL bCtrl = nFlags & MK_CONTROL;
  3060. BOOL bShift = nFlags & MK_SHIFT;
  3061. BOOL bRMB = (GetKeyState( VK_RBUTTON)&0x8000) != 0;
  3062. // space+ctrl+lmb zoomes in 2x
  3063. if( (bSpace) && (bCtrl))
  3064. {
  3065. if( bRMB) return;
  3066. // set new target
  3067. GetChildFrame()->m_mvViewer.SetTargetPlacement( m_vHitOnMouseDown);
  3068. // move mouse to center of screen
  3069. CPoint ptCenter = CPoint( m_pdpDrawPort->GetWidth()/2, m_pdpDrawPort->GetHeight()/2);
  3070. ClientToScreen( &ptCenter);
  3071. SetCursorPos(ptCenter.x, ptCenter.y);
  3072. OnZoomMore();
  3073. pDoc->UpdateAllViews( NULL);
  3074. return;
  3075. }
  3076. // obtain information about where mouse points into the world
  3077. CCastRay crRayHit = GetMouseHitInformation( point);
  3078. // space + doubble click center point that mouse points to
  3079. if( bSpace)
  3080. {
  3081. // set new target
  3082. GetChildFrame()->m_mvViewer.SetTargetPlacement( crRayHit.cr_vHit);
  3083. // update all views
  3084. pDoc->UpdateAllViews( NULL);
  3085. }
  3086. // if we are in measure or cut mode, no operation
  3087. else if( theApp.m_bMeasureModeOn || theApp.m_bCutModeOn)
  3088. {
  3089. }
  3090. // if we are in sector mode, no operation
  3091. else if( pDoc->GetEditingMode() == SECTOR_MODE)
  3092. {
  3093. }
  3094. // if we are in polygon mode, select similar polygons
  3095. else if( pDoc->GetEditingMode() == POLYGON_MODE)
  3096. {
  3097. // Alt+Ctrl+RMB requests that clicked polygon sizes its texture
  3098. if( bAlt && bCtrl)
  3099. {
  3100. MultiplyMappingOnPolygon( 0.5f);
  3101. }
  3102. // if we hit some brush entity
  3103. else if( (crRayHit.cr_penHit != NULL) &&
  3104. (crRayHit.cr_pbpoBrushPolygon != NULL))
  3105. {
  3106. // if shift is not pressed, delelect all polygons
  3107. if( !bShift && !bCtrl)
  3108. {
  3109. pDoc->m_selPolygonSelection.Clear();
  3110. }
  3111. // LMBx2 centers mapping on polygon
  3112. if( bCtrl && !bShift &&(crRayHit.cr_pbpoBrushPolygon != NULL) )
  3113. {
  3114. CBrushPolygon &bpo = *crRayHit.cr_pbpoBrushPolygon;
  3115. CEntity *pen = bpo.bpo_pbscSector->bsc_pbmBrushMip->bm_pbrBrush->br_penEntity;
  3116. CMappingDefinition mdOriginal = bpo.bpo_abptTextures[pDoc->m_iTexture].bpt_mdMapping;
  3117. CMappingDefinition mdTranslated = mdOriginal;
  3118. CSimpleProjection3D pr;
  3119. pr.ObjectPlacementL() = _plOrigin;
  3120. pr.ViewerPlacementL() = pen->GetPlacement();
  3121. pr.Prepare();
  3122. FLOAT3D vRelative;
  3123. pr.ProjectCoordinate(crRayHit.cr_vHit, vRelative);
  3124. CMappingDefinition mdRelative = theApp.m_mdMapping;
  3125. mdTranslated.Center(bpo.bpo_pbplPlane->bpl_pwplWorking->wpl_mvRelative, vRelative);
  3126. FLOAT fUOffset = mdTranslated.md_fUOffset-mdOriginal.md_fUOffset;
  3127. FLOAT fVOffset = mdTranslated.md_fVOffset-mdOriginal.md_fVOffset;
  3128. if( !crRayHit.cr_pbpoBrushPolygon->IsSelected(BPOF_SELECTED))
  3129. {
  3130. // add the offsets to its mapping
  3131. crRayHit.cr_pbpoBrushPolygon->bpo_abptTextures[pDoc->m_iTexture].bpt_mdMapping.md_fUOffset+=fUOffset;
  3132. crRayHit.cr_pbpoBrushPolygon->bpo_abptTextures[pDoc->m_iTexture].bpt_mdMapping.md_fVOffset+=fVOffset;
  3133. }
  3134. else
  3135. {
  3136. // for each selected polygon
  3137. FOREACHINDYNAMICCONTAINER(pDoc->m_selPolygonSelection, CBrushPolygon, itbpo)
  3138. {
  3139. // add the offsets to its mapping
  3140. itbpo->bpo_abptTextures[pDoc->m_iTexture].bpt_mdMapping.md_fUOffset+=fUOffset;
  3141. itbpo->bpo_abptTextures[pDoc->m_iTexture].bpt_mdMapping.md_fVOffset+=fVOffset;
  3142. }
  3143. }
  3144. pDoc->m_chSelections.MarkChanged();
  3145. pDoc->SetModifiedFlag( TRUE);
  3146. pDoc->UpdateAllViews( NULL);
  3147. }
  3148. // Ctrl+Shift+LMBx2 slects similar by texture in sector
  3149. else if( bCtrl && bShift)
  3150. {
  3151. OnSelectByTextureInSector();
  3152. }
  3153. else
  3154. {
  3155. // select similar to hitted polygon
  3156. crRayHit.cr_pbpoBrushPolygon->SelectSimilarByColor( pDoc->m_selPolygonSelection);
  3157. pDoc->m_chSelections.MarkChanged();
  3158. pDoc->UpdateAllViews( NULL);
  3159. }
  3160. }
  3161. }
  3162. else if( pDoc->GetEditingMode() == VERTEX_MODE)
  3163. {
  3164. // if we hit some polygon
  3165. if( (crRayHit.cr_penHit != NULL) && (crRayHit.cr_pbpoBrushPolygon != NULL))
  3166. {
  3167. CBrushPolygon &bpo=*crRayHit.cr_pbpoBrushPolygon;
  3168. // select vertices
  3169. FOREACHINSTATICARRAY(bpo.bpo_apbvxTriangleVertices, CBrushVertex *, itpbvx)
  3170. {
  3171. if( !(*itpbvx)->IsSelected(BVXF_SELECTED)) pDoc->m_selVertexSelection.Select( **itpbvx);
  3172. }
  3173. pDoc->m_chSelections.MarkChanged();
  3174. pDoc->UpdateAllViews( NULL);
  3175. }
  3176. }
  3177. // if we are in entity mode
  3178. else if( pDoc->GetEditingMode() == ENTITY_MODE)
  3179. {
  3180. // if nothing pressed
  3181. if( !bCtrl && !bAlt && !bSpace)
  3182. {
  3183. if( crRayHit.cr_penHit != NULL)
  3184. {
  3185. SelectDescendents( pDoc->m_selEntitySelection, *crRayHit.cr_penHit);
  3186. pDoc->m_chSelections.MarkChanged();
  3187. pDoc->UpdateAllViews( NULL);
  3188. }
  3189. }
  3190. // CTRL + LMB teleports entities
  3191. if( (pDoc->m_selEntitySelection.Count() != 0) && (bCtrl) && (!bAlt) )
  3192. {
  3193. // lock selection's dynamic container
  3194. pDoc->m_selEntitySelection.Lock();
  3195. FLOATaabbox3D box;
  3196. {FOREACHINDYNAMICCONTAINER(pDoc->m_selEntitySelection, CEntity, iten)
  3197. {
  3198. box |= iten->GetPlacement().pl_PositionVector;
  3199. }}
  3200. FLOAT3D f3dCenter = box.Center();
  3201. f3dCenter(2) = box.Min()(2);
  3202. FLOAT3D f3dOffset = crRayHit.cr_vHit - f3dCenter;
  3203. CEntity *penBrush = NULL;
  3204. // for each of the selected entities
  3205. FOREACHINDYNAMICCONTAINER(pDoc->m_selEntitySelection, CEntity, iten)
  3206. {
  3207. if (iten->en_RenderType == CEntity::RT_BRUSH) {
  3208. penBrush = &*iten;
  3209. }
  3210. // if movement of anchored entities is allowed or entity is not anchored
  3211. if( (((iten->GetFlags() & ENF_ANCHORED) == 0) ||
  3212. (GetChildFrame()->m_bAncoredMovingAllowed)) &&
  3213. ((iten->GetParent()==NULL) || !(iten->GetParent()->IsSelected( ENF_SELECTED))) )
  3214. {
  3215. // get placement of current entity
  3216. CPlacement3D plEntityPlacement = iten->GetPlacement();
  3217. plEntityPlacement.pl_PositionVector += f3dOffset;
  3218. // snap to grid entity's placement
  3219. pDoc->SnapToGrid( plEntityPlacement, m_fGridInMeters/GRID_DISCRETE_VALUES);
  3220. // set placement back to entity
  3221. iten->SetPlacement( plEntityPlacement);
  3222. // mark that document is changed
  3223. pDoc->SetModifiedFlag();
  3224. }
  3225. if( penBrush != NULL)
  3226. {
  3227. DiscardShadows( penBrush);
  3228. }
  3229. }
  3230. }
  3231. pDoc->UpdateAllViews( NULL);
  3232. // refresh position page
  3233. pDoc->RefreshCurrentInfoPage();
  3234. }
  3235. // if we are in csg mode, CTRL + LMB teleports second layer's world (primitive)
  3236. else if( (pDoc->GetEditingMode() == CSG_MODE) && bCtrl)
  3237. {
  3238. // set new placement of second layer
  3239. pDoc->m_plSecondLayer.pl_PositionVector = crRayHit.cr_vHit;
  3240. // snap to grid whole second layer's placement
  3241. pDoc->SnapToGrid( pDoc->m_plSecondLayer, m_fGridInMeters/GRID_DISCRETE_VALUES);
  3242. theApp.m_vfpCurrent.vfp_plPrimitive = pDoc->m_plSecondLayer;
  3243. // refresh all views
  3244. pDoc->UpdateAllViews( NULL);
  3245. // refresh position page
  3246. pDoc->RefreshCurrentInfoPage();
  3247. }
  3248. CView::OnLButtonDblClk(nFlags, point);
  3249. }
  3250. void CWorldEditorView::CallPopupMenu(CPoint point)
  3251. {
  3252. CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
  3253. CWorldEditorDoc* pDoc = GetDocument();
  3254. ASSERT_VALID(pDoc);
  3255. BOOL bHitFields = (pDoc->GetEditingMode() == ENTITY_MODE);
  3256. // obtain information about where mouse pointed into the world in the moment of mouse down
  3257. CCastRay crRayHitOnContext = GetMouseHitInformation( point, FALSE, TRUE, bHitFields);
  3258. // create popup menu
  3259. CMenu menu;
  3260. INDEX iMenuID;
  3261. // choose popup menu
  3262. switch( pDoc->GetEditingMode())
  3263. {
  3264. case POLYGON_MODE:{ iMenuID = IDR_POLYGON_POPUP; break; }
  3265. case SECTOR_MODE:{ iMenuID = IDR_SECTOR_POPUP;break; }
  3266. case VERTEX_MODE:{ iMenuID = IDR_VERTEX_POPUP;break; }
  3267. case ENTITY_MODE:{ iMenuID = IDR_ENTITY_POPUP;break; }
  3268. case TERRAIN_MODE:{ iMenuID = IDR_TERRAIN_POPUP;break; }
  3269. case CSG_MODE:
  3270. {
  3271. if( pDoc->m_bPrimitiveMode) iMenuID = IDR_CSG_PRIMITIVE_POPUP;
  3272. else iMenuID = IDR_CSG_TEMPLATE_POPUP;
  3273. break;
  3274. }
  3275. default: { FatalError("Unknown editing mode."); break;};
  3276. }
  3277. // load popup menu
  3278. if( menu.LoadMenu(iMenuID))
  3279. {
  3280. BOOL bEntityClicked = FALSE;
  3281. BOOL bBrushClicked = FALSE;
  3282. BOOL bSecondLayerHited = FALSE;
  3283. BOOL bPortalClicked = FALSE;
  3284. m_penEntityHitOnContext = NULL;
  3285. if( crRayHitOnContext.cr_penHit != NULL)
  3286. {
  3287. m_penEntityHitOnContext = crRayHitOnContext.cr_penHit;
  3288. bEntityClicked = TRUE;
  3289. // test if we hited second layer
  3290. if( crRayHitOnContext.cr_penHit->GetWorld() != &pDoc->m_woWorld)
  3291. {
  3292. bSecondLayerHited = TRUE;
  3293. }
  3294. m_plEntityHitOnContext = crRayHitOnContext.cr_penHit->GetPlacement();
  3295. m_plEntityHitOnContext.pl_PositionVector = crRayHitOnContext.cr_vHit;
  3296. CEntity::RenderType rt = crRayHitOnContext.cr_penHit->GetRenderType();
  3297. if( rt==CEntity::RT_BRUSH || rt==CEntity::RT_FIELDBRUSH)
  3298. {
  3299. bBrushClicked = TRUE;
  3300. }
  3301. m_pbpoRightClickedPolygon = crRayHitOnContext.cr_pbpoBrushPolygon;
  3302. if( m_pbpoRightClickedPolygon != NULL)
  3303. {
  3304. bPortalClicked = m_pbpoRightClickedPolygon->bpo_ulFlags & BPOF_PORTAL;
  3305. }
  3306. }
  3307. // remember if we hited any entity with cntext menu
  3308. m_bEntityHitedOnContext = bEntityClicked;
  3309. CMenu* pPopup = menu.GetSubMenu(0);
  3310. pPopup->EnableMenuItem( ID_ENTITY_CONTEXT_HELP, MF_DISABLED|MF_GRAYED);
  3311. pPopup->EnableMenuItem(ID_SET_AS_CSG_TARGET, MF_DISABLED|MF_GRAYED);
  3312. if(bBrushClicked && !bSecondLayerHited) pPopup->EnableMenuItem(ID_SET_AS_CSG_TARGET, MF_ENABLED);
  3313. // disable commands that can't be applied
  3314. switch( pDoc->GetEditingMode())
  3315. {
  3316. case POLYGON_MODE:
  3317. {
  3318. pPopup->EnableMenuItem(ID_POLYGON_MODE, MF_DISABLED|MF_GRAYED);
  3319. if( !bPortalClicked)
  3320. {
  3321. pPopup->EnableMenuItem(ID_SELECT_SECTORS_OTHER_SIDE, MF_DISABLED|MF_GRAYED);
  3322. }
  3323. if( !bBrushClicked)
  3324. {
  3325. pPopup->EnableMenuItem(ID_MENU_COPY_MAPPING, MF_DISABLED|MF_GRAYED);
  3326. pPopup->EnableMenuItem(ID_COPY_TEXTURE, MF_DISABLED|MF_GRAYED);
  3327. pPopup->EnableMenuItem(ID_SELECT_BY_TEXTURE_ADJACENT, MF_DISABLED|MF_GRAYED);
  3328. pPopup->EnableMenuItem(ID_SELECT_BY_TEXTURE_IN_SECTOR, MF_DISABLED|MF_GRAYED);
  3329. pPopup->EnableMenuItem(ID_SELECT_BY_COLOR_IN_SECTOR, MF_DISABLED|MF_GRAYED);
  3330. pPopup->EnableMenuItem(ID_FIND_TEXTURE, MF_DISABLED|MF_GRAYED);
  3331. pPopup->EnableMenuItem(ID_DESELECT_BY_ORIENTATION, MF_DISABLED|MF_GRAYED);
  3332. }
  3333. if( pDoc->m_selPolygonSelection.Count() == 0)
  3334. {
  3335. pPopup->EnableMenuItem(ID_FILTER_SELECTION, MF_DISABLED|MF_GRAYED);
  3336. pPopup->EnableMenuItem(ID_CHOOSE_COLOR, MF_DISABLED|MF_GRAYED);
  3337. pPopup->EnableMenuItem(ID_EXPORT_DISPLACE_MAP, MF_DISABLED|MF_GRAYED);
  3338. pPopup->EnableMenuItem(ID_RANDOM_OFFSET_U, MF_DISABLED|MF_GRAYED);
  3339. pPopup->EnableMenuItem(ID_RANDOM_OFFSET_V, MF_DISABLED|MF_GRAYED);
  3340. pPopup->EnableMenuItem(ID_POLYGONS_TO_BRUSH, MF_DISABLED|MF_GRAYED);
  3341. pPopup->EnableMenuItem(ID_CLONE_POLYGONS, MF_DISABLED|MF_GRAYED);
  3342. pPopup->EnableMenuItem(ID_DELETE_POLYGONS, MF_DISABLED|MF_GRAYED);
  3343. }
  3344. if( !pDoc->m_woWorld.CanJoinPolygons( pDoc->m_selPolygonSelection))
  3345. {
  3346. pPopup->EnableMenuItem( ID_CSG_JOIN_POLYGONS, MF_DISABLED|MF_GRAYED);
  3347. }
  3348. if( !pDoc->m_woWorld.CanJoinAllPossiblePolygons( pDoc->m_selPolygonSelection))
  3349. {
  3350. pPopup->EnableMenuItem( ID_CSG_JOIN_ALL_POLYGONS, MF_DISABLED|MF_GRAYED);
  3351. }
  3352. BOOL bEnableRetripling = FALSE;
  3353. if( pDoc->m_selPolygonSelection.Count() != 0)
  3354. {
  3355. CBrushPolygon *pbpo = pDoc->m_selPolygonSelection.GetFirstInSelection();
  3356. bEnableRetripling = pbpo->bpo_pbscSector->IsReTripleAvailable( pDoc->m_selPolygonSelection);
  3357. }
  3358. if( !bEnableRetripling)
  3359. {
  3360. pPopup->EnableMenuItem( ID_RE_TRIPLE, MF_DISABLED|MF_GRAYED);
  3361. }
  3362. if( !pDoc->m_woWorld.CanJoinPolygons( pDoc->m_selPolygonSelection))
  3363. {
  3364. pPopup->EnableMenuItem( ID_CSG_JOIN_POLYGONS, MF_DISABLED|MF_GRAYED);
  3365. }
  3366. break;
  3367. }
  3368. case SECTOR_MODE:
  3369. {
  3370. if( !bBrushClicked)
  3371. {
  3372. pPopup->EnableMenuItem(ID_SELECT_LINKS_TO_SECTOR, MF_DISABLED|MF_GRAYED);
  3373. pPopup->EnableMenuItem(ID_SELECT_SECTORS_WITH_SAME_NAME, MF_DISABLED|MF_GRAYED);
  3374. }
  3375. if( pDoc->m_selSectorSelection.Count() == 0)
  3376. {
  3377. pPopup->EnableMenuItem(ID_HIDE_SELECTED_SECTORS, MF_DISABLED|MF_GRAYED);
  3378. pPopup->EnableMenuItem(ID_HIDE_UNSELECTED_SECTORS, MF_DISABLED|MF_GRAYED);
  3379. pPopup->EnableMenuItem(ID_DELETE_SECTORS, MF_DISABLED|MF_GRAYED);
  3380. pPopup->EnableMenuItem(ID_CHOOSE_COLOR, MF_DISABLED|MF_GRAYED);
  3381. pPopup->EnableMenuItem(ID_SECTORS_TO_BRUSH, MF_DISABLED|MF_GRAYED);
  3382. }
  3383. if( !pDoc->m_woWorld.CanCopySectors(pDoc->m_selSectorSelection))
  3384. {
  3385. pPopup->EnableMenuItem( ID_COPY_SECTORS, MF_DISABLED|MF_GRAYED);
  3386. pPopup->EnableMenuItem( ID_EDIT_COPY_ALTERNATIVE, MF_DISABLED|MF_GRAYED);
  3387. }
  3388. if( pDoc->m_woWorld.CanJoinSectors(pDoc->m_selSectorSelection))
  3389. {
  3390. pPopup->EnableMenuItem( ID_CSG_JOIN_SECTORS, MF_DISABLED|MF_GRAYED);
  3391. }
  3392. break;
  3393. }
  3394. case TERRAIN_MODE:
  3395. {
  3396. CTerrain *ptrTerrain=GetTerrain();
  3397. if(ptrTerrain==NULL)
  3398. {
  3399. pPopup->EnableMenuItem( ID_PICK_LAYER, MF_DISABLED|MF_GRAYED);
  3400. pPopup->EnableMenuItem( ID_SELECT_LAYER, MF_DISABLED|MF_GRAYED);
  3401. pPopup->EnableMenuItem( ID_CHANGE_TERRAIN_SIZE, MF_DISABLED|MF_GRAYED);
  3402. pPopup->EnableMenuItem( ID_CHANGE_HEIGHTMAP_SIZE, MF_DISABLED|MF_GRAYED);
  3403. pPopup->EnableMenuItem( ID_RECALCULATE_TERRAIN_SHADOWS, MF_DISABLED|MF_GRAYED);
  3404. pPopup->EnableMenuItem( ID_OPTIMIZE_TERRAIN, MF_DISABLED|MF_GRAYED);
  3405. pPopup->EnableMenuItem( ID_IMPORT_HEIGHTMAP, MF_DISABLED|MF_GRAYED);
  3406. pPopup->EnableMenuItem( ID_IMPORT_HEIGHTMAP16, MF_DISABLED|MF_GRAYED);
  3407. pPopup->EnableMenuItem( ID_EXPORT_HEIGHTMAP, MF_DISABLED|MF_GRAYED);
  3408. pPopup->EnableMenuItem( ID_EXPORT_HEIGHTMAP16, MF_DISABLED|MF_GRAYED);
  3409. pPopup->EnableMenuItem( ID_VIEW_HEIGHTMAP, MF_DISABLED|MF_GRAYED);
  3410. CTerrainLayer *ptlLayer=GetLayer();
  3411. if(ptlLayer==NULL)
  3412. {
  3413. pPopup->EnableMenuItem( ID_LAYER_OPTIONS, MF_DISABLED|MF_GRAYED);
  3414. }
  3415. }
  3416. break;
  3417. }
  3418. case ENTITY_MODE:
  3419. {
  3420. if( bEntityClicked)
  3421. {
  3422. pPopup->EnableMenuItem(ID_ENTITY_CONTEXT_HELP, MF_ENABLED);
  3423. }
  3424. BOOL bDisableSelectTarget = FALSE;
  3425. if( pDoc->m_selEntitySelection.Count() == 1)
  3426. {
  3427. CPropertyID *ppidProperty = pMainFrame->m_PropertyComboBar.GetSelectedProperty();
  3428. if( (ppidProperty == NULL) ||
  3429. !((ppidProperty->pid_eptType == CEntityProperty::EPT_PARENT) ||
  3430. (ppidProperty->pid_eptType == CEntityProperty::EPT_ENTITYPTR)))
  3431. {
  3432. bDisableSelectTarget = TRUE;
  3433. }
  3434. }
  3435. else
  3436. {
  3437. bDisableSelectTarget = TRUE;
  3438. }
  3439. if( bDisableSelectTarget)
  3440. {
  3441. pPopup->EnableMenuItem(ID_SELECT_TARGET, MF_DISABLED|MF_GRAYED);
  3442. }
  3443. pPopup->EnableMenuItem(ID_ENTITY_MODE, MF_DISABLED|MF_GRAYED);
  3444. // see if should disable delete
  3445. if( !IsDeleteEntityEnabled())
  3446. {
  3447. pPopup->EnableMenuItem(ID_DELETE_ENTITIES, MF_DISABLED|MF_GRAYED);
  3448. }
  3449. // if clear all target is disabled
  3450. if( !m_bEntityHitedOnContext)
  3451. {
  3452. pPopup->EnableMenuItem(ID_ROTATE_TO_TARGET_ORIGIN, MF_DISABLED|MF_GRAYED);
  3453. pPopup->EnableMenuItem(ID_ROTATE_TO_TARGET_CENTER, MF_DISABLED|MF_GRAYED);
  3454. pPopup->EnableMenuItem(ID_COPY_POSITION, MF_DISABLED|MF_GRAYED);
  3455. pPopup->EnableMenuItem(ID_COPY_ORIENTATION, MF_DISABLED|MF_GRAYED);
  3456. pPopup->EnableMenuItem(ID_COPY_PLACEMENT, MF_DISABLED|MF_GRAYED);
  3457. pPopup->EnableMenuItem(ID_PASTE_POSITION, MF_DISABLED|MF_GRAYED);
  3458. pPopup->EnableMenuItem(ID_CLEAR_ALL_TARGETS, MF_DISABLED|MF_GRAYED);
  3459. }
  3460. // if clone updating is disabled
  3461. if( !pDoc->IsCloneUpdatingAllowed())
  3462. {
  3463. pPopup->EnableMenuItem(ID_UPDATE_CLONES, MF_DISABLED|MF_GRAYED);
  3464. }
  3465. // if brush updating is disabled
  3466. if( !pDoc->IsBrushUpdatingAllowed())
  3467. {
  3468. pPopup->EnableMenuItem(ID_UPDATE_BRUSHES, MF_DISABLED|MF_GRAYED);
  3469. }
  3470. // if copy is not allowed
  3471. if( pDoc->m_selEntitySelection.Count() == 0)
  3472. {
  3473. pPopup->EnableMenuItem(ID_EDIT_COPY, MF_DISABLED|MF_GRAYED);
  3474. pPopup->EnableMenuItem(ID_SELECT_DESCENDANTS, MF_DISABLED|MF_GRAYED);
  3475. }
  3476. // if clipboard world does not exist
  3477. if( GetFileAttributesA( _fnmApplicationPath + "Temp\\ClipboardWorld.wld") == -1)
  3478. {
  3479. // disable pasting
  3480. pPopup->EnableMenuItem(ID_EDIT_PASTE, MF_DISABLED|MF_GRAYED);
  3481. }
  3482. if( !IsSelectClonesOnContextEnabled())
  3483. {
  3484. // disable select clones
  3485. pPopup->EnableMenuItem(ID_SELECT_CLONES_ON_CONTEXT, MF_DISABLED|MF_GRAYED);
  3486. }
  3487. if( !IsSelectOfSameClassOnContextEnabled())
  3488. {
  3489. // disable select clones
  3490. pPopup->EnableMenuItem(ID_SELECT_OF_SAME_CLASS_ON_CONTEXT, MF_DISABLED|MF_GRAYED);
  3491. }
  3492. break;
  3493. }
  3494. }
  3495. // convert mouse coordinates into screen coordinates
  3496. ClientToScreen( &point);
  3497. // call popup menu
  3498. pPopup->TrackPopupMenu( TPM_LEFTBUTTON | TPM_RIGHTBUTTON | TPM_LEFTALIGN,
  3499. point.x, point.y, this);
  3500. }
  3501. }
  3502. void CWorldEditorView::SetEditingDataPaneInfo( BOOL bImidiateRepainting)
  3503. {
  3504. // obtain current time
  3505. FLOAT fTimeNow = _pTimer->GetRealTimeTick();
  3506. // get difference to time when last mip brushing option has been used
  3507. FLOAT fSecondsPassed = fTimeNow-_fLastMipBrushingOptionUsed;
  3508. // if we used any mip brushing option inside last 30 seconds
  3509. BOOL bUsingMipBrushing;
  3510. if( fSecondsPassed < 120) bUsingMipBrushing = TRUE;
  3511. else bUsingMipBrushing = FALSE;
  3512. // get draw port
  3513. CDrawPort *pdpValidDrawPort = GetDrawPort();
  3514. // if it is not valid
  3515. if( pdpValidDrawPort == NULL)
  3516. {
  3517. return;
  3518. }
  3519. if( !theApp.m_bShowStatusInfo)
  3520. {
  3521. return;
  3522. }
  3523. CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
  3524. CWorldEditorDoc* pDoc = GetDocument();
  3525. char strDataPaneText[ 128];
  3526. // obtain button statuses and interesting flags
  3527. BOOL bSpace = (GetKeyState( ' ') & 128) != 0;
  3528. BOOL bCtrl = (GetKeyState( VK_CONTROL)&0x8000) != 0;
  3529. BOOL bShift = (GetKeyState( VK_SHIFT)&0x8000) != 0;
  3530. BOOL bLMB = (GetKeyState( VK_LBUTTON)&0x8000) != 0;
  3531. BOOL bRMB = (GetKeyState( VK_RBUTTON)&0x8000) != 0;
  3532. BOOL bCSGOn = pDoc->m_pwoSecondLayer != NULL;
  3533. BOOL bEntityMode = pDoc->GetEditingMode() == ENTITY_MODE;
  3534. BOOL bPolygonMode = pDoc->GetEditingMode() == POLYGON_MODE;
  3535. BOOL bTerrainMode = pDoc->GetEditingMode() == TERRAIN_MODE;
  3536. BOOL bVertexMode = pDoc->GetEditingMode() == VERTEX_MODE;
  3537. CEntity *penBrush = pMainFrame->m_CSGDesitnationCombo.GetSelectedBrushEntity();
  3538. // create a slave viewer
  3539. CSlaveViewer svViewer( GetChildFrame()->m_mvViewer, m_ptProjectionType,
  3540. pDoc->m_plGrid, pdpValidDrawPort);
  3541. //---------------- Now we will prepare status line' text describing editing data
  3542. if( theApp.m_bMeasureModeOn)
  3543. {
  3544. strcpy( strDataPaneText, m_strMeasuring);
  3545. }
  3546. else if( theApp.m_bCutModeOn)
  3547. {
  3548. sprintf( strDataPaneText, "Cut/Mirror mode");
  3549. }
  3550. else if( (penBrush != NULL) && bUsingMipBrushing)
  3551. {
  3552. CBrush3D *pbrBrush = penBrush->GetBrush();
  3553. ASSERT( pbrBrush != NULL);
  3554. // get currently active mip factor
  3555. FLOAT fCurrentMipFactor = GetCurrentlyActiveMipFactor();
  3556. // get mip brush
  3557. if( pbrBrush != NULL)
  3558. {
  3559. CBrushMip *pbmCurrentMip = pbrBrush->GetBrushMipByDistance( fCurrentMipFactor);
  3560. if( pbmCurrentMip != NULL)
  3561. {
  3562. // get mip switch factor for currently visible brush
  3563. FLOAT fCurrentMipSwitchFactor = pbmCurrentMip->GetMipDistance();
  3564. // so prepare string telling selected brush's mip switch factor
  3565. sprintf( strDataPaneText, "factor=%.2f, mip=%d/%d, switch=%.2f",
  3566. fCurrentMipFactor, pbmCurrentMip->GetMipIndex(),
  3567. pbrBrush->br_lhBrushMips.Count(), fCurrentMipSwitchFactor);
  3568. }
  3569. else
  3570. {
  3571. // so prepare string telling selected brush's mip switch factor
  3572. sprintf( strDataPaneText, "factor=%.2f, after last mip", fCurrentMipFactor);
  3573. }
  3574. }
  3575. else
  3576. {
  3577. // brush wasn't valid, report error
  3578. sprintf( strDataPaneText, "entity has invalid brush");
  3579. }
  3580. }
  3581. // if space pressed, we are interested in viewer placement
  3582. else if( bSpace)
  3583. {
  3584. // get viewer position and orientation data
  3585. CPlacement3D plViewer = GetChildFrame()->m_mvViewer.GetViewerPlacement();
  3586. // if both mouses are pressed, we want to rotate viewer
  3587. if( bLMB && bRMB)
  3588. {
  3589. // so prepare string telling viewer orientation
  3590. sprintf( strDataPaneText, "H=%g P=%g B=%g",
  3591. DegAngle( plViewer.pl_OrientationAngle(1)),
  3592. DegAngle( plViewer.pl_OrientationAngle(2)),
  3593. DegAngle( plViewer.pl_OrientationAngle(3)) );
  3594. }
  3595. // we are interested in viewer's current position
  3596. else
  3597. {
  3598. // so prepare string telling viewer position
  3599. sprintf( strDataPaneText, "X=%g Y=%g Z=%g",
  3600. plViewer.pl_PositionVector(1),
  3601. plViewer.pl_PositionVector(2),
  3602. plViewer.pl_PositionVector(3) );
  3603. }
  3604. }
  3605. else if( (bVertexMode) && ( pDoc->m_selVertexSelection.Count() != 0) )
  3606. {
  3607. // so prepare string telling entity position
  3608. if (pDoc->m_selVertexSelection.Count()==1) {
  3609. const FLOAT3D &v = pDoc->m_selVertexSelection.GetFirst().bvx_vAbsolute;
  3610. sprintf( strDataPaneText, "%f,%f,%f", v(1), v(2), v(3));
  3611. } else {
  3612. sprintf( strDataPaneText, "Dragging %d vertices", pDoc->m_selVertexSelection.Count());
  3613. }
  3614. }
  3615. // if we are in entity mode and there is selected entity
  3616. else if( (bEntityMode) && ( pDoc->m_selEntitySelection.Count() != 0) )
  3617. {
  3618. // lock selection's dynamic container
  3619. pDoc->m_selEntitySelection.Lock();
  3620. // get first entity
  3621. CEntity *penEntityOne = pDoc->m_selEntitySelection.Pointer(0);
  3622. // unlock selection's dynamic container
  3623. pDoc->m_selEntitySelection.Unlock();
  3624. // get placement of first entity
  3625. CPlacement3D plEntityOnePlacement = penEntityOne->GetPlacement();
  3626. // if both mouses are pressed, we want to rotate entity so prepare text telling angles
  3627. if( bLMB && bRMB)
  3628. {
  3629. // so prepare string telling entity orientation
  3630. sprintf( strDataPaneText, "H=%g P=%g B=%g",
  3631. DegAngle( plEntityOnePlacement.pl_OrientationAngle(1)),
  3632. DegAngle( plEntityOnePlacement.pl_OrientationAngle(2)),
  3633. DegAngle( plEntityOnePlacement.pl_OrientationAngle(3)) );
  3634. }
  3635. // we are interested in entity one's current position
  3636. else
  3637. {
  3638. // so prepare string telling entity position
  3639. sprintf( strDataPaneText, "X=%g Y=%g Z=%g",
  3640. plEntityOnePlacement.pl_PositionVector(1),
  3641. plEntityOnePlacement.pl_PositionVector(2),
  3642. plEntityOnePlacement.pl_PositionVector(3) );
  3643. }
  3644. }
  3645. // if we are in polygon mode and only one polygon is selected
  3646. else if( (bPolygonMode) && (pDoc->m_selPolygonSelection.Count() == 1) && bCtrl)
  3647. {
  3648. pDoc->m_selPolygonSelection.Lock();
  3649. CBrushPolygon *pbpoBrushPolygon = pDoc->m_selPolygonSelection.Pointer(0);
  3650. pDoc->m_selPolygonSelection.Unlock();
  3651. CMappingDefinitionUI mdui;
  3652. pbpoBrushPolygon->bpo_abptTextures[pDoc->m_iTexture].bpt_mdMapping.ToUI( mdui);
  3653. // prepare text telling about mapping info
  3654. sprintf( strDataPaneText, "Tex %d: U=%.1f V=%.1f RU=%.1f RV=%.1f",
  3655. pDoc->m_iTexture+1, mdui.mdui_fUOffset, mdui.mdui_fVOffset,
  3656. mdui.mdui_aURotation, mdui.mdui_aVRotation);
  3657. }
  3658. else if( bTerrainMode)
  3659. {
  3660. // pane data text has bee obtained on render's ray cast
  3661. sprintf(strDataPaneText, "%s", m_strTerrainDataPaneText);
  3662. }
  3663. else if( bCSGOn)
  3664. {
  3665. // if primitive mode on and ctrl+shift+RMB pressed
  3666. if( pDoc->m_bPrimitiveMode && bCtrl && bShift && bRMB)
  3667. {
  3668. // prepare pane text telling primitive shear info
  3669. sprintf( strDataPaneText, "Shear X=%g Shear Z=%g",
  3670. theApp.m_vfpCurrent.vfp_fShearX, theApp.m_vfpCurrent.vfp_fShearZ);
  3671. }
  3672. // if primitive mode on and ctrl+shift+LMB pressed
  3673. else if( pDoc->m_bPrimitiveMode && bCtrl && bShift)
  3674. {
  3675. // prepare pane text telling primitive size info
  3676. sprintf( strDataPaneText, "W=%g H=%g L=%g",
  3677. theApp.m_vfpCurrent.vfp_fXMax-theApp.m_vfpCurrent.vfp_fXMin,
  3678. theApp.m_vfpCurrent.vfp_fYMax-theApp.m_vfpCurrent.vfp_fYMin,
  3679. theApp.m_vfpCurrent.vfp_fZMax-theApp.m_vfpCurrent.vfp_fZMin);
  3680. }
  3681. // else if ctrl and both mouses are pressed
  3682. else if( bCtrl && bLMB && bRMB)
  3683. {
  3684. // prepare text telling CSG layer orientation
  3685. sprintf( strDataPaneText, "H=%g P=%g B=%g",
  3686. DegAngle( pDoc->m_plSecondLayer.pl_OrientationAngle(1)),
  3687. DegAngle( pDoc->m_plSecondLayer.pl_OrientationAngle(2)),
  3688. DegAngle( pDoc->m_plSecondLayer.pl_OrientationAngle(3)) );
  3689. }
  3690. // else
  3691. else
  3692. {
  3693. // prepare text telling CSG layer position
  3694. sprintf( strDataPaneText, "X=%g Y=%g Z=%g",
  3695. pDoc->m_plSecondLayer.pl_PositionVector(1),
  3696. pDoc->m_plSecondLayer.pl_PositionVector(2),
  3697. pDoc->m_plSecondLayer.pl_PositionVector(3) );
  3698. }
  3699. }
  3700. else
  3701. {
  3702. // sprintf( strDataPaneText, "Idle time");
  3703. // obtain information about where mouse points into the world
  3704. CCastRay crRayHit = GetMouseHitInformation( m_ptMouse);
  3705. // if any kind of entity was hitted
  3706. if( crRayHit.cr_penHit != NULL)
  3707. {
  3708. // get hitted coordinate
  3709. FLOAT3D f3Coordinate = crRayHit.cr_vHit;
  3710. // snap it
  3711. SnapVector( f3Coordinate);
  3712. // prepare text describing hitted coordinate
  3713. sprintf( strDataPaneText, "X=%g Y=%g Z=%g", f3Coordinate(1), f3Coordinate(2), f3Coordinate(3));
  3714. }
  3715. else
  3716. {
  3717. // if the ray hits the empty space
  3718. sprintf( strDataPaneText, "Over nothing");
  3719. }
  3720. }
  3721. // put editing data info into status line
  3722. pMainFrame->m_wndStatusBar.SetPaneText( POSITION_PANE, CString(strDataPaneText), bImidiateRepainting);
  3723. }
  3724. #define SCROLL_CHANGE 0.2f
  3725. #define ZOOM_CHANGE 0.05f
  3726. #define ANGLE_CHANGE 1.0f
  3727. void CWorldEditorView::OnMouseMove(UINT nFlags, CPoint point)
  3728. {
  3729. BOOL bLMB = (GetKeyState( VK_LBUTTON)&0x8000) != 0;
  3730. BOOL bRMB = (GetKeyState( VK_RBUTTON)&0x8000) != 0;
  3731. BOOL bCtrl = (GetKeyState( VK_CONTROL)&0x8000) != 0;
  3732. BOOL bShift = (GetKeyState( VK_SHIFT)&0x8000) != 0;
  3733. BOOL bAlt = (GetKeyState( VK_MENU)&0x8000) != 0;
  3734. if(((m_iaInputAction == IA_SELECT_LASSO_ENTITY) ||
  3735. (m_iaInputAction == IA_SELECT_LASSO_BRUSH_VERTEX)) && !bLMB)
  3736. {
  3737. m_iaInputAction = IA_NONE;
  3738. // discard laso selection
  3739. m_avpixLaso.Clear();
  3740. }
  3741. // if neather mouse key is pressed, simulate that action is none
  3742. if( !bLMB && !bRMB) m_iaInputAction = IA_NONE;
  3743. CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
  3744. CWorldEditorDoc* pDoc = GetDocument();
  3745. CWorldEditorView *pWorldEditorView = theApp.GetActiveView();
  3746. if( pWorldEditorView == NULL) return;
  3747. HWND hwndUnderMouse = ::WindowFromPoint( point);
  3748. HWND hwndInfo = NULL;
  3749. if( pMainFrame->m_pInfoFrame != NULL)
  3750. {
  3751. hwndInfo = pMainFrame->m_pInfoFrame->m_hWnd;
  3752. }
  3753. HWND hwndFocused = ::GetFocus();
  3754. //HWND hwndForeground = ::GetForegroundWindow();
  3755. //if( hwndForeground==pMainFrame->m_hWnd)
  3756. {
  3757. // if this is the first mouse move over new view and it is not over info window,
  3758. // set focus and loose all previous actions
  3759. if( (m_hWnd != hwndFocused) && ( hwndInfo != hwndUnderMouse) )
  3760. {
  3761. SetActiveWindow();
  3762. SetFocus();
  3763. GetChildFrame()->SetActiveView( this);
  3764. pMainFrame->MDIActivate(GetParentFrame());
  3765. // cancel any possible previous actions
  3766. m_iaInputAction = IA_NONE;
  3767. }
  3768. }
  3769. CDrawPort *pdpValidDrawPort = GetDrawPort();
  3770. if( pdpValidDrawPort == NULL) return;
  3771. CView::OnMouseMove(nFlags, point);
  3772. CPoint ptScreen = point;
  3773. LONG lOffsetX = point.x - m_ptMouse.x;
  3774. LONG lOffsetY = point.y - m_ptMouse.y;
  3775. float fOriginOffsetX = (FLOAT) (point.x - m_ptMouseDown.x);
  3776. float fOriginOffsetY = (FLOAT) (point.y - m_ptMouseDown.y);
  3777. //_RPT2(_CRT_WARN, "%f %f\n", fOriginOffsetX, fOriginOffsetY);
  3778. // create a slave viewer
  3779. CSlaveViewer svViewer( GetChildFrame()->m_mvViewer, m_ptProjectionType,
  3780. pDoc->m_plGrid, pdpValidDrawPort);
  3781. BOOL bHitModels = (pDoc->GetEditingMode() != POLYGON_MODE) &&
  3782. (pDoc->GetEditingMode() != TERRAIN_MODE);
  3783. BOOL bHitFields = pDoc->GetEditingMode() == ENTITY_MODE;
  3784. BOOL bHitBrushes = pDoc->GetEditingMode() != TERRAIN_MODE;
  3785. // set dummy ray hit result
  3786. CCastRay crRayHit( NULL, CPlacement3D(FLOAT3D(0.0f,0.0f,0.0f), ANGLE3D(0,0,0)) );
  3787. BOOL bRayHitNeeded;
  3788. if( (m_iaInputAction == IA_MOVING_VIEWER_IN_FLOOR_PLANE) ||
  3789. (m_iaInputAction == IA_MOVING_VIEWER_IN_VIEW_PLANE) ||
  3790. (m_iaInputAction == IA_ROTATING_VIEWER) ||
  3791. (m_iaInputAction == IA_MOVING_SECOND_LAYER_IN_FLOOR_PLANE) ||
  3792. (m_iaInputAction == IA_MOVING_SECOND_LAYER_IN_VIEW_PLANE) ||
  3793. (m_iaInputAction == IA_ROTATING_SECOND_LAYER) ||
  3794. (m_iaInputAction == IA_MOVING_ENTITY_SELECTION_IN_FLOOR_PLANE) ||
  3795. (m_iaInputAction == IA_MOVING_ENTITY_SELECTION_IN_VIEW_PLANE) ||
  3796. (m_iaInputAction == IA_ROTATING_ENTITY_SELECTION) ||
  3797. (m_iaInputAction == IA_DRAG_BRUSH_VERTEX_IN_FLOOR_PLANE) ||
  3798. (m_iaInputAction == IA_DRAG_BRUSH_VERTEX_IN_VIEW_PLANE) ||
  3799. (m_iaInputAction == IA_SELECT_LASSO_ENTITY) ||
  3800. (m_iaInputAction == IA_SELECT_LASSO_BRUSH_VERTEX) ||
  3801. (m_iaInputAction == IA_STRETCH_BRUSH_VERTEX) ||
  3802. (m_iaInputAction == IA_ROTATE_BRUSH_VERTEX) ) {
  3803. bRayHitNeeded = FALSE;
  3804. } else {
  3805. bRayHitNeeded = TRUE;
  3806. }
  3807. BOOL bSelectPortals = FALSE;
  3808. // for right mouse button select portals
  3809. if( bRMB)
  3810. {
  3811. bSelectPortals = TRUE;
  3812. }
  3813. if( bRayHitNeeded)
  3814. {
  3815. crRayHit = GetMouseHitInformation( m_ptMouse, bSelectPortals, bHitModels, bHitFields, NULL, bHitBrushes);
  3816. if(abs(lOffsetX)>=1 || abs(lOffsetY)>=1)
  3817. {
  3818. theApp.m_vLastTerrainHit=crRayHit.cr_vHit;
  3819. theApp.m_penLastTerrainHit=crRayHit.cr_penHit;
  3820. }
  3821. m_strTerrainDataPaneText="Terrain not hit";
  3822. if( pDoc->GetEditingMode() == TERRAIN_MODE && !_pInput->IsInputEnabled())
  3823. {
  3824. if( (crRayHit.cr_penHit!=NULL) && (crRayHit.cr_penHit->GetRenderType() == CEntity::RT_TERRAIN))
  3825. {
  3826. CTerrain *ptrTerrain=crRayHit.cr_penHit->GetTerrain();
  3827. INDEX iLayerBeneath=-1;
  3828. UBYTE ubLayerPower=0;
  3829. INDEX ctLayers=ptrTerrain->tr_atlLayers.Count();
  3830. for(INDEX iLayer=0; iLayer<ctLayers; iLayer++)
  3831. {
  3832. UBYTE ubPower=GetValueFromMask(ptrTerrain, iLayer, crRayHit.cr_vHit);
  3833. if(ubPower>0)
  3834. {
  3835. iLayerBeneath=iLayer;
  3836. ubLayerPower=ubPower;
  3837. }
  3838. }
  3839. if(iLayerBeneath!=-1)
  3840. {
  3841. if(theApp.m_iTerrainEditMode==TEM_HEIGHTMAP)
  3842. {
  3843. if( bCtrl&&bAlt)
  3844. {
  3845. Point pt=Calculate2dHitPoint(ptrTerrain, crRayHit.cr_vHit);
  3846. INDEX iWidth=ptrTerrain->tr_pixHeightMapWidth;
  3847. UWORD uwAltitude=*(ptrTerrain->tr_auwHeightMap+iWidth*pt.pt_iY+pt.pt_iX);
  3848. FLOAT fAltitudeBeneath=FLOAT(uwAltitude)/65535*ptrTerrain->tr_vTerrainSize(2);
  3849. m_strTerrainDataPaneText.PrintF("Altitude: %g", fAltitudeBeneath);
  3850. }
  3851. else
  3852. {
  3853. FLOAT fReferenceAltitude=FLOAT(theApp.m_uwEditAltitude)/65535*ptrTerrain->tr_vTerrainSize(2);
  3854. m_strTerrainDataPaneText.PrintF("Reference altitude: %g", fReferenceAltitude);
  3855. }
  3856. }
  3857. else
  3858. {
  3859. m_strTerrainDataPaneText.PrintF("Layer: %d (%d%%)", iLayerBeneath+1, INDEX(ubLayerPower/255.0f*100.0f));
  3860. }
  3861. }
  3862. else
  3863. {
  3864. m_strTerrainDataPaneText.PrintF("No layers");
  3865. }
  3866. }
  3867. else
  3868. {
  3869. m_strTerrainDataPaneText.PrintF("No terrain hit");
  3870. }
  3871. }
  3872. }
  3873. BOOL bRefreshView = FALSE;// view refresh is not needed for now
  3874. BOOL bObjectMoved = FALSE;// nothing has moved for now
  3875. BOOL bRepaintImmediately = FALSE; // force immediate repainting
  3876. BOOL bRecreatePrimitive = FALSE;// there is no need for recreating primitive
  3877. // act acording to action started in OnLButtonDown() and OnRButtonDown()
  3878. switch( m_iaInputAction)
  3879. {
  3880. case IA_MIP_SETTING:
  3881. {
  3882. // remember current time as time when last mip brushing option has been used
  3883. _fLastMipBrushingOptionUsed = _pTimer->GetRealTimeTick();
  3884. if( lOffsetY > 0) lOffsetY = 0;
  3885. // translate viewer in floor plane
  3886. svViewer.Translate_OwnSystem( 0, 0, -lOffsetY);
  3887. // set new viewer position
  3888. GetChildFrame()->m_mvViewer = svViewer;
  3889. bRefreshView = TRUE;
  3890. break;
  3891. }
  3892. case IA_MANUAL_MIP_SWITCH_FACTOR_CHANGING:
  3893. {
  3894. if( GetChildFrame()->m_fManualMipBrushingFactor - lOffsetY/50.0f > 0.0f)
  3895. {
  3896. // remember current time as time when last mip brushing option has been used
  3897. _fLastMipBrushingOptionUsed = _pTimer->GetRealTimeTick();
  3898. GetChildFrame()->m_fManualMipBrushingFactor -= lOffsetY/50.0f;
  3899. }
  3900. bRefreshView = TRUE;
  3901. break;
  3902. }
  3903. case IA_ROTATING_VIEWER:
  3904. {
  3905. svViewer.Rotate_HPB( lOffsetX, lOffsetY, 0);
  3906. // set new viewer position
  3907. GetChildFrame()->m_mvViewer = svViewer;
  3908. bRefreshView = TRUE;
  3909. break;
  3910. }
  3911. case IA_MOVING_VIEWER_IN_FLOOR_PLANE:
  3912. {
  3913. // translate viewer in floor plane
  3914. svViewer.Translate_OwnSystem( lOffsetX, lOffsetY, 0);
  3915. // set new viewer position
  3916. GetChildFrame()->m_mvViewer = svViewer;
  3917. bRefreshView = TRUE;
  3918. break;
  3919. }
  3920. case IA_MOVING_VIEWER_IN_VIEW_PLANE:
  3921. {
  3922. // translate viewer in view plane
  3923. svViewer.Translate_OwnSystem( lOffsetX, 0, -lOffsetY);
  3924. // set new viewer position
  3925. GetChildFrame()->m_mvViewer = svViewer;
  3926. bRefreshView = TRUE;
  3927. break;
  3928. }
  3929. case IA_SHEARING_PRIMITIVE:
  3930. {
  3931. // get translation vector in view space
  3932. FLOAT fZoom = svViewer.GetZoomFactor();
  3933. CPlacement3D plVector0(FLOAT3D(0.0f,0.0f,0.0f), ANGLE3D(0,0,0));
  3934. CPlacement3D plVector1(
  3935. FLOAT3D( fOriginOffsetX/fZoom, -fOriginOffsetY/fZoom, 0.0f),
  3936. ANGLE3D(0,0,0));
  3937. // project translation vector from view space to absolute space
  3938. CPlacement3D plViewer = svViewer.GetViewerPlacement();
  3939. plVector0.RelativeToAbsolute(plViewer);
  3940. plVector1.RelativeToAbsolute(plViewer);
  3941. // project translation vector from absolute space to second layer space
  3942. plVector0.AbsoluteToRelative(pDoc->m_plSecondLayer);
  3943. plVector1.AbsoluteToRelative(pDoc->m_plSecondLayer);
  3944. // extract translation vector from placements
  3945. FLOAT3D vSizeDelta = plVector1.pl_PositionVector-plVector0.pl_PositionVector;
  3946. // apply mouse movement
  3947. theApp.m_vfpCurrent.vfp_fShearX = m_VFPMouseDown.vfp_fShearX+vSizeDelta(1);
  3948. theApp.m_vfpCurrent.vfp_fShearZ = m_VFPMouseDown.vfp_fShearZ+vSizeDelta(3);
  3949. pDoc->SnapFloat( theApp.m_vfpCurrent.vfp_fShearX, m_fGridInMeters/GRID_DISCRETE_VALUES);
  3950. pDoc->SnapFloat( theApp.m_vfpCurrent.vfp_fShearZ, m_fGridInMeters/GRID_DISCRETE_VALUES);
  3951. bRefreshView = TRUE;
  3952. bRecreatePrimitive = TRUE;
  3953. break;
  3954. }
  3955. case IA_STRETCHING_PRIMITIVE:
  3956. {
  3957. // get translation vector in view space
  3958. FLOAT fZoom = svViewer.GetZoomFactor();
  3959. CPlacement3D plVector0(FLOAT3D(0.0f,0.0f,0.0f), ANGLE3D(0,0,0));
  3960. CPlacement3D plVector1(
  3961. FLOAT3D( fOriginOffsetX/fZoom, -fOriginOffsetY/fZoom,0.0f),
  3962. ANGLE3D(0,0,0));
  3963. // project translation vector from view space to absolute space
  3964. CPlacement3D plViewer = svViewer.GetViewerPlacement();
  3965. plVector0.RelativeToAbsolute(plViewer);
  3966. plVector1.RelativeToAbsolute(plViewer);
  3967. // project translation vector from absolute space to second layer space
  3968. plVector0.AbsoluteToRelative(pDoc->m_plSecondLayer);
  3969. plVector1.AbsoluteToRelative(pDoc->m_plSecondLayer);
  3970. // extract translation vector from placements
  3971. FLOAT3D vSizeDelta = plVector1.pl_PositionVector-plVector0.pl_PositionVector;
  3972. // apply mouse movement
  3973. CValuesForPrimitive vfpTemp = theApp.m_vfpCurrent;
  3974. vfpTemp.vfp_fXMin = m_VFPMouseDown.vfp_fXMin+vSizeDelta(1)*aiForAllowedSizing[m_iSizeControlVertice][0];
  3975. vfpTemp.vfp_fXMax = m_VFPMouseDown.vfp_fXMax+vSizeDelta(1)*aiForAllowedSizing[m_iSizeControlVertice][1];
  3976. vfpTemp.vfp_fYMin = m_VFPMouseDown.vfp_fYMin+vSizeDelta(2)*aiForAllowedSizing[m_iSizeControlVertice][2];
  3977. vfpTemp.vfp_fYMax = m_VFPMouseDown.vfp_fYMax+vSizeDelta(2)*aiForAllowedSizing[m_iSizeControlVertice][3];
  3978. vfpTemp.vfp_fZMin = m_VFPMouseDown.vfp_fZMin+vSizeDelta(3)*aiForAllowedSizing[m_iSizeControlVertice][4];
  3979. vfpTemp.vfp_fZMax = m_VFPMouseDown.vfp_fZMax+vSizeDelta(3)*aiForAllowedSizing[m_iSizeControlVertice][5];
  3980. pDoc->SnapFloat( vfpTemp.vfp_fXMin, m_fGridInMeters/GRID_DISCRETE_VALUES);
  3981. pDoc->SnapFloat( vfpTemp.vfp_fXMax, m_fGridInMeters/GRID_DISCRETE_VALUES);
  3982. pDoc->SnapFloat( vfpTemp.vfp_fYMin, m_fGridInMeters/GRID_DISCRETE_VALUES);
  3983. pDoc->SnapFloat( vfpTemp.vfp_fYMax, m_fGridInMeters/GRID_DISCRETE_VALUES);
  3984. pDoc->SnapFloat( vfpTemp.vfp_fZMin, m_fGridInMeters/GRID_DISCRETE_VALUES);
  3985. pDoc->SnapFloat( vfpTemp.vfp_fZMax, m_fGridInMeters/GRID_DISCRETE_VALUES);
  3986. // if movement produced valid primitive
  3987. if( (vfpTemp.vfp_fXMax>vfpTemp.vfp_fXMin) &&
  3988. (vfpTemp.vfp_fYMax>vfpTemp.vfp_fYMin) &&
  3989. (vfpTemp.vfp_fZMax>vfpTemp.vfp_fZMin) )
  3990. {
  3991. theApp.m_vfpCurrent = vfpTemp;
  3992. bRefreshView = TRUE;
  3993. bRecreatePrimitive = TRUE;
  3994. }
  3995. break;
  3996. }
  3997. case IA_CHANGING_RANGE_PROPERTY:
  3998. case IA_CHANGING_ANGLE3D_PROPERTY:
  3999. {
  4000. CPropertyID *ppid = pMainFrame->m_PropertyComboBar.GetSelectedProperty();
  4001. if( ppid == NULL) return;
  4002. //for all selected entities
  4003. FOREACHINDYNAMICCONTAINER(pDoc->m_selEntitySelection, CEntity, iten)
  4004. {
  4005. // obtain property ptr
  4006. CEntityProperty *penpProperty = iten->PropertyForName( ppid->pid_strName);
  4007. if( penpProperty == NULL) return;
  4008. // discard old entity settings
  4009. iten->End();
  4010. if( ppid->pid_eptType == CEntityProperty::EPT_RANGE)
  4011. {
  4012. // get editing range for current entity
  4013. FLOAT fRange = ENTITYPROPERTY( &*iten, penpProperty->ep_slOffset, FLOAT);
  4014. // add range offset received during L/R mouse move
  4015. fRange += svViewer.PixelsToMeters(lOffsetX);
  4016. // set new range
  4017. ENTITYPROPERTY( &*iten, penpProperty->ep_slOffset, FLOAT) = fRange;
  4018. // change dialog's range variable
  4019. pMainFrame->m_PropertyComboBar.m_fEditingFloat = fRange;
  4020. }
  4021. else
  4022. {
  4023. // get angle3d for current entity
  4024. ANGLE3D aAngle = ENTITYPROPERTY( &*iten, penpProperty->ep_slOffset, ANGLE3D);
  4025. // create dummy placement
  4026. CPlacement3D plDummyPlacement;
  4027. plDummyPlacement.pl_PositionVector = FLOAT3D( 0.0f, 0.0f, 0.0f);
  4028. plDummyPlacement.pl_OrientationAngle = aAngle;
  4029. // set new angles using trackball method
  4030. svViewer.RotatePlacement_TrackBall(plDummyPlacement, lOffsetX, lOffsetY, 0);
  4031. aAngle = plDummyPlacement.pl_OrientationAngle;
  4032. // set new angle
  4033. ENTITYPROPERTY( &*iten, penpProperty->ep_slOffset, ANGLE3D) = aAngle;
  4034. // change dialog's range variable
  4035. pMainFrame->m_PropertyComboBar.m_fEditingHeading = DegAngle(aAngle(1));
  4036. pMainFrame->m_PropertyComboBar.m_fEditingPitch = DegAngle(aAngle(2));
  4037. pMainFrame->m_PropertyComboBar.m_fEditingBanking = DegAngle(aAngle(3));
  4038. }
  4039. // apply new entity settings
  4040. iten->Initialize();
  4041. // update edit range control (by updating parent dialog)
  4042. pMainFrame->m_PropertyComboBar.UpdateData( FALSE);
  4043. bRefreshView = TRUE;
  4044. }
  4045. // mark that document is changed
  4046. pDoc->SetModifiedFlag( TRUE);
  4047. break;
  4048. }
  4049. case IA_ROTATING_ENTITY_SELECTION:
  4050. case IA_ROTATING_SECOND_LAYER:
  4051. {
  4052. // use trackball method for rotation
  4053. svViewer.RotatePlacement_TrackBall(m_plMouseMove, -lOffsetX, -lOffsetY, 0);
  4054. pDoc->m_chSelections.MarkChanged();
  4055. bObjectMoved = TRUE;
  4056. break;
  4057. }
  4058. case IA_MOVING_ENTITY_SELECTION_IN_FLOOR_PLANE:
  4059. case IA_MOVING_SECOND_LAYER_IN_FLOOR_PLANE:
  4060. {
  4061. svViewer.TranslatePlacement_OwnSystem(m_plMouseMove, lOffsetX, lOffsetY, 0);
  4062. pDoc->m_chSelections.MarkChanged();
  4063. bObjectMoved = TRUE;
  4064. break;
  4065. }
  4066. case IA_MOVING_ENTITY_SELECTION_IN_VIEW_PLANE:
  4067. case IA_MOVING_SECOND_LAYER_IN_VIEW_PLANE:
  4068. {
  4069. svViewer.TranslatePlacement_OwnSystem(m_plMouseMove, lOffsetX, 0, lOffsetY);
  4070. pDoc->m_chSelections.MarkChanged();
  4071. bObjectMoved = TRUE;
  4072. break;
  4073. }
  4074. case IA_SIZING_SELECT_BY_VOLUME_BOX:
  4075. {
  4076. // get translation vector in view space
  4077. FLOAT fZoom = svViewer.GetZoomFactor();
  4078. CPlacement3D plVector0(FLOAT3D(0.0f,0.0f,0.0f), ANGLE3D(0,0,0));
  4079. CPlacement3D plVector1(FLOAT3D(fOriginOffsetX/fZoom,-fOriginOffsetY/fZoom,0.0f),
  4080. ANGLE3D(0,0,0));
  4081. // project translation vector from view space to absolute space
  4082. CPlacement3D plViewer = svViewer.GetViewerPlacement();
  4083. plVector0.RelativeToAbsolute(plViewer);
  4084. plVector1.RelativeToAbsolute(plViewer);
  4085. // extract translation vector from placements
  4086. FLOAT3D vDelta = plVector1.pl_PositionVector-plVector0.pl_PositionVector;
  4087. // apply movement
  4088. FLOAT3D vNewVolumeBoxCorner = pDoc->m_vVolumeBoxStartDragVertice+vDelta;
  4089. pDoc->CorrectBox( pDoc->m_iVolumeBoxDragVertice, vNewVolumeBoxCorner);
  4090. bRefreshView = TRUE;
  4091. break;
  4092. }
  4093. case IA_DRAG_VERTEX_ON_PRIMITIVE_BASE:
  4094. {
  4095. if( m_iDragVertice == -1) break;
  4096. // ------ Move closest vertice on base of primitive
  4097. CPlacement3D plVector0(FLOAT3D(0.0f,0.0f,0.0f), ANGLE3D(0,0,0));
  4098. FLOAT fZoom = svViewer.GetZoomFactor();
  4099. CPlacement3D plVector1(FLOAT3D(fOriginOffsetX/fZoom,-fOriginOffsetY/fZoom,0.0f),
  4100. ANGLE3D(0,0,0));
  4101. // project translation vector from view space to absolute space
  4102. CPlacement3D plViewer = svViewer.GetViewerPlacement();
  4103. plVector0.RelativeToAbsolute(plViewer);
  4104. plVector1.RelativeToAbsolute(plViewer);
  4105. // project translation vector from absolute space to second layer space
  4106. plVector0.AbsoluteToRelative(pDoc->m_plSecondLayer);
  4107. plVector1.AbsoluteToRelative(pDoc->m_plSecondLayer);
  4108. // extract translation vector from placements
  4109. DOUBLE3D vDelta = FLOATtoDOUBLE(plVector1.pl_PositionVector)-
  4110. FLOATtoDOUBLE(plVector0.pl_PositionVector);
  4111. DOUBLE3D &vDrag = theApp.m_vfpCurrent.vfp_avVerticesOnBaseOfPrimitive[m_iDragVertice];
  4112. // apply movement
  4113. vDrag = m_vStartDragVertice + vDelta;
  4114. // snap resulting vertex coordinate
  4115. SnapVector( vDrag);
  4116. // refresh primitive
  4117. pDoc->CreatePrimitive();
  4118. bRefreshView = TRUE;
  4119. break;
  4120. }
  4121. case IA_DRAG_VERTEX_ON_PRIMITIVE:
  4122. {
  4123. FLOAT fZoom = svViewer.GetZoomFactor();
  4124. DragVerticesOnPrimitive(fOriginOffsetX/fZoom,-fOriginOffsetY/fZoom, 0.0f, FALSE);
  4125. bRefreshView = TRUE;
  4126. break;
  4127. }
  4128. case IA_SELECT_LASSO_BRUSH_VERTEX:
  4129. case IA_SELECT_LASSO_ENTITY:
  4130. {
  4131. INDEX ctLasoPts = m_avpixLaso.Count();
  4132. m_avpixLaso.Push(1);
  4133. m_avpixLaso[ctLasoPts](1) = point.x;
  4134. m_avpixLaso[ctLasoPts](2) = point.y;
  4135. Invalidate( FALSE);
  4136. break;
  4137. }
  4138. case IA_SELECT_SINGLE_BRUSH_VERTEX:
  4139. {
  4140. // if mouse moved more than few pixels arround
  4141. if( (abs( lOffsetX) > 3) || (abs( lOffsetY) > 3) )
  4142. {
  4143. // if shift nor alt were pressed on mouse down
  4144. if( !m_bOnSelectVertexShiftDown && !m_bOnSelectVertexAltDown)
  4145. {
  4146. // clear vertex selection
  4147. pDoc->m_selVertexSelection.Clear();
  4148. }
  4149. // switch to laso select
  4150. m_iaInputAction = IA_SELECT_LASSO_BRUSH_VERTEX;
  4151. // add mouse down and current mouse positions to lasso buffer
  4152. m_avpixLaso.Push(2);
  4153. m_avpixLaso[0](1) = m_ptMouseDown.x;
  4154. m_avpixLaso[0](2) = m_ptMouseDown.y;
  4155. m_avpixLaso[1](1) = point.x;
  4156. m_avpixLaso[1](2) = point.y;
  4157. pDoc->m_chSelections.MarkChanged();
  4158. Invalidate( FALSE);
  4159. }
  4160. break;
  4161. }
  4162. case IA_DRAG_BRUSH_VERTEX_IN_FLOOR_PLANE:
  4163. {
  4164. bRepaintImmediately = TRUE;
  4165. FLOAT fZoom = svViewer.GetZoomFactor();
  4166. DragBrushVertex(fOriginOffsetX/fZoom,-fOriginOffsetY/fZoom, 0.0f);
  4167. pDoc->SetModifiedFlag( TRUE);
  4168. bRefreshView = TRUE;
  4169. break;
  4170. }
  4171. case IA_DRAG_BRUSH_VERTEX_IN_VIEW_PLANE:
  4172. {
  4173. bRepaintImmediately = TRUE;
  4174. FLOAT fZoom = svViewer.GetZoomFactor();
  4175. DragBrushVertex(fOriginOffsetX/fZoom, 0.0f, fOriginOffsetY/fZoom);
  4176. pDoc->SetModifiedFlag( TRUE);
  4177. bRefreshView = TRUE;
  4178. break;
  4179. }
  4180. case IA_ROTATE_BRUSH_VERTEX:
  4181. {
  4182. bRepaintImmediately = TRUE;
  4183. // apply brush vertex rotation
  4184. RotateOrStretchBrushVertex(-fOriginOffsetX, -fOriginOffsetY, TRUE);
  4185. pDoc->SetModifiedFlag( TRUE);
  4186. // calculate BBox of all vertices before rotating started
  4187. bRefreshView = TRUE;
  4188. break;
  4189. }
  4190. case IA_STRETCH_BRUSH_VERTEX:
  4191. {
  4192. bRepaintImmediately = TRUE;
  4193. // apply brush stretch
  4194. FLOAT fZoom = svViewer.GetZoomFactor();
  4195. RotateOrStretchBrushVertex(fOriginOffsetX, fZoom, FALSE);
  4196. pDoc->SetModifiedFlag( TRUE);
  4197. // calculate BBox of all vertices before rotating started
  4198. bRefreshView = TRUE;
  4199. break;
  4200. }
  4201. case IA_SELECTING_POLYGONS:
  4202. {
  4203. // if mouse is not over some polygon, break
  4204. if( (crRayHit.cr_penHit == NULL) ||
  4205. (crRayHit.cr_pbpoBrushPolygon == NULL) ) break;
  4206. // if polygon under mouse is selected and first polygon that we hitted
  4207. // was deselected
  4208. if( crRayHit.cr_pbpoBrushPolygon->IsSelected( BPOF_SELECTED) && m_bWeDeselectedFirstPolygon)
  4209. {
  4210. // deselect polygon under mouse
  4211. pDoc->m_selPolygonSelection.Deselect( *crRayHit.cr_pbpoBrushPolygon);
  4212. }
  4213. // if polygon under mouse is not selected and first polygon that we hitted
  4214. // at the begining of selecting was selected
  4215. if( !crRayHit.cr_pbpoBrushPolygon->IsSelected( BPOF_SELECTED) && !m_bWeDeselectedFirstPolygon)
  4216. {
  4217. // select polygon under mouse
  4218. pDoc->m_selPolygonSelection.Select( *crRayHit.cr_pbpoBrushPolygon);
  4219. }
  4220. // mark that selections have been changed
  4221. pDoc->m_chSelections.MarkChanged();
  4222. // and refresh property combo manualy calling on idle
  4223. pMainFrame->m_PropertyComboBar.m_PropertyComboBox.OnIdle( 0);
  4224. bRefreshView = TRUE;
  4225. break;
  4226. }
  4227. case IA_SELECTING_SECTORS:
  4228. {
  4229. // if mouse is not over some polygon, break
  4230. if( (crRayHit.cr_penHit == NULL) ||
  4231. (crRayHit.cr_pbpoBrushPolygon == NULL) ) break;
  4232. // if sector under mouse is selected and first sector that we hitted
  4233. // at the begining of selecting was deselected
  4234. if( crRayHit.cr_pbscBrushSector->IsSelected( BSCF_SELECTED) && m_bWeDeselectedFirstSector)
  4235. {
  4236. // deselect sector under mouse
  4237. pDoc->m_selSectorSelection.Deselect( *crRayHit.cr_pbscBrushSector);
  4238. }
  4239. // if sector under mouse is not selected and first sector that we hitted
  4240. // at the begining of selecting was selected
  4241. if( !crRayHit.cr_pbscBrushSector->IsSelected( BSCF_SELECTED) && !m_bWeDeselectedFirstSector)
  4242. {
  4243. // select sector under mouse
  4244. pDoc->m_selSectorSelection.Select( *crRayHit.cr_pbscBrushSector);
  4245. }
  4246. // mark that selections have been changed
  4247. pDoc->m_chSelections.MarkChanged();
  4248. // and refresh property combo manualy calling on idle
  4249. pMainFrame->m_PropertyComboBar.m_PropertyComboBox.OnIdle( 0);
  4250. bRefreshView = TRUE;
  4251. break;
  4252. }
  4253. case IA_SELECTING_ENTITIES:
  4254. {
  4255. // if mouse moved more than few pixels arround
  4256. if( (abs( lOffsetX) > 3) || (abs( lOffsetY) > 3) )
  4257. {
  4258. // if shift nor alt were pressed on mouse down
  4259. if( !m_bOnSelectEntityShiftDown && !m_bOnSelectEntityAltDown)
  4260. {
  4261. // clear entity selection
  4262. pDoc->m_selEntitySelection.Clear();
  4263. }
  4264. // switch to laso select
  4265. m_iaInputAction = IA_SELECT_LASSO_ENTITY;
  4266. // add mouse down and current mouse positions to lasso buffer
  4267. m_avpixLaso.Push(2);
  4268. m_avpixLaso[0](1) = m_ptMouseDown.x;
  4269. m_avpixLaso[0](2) = m_ptMouseDown.y;
  4270. m_avpixLaso[1](1) = point.x;
  4271. m_avpixLaso[1](2) = point.y;
  4272. Invalidate( FALSE);
  4273. }
  4274. break;
  4275. }
  4276. case IA_MEASURING:
  4277. {
  4278. // just refresh view
  4279. bRefreshView = TRUE;
  4280. break;
  4281. }
  4282. case IA_MOVING_CUT_LINE_START:
  4283. {
  4284. FLOAT fZoom = svViewer.GetZoomFactor();
  4285. FLOAT3D vDelta = ProjectVectorToWorldSpace( fOriginOffsetX/fZoom, -fOriginOffsetY/fZoom, 0.0f);
  4286. // calculate and snap new position
  4287. pDoc->m_vCutLineStart = pDoc->m_vControlLineDragStart+vDelta;
  4288. SnapVector( pDoc->m_vCutLineStart);
  4289. bRefreshView = TRUE;
  4290. break;
  4291. }
  4292. case IA_MOVING_CUT_LINE_END:
  4293. {
  4294. // get 3D delta vector in world, from mouse down point to current mouse position
  4295. FLOAT fZoom = svViewer.GetZoomFactor();
  4296. FLOAT3D vDelta = ProjectVectorToWorldSpace( fOriginOffsetX/fZoom, -fOriginOffsetY/fZoom, 0.0f);
  4297. // calculate and snap new position
  4298. pDoc->m_vCutLineEnd = pDoc->m_vControlLineDragStart+vDelta;
  4299. SnapVector( pDoc->m_vCutLineEnd);
  4300. bRefreshView = TRUE;
  4301. break;
  4302. }
  4303. case IA_CUT_MODE:
  4304. {
  4305. // calculate current cut line end
  4306. pDoc->m_vCutLineEnd = Get3DCoordinateFrom2D( point);
  4307. bRefreshView = TRUE;
  4308. break;
  4309. }
  4310. case IA_ROTATING_POLYGON_MAPPING:
  4311. {
  4312. if(crRayHit.cr_pbpoBrushPolygon==NULL) return;
  4313. svViewer.RotatePlacement_TrackBall(m_plMouseMove, lOffsetX, lOffsetY, 0);
  4314. // get rotation angle
  4315. ANGLE3D angMappingRotation = m_plMouseMove.pl_OrientationAngle;
  4316. CTString strDataPaneText;
  4317. strDataPaneText.PrintF("H=%g,P=%g,B=%g",
  4318. DegAngle( angMappingRotation(1)),
  4319. DegAngle( angMappingRotation(2)),
  4320. DegAngle( angMappingRotation(3)));
  4321. pMainFrame->m_wndStatusBar.SetPaneText( STATUS_LINE_PANE, CString(strDataPaneText), TRUE);
  4322. // for each selected polygon
  4323. FOREACHINDYNAMICCONTAINER(pDoc->m_selPolygonSelection, CBrushPolygon, itbpo)
  4324. {
  4325. CBrushPolygon *pbpo = itbpo;
  4326. CEntity *pen = pbpo->bpo_pbscSector->bsc_pbmBrushMip->bm_pbrBrush->br_penEntity;
  4327. CSimpleProjection3D pr;
  4328. pr.ObjectPlacementL() = _plOrigin;
  4329. pr.ViewerPlacementL() = pen->GetPlacement();
  4330. pr.Prepare();
  4331. FLOATplane3D vRelative;
  4332. pr.ProjectCoordinate(m_vHitOnMouseDown, vRelative);
  4333. // rotate it
  4334. itbpo->bpo_abptTextures[pDoc->m_iTexture].bpt_mdMapping.Rotate(
  4335. pbpo->bpo_pbplPlane->bpl_pwplWorking->wpl_mvRelative,
  4336. vRelative, angMappingRotation(1));
  4337. }
  4338. // mark that document is changed
  4339. pDoc->SetModifiedFlag();
  4340. bRefreshView = TRUE;
  4341. pDoc->UpdateAllViews( NULL);
  4342. // reset mouse placement
  4343. m_plMouseMove.pl_PositionVector = crRayHit.cr_vHit;
  4344. m_plMouseMove.pl_OrientationAngle = ANGLE3D( 0, 0, 0);
  4345. // refresh position page
  4346. pDoc->RefreshCurrentInfoPage();
  4347. break;
  4348. }
  4349. case IA_MOVING_POLYGON_MAPPING:
  4350. {
  4351. // find translation vector in 3d
  4352. crRayHit.cr_vHit = GetMouseHitOnPlane(point, m_plTranslationPlane);
  4353. FLOAT3D f3dMappingTranslation = crRayHit.cr_vHit-m_plMouseMove.pl_PositionVector;
  4354. // find how much that offsets hit polygon
  4355. if( m_pbpoTranslationPlane == NULL) return;
  4356. CBrushPolygon &bpo = *m_pbpoTranslationPlane;
  4357. CEntity *pen = bpo.bpo_pbscSector->bsc_pbmBrushMip->bm_pbrBrush->br_penEntity;
  4358. CSimpleProjection3D pr;
  4359. pr.ObjectPlacementL() = _plOrigin;
  4360. pr.ViewerPlacementL() = pen->GetPlacement();
  4361. pr.Prepare();
  4362. FLOATplane3D vRelative;
  4363. pr.ProjectDirection(f3dMappingTranslation, vRelative);
  4364. CMappingDefinition mdOriginal = bpo.bpo_abptTextures[pDoc->m_iTexture].bpt_mdMapping;
  4365. CMappingDefinition mdTranslated = mdOriginal;
  4366. mdTranslated.Translate(
  4367. bpo.bpo_pbplPlane->bpl_pwplWorking->wpl_mvRelative, vRelative);
  4368. FLOAT fUOffset = mdTranslated.md_fUOffset-mdOriginal.md_fUOffset;
  4369. FLOAT fVOffset = mdTranslated.md_fVOffset-mdOriginal.md_fVOffset;
  4370. // for each selected polygon
  4371. FOREACHINDYNAMICCONTAINER(pDoc->m_selPolygonSelection, CBrushPolygon, itbpo)
  4372. {
  4373. // add the offsets to its mapping
  4374. itbpo->bpo_abptTextures[pDoc->m_iTexture].bpt_mdMapping.md_fUOffset+=fUOffset;
  4375. itbpo->bpo_abptTextures[pDoc->m_iTexture].bpt_mdMapping.md_fVOffset+=fVOffset;
  4376. }
  4377. // mark that document is changed
  4378. pDoc->SetModifiedFlag();
  4379. bRefreshView = TRUE;
  4380. pDoc->UpdateAllViews( NULL);
  4381. // reset mouse placement
  4382. m_plMouseMove.pl_PositionVector = crRayHit.cr_vHit;
  4383. m_plMouseMove.pl_OrientationAngle = ANGLE3D( 0, 0, 0);
  4384. // refresh position page
  4385. pDoc->RefreshCurrentInfoPage();
  4386. break;
  4387. }
  4388. }
  4389. // if recreating of primitive requested
  4390. if( bRecreatePrimitive)
  4391. {
  4392. pDoc->RefreshPrimitivePage();
  4393. pDoc->CreatePrimitive();
  4394. }
  4395. // if something has moved
  4396. if( bObjectMoved)
  4397. {
  4398. if( (m_iaInputAction == IA_MOVING_SECOND_LAYER_IN_FLOOR_PLANE) ||
  4399. (m_iaInputAction == IA_MOVING_SECOND_LAYER_IN_VIEW_PLANE) ||
  4400. (m_iaInputAction == IA_ROTATING_SECOND_LAYER) )
  4401. {
  4402. // copy new placement to second layer
  4403. pDoc->m_plSecondLayer = m_plMouseMove;
  4404. pDoc->SnapToGrid( pDoc->m_plSecondLayer, m_fGridInMeters/GRID_DISCRETE_VALUES);
  4405. theApp.m_vfpCurrent.vfp_plPrimitive = pDoc->m_plSecondLayer;
  4406. }
  4407. else if( (m_iaInputAction == IA_MOVING_ENTITY_SELECTION_IN_FLOOR_PLANE) ||
  4408. (m_iaInputAction == IA_MOVING_ENTITY_SELECTION_IN_VIEW_PLANE) ||
  4409. (m_iaInputAction == IA_ROTATING_ENTITY_SELECTION) )
  4410. {
  4411. ASSERT( pDoc->m_aSelectedEntityPlacements.Count()==pDoc->m_selEntitySelection.Count());
  4412. if( pDoc->m_aSelectedEntityPlacements.Count()!=pDoc->m_selEntitySelection.Count()) return;
  4413. // if there is no anchored entity in selection or if moving of
  4414. // anchored entities is allowed
  4415. {FOREACHINDYNAMICCONTAINER(pDoc->m_selEntitySelection, CEntity, iten)
  4416. {
  4417. if( ((iten->GetFlags() & ENF_ANCHORED) != 0) &&
  4418. (!GetChildFrame()->m_bAncoredMovingAllowed) ) return;
  4419. }}
  4420. INDEX ienCurrent = 0;
  4421. CEntity *penBrush = NULL;
  4422. // for each of the selected entities
  4423. {FOREACHINDYNAMICCONTAINER(pDoc->m_selEntitySelection, CEntity, iten)
  4424. {
  4425. if (iten->en_RenderType == CEntity::RT_BRUSH) {
  4426. penBrush = &*iten;
  4427. }
  4428. if( (iten->GetParent()==NULL) || !(iten->GetParent()->IsSelected( ENF_SELECTED)) )
  4429. {
  4430. // set new entity placement
  4431. CPlacement3D plEntityPlacement = pDoc->m_aSelectedEntityPlacements[ienCurrent];
  4432. plEntityPlacement.RelativeToAbsoluteSmooth(m_plMouseMove);
  4433. pDoc->SnapToGrid( plEntityPlacement, m_fGridInMeters/GRID_DISCRETE_VALUES);
  4434. iten->SetPlacement(plEntityPlacement);
  4435. pDoc->SetModifiedFlag();
  4436. }
  4437. ienCurrent++;
  4438. }}
  4439. if( penBrush != NULL)
  4440. {
  4441. DiscardShadows( penBrush);
  4442. }
  4443. if(m_iaInputAction == IA_ROTATING_ENTITY_SELECTION)
  4444. {
  4445. // check for terrain updating
  4446. {FOREACHINDYNAMICCONTAINER(pDoc->m_selEntitySelection, CEntity, iten)
  4447. {
  4448. CLightSource *pls = iten->GetLightSource();
  4449. if (pls!=NULL)
  4450. {
  4451. // if light is directional
  4452. if(pls->ls_ulFlags &LSF_DIRECTIONAL)
  4453. {
  4454. CTerrain *ptrTerrain=GetTerrain();
  4455. if(ptrTerrain!=NULL) ptrTerrain->UpdateShadowMap();
  4456. }
  4457. }
  4458. }}
  4459. }
  4460. }
  4461. }
  4462. // if rotating/moving viewer (bRefreshView) or moving CSG layer, entities or polygon's
  4463. // mapping (bObjectMoved) or editing primitive (bRecreatePrimitive)
  4464. if( bRefreshView || bObjectMoved || bRecreatePrimitive)
  4465. {
  4466. // see in preferences if all views should be updated
  4467. if( theApp.m_Preferences.ap_UpdateAllways || bRepaintImmediately ||
  4468. (bCtrl && bLMB && pDoc->GetEditingMode()==POLYGON_MODE) )
  4469. {
  4470. // force immediatly repainting
  4471. RedrawWindow( NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
  4472. // update other views
  4473. pDoc->UpdateAllViews( this);
  4474. }
  4475. else
  4476. {
  4477. // just invalidate
  4478. Invalidate( FALSE);
  4479. }
  4480. }
  4481. // set text describing data that is edited
  4482. SetEditingDataPaneInfo( TRUE);
  4483. // remember current mouse position as last pressed
  4484. m_ptMouse = point;
  4485. }
  4486. /*
  4487. * Called by document at the end of CSG
  4488. */
  4489. void CWorldEditorView::AtStopCSG(void)
  4490. {
  4491. }
  4492. /*
  4493. * Called by MFC from CWorldEditorDoc::UpdateAllViews().
  4494. */
  4495. void CWorldEditorView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint)
  4496. {
  4497. // just invalidate the whole window area
  4498. Invalidate(FALSE);
  4499. }
  4500. void CWorldEditorView::OnDropFiles(HDROP hDropInfo)
  4501. {
  4502. CWorldEditorDoc* pDoc = GetDocument();
  4503. CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
  4504. BOOL bCSGOn = pDoc->m_pwoSecondLayer != NULL;
  4505. // You can't drag anything while CSG is on
  4506. if( bCSGOn)
  4507. {
  4508. return;
  4509. }
  4510. // get number of dropped files
  4511. INDEX iNoOfFiles = DragQueryFile( hDropInfo, 0xFFFFFFFF, NULL, 0);
  4512. // there can be only one file dropped
  4513. if( iNoOfFiles != 1)
  4514. {
  4515. AfxMessageBox( L"You can drop only one file at a time.");
  4516. return;
  4517. }
  4518. // buffer for dropped file name
  4519. char chrFile[ 256];
  4520. // place dropped file name into buffer
  4521. DragQueryFileA( hDropInfo, 0, chrFile, 256);
  4522. // create file name from buffer
  4523. CTFileName fnDropped = CTString(chrFile);
  4524. // don't allow document self-drop
  4525. /*if( CTFileName(pDoc->GetPathName()) == fnDropped)
  4526. {
  4527. return;
  4528. }*/
  4529. // object to hold coordinates
  4530. CPoint point;
  4531. // get dropped coordinates
  4532. DragQueryPoint( hDropInfo, &point);
  4533. // try to
  4534. try
  4535. {
  4536. // remove application path
  4537. fnDropped.RemoveApplicationPath_t();
  4538. }
  4539. catch( char* err_str)
  4540. {
  4541. AfxMessageBox( CString(err_str));
  4542. return;
  4543. }
  4544. CPlacement3D plDrop;
  4545. // obtain information about where mouse points into the world
  4546. CCastRay crRayHit = GetMouseHitInformation( point);
  4547. // place the dropped object at hitted point
  4548. plDrop.pl_PositionVector = crRayHit.cr_vHit;
  4549. // reset angles
  4550. plDrop.pl_OrientationAngle = ANGLE3D(0,0,0);
  4551. // if the hit entity was a brush
  4552. if( (crRayHit.cr_penHit != NULL) &&
  4553. (crRayHit.cr_pbpoBrushPolygon != NULL) ) {
  4554. // get the hit normal in absolute space
  4555. CSimpleProjection3D prBrushToAbsolute;
  4556. prBrushToAbsolute.ObjectPlacementL() = crRayHit.cr_penHit->GetPlacement();
  4557. prBrushToAbsolute.ViewerPlacementL() = CPlacement3D(
  4558. FLOAT3D(0.0f,0.0f,0.0f), ANGLE3D(0,0,0));
  4559. prBrushToAbsolute.Prepare();
  4560. FLOAT3D vHitNormal;
  4561. prBrushToAbsolute.ProjectDirection(crRayHit.cr_pbpoBrushPolygon->bpo_pbplPlane->bpl_plAbsolute,
  4562. vHitNormal);
  4563. // if the normal is more horizontal
  4564. if (Abs(vHitNormal(2))<0.5f) {
  4565. // calculate angles to align -z axis towards the plane
  4566. DirectionVectorToAngles(-vHitNormal, plDrop.pl_OrientationAngle);
  4567. }
  4568. }
  4569. pDoc->SnapToGrid( plDrop, m_fGridInMeters/GRID_DISCRETE_VALUES);
  4570. // if the dragged object is an entity class
  4571. if (fnDropped.FileExt()==".ecl")
  4572. {
  4573. // create dragged entity
  4574. CPlacement3D plEntity;
  4575. CEntity *pen = NULL;
  4576. try
  4577. {
  4578. extern BOOL _bInOnDraw;
  4579. _bInOnDraw = TRUE;
  4580. pen = pDoc->m_woWorld.CreateEntity_t(plDrop, fnDropped);
  4581. // prepare the entity
  4582. pen->Initialize();
  4583. _bInOnDraw = FALSE;
  4584. // the drop was successful
  4585. pDoc->SetModifiedFlag();
  4586. // mark that document changeable was changed
  4587. pDoc->m_chDocument.MarkChanged();
  4588. }
  4589. catch(char *err_str)
  4590. {
  4591. _bInOnDraw = FALSE;
  4592. AfxMessageBox(CString(err_str));
  4593. if (pen!=NULL) {
  4594. pen->Destroy();
  4595. }
  4596. // the drop was no successful
  4597. return;
  4598. }
  4599. // deselect all entities
  4600. pDoc->m_selEntitySelection.Clear();
  4601. // if succeseful, switch to entity mode and only-select dropped entity
  4602. pDoc->m_selEntitySelection.Select( *pen);
  4603. // mark that selections have been changed
  4604. pDoc->m_chSelections.MarkChanged();
  4605. // switch to entity mode
  4606. OnEntityMode();
  4607. // and refresh property combo manualy calling on idle
  4608. pMainFrame->m_PropertyComboBar.m_PropertyComboBox.OnIdle( 0);
  4609. if( (pen->GetRenderType() == CEntity::RT_BRUSH) ||
  4610. (pen->GetRenderType() == CEntity::RT_FIELDBRUSH) )
  4611. {
  4612. pMainFrame->m_CSGDesitnationCombo.OnIdle(0);
  4613. pMainFrame->m_CSGDesitnationCombo.SelectBrushEntity(pen);
  4614. }
  4615. pDoc->SetModifiedFlag( TRUE);
  4616. pDoc->m_chDocument.MarkChanged();
  4617. // update all views
  4618. pDoc->UpdateAllViews( this);
  4619. }
  4620. // if the dragged object is a world
  4621. else if (fnDropped.FileExt()==".wld")
  4622. {
  4623. pDoc->StartTemplateCSG( plDrop, fnDropped, FALSE /*don't reset angles*/);
  4624. // the drop was successful
  4625. return;
  4626. }
  4627. else if (fnDropped.FileExt()==".tex")
  4628. {
  4629. // if we hit some entity and hitted entity is brush
  4630. if( (crRayHit.cr_penHit != NULL) &&
  4631. (crRayHit.cr_pbpoBrushPolygon != NULL) )
  4632. {
  4633. // try to apply dropped texture to current selection
  4634. try
  4635. {
  4636. // if polygon that is hit with mouse is selected
  4637. if( crRayHit.cr_pbpoBrushPolygon->IsSelected( BPOF_SELECTED))
  4638. {
  4639. // paste dropped texture over polygon selection
  4640. pDoc->PasteTextureOverSelection_t( fnDropped);
  4641. }
  4642. // otherwise
  4643. else
  4644. {
  4645. // paste it only for drop-hitted polygon
  4646. crRayHit.cr_pbpoBrushPolygon->bpo_abptTextures[pDoc->m_iTexture].bpt_toTexture.SetData_t( fnDropped);
  4647. // mark that document has been modified
  4648. pDoc->SetModifiedFlag( TRUE);
  4649. // mark that selections have been changed to update entity intersection properties
  4650. pDoc->m_chSelections.MarkChanged();
  4651. // update all views
  4652. pDoc->UpdateAllViews( NULL);
  4653. }
  4654. }
  4655. // if failed
  4656. catch( char *err_str)
  4657. {
  4658. // report error
  4659. AfxMessageBox( CString(err_str));
  4660. return;
  4661. }
  4662. }
  4663. else
  4664. {
  4665. // inform user that drop can be achived only over polygons
  4666. AfxMessageBox( L"You can drop textures only by hitting some polygon, but You hit some entity.");
  4667. return;
  4668. }
  4669. }
  4670. else
  4671. {
  4672. // the drop was not successful, report error
  4673. AfxMessageBox( L"You can drop only textures, classes and worlds.");
  4674. return;
  4675. }
  4676. }
  4677. /*
  4678. * Get pointer to the child frame of this view.
  4679. */
  4680. CChildFrame *CWorldEditorView::GetChildFrame(void)
  4681. {
  4682. return (CChildFrame *)GetParentFrame();
  4683. }
  4684. void CWorldEditorView::OnIsometricFront()
  4685. {
  4686. m_ptProjectionType = CSlaveViewer::PT_ISOMETRIC_FRONT;
  4687. Invalidate( FALSE);
  4688. }
  4689. void CWorldEditorView::OnIsometricBack()
  4690. {
  4691. m_ptProjectionType = CSlaveViewer::PT_ISOMETRIC_BACK;
  4692. Invalidate( FALSE);
  4693. }
  4694. void CWorldEditorView::OnIsometricBottom()
  4695. {
  4696. m_ptProjectionType = CSlaveViewer::PT_ISOMETRIC_BOTTOM;
  4697. Invalidate( FALSE);
  4698. }
  4699. void CWorldEditorView::OnIsometricLeft()
  4700. {
  4701. m_ptProjectionType = CSlaveViewer::PT_ISOMETRIC_LEFT;
  4702. Invalidate( FALSE);
  4703. }
  4704. void CWorldEditorView::OnIsometricRight()
  4705. {
  4706. m_ptProjectionType = CSlaveViewer::PT_ISOMETRIC_RIGHT;
  4707. Invalidate( FALSE);
  4708. }
  4709. void CWorldEditorView::OnIsometricTop()
  4710. {
  4711. m_ptProjectionType = CSlaveViewer::PT_ISOMETRIC_TOP;
  4712. Invalidate( FALSE);
  4713. }
  4714. void CWorldEditorView::OnPerspective()
  4715. {
  4716. m_ptProjectionType = CSlaveViewer::PT_PERSPECTIVE;
  4717. Invalidate( FALSE);
  4718. }
  4719. void CWorldEditorView::OnZoomLess()
  4720. {
  4721. // get draw port
  4722. CDrawPort *pdpValidDrawPort = GetDrawPort();
  4723. // if it is not valid
  4724. if( pdpValidDrawPort == NULL)
  4725. {
  4726. return;
  4727. }
  4728. CWorldEditorDoc* pDoc = GetDocument();
  4729. // create a slave viewer
  4730. CSlaveViewer svViewer(GetChildFrame()->m_mvViewer, m_ptProjectionType,
  4731. pDoc->m_plGrid, pdpValidDrawPort);
  4732. // scale target distance by 2 - zoom out x2
  4733. svViewer.ScaleTargetDistance( 2.0f);
  4734. // copy slave viewer back to master
  4735. GetChildFrame()->m_mvViewer = svViewer;
  4736. // redraw all viewes
  4737. pDoc->UpdateAllViews( NULL);
  4738. }
  4739. void CWorldEditorView::OnZoomMore()
  4740. {
  4741. // get draw port
  4742. CDrawPort *pdpValidDrawPort = GetDrawPort();
  4743. // if it is not valid
  4744. if( pdpValidDrawPort == NULL)
  4745. {
  4746. return;
  4747. }
  4748. CWorldEditorDoc* pDoc = GetDocument();
  4749. // create a slave viewer
  4750. CSlaveViewer svViewer(GetChildFrame()->m_mvViewer, m_ptProjectionType,
  4751. pDoc->m_plGrid, pdpValidDrawPort);
  4752. // scale target distance by -1/2 - zoom in x2
  4753. svViewer.ScaleTargetDistance( -0.5f);
  4754. // copy slave viewer back to master
  4755. GetChildFrame()->m_mvViewer = svViewer;
  4756. // redraw all viewes
  4757. pDoc->UpdateAllViews( NULL);
  4758. }
  4759. void CWorldEditorView::RotateOrStretchBrushVertex(FLOAT fDX, FLOAT fDY, BOOL bRotate)
  4760. {
  4761. CWorldEditorDoc* pDoc = GetDocument();
  4762. // project translation vector from view space to absolute space
  4763. CDrawPort *pdpValidDrawPort = GetDrawPort();
  4764. if( pdpValidDrawPort == NULL) return;
  4765. CSlaveViewer svViewer( GetChildFrame()->m_mvViewer, m_ptProjectionType,
  4766. pDoc->m_plGrid, pdpValidDrawPort);
  4767. // both selection and coordinate arrays must be sinchronized
  4768. if( pDoc->m_avStartDragVertices.Count()!=pDoc->m_selVertexSelection.Count()) {
  4769. ASSERT(FALSE);
  4770. return;
  4771. }
  4772. // -------- Calculate BBox of all selected brush vertices
  4773. FLOATaabbox3D boxVtx;
  4774. // for each vertex
  4775. {for( INDEX iVtx=0; iVtx<pDoc->m_avStartDragVertices.Count(); iVtx++)
  4776. {
  4777. // get new position
  4778. boxVtx |= DOUBLEtoFLOAT(pDoc->m_avStartDragVertices[ iVtx]);
  4779. }}
  4780. // create dummy placement
  4781. CPlacement3D plDummy;
  4782. plDummy.pl_PositionVector = boxVtx.Center();
  4783. DOUBLE3D vCenter = FLOATtoDOUBLE(plDummy.pl_PositionVector);
  4784. plDummy.pl_OrientationAngle = ANGLE3D(0.0f, 0.0f, 0.0f);
  4785. // use trackball method for rotation
  4786. if( bRotate)
  4787. {
  4788. svViewer.RotatePlacement_TrackBall( plDummy, -fDX, -fDY, 0);
  4789. }
  4790. // get rotation matrix
  4791. FLOATmatrix3D t3dRotation;
  4792. MakeRotationMatrixFast( t3dRotation, plDummy.pl_OrientationAngle);
  4793. DOUBLEmatrix3D t3ddRotation;
  4794. t3ddRotation = FLOATtoDOUBLE(t3dRotation);
  4795. FLOAT fFactor=1.0f;
  4796. if( !bRotate)
  4797. {
  4798. FLOAT fDiag=boxVtx.Size().Length();
  4799. // fDY is actually current view's zoom factor
  4800. fFactor=(fDiag+fDX/fDY)/fDiag;
  4801. }
  4802. // for each vertex
  4803. INDEX iVtx = 0;
  4804. {FOREACHINDYNAMICCONTAINER( pDoc->m_selVertexSelection, CBrushVertex, itbvx)
  4805. {
  4806. DOUBLE3D vRelative = pDoc->m_avStartDragVertices[ iVtx]-vCenter;
  4807. // rotate vertex around bbox center to get new position
  4808. DOUBLE3D vNew = vRelative*fFactor*t3ddRotation;
  4809. // snap resulting vertex coordinate
  4810. SnapVector(vNew);
  4811. // set its new position
  4812. itbvx->SetAbsolutePosition(vNew+vCenter);
  4813. iVtx++;
  4814. }}
  4815. // update sectors
  4816. pDoc->m_woWorld.UpdateSectorsDuringVertexChange( pDoc->m_selVertexSelection);
  4817. }
  4818. FLOAT3D CWorldEditorView::ProjectVectorToWorldSpace(FLOAT fDX,FLOAT fDY,FLOAT fDZ)
  4819. {
  4820. CWorldEditorDoc* pDoc = GetDocument();
  4821. CPlacement3D plVector0(FLOAT3D(0.0f,0.0f,0.0f), ANGLE3D(0,0,0));
  4822. CPlacement3D plVector1(FLOAT3D(fDX,fDY,fDZ), ANGLE3D(0,0,0));
  4823. CDrawPort *pdp = GetDrawPort();
  4824. if( pdp == NULL)
  4825. {
  4826. ASSERTALWAYS("Invalid draw port found!");
  4827. return FLOAT3D( 0.0f, 0.0f, 0.0f);
  4828. }
  4829. // project translation vector from view space to absolute space
  4830. CSlaveViewer svViewer( GetChildFrame()->m_mvViewer, m_ptProjectionType, pDoc->m_plGrid, pdp);
  4831. CPlacement3D plViewer = svViewer.GetViewerPlacement();
  4832. plVector0.RelativeToAbsolute(plViewer);
  4833. plVector1.RelativeToAbsolute(plViewer);
  4834. // obtain translation vector from placements
  4835. FLOAT3D vDelta = (plVector1.pl_PositionVector-plVector0.pl_PositionVector);
  4836. return vDelta;
  4837. }
  4838. void CWorldEditorView::DragBrushVertex(FLOAT fDX,FLOAT fDY,FLOAT fDZ)
  4839. {
  4840. CWorldEditorDoc* pDoc = GetDocument();
  4841. // obtain 3d translation vector
  4842. DOUBLE3D vDelta = FLOATtoDOUBLE( ProjectVectorToWorldSpace( fDX, fDY, fDZ));
  4843. // both selection and coordinate arrays must be sinchronized
  4844. if( pDoc->m_avStartDragVertices.Count()!=pDoc->m_selVertexSelection.Count()) {
  4845. ASSERT(FALSE);
  4846. return;
  4847. }
  4848. // ---- apply movement
  4849. // for each vertex
  4850. INDEX iVtx = 0;
  4851. {FOREACHINDYNAMICCONTAINER( pDoc->m_selVertexSelection, CBrushVertex, itbvx)
  4852. {
  4853. // get new position
  4854. DOUBLE3D vNew = pDoc->m_avStartDragVertices[ iVtx] + vDelta;
  4855. SnapVector( vNew);
  4856. // set its new position
  4857. itbvx->SetAbsolutePosition(vNew);
  4858. iVtx++;
  4859. }}
  4860. // update sectors
  4861. pDoc->m_woWorld.UpdateSectorsDuringVertexChange( pDoc->m_selVertexSelection);
  4862. }
  4863. void CWorldEditorView::DragVerticesOnPrimitive(FLOAT fDX,FLOAT fDY,FLOAT fDZ, BOOL bAbsolute,
  4864. BOOL bSnap/*=TRUE*/)
  4865. {
  4866. CWorldEditorDoc* pDoc = GetDocument();
  4867. CPlacement3D plVector0(FLOAT3D(0.0f,0.0f,0.0f), ANGLE3D(0,0,0));
  4868. CPlacement3D plVector1(FLOAT3D(fDX,fDY,fDZ), ANGLE3D(0,0,0));
  4869. // project translation vector from view space to absolute space
  4870. CDrawPort *pdpValidDrawPort = GetDrawPort();
  4871. if( pdpValidDrawPort == NULL) return;
  4872. CSlaveViewer svViewer( GetChildFrame()->m_mvViewer, m_ptProjectionType,
  4873. pDoc->m_plGrid, pdpValidDrawPort);
  4874. CPlacement3D plViewer = svViewer.GetViewerPlacement();
  4875. plVector0.RelativeToAbsolute(plViewer);
  4876. plVector1.RelativeToAbsolute(plViewer);
  4877. // project translation vector from absolute space to second layer space
  4878. plVector0.AbsoluteToRelative(pDoc->m_plSecondLayer);
  4879. plVector1.AbsoluteToRelative(pDoc->m_plSecondLayer);
  4880. // extract translation vector from placements
  4881. DOUBLE3D vDelta = FLOATtoDOUBLE(plVector1.pl_PositionVector)-
  4882. FLOATtoDOUBLE(plVector0.pl_PositionVector);
  4883. theApp.m_vfpCurrent.vfp_o3dPrimitive.ob_aoscSectors.Lock();
  4884. CDynamicArray<CObjectVertex> &aVtx = theApp.m_vfpCurrent.vfp_o3dPrimitive.ob_aoscSectors[0].osc_aovxVertices;
  4885. theApp.m_vfpCurrent.vfp_o3dPrimitive.ob_aoscSectors.Unlock();
  4886. aVtx.Lock();
  4887. DOUBLE3D vClosest;
  4888. DOUBLE3D vFirstInSelection;
  4889. BOOL bHasSelection = FALSE;
  4890. // see if any of the vertices is selected
  4891. INDEX iVtx=0;
  4892. for( ; iVtx<aVtx.Count(); iVtx++)
  4893. {
  4894. if( aVtx[ iVtx].ovx_ulFlags & OVXF_CLOSEST) vClosest = aVtx[ iVtx];
  4895. if( (aVtx[ iVtx].ovx_ulFlags & OVXF_SELECTED) && !bHasSelection)
  4896. {
  4897. vFirstInSelection = aVtx[ iVtx];
  4898. bHasSelection = TRUE;
  4899. }
  4900. }
  4901. DOUBLE3D vVectorForAdding;
  4902. // if given delta vector should be applied absolutly
  4903. if( bAbsolute)
  4904. {
  4905. vVectorForAdding = vDelta;
  4906. }
  4907. else
  4908. {
  4909. if( bHasSelection)
  4910. {
  4911. vVectorForAdding = m_vStartDragO3DVertice+vDelta-vFirstInSelection;
  4912. }
  4913. else
  4914. {
  4915. vVectorForAdding = m_vStartDragO3DVertice+vDelta-vClosest;
  4916. }
  4917. }
  4918. // apply movement
  4919. for( iVtx=0; iVtx<aVtx.Count(); iVtx++)
  4920. {
  4921. if( ((aVtx[ iVtx].ovx_ulFlags & OVXF_CLOSEST) && !bHasSelection) ||
  4922. ((aVtx[ iVtx].ovx_ulFlags & OVXF_SELECTED) && bHasSelection) )
  4923. {
  4924. aVtx[ iVtx] += vVectorForAdding;
  4925. if( pDoc->m_bAutoSnap && bSnap)
  4926. {
  4927. // snap resulting vertex coordinate
  4928. Snap(aVtx[iVtx](1), m_fGridInMeters/GRID_DISCRETE_VALUES);
  4929. Snap(aVtx[iVtx](2), m_fGridInMeters/GRID_DISCRETE_VALUES);
  4930. Snap(aVtx[iVtx](3), m_fGridInMeters/GRID_DISCRETE_VALUES);
  4931. }
  4932. else
  4933. {
  4934. Snap(aVtx[iVtx](1), SNAP_DOUBLE_CM);
  4935. Snap(aVtx[iVtx](2), SNAP_DOUBLE_CM);
  4936. Snap(aVtx[iVtx](3), SNAP_DOUBLE_CM);
  4937. }
  4938. }
  4939. }
  4940. aVtx.Unlock();
  4941. pDoc->ConvertObject3DToBrush(theApp.m_vfpCurrent.vfp_o3dPrimitive, TRUE);
  4942. // redraw all viewes
  4943. pDoc->UpdateAllViews( NULL);
  4944. }
  4945. void CWorldEditorView::OnMoveUp()
  4946. {
  4947. CWorldEditorDoc* pDoc = GetDocument();
  4948. if( (pDoc->m_pwoSecondLayer != NULL) &&
  4949. (pDoc->m_bPrimitiveMode) &&
  4950. (theApp.m_vfpCurrent.vfp_ttTriangularisationType != TT_NONE) &&
  4951. ((!theApp.m_vfpCurrent.vfp_bAutoCreateMipBrushes)||
  4952. (theApp.m_vfpCurrent.vfp_ptPrimitiveType != PT_TERRAIN)) )
  4953. {
  4954. MarkClosestVtxOnPrimitive( FALSE);
  4955. DragVerticesOnPrimitive( 0.0, 0.0, m_fGridInMeters/GRID_DISCRETE_VALUES, TRUE, FALSE);
  4956. }
  4957. // redraw all viewes
  4958. pDoc->UpdateAllViews( NULL);
  4959. }
  4960. void CWorldEditorView::OnMoveDown()
  4961. {
  4962. CWorldEditorDoc* pDoc = GetDocument();
  4963. if( (pDoc->m_pwoSecondLayer != NULL) &&
  4964. (pDoc->m_bPrimitiveMode) &&
  4965. (theApp.m_vfpCurrent.vfp_ttTriangularisationType != TT_NONE) &&
  4966. ((!theApp.m_vfpCurrent.vfp_bAutoCreateMipBrushes)||
  4967. (theApp.m_vfpCurrent.vfp_ptPrimitiveType != PT_TERRAIN)) )
  4968. {
  4969. MarkClosestVtxOnPrimitive( FALSE);
  4970. DragVerticesOnPrimitive( 0.0, 0.0, -m_fGridInMeters/GRID_DISCRETE_VALUES, TRUE, FALSE);
  4971. }
  4972. // redraw all viewes
  4973. pDoc->UpdateAllViews( NULL);
  4974. }
  4975. void CWorldEditorView::OnMeasurementTape()
  4976. {
  4977. m_vpViewPrefs.m_bMeasurementTape = !m_vpViewPrefs.m_bMeasurementTape;
  4978. Invalidate( FALSE);
  4979. }
  4980. void CWorldEditorView::OnUpdateMeasurementTape(CCmdUI* pCmdUI)
  4981. {
  4982. if( m_ptProjectionType == CSlaveViewer::PT_PERSPECTIVE)
  4983. {
  4984. pCmdUI->Enable( FALSE);
  4985. pCmdUI->SetCheck( FALSE);
  4986. }
  4987. else
  4988. {
  4989. pCmdUI->Enable( TRUE);
  4990. pCmdUI->SetCheck( m_vpViewPrefs.m_bMeasurementTape);
  4991. }
  4992. }
  4993. void CWorldEditorView::OnKeyBuffer(UINT nID)
  4994. {
  4995. // get difference of key "1", which means buffer index
  4996. INDEX iPreferencesBuffer = nID-ID_BUFFER01;
  4997. // copy selected preferences to view's rendering preferences
  4998. m_vpViewPrefs = theApp.m_vpViewPrefs[ iPreferencesBuffer];
  4999. // see the change
  5000. Invalidate( FALSE);
  5001. }
  5002. void CWorldEditorView::OnKeyEditBuffer(UINT nID)
  5003. {
  5004. // get difference of key "1", which means buffer index
  5005. INDEX iPreferencesBuffer = nID-ID_EDIT_BUFFER01;
  5006. CDlgRenderingPreferences dlg( iPreferencesBuffer);
  5007. // if dialog ended with cancel or esc, dont switch to changed preferences
  5008. if( dlg.DoModal() != IDOK)
  5009. {
  5010. // don't set new preferences
  5011. return;
  5012. }
  5013. // copy selected preferences to view's rendering preferences
  5014. m_vpViewPrefs = theApp.m_vpViewPrefs[ iPreferencesBuffer];
  5015. // see the change
  5016. Invalidate( FALSE);
  5017. }
  5018. void CWorldEditorView::OnCircleModes()
  5019. {
  5020. CWorldEditorDoc* pDoc = GetDocument();
  5021. ASSERT_VALID(pDoc);
  5022. switch( pDoc->GetEditingMode())
  5023. {
  5024. case ENTITY_MODE: { pDoc->SetEditingMode( SECTOR_MODE); break;};
  5025. case SECTOR_MODE: { pDoc->SetEditingMode( POLYGON_MODE); break;};
  5026. case POLYGON_MODE: { pDoc->SetEditingMode( VERTEX_MODE); break;};
  5027. case VERTEX_MODE: { pDoc->SetEditingMode( TERRAIN_MODE); break;};
  5028. case TERRAIN_MODE: { pDoc->SetEditingMode( ENTITY_MODE); break;};
  5029. default: { FatalError("Unknown editing mode."); break;};
  5030. }
  5031. }
  5032. void CWorldEditorView::OnUpdateCircleModes(CCmdUI* pCmdUI)
  5033. {
  5034. CWorldEditorDoc* pDoc = GetDocument();
  5035. ASSERT_VALID(pDoc);
  5036. pCmdUI->Enable( pDoc->GetEditingMode() != CSG_MODE);
  5037. }
  5038. void CWorldEditorView::OnDeselectAll()
  5039. {
  5040. CWorldEditorDoc* pDoc = GetDocument();
  5041. ASSERT_VALID(pDoc);
  5042. pDoc->DeselectAll();
  5043. BOOL bCSGOn = pDoc->m_pwoSecondLayer != NULL;
  5044. // if we are in triangularisation primitive mode
  5045. if( (theApp.m_vfpCurrent.vfp_ttTriangularisationType != TT_NONE) &&
  5046. (bCSGOn && pDoc->m_bPrimitiveMode) )
  5047. {
  5048. theApp.m_vfpCurrent.vfp_o3dPrimitive.ob_aoscSectors.Lock();
  5049. CDynamicArray<CObjectVertex> &aVtx = theApp.m_vfpCurrent.vfp_o3dPrimitive.ob_aoscSectors[0].osc_aovxVertices;
  5050. theApp.m_vfpCurrent.vfp_o3dPrimitive.ob_aoscSectors.Unlock();
  5051. aVtx.Lock();
  5052. // reset selected flags for all vertices
  5053. for( INDEX iVtx=0; iVtx<aVtx.Count(); iVtx++)
  5054. {
  5055. aVtx[ iVtx].ovx_ulFlags &= ~OVXF_SELECTED;
  5056. }
  5057. aVtx.Unlock();
  5058. // update all views
  5059. pDoc->UpdateAllViews(NULL);
  5060. }
  5061. }
  5062. void CWorldEditorView::RemoveFromLinkedChain(CEntity *pen)
  5063. {
  5064. CTFileName fnDropClass;
  5065. CTString strTargetProperty;
  5066. CEntityProperty *penpProperty;
  5067. CEntity &enOnly = *pen;
  5068. // obtain drop class and target property name
  5069. if( !enOnly.DropsMarker( fnDropClass, strTargetProperty)) return;
  5070. penpProperty = enOnly.PropertyForName( strTargetProperty);
  5071. CEntity *penHisTarget = ENTITYPROPERTY( &enOnly, penpProperty->ep_slOffset, CEntityPointer);
  5072. // or ptr is NULL
  5073. if( penHisTarget == NULL) return;
  5074. CEntity *penCurrent = pen;
  5075. INDEX iInfiniteLoopProtector = 0;
  5076. // loop forever
  5077. FOREVER
  5078. {
  5079. if( !penCurrent->DropsMarker( fnDropClass, strTargetProperty)) return;
  5080. penpProperty = penCurrent->PropertyForName( strTargetProperty);
  5081. CEntity *penNext = ENTITYPROPERTY( penCurrent, penpProperty->ep_slOffset, CEntityPointer);
  5082. if( penNext == NULL) return;
  5083. if( penNext == pen) break;
  5084. // jump to next in chain
  5085. penCurrent = penNext;
  5086. iInfiniteLoopProtector ++;
  5087. if( iInfiniteLoopProtector >= 256) return;
  5088. }
  5089. if( !penCurrent->DropsMarker( fnDropClass, strTargetProperty)) return;
  5090. penpProperty = penCurrent->PropertyForName( strTargetProperty);
  5091. ENTITYPROPERTY( penCurrent, penpProperty->ep_slOffset, CEntityPointer) = penHisTarget;
  5092. }
  5093. void CWorldEditorView::OnDeleteEntities()
  5094. {
  5095. CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
  5096. CWorldEditorDoc* pDoc = GetDocument();
  5097. if( pDoc->GetEditingMode() == CSG_MODE) return;
  5098. if( pDoc->GetEditingMode() == SECTOR_MODE)
  5099. {
  5100. if( pDoc->m_selSectorSelection.Count() != 0)
  5101. {
  5102. if( theApp.m_Preferences.ap_bSaveUndoForDelete)
  5103. {
  5104. pDoc->RememberUndo();
  5105. }
  5106. pDoc->ClearSelections( ST_SECTOR);
  5107. pDoc->m_woWorld.DeleteSectors( pDoc->m_selSectorSelection, TRUE);
  5108. }
  5109. }
  5110. else
  5111. {
  5112. // if any of selected entities is anchored, anchored operation flag must be allowed or deleting is disabled
  5113. FOREACHINDYNAMICCONTAINER(pDoc->m_selEntitySelection, CEntity, iten)
  5114. {
  5115. {FOREACHINDYNAMICCONTAINER(pDoc->m_selEntitySelection, CEntity, iten)
  5116. {
  5117. if( (iten->GetFlags() & ENF_ANCHORED) && !GetChildFrame()->m_bAncoredMovingAllowed) return;
  5118. }}
  5119. }
  5120. if( pDoc->m_selEntitySelection.Count() != 0)
  5121. {
  5122. if( theApp.m_Preferences.ap_bSaveUndoForDelete)
  5123. {
  5124. pDoc->RememberUndo();
  5125. }
  5126. }
  5127. // check for deleting terrain
  5128. {FOREACHINDYNAMICCONTAINER(pDoc->m_selEntitySelection, CEntity, iten)
  5129. {
  5130. CEntity &en=*iten;
  5131. // if it is terrain
  5132. if(en.GetRenderType()==CEntity::RT_TERRAIN)
  5133. {
  5134. // if it is selected terrain
  5135. if(pDoc->m_ptrSelectedTerrain==en.GetTerrain())
  5136. {
  5137. pDoc->m_ptrSelectedTerrain=NULL;
  5138. theApp.m_ctTerrainPage.MarkChanged();
  5139. break;
  5140. }
  5141. }
  5142. }}
  5143. // for each of the selected entities
  5144. {FOREACHINDYNAMICCONTAINER(pDoc->m_selEntitySelection, CEntity, iten)
  5145. {
  5146. if( pDoc->m_cenEntitiesSelectedByVolume.IsMember(iten))
  5147. pDoc->m_cenEntitiesSelectedByVolume.Remove(iten);
  5148. }}
  5149. // for each of the selected entities
  5150. {FOREACHINDYNAMICCONTAINER(pDoc->m_selEntitySelection, CEntity, iten)
  5151. {
  5152. RemoveFromLinkedChain(iten);
  5153. }}
  5154. // clear selections
  5155. pDoc->m_selVertexSelection.Clear();
  5156. pDoc->m_selSectorSelection.Clear();
  5157. pDoc->m_selPolygonSelection.Clear();
  5158. // delete all selected entities
  5159. pDoc->m_woWorld.DestroyEntities( pDoc->m_selEntitySelection);
  5160. }
  5161. // mark that document was changed (for saving)
  5162. pDoc->SetModifiedFlag();
  5163. // mark that document changeable was changed to update CSG target combo box
  5164. pDoc->m_chDocument.MarkChanged();
  5165. // mark that selections have been changed to update entity intersection properties
  5166. pDoc->m_chSelections.MarkChanged();
  5167. // update all views
  5168. pDoc->UpdateAllViews(NULL);
  5169. }
  5170. void CWorldEditorView::OnUpdateDeleteEntities(CCmdUI* pCmdUI)
  5171. {
  5172. CWorldEditorDoc* pDoc = GetDocument();
  5173. if( pDoc->GetEditingMode() == ENTITY_MODE)
  5174. {
  5175. pCmdUI->Enable( IsDeleteEntityEnabled());
  5176. }
  5177. else if( pDoc->GetEditingMode() == SECTOR_MODE)
  5178. {
  5179. pCmdUI->Enable( pDoc->m_woWorld.CanCopySectors( pDoc->m_selSectorSelection));
  5180. }
  5181. else
  5182. {
  5183. pCmdUI->Enable( FALSE);
  5184. }
  5185. }
  5186. BOOL CWorldEditorView::IsDeleteEntityEnabled(void)
  5187. {
  5188. CWorldEditorDoc* pDoc = GetDocument();
  5189. // enable button if we are in entity mode and there is at least 1 brush entity unselected
  5190. BOOL bEnable = FALSE;
  5191. if( (pDoc->GetEditingMode() == ENTITY_MODE) &&
  5192. (pDoc->m_selEntitySelection.Count() != 0) )
  5193. {
  5194. // for all of the world's entities
  5195. FOREACHINDYNAMICCONTAINER(pDoc->m_woWorld.wo_cenEntities, CEntity, iten)
  5196. {
  5197. // if the entity is brush
  5198. if (iten->GetRenderType() == CEntity::RT_BRUSH)
  5199. {
  5200. // if this is brush entity and is not selected
  5201. if( !iten->IsSelected( ENF_SELECTED))
  5202. {
  5203. // enable delete entity button
  5204. bEnable = TRUE;
  5205. break;
  5206. }
  5207. }
  5208. }
  5209. }
  5210. return bEnable;
  5211. }
  5212. void CWorldEditorView::UpdateCursor(void)
  5213. {
  5214. BOOL bAlt = (GetKeyState( VK_MENU)&0x8000) != 0;
  5215. BOOL bCtrl = (GetKeyState( VK_CONTROL)&0x8000) != 0;
  5216. CWorldEditorDoc* pDoc = GetDocument();
  5217. CTerrainLayer *ptlLayer=GetLayer();
  5218. if( theApp.m_bMeasureModeOn)
  5219. {
  5220. SetCursor(AfxGetApp()->LoadStandardCursor(IDC_CROSS));
  5221. }
  5222. else if( theApp.m_bCutModeOn)
  5223. {
  5224. if( pDoc->GetEditingMode() == ENTITY_MODE)
  5225. {
  5226. SetCursor( AfxGetApp()->LoadCursor(IDC_MIRROR));
  5227. }
  5228. else
  5229. {
  5230. SetCursor( AfxGetApp()->LoadCursor(IDC_CUT_LINE));
  5231. }
  5232. }
  5233. else if( pDoc->GetEditingMode()==TERRAIN_MODE && GetTerrain()!=NULL && ptlLayer!=NULL)
  5234. {
  5235. if(bCtrl&&bAlt)
  5236. {
  5237. SetCursor( AfxGetApp()->LoadCursor(IDC_TE_PICK));
  5238. }
  5239. else if(theApp.m_iTerrainEditMode==TEM_LAYER && ptlLayer->tl_ltType==LT_TILE)
  5240. {
  5241. SetCursor( AfxGetApp()->LoadCursor(IDC_TE_TILE_PAINTING));
  5242. }
  5243. else if(theApp.m_iTerrainBrushMode==TBM_ERASE)
  5244. {
  5245. SetCursor( AfxGetApp()->LoadCursor(IDC_TE_ERASE));
  5246. }
  5247. else if(theApp.m_iTerrainBrushMode==TBM_SMOOTH)
  5248. {
  5249. SetCursor( AfxGetApp()->LoadCursor(IDC_TE_SMOOTH));
  5250. }
  5251. else if(theApp.m_iTerrainBrushMode==TBM_FILTER)
  5252. {
  5253. SetCursor( AfxGetApp()->LoadCursor(IDC_TE_FILTER));
  5254. }
  5255. else if(theApp.m_iTerrainBrushMode==TBM_MINIMUM)
  5256. {
  5257. SetCursor( AfxGetApp()->LoadCursor(IDC_TE_MIN));
  5258. }
  5259. else if(theApp.m_iTerrainBrushMode==TBM_MAXIMUM)
  5260. {
  5261. SetCursor( AfxGetApp()->LoadCursor(IDC_TE_MAX));
  5262. }
  5263. else if(theApp.m_iTerrainBrushMode==TBM_FLATTEN)
  5264. {
  5265. SetCursor( AfxGetApp()->LoadCursor(IDC_TE_FLATTEN));
  5266. }
  5267. else if(theApp.m_iTerrainBrushMode==TBM_POSTERIZE)
  5268. {
  5269. SetCursor( AfxGetApp()->LoadCursor(IDC_TE_POSTERIZE));
  5270. }
  5271. else if(theApp.m_iTerrainBrushMode==TBM_RND_NOISE)
  5272. {
  5273. SetCursor( AfxGetApp()->LoadCursor(IDC_TE_RND_NOISE));
  5274. }
  5275. else if(theApp.m_iTerrainBrushMode==TBM_CONTINOUS_NOISE)
  5276. {
  5277. SetCursor( AfxGetApp()->LoadCursor(IDC_TE_CONTINOUS_NOISE));
  5278. }
  5279. else if(theApp.m_iTerrainBrushMode==TBM_PAINT)
  5280. {
  5281. if(theApp.m_iTerrainEditMode==TEM_HEIGHTMAP)
  5282. {
  5283. SetCursor( AfxGetApp()->LoadCursor(IDC_TE_HEIGHTMAP));
  5284. }
  5285. else if(theApp.m_iTerrainEditMode==TEM_LAYER)
  5286. {
  5287. SetCursor( AfxGetApp()->LoadCursor(IDC_TE_LAYER_PAINT));
  5288. }
  5289. }
  5290. }
  5291. else
  5292. {
  5293. SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
  5294. }
  5295. }
  5296. BOOL CWorldEditorView::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
  5297. {
  5298. return TRUE;
  5299. }
  5300. void CWorldEditorView::OnTakeSs()
  5301. {
  5302. // get draw port
  5303. CDrawPort *pdpValidDrawPort = GetDrawPort();
  5304. // if it is not valid
  5305. if( pdpValidDrawPort == NULL)
  5306. {
  5307. return;
  5308. }
  5309. CImageInfo iiImageInfo;
  5310. /* First remember current screen-shot in memory. */
  5311. if( pdpValidDrawPort->Lock())
  5312. {
  5313. RenderView( pdpValidDrawPort);
  5314. pdpValidDrawPort->Unlock();
  5315. }
  5316. // grab screen creating image info
  5317. pdpValidDrawPort->GrabScreen( iiImageInfo, 1);
  5318. // ask for save screen shot name
  5319. CTFileName fnDocName = CTString( CStringA(GetDocument()->GetPathName()));
  5320. CTFileName fnScreenShoot = _EngineGUI.FileRequester(
  5321. "Choose file name for screen shoot", FILTER_TGA FILTER_ALL FILTER_END, KEY_NAME_SCREEN_SHOT_DIR,
  5322. "ScreenShots\\", fnDocName.FileName()+"xx"+".tga", NULL, FALSE);
  5323. if( fnScreenShoot == "") return;
  5324. // try to
  5325. try {
  5326. // save screen shot as TGA
  5327. iiImageInfo.SaveTGA_t( fnScreenShoot);
  5328. } // if failed
  5329. catch (char *strError) {
  5330. // report error
  5331. AfxMessageBox(CString(strError));
  5332. }
  5333. }
  5334. void CWorldEditorView::OnEntityMode()
  5335. {
  5336. CWorldEditorDoc* pDoc = GetDocument();
  5337. ASSERT_VALID(pDoc);
  5338. pDoc->SetEditingMode( ENTITY_MODE);
  5339. }
  5340. void CWorldEditorView::OnUpdateEntityMode(CCmdUI* pCmdUI)
  5341. {
  5342. CWorldEditorDoc* pDoc = GetDocument();
  5343. ASSERT_VALID(pDoc);
  5344. pCmdUI->Enable( pDoc->GetEditingMode() != CSG_MODE);
  5345. }
  5346. void CWorldEditorView::OnTerrainMode()
  5347. {
  5348. CWorldEditorDoc* pDoc = GetDocument();
  5349. ASSERT_VALID(pDoc);
  5350. pDoc->SetEditingMode( TERRAIN_MODE);
  5351. }
  5352. void CWorldEditorView::OnUpdateTerrainMode(CCmdUI* pCmdUI)
  5353. {
  5354. CWorldEditorDoc* pDoc = GetDocument();
  5355. ASSERT_VALID(pDoc);
  5356. pCmdUI->Enable( pDoc->GetEditingMode() != CSG_MODE);
  5357. }
  5358. void CWorldEditorView::OnSectorMode()
  5359. {
  5360. CWorldEditorDoc* pDoc = GetDocument();
  5361. ASSERT_VALID(pDoc);
  5362. pDoc->SetEditingMode( SECTOR_MODE);
  5363. }
  5364. void CWorldEditorView::OnUpdateSectorMode(CCmdUI* pCmdUI)
  5365. {
  5366. CWorldEditorDoc* pDoc = GetDocument();
  5367. ASSERT_VALID(pDoc);
  5368. pCmdUI->Enable( pDoc->GetEditingMode() != CSG_MODE);
  5369. }
  5370. void CWorldEditorView::OnPolygonMode()
  5371. {
  5372. CWorldEditorDoc* pDoc = GetDocument();
  5373. ASSERT_VALID(pDoc);
  5374. pDoc->SetEditingMode( POLYGON_MODE);
  5375. }
  5376. void CWorldEditorView::OnUpdatePolygonMode(CCmdUI* pCmdUI)
  5377. {
  5378. CWorldEditorDoc* pDoc = GetDocument();
  5379. ASSERT_VALID(pDoc);
  5380. pCmdUI->Enable( pDoc->GetEditingMode() != CSG_MODE);
  5381. }
  5382. void CWorldEditorView::OnEditCopy()
  5383. {
  5384. EditCopy( FALSE);
  5385. }
  5386. void CWorldEditorView::OnVertexMode()
  5387. {
  5388. CWorldEditorDoc* pDoc = GetDocument();
  5389. ASSERT_VALID(pDoc);
  5390. pDoc->OnCsgCancel();
  5391. }
  5392. void CWorldEditorView::EditCopy( BOOL bAlternative)
  5393. {
  5394. CWorldEditorDoc* pDoc = GetDocument();
  5395. BOOL bCopyWorld = FALSE;
  5396. // if we are in entity mode
  5397. if( pDoc->GetEditingMode() == ENTITY_MODE)
  5398. {
  5399. // if we have some entities selected
  5400. if( pDoc->m_selEntitySelection.Count() != 0)
  5401. {
  5402. if( bAlternative)
  5403. {
  5404. CDynamicContainer<CEntity> selClones;
  5405. CPlacement3D plPaste = GetMouseInWorldPlacement();
  5406. // for all selected entities
  5407. {FOREACHINDYNAMICCONTAINER(pDoc->m_selEntitySelection, CEntity, iten)
  5408. {
  5409. CEntity *pClone = pDoc->m_woWorld.CopyEntityInWorld( *iten, plPaste);
  5410. selClones.Add( pClone);
  5411. }}
  5412. // clear old selection and select clones
  5413. pDoc->m_selEntitySelection.Clear();
  5414. {FOREACHINDYNAMICCONTAINER( selClones, CEntity, itenClone)
  5415. {
  5416. pDoc->m_selEntitySelection.Select( *itenClone);
  5417. }}
  5418. pDoc->m_chSelections.MarkChanged();
  5419. pDoc->SetModifiedFlag();
  5420. pDoc->UpdateAllViews( NULL);
  5421. }
  5422. else
  5423. {
  5424. // calculate bounding boxes of all selected entities
  5425. FLOATaabbox3D boxEntities;
  5426. // for all selected entities
  5427. {FOREACHINDYNAMICCONTAINER(pDoc->m_selEntitySelection, CEntity, iten)
  5428. {
  5429. FLOATaabbox3D boxCurrentEntity;
  5430. iten->GetSize( boxCurrentEntity);
  5431. boxCurrentEntity += iten->GetPlacement().pl_PositionVector;
  5432. boxEntities |= boxCurrentEntity;
  5433. }}
  5434. // average for all vectors of entities
  5435. FLOAT3D vCenter = boxEntities.Center();
  5436. vCenter(2) = boxEntities.Min()(2);
  5437. CPlacement3D plCenter = CPlacement3D( -vCenter, ANGLE3D(0,0,0) );
  5438. FLOAT3D vSize = boxEntities.Size();
  5439. FLOAT fMaxEdge = Max( Max(vSize(1), vSize(2)), vSize(3));
  5440. FLOAT fSnapValue;
  5441. if( theApp.m_bDecadicGrid)
  5442. {
  5443. INDEX iLog = (INDEX) (Log2( fMaxEdge/GRID_DISCRETE_VALUES)/Log2(10.0f));
  5444. fSnapValue = FLOAT(pow(10.0f, iLog));
  5445. }
  5446. else
  5447. {
  5448. INDEX iLog = (INDEX) Log2( fMaxEdge/GRID_DISCRETE_VALUES);
  5449. fSnapValue = FLOAT(pow(2.0f, iLog));
  5450. }
  5451. pDoc->SnapToGrid( plCenter, fSnapValue);
  5452. // create world to receive selected entities
  5453. CWorld woEntityClipboard;
  5454. woEntityClipboard.SetBackgroundColor( C_WHITE);
  5455. woEntityClipboard.SetDescription( "No description");
  5456. theApp.m_ctLastCopyType = CT_ENTITY;
  5457. // copy entities in selection
  5458. CEntitySelection senDummy;
  5459. woEntityClipboard.CopyEntities(pDoc->m_woWorld, pDoc->m_selEntitySelection,
  5460. senDummy, plCenter);
  5461. senDummy.Clear();
  5462. // try to
  5463. try
  5464. {
  5465. // save entity clipboard world
  5466. woEntityClipboard.Save_t(CTString("Temp\\ClipboardEntityWorld.wld"));
  5467. }
  5468. catch( char *strError)
  5469. {
  5470. AfxMessageBox( CString(strError));
  5471. return;
  5472. }
  5473. }
  5474. }
  5475. else
  5476. {
  5477. // we will copy whole world
  5478. bCopyWorld = TRUE;
  5479. }
  5480. }
  5481. // if we are in polygon mode
  5482. else if( pDoc->GetEditingMode() == POLYGON_MODE)
  5483. {
  5484. // obtain point in the world where mouse pointed last time it was moved
  5485. CCastRay crRayHit = GetMouseHitInformation( m_ptMouse, FALSE, FALSE, FALSE);
  5486. // if mouse is over polygon
  5487. if( (crRayHit.cr_penHit != NULL) &&
  5488. (crRayHit.cr_pbpoBrushPolygon != NULL) )
  5489. {
  5490. // remember selected polygon's parameters to application
  5491. theApp.m_pbpoClipboardPolygon->CopyProperties( *crRayHit.cr_pbpoBrushPolygon);
  5492. if( bAlternative)
  5493. {
  5494. theApp.m_ctLastCopyType = CT_POLYGON_PROPERTIES_ALTERNATIVE;
  5495. CopyMapping(crRayHit.cr_pbpoBrushPolygon);
  5496. }
  5497. else
  5498. {
  5499. theApp.m_ctLastCopyType = CT_POLYGON_PROPERTIES;
  5500. }
  5501. }
  5502. else
  5503. {
  5504. // we will copy whole world
  5505. bCopyWorld = TRUE;
  5506. }
  5507. }
  5508. // if we are in sector mode
  5509. else if( pDoc->GetEditingMode() == SECTOR_MODE)
  5510. {
  5511. // if there are no sectors selected
  5512. if( pDoc->m_selSectorSelection.Count() == 0)
  5513. {
  5514. // we will copy whole world
  5515. bCopyWorld = TRUE;
  5516. }
  5517. // copy selected sectors
  5518. else
  5519. {
  5520. if( !pDoc->m_woWorld.CanCopySectors( pDoc->m_selSectorSelection))
  5521. {
  5522. WarningMessage( "Error: Can't copy selected sectors. "
  5523. "All sectors must be in same brush and same mip factor.");
  5524. return;
  5525. }
  5526. // create world to receive selected sectors
  5527. CWorld woClipboard;
  5528. woClipboard.SetBackgroundColor( C_WHITE);
  5529. woClipboard.SetDescription( "No description");
  5530. // now create world base entity
  5531. CEntity *penWorldBase;
  5532. CPlacement3D plWorld = CPlacement3D( FLOAT3D(0.0f,0.0f,0.0f), ANGLE3D(0,0,0));
  5533. // try to
  5534. try
  5535. {
  5536. penWorldBase = woClipboard.CreateEntity_t(plWorld, CTFILENAME("Classes\\WorldBase.ecl"));
  5537. }
  5538. // catch and
  5539. catch( char *err_str)
  5540. {
  5541. // report errors
  5542. WarningMessage( err_str);
  5543. return;
  5544. }
  5545. // prepare the entity
  5546. penWorldBase->Initialize();
  5547. EFirstWorldBase eFirstWorldBase;
  5548. penWorldBase->SendEvent( eFirstWorldBase);
  5549. CEntity::HandleSentEvents();
  5550. pDoc->m_woWorld.CopySectors( pDoc->m_selSectorSelection, penWorldBase, !bAlternative);
  5551. try
  5552. {
  5553. // save world to clipboard
  5554. woClipboard.Save_t(CTString("Temp\\ClipboardSectorWorld.wld"));
  5555. }
  5556. catch( char *strError)
  5557. {
  5558. AfxMessageBox( CString(strError));
  5559. return;
  5560. }
  5561. theApp.m_ctLastCopyType = CT_SECTOR;
  5562. }
  5563. }
  5564. // if we should copy the whole world
  5565. if( bCopyWorld)
  5566. {
  5567. try
  5568. {
  5569. // save world into clipboard file
  5570. pDoc->m_woWorld.Save_t( (CTString)"Temp\\ClipboardWorld.wld");
  5571. }
  5572. catch( char *strError)
  5573. {
  5574. AfxMessageBox( CString(strError));
  5575. }
  5576. theApp.m_ctLastCopyType = CT_WORLD;
  5577. }
  5578. }
  5579. // obtain point in the world where mouse pointed last time it was moved
  5580. CPlacement3D CWorldEditorView::GetMouseInWorldPlacement(void)
  5581. {
  5582. CWorldEditorDoc* pDoc = GetDocument();
  5583. CCastRay crRayHit = GetMouseHitInformation( m_ptMouse);
  5584. // get hitted point
  5585. CPlacement3D plMouse;
  5586. // if any kind of entity was hitted with mouse
  5587. if( crRayHit.cr_penHit != NULL)
  5588. {
  5589. // hitted entity exist
  5590. plMouse.pl_PositionVector = crRayHit.cr_vHit;
  5591. }
  5592. // if none of entities (brushes) was hitted with mouse
  5593. else
  5594. {
  5595. // set position in front of viewer, at the placement of viewing point (target)
  5596. plMouse = GetChildFrame()->m_mvViewer.GetTargetPlacement();
  5597. }
  5598. // reset angles
  5599. plMouse.pl_OrientationAngle = ANGLE3D(0,0,0);
  5600. // snap placement
  5601. pDoc->SnapToGrid( plMouse, m_fGridInMeters/GRID_DISCRETE_VALUES);
  5602. return plMouse;
  5603. }
  5604. void CWorldEditorView::OnEditPaste()
  5605. {
  5606. CWorldEditorDoc* pDoc = GetDocument();
  5607. BOOL bCSGOn = pDoc->m_pwoSecondLayer != NULL;
  5608. // You can't paste anything while CSG is on
  5609. if( bCSGOn)
  5610. {
  5611. return;
  5612. }
  5613. BOOL bHitModels = FALSE;
  5614. if( theApp.m_ctLastCopyType == CT_ENTITY) bHitModels = TRUE;
  5615. CPlacement3D plPaste = GetMouseInWorldPlacement();
  5616. CCastRay crRayHit = GetMouseHitInformation( m_ptMouse, FALSE, bHitModels, FALSE);
  5617. // if last copy operation was with entities
  5618. if( theApp.m_ctLastCopyType == CT_ENTITY)
  5619. {
  5620. // switch to entity mode
  5621. pDoc->SetEditingMode( ENTITY_MODE);
  5622. // create world to receive pasted entities
  5623. CWorld woEntityClipboard;
  5624. // try to
  5625. try
  5626. {
  5627. // load clipboard entity World
  5628. woEntityClipboard.Load_t( (CTString)"Temp\\ClipboardEntityWorld.wld");
  5629. }
  5630. catch( char *err_str)
  5631. {
  5632. AfxMessageBox( CString(err_str));
  5633. return;
  5634. }
  5635. // deselect all entities
  5636. pDoc->m_selEntitySelection.Clear();
  5637. // make container of entities to copy
  5638. CDynamicContainer<CEntity> cenToCopy;
  5639. cenToCopy = woEntityClipboard.wo_cenEntities;
  5640. // remove empty brushes from it
  5641. {FOREACHINDYNAMICCONTAINER(woEntityClipboard.wo_cenEntities, CEntity, iten)
  5642. {
  5643. if( iten->IsEmptyBrush() && (iten->GetFlags()&ENF_ZONING))
  5644. {
  5645. cenToCopy.Remove(iten);
  5646. }
  5647. }}
  5648. // copy entities in clipboard
  5649. pDoc->m_woWorld.CopyEntities(woEntityClipboard, cenToCopy,
  5650. pDoc->m_selEntitySelection, plPaste);
  5651. pDoc->m_chSelections.MarkChanged();
  5652. pDoc->SetModifiedFlag();
  5653. pDoc->UpdateAllViews( NULL);
  5654. }
  5655. // if last copy operation was with polygon properties
  5656. else if( theApp.m_ctLastCopyType == CT_POLYGON_PROPERTIES)
  5657. {
  5658. // if mouse is over polygon
  5659. if( (crRayHit.cr_penHit != NULL) &&
  5660. (crRayHit.cr_pbpoBrushPolygon != NULL) )
  5661. {
  5662. if( crRayHit.cr_pbpoBrushPolygon->IsSelected( BPOF_SELECTED))
  5663. {
  5664. FOREACHINDYNAMICCONTAINER(pDoc->m_selPolygonSelection, CBrushPolygon, itbpo)
  5665. {
  5666. // apply remembered polygon's parameters to selection
  5667. itbpo->CopyTextures( *theApp.m_pbpoClipboardPolygon);
  5668. }
  5669. }
  5670. else
  5671. {
  5672. // apply remembered polygon's parameters to polygon under mouse
  5673. crRayHit.cr_pbpoBrushPolygon->CopyTextures( *theApp.m_pbpoClipboardPolygon);
  5674. }
  5675. }
  5676. pDoc->m_chSelections.MarkChanged();
  5677. pDoc->SetModifiedFlag();
  5678. pDoc->UpdateAllViews( NULL);
  5679. }
  5680. // if last copy operation was with whole world
  5681. else if( theApp.m_ctLastCopyType == CT_WORLD)
  5682. {
  5683. // load world from clipboard file and start template CSG
  5684. pDoc->StartTemplateCSG( plPaste, (CTString)"Temp\\ClipboardWorld.wld");
  5685. }
  5686. // if last copy operation was with selected sectors
  5687. else if( theApp.m_ctLastCopyType == CT_SECTOR)
  5688. {
  5689. // load world from sectors clipboard file and start template CSG
  5690. pDoc->StartTemplateCSG( plPaste, (CTString)"Temp\\ClipboardSectorWorld.wld");
  5691. }
  5692. }
  5693. void ProcesWEDConsoleShortcuts( MSG *pMsg)
  5694. {
  5695. if( pMsg->message==WM_KEYDOWN)
  5696. {
  5697. BOOL bShift = (GetKeyState( VK_SHIFT)&0x8000) != 0;
  5698. if( !bShift && pMsg->wParam == VK_F2) _pShell->Execute( "include \"Scripts\\WorldEditorKeys\\F2.ini\"");
  5699. if( !bShift && pMsg->wParam == VK_F3) _pShell->Execute( "include \"Scripts\\WorldEditorKeys\\F3.ini\"");
  5700. if( !bShift && pMsg->wParam == VK_F4) _pShell->Execute( "include \"Scripts\\WorldEditorKeys\\F4.ini\"");
  5701. if( bShift && (pMsg->wParam == VK_F2)) _pShell->Execute( "include \"Scripts\\WorldEditorKeys\\Shift_F2.ini\"");
  5702. if( bShift && (pMsg->wParam == VK_F3)) _pShell->Execute( "include \"Scripts\\WorldEditorKeys\\Shift_F3.ini\"");
  5703. if( bShift && (pMsg->wParam == VK_F4)) _pShell->Execute( "include \"Scripts\\WorldEditorKeys\\Shift_F4.ini\"");
  5704. }
  5705. if( pMsg->message==WM_MBUTTONDOWN || pMsg->message==WM_MBUTTONDBLCLK )
  5706. {
  5707. _pShell->Execute( "include \"Scripts\\WorldEditorKeys\\MiddleMouse.ini\"");
  5708. }
  5709. }
  5710. BOOL CWorldEditorView::PreTranslateMessage(MSG* pMsg)
  5711. {
  5712. CWorldEditorDoc* pDoc = GetDocument();
  5713. CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
  5714. // get csg and primitive flags
  5715. BOOL bCSGOn = pDoc->m_pwoSecondLayer != NULL;
  5716. BOOL bPrimitive = pDoc->m_bPrimitiveMode;
  5717. // get editting mode flags
  5718. BOOL bEntityMode = pDoc->GetEditingMode() == ENTITY_MODE;
  5719. BOOL bSectorMode = pDoc->GetEditingMode() == SECTOR_MODE;
  5720. BOOL bPolygonMode = pDoc->GetEditingMode() == POLYGON_MODE;
  5721. BOOL bTerrainMode = pDoc->GetEditingMode() == TERRAIN_MODE;
  5722. // get key statuses
  5723. BOOL bShift = (GetKeyState( VK_SHIFT)&0x8000) != 0;
  5724. BOOL bAlt = (GetKeyState( VK_MENU)&0x8000) != 0;
  5725. BOOL bCtrl = (GetKeyState( VK_CONTROL)&0x8000) != 0;
  5726. BOOL bSpace = (GetKeyState( VK_SPACE)&0x8000) != 0;
  5727. // get mouse button statuses
  5728. BOOL bLMB = (GetKeyState( VK_LBUTTON)&0x8000) != 0;
  5729. BOOL bRMB = (GetKeyState( VK_RBUTTON)&0x8000) != 0;
  5730. // process scripts that are invoked on shortcuts from within WED
  5731. ProcesWEDConsoleShortcuts( pMsg);
  5732. // Ctrl +'A':
  5733. // - entity -> select all in volume
  5734. // - sector -> select all entities
  5735. // - polygon -> select all polygons in sector(s)
  5736. // Alt+'A'
  5737. // - sector -> show all sectors
  5738. // - entity -> show all entities
  5739. // - polygon-> auto fit mapping
  5740. // - vertex-> auto fit mapping
  5741. // 'A':
  5742. // - select by volume -> allign volume
  5743. // - entity -> allign entity selection or world
  5744. // - primitive -> allign primitive to screen
  5745. // - sector -> allign visible sectors to screen
  5746. if( ((pMsg->message==WM_KEYDOWN) || (pMsg->message==WM_SYSKEYDOWN)) &&
  5747. ((int)pMsg->wParam=='A') )
  5748. {
  5749. // setup mouse - ray hit information
  5750. CCastRay crRayHit = GetMouseHitInformation( m_ptMouse);
  5751. m_penEntityHitOnContext = crRayHit.cr_penHit;
  5752. if( (crRayHit.cr_penHit != NULL) && (crRayHit.cr_pbpoBrushPolygon != NULL) )
  5753. {
  5754. m_pbpoRightClickedPolygon = crRayHit.cr_pbpoBrushPolygon;
  5755. }
  5756. if( bCSGOn && !bShift)
  5757. {
  5758. if( bCtrl && bPrimitive)
  5759. {
  5760. OnAlignPrimitive();
  5761. }
  5762. else
  5763. {
  5764. FLOATaabbox3D boxSecondLayer;
  5765. FOREACHINDYNAMICCONTAINER(pDoc->m_pwoSecondLayer->wo_cenEntities, CEntity, iten)
  5766. {
  5767. FLOATaabbox3D box;
  5768. iten->GetSize( box);
  5769. FLOAT fMinX = box.Min()(1);
  5770. FLOAT fMinY = box.Min()(2);
  5771. FLOAT fMinZ = box.Min()(3);
  5772. FLOAT fMaxX = box.Max()(1);
  5773. FLOAT fMaxY = box.Max()(2);
  5774. FLOAT fMaxZ = box.Max()(3);
  5775. FLOAT3D avCorners[8];
  5776. avCorners[0] = FLOAT3D(fMinX,fMinY,fMinZ);
  5777. avCorners[1] = FLOAT3D(fMaxX,fMinY,fMinZ);
  5778. avCorners[2] = FLOAT3D(fMaxX,fMinY,fMaxZ);
  5779. avCorners[3] = FLOAT3D(fMinX,fMinY,fMaxZ);
  5780. avCorners[4] = FLOAT3D(fMinX,fMaxY,fMinZ);
  5781. avCorners[5] = FLOAT3D(fMaxX,fMaxY,fMinZ);
  5782. avCorners[6] = FLOAT3D(fMaxX,fMaxY,fMaxZ);
  5783. avCorners[7] = FLOAT3D(fMinX,fMaxY,fMaxZ);
  5784. for( INDEX iVtx=0; iVtx<8; iVtx++)
  5785. {
  5786. CPlacement3D plToProject = CPlacement3D( avCorners[iVtx], ANGLE3D(0,0,0));
  5787. plToProject.RelativeToAbsolute( pDoc->m_plSecondLayer);
  5788. boxSecondLayer |= FLOATaabbox3D(plToProject.pl_PositionVector);
  5789. }
  5790. }
  5791. AllignBox( boxSecondLayer);
  5792. }
  5793. }
  5794. else if( pDoc->GetEditingMode() == ENTITY_MODE && !bShift)
  5795. {
  5796. if( bCtrl && bAlt)
  5797. {
  5798. OnSelectAllSectors();
  5799. }
  5800. else if( bCtrl)
  5801. {
  5802. pDoc->OnSelectAllInVolume();
  5803. }
  5804. else if( bAlt)
  5805. {
  5806. pDoc->OnShowAllEntities();
  5807. }
  5808. else if( pDoc->m_bBrowseEntitiesMode)
  5809. {
  5810. OnAlignVolume();
  5811. }
  5812. else
  5813. {
  5814. CenterSelected();
  5815. }
  5816. }
  5817. else if(pDoc->GetEditingMode() == SECTOR_MODE && !bShift)
  5818. {
  5819. if( bCtrl && bAlt)
  5820. {
  5821. OnSelectAllPolygons();
  5822. }
  5823. else if( bCtrl)
  5824. {
  5825. OnSelectAllEntitiesInSectors();
  5826. }
  5827. else if( bAlt)
  5828. {
  5829. pDoc->OnShowAllSectors();
  5830. }
  5831. else
  5832. {
  5833. CenterSelected();
  5834. }
  5835. }
  5836. else if( pDoc->GetEditingMode() == POLYGON_MODE)
  5837. {
  5838. if( bCtrl && bAlt && !bShift)
  5839. {
  5840. OnSelectAllVertices();
  5841. }
  5842. else if( bCtrl && !bShift && !bAlt)
  5843. {
  5844. if( (crRayHit.cr_penHit != NULL) && (crRayHit.cr_pbpoBrushPolygon != NULL) )
  5845. {
  5846. // select all polygons in hitted sector
  5847. CBrushSector *pbscSector = crRayHit.cr_pbpoBrushPolygon->bpo_pbscSector;
  5848. FOREACHINSTATICARRAY(pbscSector->bsc_abpoPolygons, CBrushPolygon, itpo)
  5849. {
  5850. if( !itpo->IsSelected(BPOF_SELECTED)) pDoc->m_selPolygonSelection.Select( *itpo);
  5851. }
  5852. pDoc->m_chSelections.MarkChanged();
  5853. }
  5854. }
  5855. else if( bAlt && bShift && bCtrl)
  5856. {
  5857. if( crRayHit.cr_penHit != NULL)
  5858. {
  5859. AutoFitMapping( crRayHit.cr_pbpoBrushPolygon, TRUE, TRUE);
  5860. }
  5861. }
  5862. else if( bAlt && bShift)
  5863. {
  5864. if( crRayHit.cr_penHit != NULL)
  5865. {
  5866. AutoFitMapping( crRayHit.cr_pbpoBrushPolygon, TRUE);
  5867. }
  5868. }
  5869. else if( bAlt)
  5870. {
  5871. if( crRayHit.cr_penHit != NULL)
  5872. {
  5873. AutoFitMapping( crRayHit.cr_pbpoBrushPolygon);
  5874. }
  5875. }
  5876. else if(!bCtrl&&!bShift&&!bAlt)
  5877. {
  5878. CenterSelected();
  5879. }
  5880. }
  5881. else if( pDoc->GetEditingMode() == TERRAIN_MODE)
  5882. {
  5883. if(!bCtrl&&!bShift&&!bAlt)
  5884. {
  5885. CenterSelected();
  5886. }
  5887. }
  5888. else if(pDoc->GetEditingMode() == VERTEX_MODE && !bShift)
  5889. {
  5890. if( bCtrl && bAlt)
  5891. {
  5892. if( (crRayHit.cr_penHit != NULL) && (crRayHit.cr_pbpoBrushPolygon != NULL) )
  5893. {
  5894. // select all vertices on hitted polygon
  5895. FOREACHINSTATICARRAY(crRayHit.cr_pbpoBrushPolygon->bpo_apbvxTriangleVertices, CBrushVertex *, itpbvx)
  5896. {
  5897. if( !(*itpbvx)->IsSelected(BVXF_SELECTED)) pDoc->m_selVertexSelection.Select( **itpbvx);
  5898. }
  5899. }
  5900. pDoc->m_chSelections.MarkChanged();
  5901. }
  5902. else if( bCtrl||bAlt)
  5903. {
  5904. CDlgAllignVertices dlg;
  5905. dlg.DoModal();
  5906. return TRUE;
  5907. }
  5908. else
  5909. {
  5910. CenterSelected();
  5911. }
  5912. }
  5913. }
  5914. // if return is pressed in primitive CSG mode
  5915. if( (pMsg->message==WM_KEYDOWN) && ((int)pMsg->wParam==VK_RETURN) && bCSGOn && bPrimitive)
  5916. {
  5917. pMainFrame->ShowInfoWindow();
  5918. CInfoSheet *pSheet = pMainFrame->m_pInfoFrame->m_pInfoSheet;
  5919. CWnd *pwndWidthEditCtrl = pSheet->m_PgPrimitive.GetDlgItem( IDC_WIDTH);
  5920. if( pwndWidthEditCtrl != NULL)
  5921. {
  5922. pSheet->SetActivePage( &pSheet->m_PgPrimitive);
  5923. pwndWidthEditCtrl->SetFocus();
  5924. }
  5925. }
  5926. FLOAT tmNow = _pTimer->GetHighPrecisionTimer().GetSeconds();
  5927. // if we caught key or button down message and not status line info pause requested
  5928. if( (theApp.m_tmStartStatusLineInfo<tmNow) &&
  5929. ( (pMsg->message==WM_SYSKEYDOWN) ||
  5930. (pMsg->message==WM_KEYDOWN) ||
  5931. (pMsg->message==WM_KEYUP) ||
  5932. (pMsg->message==WM_LBUTTONDOWN) ||
  5933. (pMsg->message==WM_RBUTTONDOWN) ||
  5934. (pMsg->message==WM_LBUTTONUP) ||
  5935. (pMsg->message==WM_RBUTTONUP) ||
  5936. (pMsg->message==WM_MOUSEMOVE) ||
  5937. (pMsg->message==WM_CHANGE_EDITING_MODE) ||
  5938. (bShift || bAlt || bCtrl || bSpace || bLMB || bRMB)) )
  5939. {
  5940. // space without mouse buttons but ctrl pressed
  5941. if( bSpace && !bLMB && !bRMB && bCtrl)
  5942. {
  5943. STATUS_LINE_MESASGE( L"LMB zoomes in 2x, RMB zoomes out 2x");
  5944. }
  5945. // space without mouse buttons
  5946. else if( bSpace && !bLMB && !bRMB && !bShift)
  5947. {
  5948. STATUS_LINE_MESASGE( L"Rotate or move viewer. Try: LMB,RMB,LMB+RMB,Space+Ctrl");
  5949. }
  5950. // space with left mouse button
  5951. else if( bSpace && bLMB && !bRMB)
  5952. {
  5953. STATUS_LINE_MESASGE( L"Move viewer in view plane");
  5954. }
  5955. // space with right mouse button
  5956. else if( bSpace && !bLMB && bRMB)
  5957. {
  5958. STATUS_LINE_MESASGE( L"Move viewer in floor plane");
  5959. }
  5960. // space with both mouse buttons
  5961. else if( bSpace && bLMB && bRMB)
  5962. {
  5963. STATUS_LINE_MESASGE( L"Rotate viewer");
  5964. }
  5965. // Alt pressed
  5966. else if( bAlt && !bCtrl && !bShift)
  5967. {
  5968. STATUS_LINE_MESASGE( L"You can drag any view and drop it into browser");
  5969. }
  5970. // for measure mode
  5971. else if( theApp.m_bMeasureModeOn)
  5972. {
  5973. STATUS_LINE_MESASGE( L"Use LMB to measure distances");
  5974. }
  5975. // for cut mode
  5976. else if( theApp.m_bCutModeOn)
  5977. {
  5978. STATUS_LINE_MESASGE( L"Use LMB to move cut/mirror line, enter to apply");
  5979. }
  5980. // for CSG mode
  5981. else if( bCSGOn)
  5982. {
  5983. // for primitive mode
  5984. if( bPrimitive)
  5985. {
  5986. // primitive mode, only <Ctrl> pressed
  5987. if( bCtrl && !bLMB && !bRMB && !bShift)
  5988. {
  5989. STATUS_LINE_MESASGE( L"Use LMBx2 to teleport primitive. Try: LMB,RMB,LMB+RMB,Shift");
  5990. }
  5991. //-------- <Ctrl+Shift> commands for primitive
  5992. // primitive mode, <Ctrl+Shift> pressed
  5993. else if( bCtrl && !bLMB && !bRMB && bShift)
  5994. {
  5995. STATUS_LINE_MESASGE( L"Size and shear primitive. Try: LMB,RMB");
  5996. }
  5997. // primitive mode, <Ctrl+Shift+LMB> pressed
  5998. else if( bCtrl && bLMB && !bRMB && bShift)
  5999. {
  6000. STATUS_LINE_MESASGE( L"Resize primitive");
  6001. }
  6002. // primitive mode, <Ctrl+Shift+RMB> pressed
  6003. else if( bCtrl && !bLMB && bRMB && bShift)
  6004. {
  6005. STATUS_LINE_MESASGE( L"Shear primitive");
  6006. }
  6007. // primitive mode, <Ctrl+LMB> pressed
  6008. else if( bCtrl && bLMB && !bRMB && !bShift)
  6009. {
  6010. STATUS_LINE_MESASGE( L"Move primitive in view plane");
  6011. }
  6012. // primitive mode, <Ctrl+RMB> pressed
  6013. else if( bCtrl && !bLMB && bRMB && !bShift)
  6014. {
  6015. STATUS_LINE_MESASGE( L"Move primitive in floor plane");
  6016. }
  6017. // primitive mode, <Ctrl+LMB+RMB> pressed
  6018. else if( bCtrl && bLMB && bRMB && !bShift)
  6019. {
  6020. STATUS_LINE_MESASGE( L"Rotate primitive in view plane");
  6021. }
  6022. // <Shift> pressed
  6023. else if( !bCtrl && !bLMB && !bRMB && bShift)
  6024. {
  6025. STATUS_LINE_MESASGE( L"LMB inserts vertex, RMB deletes vertex. Try: Ctrl");
  6026. }
  6027. // primitive mode, nothing pressed
  6028. else
  6029. {
  6030. STATUS_LINE_MESASGE( L"Primitive mode. Try: Alt,Ctrl,Shift");
  6031. }
  6032. }
  6033. // for template mode
  6034. else
  6035. {
  6036. //-------- <Ctrl> commands for template (moving and rotating)
  6037. // template mode, only <Ctrl> pressed
  6038. if( bCtrl && !bLMB && !bRMB && !bShift)
  6039. {
  6040. STATUS_LINE_MESASGE( L"Use LMB dbl. click to teleport template. Try: LMB,RMB,LMB+RMB");
  6041. }
  6042. // template mode, <Ctrl+LMB> pressed
  6043. else if( bCtrl && bLMB && !bRMB && !bShift)
  6044. {
  6045. STATUS_LINE_MESASGE( L"Move template in view plane");
  6046. }
  6047. // template mode, <Ctrl+RMB> pressed
  6048. else if( bCtrl && !bLMB && bRMB && !bShift)
  6049. {
  6050. STATUS_LINE_MESASGE( L"Move template in floor plane");
  6051. }
  6052. // template mode, <Ctrl+LMB+RMB> pressed
  6053. else if( bCtrl && bLMB && bRMB && !bShift)
  6054. {
  6055. STATUS_LINE_MESASGE( L"Rotate template");
  6056. }
  6057. // template mode, nothing pressed
  6058. else
  6059. {
  6060. STATUS_LINE_MESASGE( L"Template primitive mode. Try: Ctrl");
  6061. }
  6062. }
  6063. }
  6064. // for entity mode
  6065. else if( bEntityMode)
  6066. {
  6067. // get property ID
  6068. CPropertyID *ppidProperty = pMainFrame->m_PropertyComboBar.GetSelectedProperty();
  6069. // if we have at least one entity selected and edititng property of edit range type
  6070. // and Ctrl+Shift pressed
  6071. BOOL bEditingProperties = ( (pDoc->m_selEntitySelection.Count() != 0) &&
  6072. ( (ppidProperty != NULL) &&
  6073. ( (ppidProperty->pid_eptType == CEntityProperty::EPT_ANGLE3D) ||
  6074. (ppidProperty->pid_eptType == CEntityProperty::EPT_RANGE))) );
  6075. // entity mode, <Ctrl+Shift> pressed
  6076. if( bEditingProperties && bCtrl && bShift )
  6077. {
  6078. STATUS_LINE_MESASGE( L"Use LMB to change range or direction");
  6079. }
  6080. // <Alt + Ctrl> pressed
  6081. else if( bAlt && bCtrl)
  6082. {
  6083. STATUS_LINE_MESASGE( L"Use LMB to set entity ptr. (Entity ptr property must be selected)");
  6084. }
  6085. else if( bCtrl && bShift)
  6086. {
  6087. STATUS_LINE_MESASGE( L"Use RMB to set mip switch distance (in auto mode)");
  6088. }
  6089. else if( bSpace && bShift)
  6090. {
  6091. STATUS_LINE_MESASGE( L"Use RMB to change virtual mip distance");
  6092. }
  6093. // entity mode, <Shift> pressed
  6094. else if( !bCtrl && bShift)
  6095. {
  6096. STATUS_LINE_MESASGE( L"Use LMB to toggle selection of one entity . Try: Ctrl,Space");
  6097. }
  6098. // entity mode, <Ctrl> pressed
  6099. else if( bCtrl && !bLMB && !bRMB && !bShift)
  6100. {
  6101. if( bEditingProperties)
  6102. {
  6103. STATUS_LINE_MESASGE( L"Use LMBx2 click to teleport entity. Try: LMB,RMB,LMB+RMB,Shift");
  6104. }
  6105. else
  6106. {
  6107. STATUS_LINE_MESASGE( L"Use LMBx2 click to teleport entity. Try: Alt,LMB,RMB,LMB+RMB");
  6108. }
  6109. }
  6110. // entity mode, <Ctrl+LMB> pressed
  6111. else if( bCtrl && bLMB && !bRMB && !bShift)
  6112. {
  6113. STATUS_LINE_MESASGE( L"Move entities in view plane");
  6114. }
  6115. // entity mode, <Ctrl+RMB> pressed
  6116. else if( bCtrl && !bLMB && bRMB && !bShift)
  6117. {
  6118. STATUS_LINE_MESASGE( L"Move entities in floor plane");
  6119. }
  6120. // entity mode, <Ctrl+LMB+RMB> pressed
  6121. else if( bCtrl && bLMB && bRMB && !bShift)
  6122. {
  6123. STATUS_LINE_MESASGE( L"Rotate entities");
  6124. }
  6125. // entity mode, nothing pressed
  6126. else
  6127. {
  6128. if( bEditingProperties)
  6129. {
  6130. STATUS_LINE_MESASGE( L"Use LMB to select entities. Try: Ctrl,Shift");
  6131. }
  6132. else
  6133. {
  6134. STATUS_LINE_MESASGE( L"Use LMB to select entities. Try: Ctrl,Shift,Ctrl+Alt");
  6135. }
  6136. }
  6137. }
  6138. // for polygon mode
  6139. else if( bPolygonMode)
  6140. {
  6141. // polygon mode, <Ctrl> pressed
  6142. if( bCtrl && !bLMB && !bRMB && !bShift && !bAlt)
  6143. {
  6144. STATUS_LINE_MESASGE( L"LMBx2 centers texture. RMBx2 selects similar by texture. Try: LMB,LMB+RMB");
  6145. }
  6146. // polygon mode, <Shift> pressed
  6147. else if( !bCtrl && !bLMB && !bRMB && bShift && !bAlt)
  6148. {
  6149. STATUS_LINE_MESASGE( L"Toggle polygon using LMB or RMB. Add simillar with LMB dbl. click");
  6150. }
  6151. // polygon mode, <Ctrl+LMB> pressed
  6152. else if( bCtrl && bLMB && !bRMB && !bShift && !bAlt)
  6153. {
  6154. STATUS_LINE_MESASGE( L"Scroll polygon's mapping texture");
  6155. }
  6156. // polygon mode, <Ctrl+LMB+RMB> pressed
  6157. else if( bCtrl && bLMB && bRMB && !bShift && !bAlt)
  6158. {
  6159. STATUS_LINE_MESASGE( L"Rotate polygon's mapping texture");
  6160. }
  6161. else if( bCtrl && bAlt)
  6162. {
  6163. STATUS_LINE_MESASGE( L"Zoom in texture 2x using LMB, zoom out texture 2x using RMB");
  6164. }
  6165. // polygon mode, <Ctrl+Shift> pressed
  6166. else if( bCtrl && bShift)
  6167. {
  6168. STATUS_LINE_MESASGE( L"Select polygons similar by texture in sector with LMBx2, similar by color with RMBx2");
  6169. }
  6170. // polygon mode, nothing pressed
  6171. else if( !bCtrl && !bLMB && !bRMB && !bShift && !bAlt)
  6172. {
  6173. STATUS_LINE_MESASGE( L"Select polygons using LMB or RMB, by color using LMBx2. Try: Alt,Ctrl,Shift,Ctrl+Alt");
  6174. }
  6175. }
  6176. // for sector mode
  6177. else
  6178. {
  6179. // sector mode, <Shift> pressed
  6180. if( !bCtrl && !bLMB && !bRMB && bShift)
  6181. {
  6182. STATUS_LINE_MESASGE( L"Add to selection or deselect sector using LMB or LMB dbl. click");
  6183. }
  6184. // sector mode, nothing pressed
  6185. else
  6186. {
  6187. STATUS_LINE_MESASGE( L"Select or deselect sector using LMB or LMB dbl. click. Try: Alt,Shift");
  6188. }
  6189. }
  6190. // for these events
  6191. if( (pMsg->message==WM_KEYDOWN) ||
  6192. (pMsg->message==WM_KEYUP) ||
  6193. (pMsg->message==WM_LBUTTONDOWN) ||
  6194. (pMsg->message==WM_RBUTTONDOWN) ||
  6195. (pMsg->message==WM_LBUTTONUP) ||
  6196. (pMsg->message==WM_RBUTTONUP) )
  6197. {
  6198. // set text describing data that is edited
  6199. SetEditingDataPaneInfo( TRUE);
  6200. }
  6201. }
  6202. return CView::PreTranslateMessage(pMsg);
  6203. }
  6204. void CWorldEditorView::OnKeyO()
  6205. {
  6206. CWorldEditorDoc* pDoc = GetDocument();
  6207. if( pDoc->GetEditingMode()==TERRAIN_MODE)
  6208. {
  6209. theApp.m_iTerrainBrushMode=TBM_SMOOTH;
  6210. theApp.m_ctTerrainPageCanvas.MarkChanged();
  6211. pDoc->SetStatusLineModeInfoMessage();
  6212. }
  6213. else
  6214. {
  6215. OnCloneCSG();
  6216. }
  6217. }
  6218. void CWorldEditorView::OnUpdateKeyO(CCmdUI* pCmdUI)
  6219. {
  6220. CWorldEditorDoc* pDoc = GetDocument();
  6221. if( pDoc->GetEditingMode()==TERRAIN_MODE)
  6222. {
  6223. pCmdUI->Enable( TRUE);
  6224. }
  6225. else
  6226. {
  6227. OnUpdateCloneCsg(pCmdUI);
  6228. }
  6229. }
  6230. void CWorldEditorView::OnCloneCSG()
  6231. {
  6232. CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
  6233. CWorldEditorDoc* pDoc = GetDocument();
  6234. CDlgProgress dlgProgressDialog( pMainFrame);
  6235. // disable CSG report
  6236. theApp.m_bCSGReportEnabled = FALSE;
  6237. // and clear its values
  6238. _pfWorldEditingProfile.Reset();
  6239. // remember automatic info flag
  6240. BOOL bAutomaticInfo = theApp.m_Preferences.ap_AutomaticInfo;
  6241. // get shift pressed flag
  6242. BOOL bAlt = (GetKeyState( VK_MENU)&0x8000) != 0;
  6243. // we will have 1 clone (by default)
  6244. INDEX ctClones = 1;
  6245. // if shift is pressed, we want "array of clones" (numeric option)
  6246. if( bAlt)
  6247. {
  6248. CDlgAutoDeltaCSG dlgAutoDeltaCSG;
  6249. // if dialog wasn't succeseful
  6250. if( dlgAutoDeltaCSG.DoModal() != IDOK)
  6251. {
  6252. return;
  6253. }
  6254. // temporary disable automatic info
  6255. theApp.m_Preferences.ap_AutomaticInfo = FALSE;
  6256. // get wanted count of clones
  6257. ctClones = dlgAutoDeltaCSG.m_ctNumberOfClones;
  6258. // write it to .ini file for the next time
  6259. theApp.WriteProfileInt(L"World editor", L"Number of CSG clones", ctClones);
  6260. }
  6261. // set wait cursor
  6262. CWaitCursor StartWaitCursor;
  6263. // if there is more than 1 clone in progress
  6264. if( ctClones > 1)
  6265. {
  6266. // create progress dialog
  6267. dlgProgressDialog.Create( IDD_PROGRESS_DIALOG);
  6268. dlgProgressDialog.SetWindowText(L"Repeat CSG");
  6269. // show progress window
  6270. dlgProgressDialog.ShowWindow( SW_SHOW);
  6271. // center window
  6272. dlgProgressDialog.CenterWindow();
  6273. // set progress range
  6274. dlgProgressDialog.m_ctrlProgres.SetRange( 0, (short) ctClones);
  6275. }
  6276. // if primitive CSG was last used CSG operation
  6277. if( pDoc->m_bLastUsedPrimitiveMode)
  6278. {
  6279. // for all clones
  6280. for( INDEX iClone=0; iClone<ctClones; iClone++)
  6281. {
  6282. // if there is more than 1 clone in progress
  6283. if( ctClones > 1)
  6284. {
  6285. char achrProgressMessage[ 256];
  6286. sprintf( achrProgressMessage, "Cloning CSG operation ... (processing %d/%d)",
  6287. iClone+1, ctClones);
  6288. // set message and progress position
  6289. dlgProgressDialog.SetProgressMessageAndPosition( achrProgressMessage, iClone+1);
  6290. }
  6291. // create new placement from delta placement
  6292. CPlacement3D plNewPlacement = pDoc->m_plDeltaPlacement;
  6293. // convert it into absolute space of last used placement (delta applyed)
  6294. plNewPlacement.RelativeToAbsolute( pDoc->m_plLastPlacement);
  6295. // copy last used values for primitive as initial values for this new primitive
  6296. theApp.m_vfpPreLast = theApp.m_vfpLast;
  6297. theApp.m_vfpCurrent = theApp.m_vfpLast;
  6298. // apply width, sheer, stretch, ... delta
  6299. theApp.m_vfpCurrent += theApp.m_vfpDelta;
  6300. // after substraction we colud get some invalid values (like negative width!!!)
  6301. // so we have to correct them
  6302. theApp.m_vfpCurrent.CorrectInvalidValues();
  6303. // we will snap primitive placement
  6304. pDoc->SnapToGrid( plNewPlacement, SNAP_FLOAT_25);
  6305. // create primitive but don't reset orientation angles
  6306. pDoc->StartPrimitiveCSG( plNewPlacement, FALSE);
  6307. // for last clone enable undo remembering
  6308. if( iClone > 0)
  6309. {
  6310. // disable undo remembering
  6311. theApp.m_bRememberUndo = FALSE;
  6312. }
  6313. // if shift was helded while starting clone CSG
  6314. if( bAlt)
  6315. {
  6316. // apply same CSG operation as was used last time
  6317. pDoc->ApplyCSG( pDoc->m_csgtLastUsedCSGOperation);
  6318. }
  6319. }
  6320. // if there is more than 1 clone in progress
  6321. if( ctClones > 1)
  6322. {
  6323. // destroy progress dialog
  6324. dlgProgressDialog.DestroyWindow();
  6325. }
  6326. }
  6327. // for templates
  6328. else
  6329. {
  6330. // for all clones
  6331. for( INDEX iClone=0; iClone<ctClones; iClone++)
  6332. {
  6333. // if there is more than 1 clone in progress
  6334. if( ctClones > 1)
  6335. {
  6336. char achrProgressMessage[ 256];
  6337. sprintf( achrProgressMessage, "Repeating last operation... (processing %d/%d)",
  6338. iClone+1, ctClones);
  6339. // set message and progress position
  6340. dlgProgressDialog.SetProgressMessageAndPosition( achrProgressMessage, iClone+1);
  6341. }
  6342. // create new placement from delta placement
  6343. CPlacement3D plNewPlacement = pDoc->m_plDeltaPlacement;
  6344. // convert it into absolute space of last used placement (delta applyed)
  6345. plNewPlacement.RelativeToAbsolute( pDoc->m_plLastPlacement);
  6346. // we will snap template placement
  6347. pDoc->SnapToGrid( plNewPlacement, SNAP_FLOAT_25);
  6348. // for last clone enable undo remembering
  6349. if( iClone > 0)
  6350. {
  6351. // disable undo remembering
  6352. theApp.m_bRememberUndo = FALSE;
  6353. }
  6354. // start template CSG but don't reset orientation angles
  6355. pDoc->StartTemplateCSG( plNewPlacement, pDoc->m_fnLastDroppedTemplate, FALSE);
  6356. // if shift was helded while starting clone CSG, we want to apply CSG
  6357. // if template was automaticly joined after droping, we are not in CSG_MODE any more
  6358. if( bAlt && (pDoc->GetEditingMode() == CSG_MODE) )
  6359. {
  6360. // apply same CSG operation as was used last time
  6361. pDoc->ApplyCSG( pDoc->m_csgtLastUsedCSGOperation);
  6362. }
  6363. }
  6364. // if there is more than 1 clone in progress
  6365. if( ctClones > 1)
  6366. {
  6367. // destroy progress dialog
  6368. dlgProgressDialog.DestroyWindow();
  6369. }
  6370. }
  6371. // enable undo remembering
  6372. theApp.m_bRememberUndo = TRUE;
  6373. // restore automatic info flag
  6374. theApp.m_Preferences.ap_AutomaticInfo = bAutomaticInfo;
  6375. // enable CSG report
  6376. theApp.m_bCSGReportEnabled = TRUE;
  6377. // and report calculated CSG report values
  6378. _pfWorldEditingProfile.Report( theApp.m_strCSGAndShadowStatistics);
  6379. theApp.m_strCSGAndShadowStatistics.SaveVar(CTString("Temp\\Profile_CSGWizard.txt"));
  6380. }
  6381. void CWorldEditorView::OnUpdateCloneCsg(CCmdUI* pCmdUI)
  6382. {
  6383. CWorldEditorDoc* pDoc = GetDocument();
  6384. // there can't be any kind of CSG going on if we want to clone last CSG operation
  6385. BOOL bCSGOn = pDoc->m_pwoSecondLayer != NULL;
  6386. // there must be at least one CSG operation done
  6387. BOOL bCanBeCloned = ( (pDoc->m_csgtLastUsedCSGOperation == CSG_ADD) ||
  6388. (pDoc->m_csgtLastUsedCSGOperation == CSG_ADD_REVERSE) ||
  6389. (pDoc->m_csgtLastUsedCSGOperation == CSG_REMOVE) ||
  6390. (pDoc->m_csgtLastUsedCSGOperation == CSG_REMOVE_REVERSE) ||
  6391. (pDoc->m_csgtLastUsedCSGOperation == CSG_SPLIT_SECTORS) ||
  6392. (pDoc->m_csgtLastUsedCSGOperation == CSG_SPLIT_POLYGONS) ||
  6393. (pDoc->m_csgtLastUsedCSGOperation == CSG_JOIN_LAYERS) );
  6394. // last and current primitive CSG operation must have same primitive types
  6395. pCmdUI->Enable( bCanBeCloned && !bCSGOn &&
  6396. (pDoc->m_csgtPreLastUsedCSGOperation==pDoc->m_csgtLastUsedCSGOperation) &&
  6397. (pDoc->m_bPreLastUsedPrimitiveMode==pDoc->m_bLastUsedPrimitiveMode) &&
  6398. (!pDoc->m_bLastUsedPrimitiveMode ||
  6399. (pDoc->m_bLastUsedPrimitiveMode &&
  6400. (theApp.m_vfpPreLast.vfp_ptPrimitiveType == theApp.m_vfpLast.vfp_ptPrimitiveType))) );
  6401. }
  6402. void CWorldEditorView::OnPopupConus()
  6403. {
  6404. // start conus primitive
  6405. theApp.m_vfpCurrent = theApp.m_vfpConus;
  6406. CreatePrimitiveCalledFromPopup();
  6407. }
  6408. void CWorldEditorView::OnPopupTorus()
  6409. {
  6410. // start conus primitive
  6411. theApp.m_vfpCurrent = theApp.m_vfpTorus;
  6412. CreatePrimitiveCalledFromPopup();
  6413. }
  6414. void CWorldEditorView::OnPopupSphere()
  6415. {
  6416. // start conus primitive
  6417. theApp.m_vfpCurrent = theApp.m_vfpSphere;
  6418. CreatePrimitiveCalledFromPopup();
  6419. }
  6420. void CWorldEditorView::OnPopupStairs()
  6421. {
  6422. // start conus primitive
  6423. theApp.m_vfpCurrent = theApp.m_vfpStaircases;
  6424. CreatePrimitiveCalledFromPopup();
  6425. }
  6426. void CWorldEditorView::OnPopupTerrain()
  6427. {
  6428. // start conus primitive
  6429. theApp.m_vfpCurrent = theApp.m_vfpTerrain;
  6430. CreatePrimitiveCalledFromPopup();
  6431. }
  6432. void CWorldEditorView::CreatePrimitiveCalledFromPopup()
  6433. {
  6434. if( !m_bEntityHitedOnContext)
  6435. {
  6436. OnConusPrimitive();
  6437. }
  6438. CWorldEditorDoc* pDoc = GetDocument();
  6439. // create placement for primitive's position
  6440. CPlacement3D plDrop = m_plEntityHitOnContext;
  6441. // snap placement
  6442. pDoc->SnapToGrid( plDrop, m_fGridInMeters/GRID_DISCRETE_VALUES);
  6443. // create primitive for the first time, don't reset angles
  6444. pDoc->StartPrimitiveCSG( plDrop, FALSE);
  6445. }
  6446. void CWorldEditorView::OnMeasureOn()
  6447. {
  6448. theApp.m_bMeasureModeOn = !theApp.m_bMeasureModeOn;
  6449. theApp.m_bCutModeOn = FALSE;
  6450. }
  6451. void CWorldEditorView::OnUpdateMeasureOn(CCmdUI* pCmdUI)
  6452. {
  6453. pCmdUI->SetCheck( theApp.m_bMeasureModeOn);
  6454. }
  6455. void CWorldEditorView::OnResetViewer()
  6456. {
  6457. CWorldEditorDoc* pDoc = GetDocument();
  6458. CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
  6459. // set new target
  6460. GetChildFrame()->m_mvViewer.SetTargetPlacement( FLOAT3D(0.0f, 0.0f, 0.0f));
  6461. _fFlyModeSpeedMultiplier=theApp.m_Preferences.ap_fDefaultFlyModeSpeed;
  6462. pMainFrame->ResetInfoWindowPos();
  6463. pDoc->UpdateAllViews( NULL);
  6464. }
  6465. void CWorldEditorView::OnCenterBcgViewer()
  6466. {
  6467. CWorldEditorDoc* pDoc = GetDocument();
  6468. // for all of the world's entities
  6469. CEntity *penBackgroundViewer = pDoc->m_woWorld.GetBackgroundViewer();
  6470. if( penBackgroundViewer != NULL)
  6471. {
  6472. // set new target
  6473. GetChildFrame()->m_mvViewer.SetTargetPlacement(
  6474. penBackgroundViewer->GetPlacement().pl_PositionVector);
  6475. pDoc->UpdateAllViews( NULL);
  6476. }
  6477. }
  6478. void CWorldEditorView::OnCopyTexture()
  6479. {
  6480. CWorldEditorDoc* pDoc = GetDocument();
  6481. if( pDoc->GetEditingMode() == TERRAIN_MODE)
  6482. {
  6483. OnPickLayer();
  6484. return;
  6485. }
  6486. // obtain information about where mouse points into the world
  6487. CCastRay crRayHit = GetMouseHitInformation( m_ptMouse);
  6488. // if we hit brush entity
  6489. if( (crRayHit.cr_penHit != NULL) &&
  6490. (crRayHit.cr_pbpoBrushPolygon != NULL) )
  6491. {
  6492. if( pDoc->GetEditingMode() == SECTOR_MODE)
  6493. {
  6494. CBrushSector *pbscSector = crRayHit.cr_pbpoBrushPolygon->bpo_pbscSector;
  6495. CopySectorAmbient( pbscSector);
  6496. }
  6497. else
  6498. {
  6499. // get polygon's texture
  6500. CTextureData *pTD = (CTextureData *)crRayHit.cr_pbpoBrushPolygon->bpo_abptTextures[pDoc->m_iTexture].bpt_toTexture.GetData();
  6501. if( pTD != NULL)
  6502. {
  6503. // get name from serial object
  6504. CTFileName fnTextureName = pTD->GetName();
  6505. // set it as new active texture
  6506. theApp.SetNewActiveTexture( _fnmApplicationPath + fnTextureName);
  6507. }
  6508. }
  6509. }
  6510. }
  6511. void CWorldEditorView::OnPasteTexture()
  6512. {
  6513. CWorldEditorDoc* pDoc = GetDocument();
  6514. if( pDoc->GetEditingMode() == TERRAIN_MODE)
  6515. {
  6516. theApp.m_iTerrainBrushMode=TBM_RND_NOISE;
  6517. theApp.m_ctTerrainPageCanvas.MarkChanged();
  6518. pDoc->SetStatusLineModeInfoMessage();
  6519. return;
  6520. }
  6521. // obtain information about where mouse points into the world
  6522. CCastRay crRayHit = GetMouseHitInformation( m_ptMouse);
  6523. // if we hit brush entity
  6524. if( (crRayHit.cr_penHit != NULL) &&
  6525. (crRayHit.cr_pbpoBrushPolygon != NULL))
  6526. {
  6527. if( pDoc->GetEditingMode() == SECTOR_MODE)
  6528. {
  6529. CBrushSector *pbscSector = crRayHit.cr_pbpoBrushPolygon->bpo_pbscSector;
  6530. PasteSectorAmbient( pbscSector);
  6531. }
  6532. else if( pDoc->GetEditingMode() == POLYGON_MODE)
  6533. {
  6534. PasteTexture( crRayHit.cr_pbpoBrushPolygon);
  6535. }
  6536. }
  6537. }
  6538. void CWorldEditorView::OnSelectByTextureAdjacent()
  6539. {
  6540. CWorldEditorDoc* pDoc = GetDocument();
  6541. // obtain information about where mouse points into the world
  6542. CCastRay crRayHit = GetMouseHitInformation( m_ptMouse);
  6543. // if we hit brush entity
  6544. if( (crRayHit.cr_penHit != NULL) &&
  6545. (crRayHit.cr_pbpoBrushPolygon != NULL) )
  6546. {
  6547. // select similar by texture to hitted polygon
  6548. crRayHit.cr_pbpoBrushPolygon->SelectSimilarByTexture( pDoc->m_selPolygonSelection, pDoc->m_iTexture);
  6549. pDoc->m_chSelections.MarkChanged();
  6550. pDoc->UpdateAllViews( NULL);
  6551. }
  6552. }
  6553. void CWorldEditorView::OnSelectByTextureInSector()
  6554. {
  6555. CWorldEditorDoc* pDoc = GetDocument();
  6556. // obtain information about where mouse points into the world
  6557. CCastRay crRayHit = GetMouseHitInformation( m_ptMouse);
  6558. // if we hit brush entity
  6559. if( (crRayHit.cr_penHit != NULL) &&
  6560. (crRayHit.cr_pbpoBrushPolygon != NULL) )
  6561. {
  6562. // select similar by texture to hitted polygon
  6563. crRayHit.cr_pbpoBrushPolygon->SelectByTextureInSector( pDoc->m_selPolygonSelection, pDoc->m_iTexture);
  6564. pDoc->m_chSelections.MarkChanged();
  6565. pDoc->UpdateAllViews( NULL);
  6566. }
  6567. }
  6568. void CWorldEditorView::OnSelectByColorInSector()
  6569. {
  6570. CWorldEditorDoc* pDoc = GetDocument();
  6571. // obtain information about where mouse points into the world
  6572. CCastRay crRayHit = GetMouseHitInformation( m_ptMouse);
  6573. // if we hit brush entity
  6574. if( (crRayHit.cr_penHit != NULL) &&
  6575. (crRayHit.cr_pbpoBrushPolygon != NULL) )
  6576. {
  6577. // select similar by color to hitted polygon
  6578. crRayHit.cr_pbpoBrushPolygon->SelectByColorInSector( pDoc->m_selPolygonSelection);
  6579. pDoc->m_chSelections.MarkChanged();
  6580. pDoc->UpdateAllViews( NULL);
  6581. }
  6582. }
  6583. void CWorldEditorView::OnFunction()
  6584. {
  6585. CWorldEditorDoc* pDoc = GetDocument();
  6586. if( pDoc->m_iMode == ENTITY_MODE)
  6587. {
  6588. pDoc->m_cenEntitiesSelectedByVolume.Clear();
  6589. // for each of the entities selected by volume
  6590. FOREACHINDYNAMICCONTAINER( pDoc->m_selEntitySelection, CEntity, iten)
  6591. {
  6592. // add entity into volume selection
  6593. if( !pDoc->m_cenEntitiesSelectedByVolume.IsMember(iten))
  6594. {
  6595. pDoc->m_cenEntitiesSelectedByVolume.Add( iten);
  6596. }
  6597. }
  6598. // go out of browse by volume mode
  6599. if( pDoc->m_bBrowseEntitiesMode) pDoc->OnBrowseEntitiesMode();
  6600. // mark that selections have been changed
  6601. pDoc->m_chSelections.MarkChanged();
  6602. // obtain main frame ptr
  6603. CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
  6604. // and refresh property combo manualy calling on idle
  6605. pMainFrame->m_PropertyComboBar.m_PropertyComboBox.OnIdle( 0);
  6606. // update all views
  6607. pDoc->UpdateAllViews( NULL);
  6608. }
  6609. else if( pDoc->m_iMode == POLYGON_MODE)
  6610. {
  6611. pDoc->OnFilterSelection();
  6612. }
  6613. else if( pDoc->m_iMode == VERTEX_MODE)
  6614. {
  6615. SnapSelectedVerticesToPlane();
  6616. }
  6617. else if( pDoc->m_iMode == TERRAIN_MODE)
  6618. {
  6619. theApp.m_iTerrainBrushMode=TBM_FILTER;
  6620. theApp.m_ctTerrainPageCanvas.MarkChanged();
  6621. pDoc->SetStatusLineModeInfoMessage();
  6622. }
  6623. }
  6624. void CWorldEditorView::SnapSelectedVerticesToPlane(void)
  6625. {
  6626. CWorldEditorDoc* pDoc = GetDocument();
  6627. pDoc->RememberUndo();
  6628. pDoc->m_woWorld.TriangularizeForVertices( pDoc->m_selVertexSelection);
  6629. // obtain information about where mouse points into the world
  6630. CCastRay crRayHit = GetMouseHitInformation( m_ptMouse);
  6631. // if we hit brush entity
  6632. if( (crRayHit.cr_penHit != NULL) &&
  6633. (crRayHit.cr_pbpoBrushPolygon != NULL) )
  6634. {
  6635. CBrushPolygon *pbpo = crRayHit.cr_pbpoBrushPolygon;
  6636. CEntity *pen = pbpo->bpo_pbscSector->bsc_pbmBrushMip->bm_pbrBrush->br_penEntity;
  6637. CSimpleProjection3D_DOUBLE pr;
  6638. pr.ObjectPlacementL() = pen->GetPlacement();
  6639. pr.ViewerPlacementL() = _plOrigin;
  6640. pr.Prepare();
  6641. DOUBLEplane3D plAbsPrecise;
  6642. pr.Project(pbpo->bpo_pbplPlane->bpl_pldPreciseRelative, plAbsPrecise);
  6643. // snap vertices to plane
  6644. {FOREACHINDYNAMICCONTAINER( pDoc->m_selVertexSelection, CBrushVertex, itbvx)
  6645. {
  6646. CEntity *pen = itbvx->bvx_pbscSector->bsc_pbmBrushMip->bm_pbrBrush->br_penEntity;
  6647. CSimpleProjection3D_DOUBLE pr;
  6648. pr.ObjectPlacementL() = pen->GetPlacement();
  6649. pr.ViewerPlacementL() = _plOrigin;
  6650. pr.Prepare();
  6651. DOUBLE3D vAbsPrecise;
  6652. pr.ProjectCoordinate(itbvx->bvx_vdPreciseRelative, vAbsPrecise);
  6653. DOUBLE3D vOnPlaneAbsPrecise=plAbsPrecise.ProjectPoint(vAbsPrecise);
  6654. itbvx->SetAbsolutePosition(vOnPlaneAbsPrecise);
  6655. }}
  6656. }
  6657. pDoc->m_woWorld.UpdateSectorsDuringVertexChange( pDoc->m_selVertexSelection);
  6658. pDoc->m_woWorld.UpdateSectorsAfterVertexChange( pDoc->m_selVertexSelection);
  6659. pDoc->UpdateAllViews( NULL);
  6660. pDoc->SetModifiedFlag();
  6661. }
  6662. void CWorldEditorView::OnCrossroadForCtrlF()
  6663. {
  6664. CWorldEditorDoc* pDoc = GetDocument();
  6665. if(pDoc->GetEditingMode() == POLYGON_MODE)
  6666. {
  6667. OnFindTexture();
  6668. }
  6669. else if(pDoc->GetEditingMode() == VERTEX_MODE)
  6670. {
  6671. CDlgFilterVertexSelection dlg;
  6672. dlg.DoModal();
  6673. }
  6674. else if(pDoc->GetEditingMode() == TERRAIN_MODE)
  6675. {
  6676. theApp.m_iFilter=(theApp.m_iFilter+1)%FLT_COUNT;
  6677. theApp.m_ctTerrainPageCanvas.MarkChanged();
  6678. GetDocument()->SetStatusLineModeInfoMessage();
  6679. }
  6680. }
  6681. void CWorldEditorView::OnFindTexture()
  6682. {
  6683. CWorldEditorDoc* pDoc = GetDocument();
  6684. // obtain information about where mouse points into the world
  6685. CCastRay crRayHit = GetMouseHitInformation( m_ptMouse);
  6686. // if we hit brush entity
  6687. if( (crRayHit.cr_penHit != NULL) &&
  6688. (crRayHit.cr_pbpoBrushPolygon != NULL) )
  6689. {
  6690. // get polygon's texture
  6691. CTextureData *pTD = (CTextureData *)crRayHit.cr_pbpoBrushPolygon->bpo_abptTextures[pDoc->m_iTexture].bpt_toTexture.GetData();
  6692. if( pTD != NULL)
  6693. {
  6694. // get name from serial object
  6695. CTFileName fnTextureName = pTD->GetName();
  6696. // set it as new active texture
  6697. theApp.FindItemInBrowser( fnTextureName);
  6698. }
  6699. }
  6700. }
  6701. void CWorldEditorView::OnCenterEntity()
  6702. {
  6703. CWorldEditorDoc* pDoc = GetDocument();
  6704. if(pDoc->GetEditingMode() == CSG_MODE)
  6705. {
  6706. GetChildFrame()->m_mvViewer.SetTargetPlacement( pDoc->m_plSecondLayer.pl_PositionVector);
  6707. }
  6708. if(pDoc->GetEditingMode() == TERRAIN_MODE)
  6709. {
  6710. CTerrain *ptrTerrain=GetTerrain();
  6711. if(ptrTerrain!=NULL)
  6712. {
  6713. FLOATaabbox3D boxBoundingBox;
  6714. ptrTerrain->GetAllTerrainBBox(boxBoundingBox);
  6715. FLOAT3D vTerrainCenter=boxBoundingBox.Center();
  6716. GetChildFrame()->m_mvViewer.SetTargetPlacement( vTerrainCenter);
  6717. }
  6718. }
  6719. else
  6720. {
  6721. if( pDoc->m_selEntitySelection.Count() == 0) return;
  6722. // reset position
  6723. FLOAT3D vEntityPlacementAverage = FLOAT3D( 0.0f, 0.0f, 0.0f);
  6724. //for all selected entities
  6725. FOREACHINDYNAMICCONTAINER(pDoc->m_selEntitySelection, CEntity, iten)
  6726. {
  6727. // get placement of current entity
  6728. CPlacement3D plEntityPlacement = iten->GetPlacement();
  6729. // add movement offset to placement
  6730. vEntityPlacementAverage += plEntityPlacement.pl_PositionVector;
  6731. }
  6732. // calculate average position
  6733. vEntityPlacementAverage /= (FLOAT) pDoc->m_selEntitySelection.Count();
  6734. // set centered entity position as new viewer's target
  6735. GetChildFrame()->m_mvViewer.SetTargetPlacement( vEntityPlacementAverage);
  6736. }
  6737. // update all views
  6738. pDoc->UpdateAllViews( NULL);
  6739. }
  6740. void CWorldEditorView::OnUpdateCenterEntity(CCmdUI* pCmdUI)
  6741. {
  6742. CWorldEditorDoc* pDoc = GetDocument();
  6743. // if we are in entity mode and we have at least 1 entity selected
  6744. pCmdUI->Enable( (pDoc->GetEditingMode() == CSG_MODE) ||
  6745. ((pDoc->GetEditingMode() == TERRAIN_MODE) &&
  6746. (GetTerrain()!=NULL)) ||
  6747. ((pDoc->GetEditingMode() == ENTITY_MODE) &&
  6748. (pDoc->m_selEntitySelection.Count() != 0)) );
  6749. }
  6750. void CWorldEditorView::OnDropMarker()
  6751. {
  6752. CWorldEditorDoc* pDoc = GetDocument();
  6753. CTFileName fnDropClass;
  6754. CTString strTargetProperty;
  6755. if(pDoc->m_selEntitySelection.Count() == 1)
  6756. {
  6757. CEntity &enOnly = pDoc->m_selEntitySelection.GetFirst();
  6758. if(enOnly.DropsMarker( fnDropClass, strTargetProperty))
  6759. {
  6760. OnDropMarker(enOnly.GetPlacement());
  6761. }
  6762. }
  6763. }
  6764. void CWorldEditorView::OnDropMarker(CPlacement3D plMarker)
  6765. {
  6766. CWorldEditorDoc* pDoc = GetDocument();
  6767. CTFileName fnDropClass, fnDummy;
  6768. CTString strTargetProperty;
  6769. CEntityProperty *penpProperty;
  6770. CEntity &enOnly = pDoc->m_selEntitySelection.GetFirst();
  6771. // obtain drop class and target property name
  6772. if( !enOnly.DropsMarker( fnDropClass, strTargetProperty)) return;
  6773. penpProperty = enOnly.PropertyForName( strTargetProperty);
  6774. CEntity *penFirstInChain;
  6775. if (enOnly.IsMarker())
  6776. {
  6777. penFirstInChain = &enOnly;
  6778. }
  6779. else
  6780. {
  6781. penFirstInChain = ENTITYPROPERTY( &enOnly, penpProperty->ep_slOffset, CEntityPointer);
  6782. }
  6783. CEntity *penSecondInChain = NULL;
  6784. // if first in chain exists, try getting his target
  6785. if( penFirstInChain != NULL)
  6786. {
  6787. if( !penFirstInChain->DropsMarker( fnDropClass, strTargetProperty)) return;
  6788. penpProperty = penFirstInChain->PropertyForName( strTargetProperty);
  6789. penSecondInChain = ENTITYPROPERTY( penFirstInChain, penpProperty->ep_slOffset, CEntityPointer);
  6790. }
  6791. // spawn entity
  6792. CEntity *penSpawned;
  6793. if( !enOnly.DropsMarker( fnDropClass, strTargetProperty)) return;
  6794. penpProperty = enOnly.PropertyForName( strTargetProperty);
  6795. try
  6796. {
  6797. // spawn one entity of class selected in browser
  6798. penSpawned = pDoc->m_woWorld.CreateEntity_t( plMarker, fnDropClass);
  6799. penSpawned->Initialize();
  6800. }
  6801. catch( char *strError)
  6802. {
  6803. AfxMessageBox( CString(strError));
  6804. return;
  6805. }
  6806. // if first in chain entity exists, set spawned entity to be his target
  6807. if( penFirstInChain != NULL)
  6808. {
  6809. if( !penFirstInChain->DropsMarker( fnDropClass, strTargetProperty)) return;
  6810. penpProperty = penFirstInChain->PropertyForName( strTargetProperty);
  6811. ENTITYPROPERTY( penFirstInChain, penpProperty->ep_slOffset, CEntityPointer) = penSpawned;
  6812. }
  6813. if( !penSpawned->DropsMarker( fnDropClass, strTargetProperty)) return;
  6814. penpProperty = penSpawned->PropertyForName( strTargetProperty);
  6815. if( penSecondInChain != NULL)
  6816. {
  6817. ENTITYPROPERTY( penSpawned, penpProperty->ep_slOffset, CEntityPointer) = penSecondInChain;
  6818. }
  6819. else
  6820. {
  6821. ENTITYPROPERTY( penSpawned, penpProperty->ep_slOffset, CEntityPointer) = penFirstInChain;
  6822. }
  6823. // set our only selected entity to point to spawned entity
  6824. if( !enOnly.DropsMarker( fnDropClass, strTargetProperty)) return;
  6825. penpProperty = enOnly.PropertyForName( strTargetProperty);
  6826. ENTITYPROPERTY( &enOnly, penpProperty->ep_slOffset, CEntityPointer) = penSpawned;
  6827. pDoc->SetModifiedFlag();
  6828. pDoc->m_chSelections.MarkChanged();
  6829. pDoc->UpdateAllViews( NULL);
  6830. }
  6831. void CWorldEditorView::OnUpdateDropMarker(CCmdUI* pCmdUI)
  6832. {
  6833. CTFileName fnDropClass;
  6834. CTString strTargetProperty;
  6835. CWorldEditorDoc* pDoc = GetDocument();
  6836. // if we are in entity mode, we have 1 entity selected and entity can drop marker
  6837. if( (pDoc->GetEditingMode() == ENTITY_MODE) &&
  6838. (pDoc->m_selEntitySelection.Count() == 1) &&
  6839. (pDoc->m_selEntitySelection.GetFirst().DropsMarker( fnDropClass, strTargetProperty)) )
  6840. {
  6841. pCmdUI->Enable( TRUE);
  6842. }
  6843. else
  6844. {
  6845. pCmdUI->Enable( FALSE);
  6846. }
  6847. }
  6848. void CWorldEditorView::OnTestConnections()
  6849. {
  6850. CWorldEditorDoc* pDoc = GetDocument();
  6851. CEntityProperty *penpProperty;
  6852. CEntity &enOnly = pDoc->m_selEntitySelection.GetFirst();
  6853. CTString strTargetProperty;
  6854. // get target pointer for curently selected entity
  6855. enOnly.MovesByTargetedRoute( strTargetProperty);
  6856. penpProperty = enOnly.PropertyForName( strTargetProperty);
  6857. CEntity *penCurrent = ENTITYPROPERTY( &enOnly, penpProperty->ep_slOffset, CEntityPointer);
  6858. // if no target
  6859. if( penCurrent == NULL) {
  6860. // do nothing
  6861. return;
  6862. }
  6863. // get target pointer for its target (get next)
  6864. penCurrent->MovesByTargetedRoute( strTargetProperty);
  6865. penpProperty = penCurrent->PropertyForName( strTargetProperty);
  6866. CEntity *penNext = ENTITYPROPERTY( penCurrent, penpProperty->ep_slOffset, CEntityPointer);
  6867. // if no target
  6868. if( penNext == NULL) {
  6869. // do nothing
  6870. return;
  6871. }
  6872. // teleport to next
  6873. enOnly.SetPlacement( penNext->GetPlacement());
  6874. if (enOnly.en_RenderType == CEntity::RT_BRUSH)
  6875. {
  6876. DiscardShadows( &enOnly);
  6877. }
  6878. // set target pointer to next next
  6879. enOnly.MovesByTargetedRoute( strTargetProperty);
  6880. penpProperty = enOnly.PropertyForName( strTargetProperty);
  6881. ENTITYPROPERTY( &enOnly, penpProperty->ep_slOffset, CEntityPointer) = penNext;
  6882. // mark that document and selections are changed
  6883. pDoc->SetModifiedFlag();
  6884. pDoc->m_chSelections.MarkChanged();
  6885. pDoc->UpdateAllViews( NULL);
  6886. }
  6887. void CWorldEditorView::OnTestConnectionsBack()
  6888. {
  6889. CWorldEditorDoc* pDoc = GetDocument();
  6890. CEntityProperty *penpProperty;
  6891. CEntity &enOnly = pDoc->m_selEntitySelection.GetFirst();
  6892. CTString strTargetProperty;
  6893. // get target pointer for curently selected entity
  6894. enOnly.MovesByTargetedRoute( strTargetProperty);
  6895. penpProperty = enOnly.PropertyForName( strTargetProperty);
  6896. CEntity *penCurrent = ENTITYPROPERTY( &enOnly, penpProperty->ep_slOffset, CEntityPointer);
  6897. // if no target
  6898. if( penCurrent == NULL) {
  6899. // do nothing
  6900. return;
  6901. }
  6902. // start from current
  6903. CEntity *penNext=penCurrent;
  6904. // repeat
  6905. FOREVER {
  6906. // get next target pointer
  6907. penNext->MovesByTargetedRoute( strTargetProperty);
  6908. penpProperty = penCurrent->PropertyForName( strTargetProperty);
  6909. CEntity *penNextNext = ENTITYPROPERTY( penNext, penpProperty->ep_slOffset, CEntityPointer);
  6910. // if no target
  6911. if( penNextNext == NULL) {
  6912. // do nothing
  6913. return;
  6914. }
  6915. // if the next one is same as where the entity started
  6916. if( penNextNext==penCurrent) {
  6917. // stop searching
  6918. break;
  6919. }
  6920. // go to that target
  6921. penNext = penNextNext;
  6922. }
  6923. // teleport to next
  6924. enOnly.SetPlacement( penNext->GetPlacement());
  6925. if (enOnly.en_RenderType == CEntity::RT_BRUSH)
  6926. {
  6927. DiscardShadows( &enOnly);
  6928. }
  6929. // set target pointer to next next
  6930. enOnly.MovesByTargetedRoute( strTargetProperty);
  6931. penpProperty = enOnly.PropertyForName( strTargetProperty);
  6932. ENTITYPROPERTY( &enOnly, penpProperty->ep_slOffset, CEntityPointer) = penNext;
  6933. // mark that document and selections are changed
  6934. pDoc->SetModifiedFlag();
  6935. pDoc->m_chSelections.MarkChanged();
  6936. pDoc->UpdateAllViews( NULL);
  6937. }
  6938. void CWorldEditorView::OnUpdateTestConnections(CCmdUI* pCmdUI)
  6939. {
  6940. CWorldEditorDoc* pDoc = GetDocument();
  6941. BOOL bModeAndCount = (pDoc->GetEditingMode() == ENTITY_MODE) &&
  6942. ( pDoc->m_selEntitySelection.Count() == 1);
  6943. BOOL bEnableCommand = FALSE;
  6944. // if we have only one entity selected and we are in entity mode
  6945. if( bModeAndCount)
  6946. {
  6947. CEntity &enOnly = pDoc->m_selEntitySelection.GetFirst();
  6948. CTString strTargetProperty;
  6949. // if we can perform test path function on this entity
  6950. if( enOnly.MovesByTargetedRoute( strTargetProperty))
  6951. bEnableCommand = TRUE;
  6952. }
  6953. pCmdUI->Enable( bEnableCommand);
  6954. }
  6955. void CWorldEditorView::OnUpdateTestConnectionsBack(CCmdUI* pCmdUI)
  6956. {
  6957. // update same as it is forward
  6958. OnUpdateTestConnections( pCmdUI);
  6959. }
  6960. #define PAPER (4.0f/5.0f)
  6961. void CWorldEditorView::OnAlignVolume()
  6962. {
  6963. // get draw port
  6964. CDrawPort *pdpValidDrawPort = GetDrawPort();
  6965. // if it is not valid
  6966. if( pdpValidDrawPort == NULL)
  6967. {
  6968. return;
  6969. }
  6970. CWorldEditorDoc* pDoc = GetDocument();
  6971. // create a slave viewer
  6972. CSlaveViewer svViewer(GetChildFrame()->m_mvViewer, m_ptProjectionType, pDoc->m_plGrid,
  6973. pdpValidDrawPort);
  6974. // get zoom factor
  6975. FLOAT fZoom = svViewer.GetZoomFactor();
  6976. PIX pixWidth = pdpValidDrawPort->GetWidth();
  6977. PIX pixHeight = pdpValidDrawPort->GetHeight();
  6978. FLOAT fWidth = pixWidth/fZoom;
  6979. FLOAT fHeight = pixHeight/fZoom;
  6980. // get point in space that user is looking
  6981. FLOAT3D vTargetPoint = GetChildFrame()->m_mvViewer.GetTargetPlacement().pl_PositionVector;
  6982. pDoc->m_vCreateBoxVertice0 = FLOAT3D(
  6983. vTargetPoint(1)-fWidth*PAPER/2,
  6984. vTargetPoint(2)-fHeight*PAPER/2,
  6985. vTargetPoint(3)-fHeight*PAPER/2);
  6986. pDoc->m_vCreateBoxVertice1 = FLOAT3D(
  6987. vTargetPoint(1)+fWidth*PAPER/2,
  6988. vTargetPoint(2)+fHeight*PAPER/2,
  6989. vTargetPoint(3)+fHeight*PAPER/2);
  6990. pDoc->SelectEntitiesByVolumeBox();
  6991. // try to select first entity in volume
  6992. pDoc->SelectGivenEntity( 0);
  6993. pDoc->UpdateAllViews( NULL);
  6994. }
  6995. void CWorldEditorView::OnAlignPrimitive()
  6996. {
  6997. // get draw port
  6998. CDrawPort *pdpValidDrawPort = GetDrawPort();
  6999. // if it is not valid
  7000. if( pdpValidDrawPort == NULL)
  7001. {
  7002. return;
  7003. }
  7004. CWorldEditorDoc* pDoc = GetDocument();
  7005. // create a slave viewer
  7006. CSlaveViewer svViewer(GetChildFrame()->m_mvViewer, m_ptProjectionType, pDoc->m_plGrid,
  7007. pdpValidDrawPort);
  7008. // get zoom factor
  7009. FLOAT fZoom = svViewer.GetZoomFactor();
  7010. PIX pixWidth = pdpValidDrawPort->GetWidth()*8/10;
  7011. PIX pixHeight = pdpValidDrawPort->GetHeight()*8/10;
  7012. FLOAT fWidth = pixWidth/fZoom;
  7013. FLOAT fHeight = pixHeight/fZoom;
  7014. // get point in space that user is looking
  7015. FLOAT3D vTargetPoint = GetChildFrame()->m_mvViewer.GetTargetPlacement().pl_PositionVector;
  7016. pDoc->m_plSecondLayer.pl_PositionVector = vTargetPoint;
  7017. fWidth = FLOAT( pow( 2.0f, floor(Log2(fWidth))));
  7018. fHeight = FLOAT( pow( 2.0f, floor(Log2(fHeight))));
  7019. theApp.m_vfpCurrent.vfp_fXMin = -fWidth/2.0f;
  7020. theApp.m_vfpCurrent.vfp_fXMax = fWidth/2.0f;
  7021. theApp.m_vfpCurrent.vfp_fYMin = -fHeight/2.0f;
  7022. theApp.m_vfpCurrent.vfp_fYMax = fHeight/2.0f;
  7023. theApp.m_vfpCurrent.vfp_fZMin = -fHeight/2.0f;
  7024. theApp.m_vfpCurrent.vfp_fZMax = fHeight/2.0f;
  7025. pDoc->SnapToGrid( pDoc->m_plSecondLayer, m_fGridInMeters/GRID_DISCRETE_VALUES);
  7026. if( pDoc->m_bAutoSnap)
  7027. {
  7028. pDoc->SnapFloat( theApp.m_vfpCurrent.vfp_fXMin, m_fGridInMeters/GRID_DISCRETE_VALUES);
  7029. pDoc->SnapFloat( theApp.m_vfpCurrent.vfp_fXMax, m_fGridInMeters/GRID_DISCRETE_VALUES);
  7030. pDoc->SnapFloat( theApp.m_vfpCurrent.vfp_fYMin, m_fGridInMeters/GRID_DISCRETE_VALUES);
  7031. pDoc->SnapFloat( theApp.m_vfpCurrent.vfp_fYMax, m_fGridInMeters/GRID_DISCRETE_VALUES);
  7032. pDoc->SnapFloat( theApp.m_vfpCurrent.vfp_fZMin, m_fGridInMeters/GRID_DISCRETE_VALUES);
  7033. pDoc->SnapFloat( theApp.m_vfpCurrent.vfp_fZMax, m_fGridInMeters/GRID_DISCRETE_VALUES);
  7034. }
  7035. else
  7036. {
  7037. pDoc->SnapFloat( theApp.m_vfpCurrent.vfp_fXMin, SNAP_FLOAT_CM);
  7038. pDoc->SnapFloat( theApp.m_vfpCurrent.vfp_fXMax, SNAP_FLOAT_CM);
  7039. pDoc->SnapFloat( theApp.m_vfpCurrent.vfp_fYMin, SNAP_FLOAT_CM);
  7040. pDoc->SnapFloat( theApp.m_vfpCurrent.vfp_fYMax, SNAP_FLOAT_CM);
  7041. pDoc->SnapFloat( theApp.m_vfpCurrent.vfp_fZMin, SNAP_FLOAT_CM);
  7042. pDoc->SnapFloat( theApp.m_vfpCurrent.vfp_fZMax, SNAP_FLOAT_CM);
  7043. }
  7044. pDoc->RefreshPrimitivePage();
  7045. pDoc->CreatePrimitive();
  7046. pDoc->UpdateAllViews( NULL);
  7047. }
  7048. void CWorldEditorView::OnUpdateAlignVolume(CCmdUI* pCmdUI)
  7049. {
  7050. CWorldEditorDoc* pDoc = GetDocument();
  7051. pCmdUI->Enable( pDoc->m_bBrowseEntitiesMode);
  7052. }
  7053. void CWorldEditorView::OnCurrentViewProperties()
  7054. {
  7055. // copy selected preferences from view rendering preferences to temporary buffer
  7056. theApp.m_vpViewPrefs[ VIEW_PREFERENCES_CT] = m_vpViewPrefs;
  7057. // call edit view preferences with temporary view preferences buffer (last one)
  7058. CDlgRenderingPreferences dlg( VIEW_PREFERENCES_CT);
  7059. // if dialog ended with cancel or esc, dont switch to changed preferences
  7060. if( dlg.DoModal() != IDOK)
  7061. {
  7062. // don't set new preferences
  7063. return;
  7064. }
  7065. // copy selected preferences to view's rendering preferences
  7066. m_vpViewPrefs = theApp.m_vpViewPrefs[ VIEW_PREFERENCES_CT];
  7067. // see the change
  7068. Invalidate( FALSE);
  7069. }
  7070. void CWorldEditorView::OnChooseColor()
  7071. {
  7072. /*
  7073. // find toll bar's rectangle
  7074. RECT rectToolBar;
  7075. m_wndSelectionTools.GetWindowRect( &rectToolBar);
  7076. // Then we find tool button's index
  7077. INDEX iToolButton = m_wndSelectionTools.CommandToIndex( ID_CHOOSE_COLOR);
  7078. // Using given index, we obtain button's rectangle
  7079. RECT rectButton;
  7080. m_wndSelectionTools.GetItemRect( iToolButton, &rectButton);
  7081. // set screen coordinates of LU point of clicked tool button
  7082. CustomColorPicker( rectToolBar.left + rectButton.left, rectToolBar.top + rectButton.bottom);
  7083. */
  7084. CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
  7085. POINT ptCursor;
  7086. GetCursorPos( &ptCursor);
  7087. if( ptCursor.y < 100)
  7088. {
  7089. pMainFrame->CustomColorPicker( ptCursor.x-50, ptCursor.y);
  7090. }
  7091. else
  7092. {
  7093. pMainFrame->CustomColorPicker( ptCursor.x-50, ptCursor.y-100);
  7094. }
  7095. }
  7096. void CWorldEditorView::OnUpdateChooseColor(CCmdUI* pCmdUI)
  7097. {
  7098. // don't enable initially
  7099. BOOL bEnable = FALSE;
  7100. // obtain document
  7101. CWorldEditorDoc *pDoc = GetDocument();
  7102. // if sector mode is on and there is at least 1 selected sector
  7103. if( (pDoc->m_iMode == SECTOR_MODE) && (pDoc->m_selSectorSelection.Count() != 0) )
  7104. {
  7105. bEnable = TRUE;
  7106. }
  7107. // if polygon mode is on and there is at least 1 selected polygon
  7108. if( (pDoc->m_iMode == POLYGON_MODE) && (pDoc->m_selPolygonSelection.Count() != 0) )
  7109. {
  7110. bEnable = TRUE;
  7111. }
  7112. pCmdUI->Enable( bEnable);
  7113. }
  7114. void CWorldEditorView::OnCrossroadForC()
  7115. {
  7116. PostMessage( WM_COMMAND, ID_CHOOSE_COLOR, 0);
  7117. PostMessage( WM_COMMAND, ID_CENTER_ENTITY, 0);
  7118. }
  7119. void CWorldEditorView::SetAsCsgTarget(CEntity *pen)
  7120. {
  7121. if( (pen != NULL) &&
  7122. ( (pen->GetRenderType() == CEntity::RT_BRUSH) ||
  7123. (pen->GetRenderType() == CEntity::RT_FIELDBRUSH)) )
  7124. {
  7125. CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
  7126. pMainFrame->m_CSGDesitnationCombo.SelectBrushEntity(pen);
  7127. }
  7128. }
  7129. void CWorldEditorView::OnSetAsCsgTarget()
  7130. {
  7131. SetAsCsgTarget(m_penEntityHitOnContext);
  7132. }
  7133. void CWorldEditorView::OnCsgSelectSector()
  7134. {
  7135. if( (m_penEntityHitOnContext != NULL) &&
  7136. ((m_penEntityHitOnContext->GetRenderType() == CEntity::RT_BRUSH) ||
  7137. (m_penEntityHitOnContext->GetRenderType() == CEntity::RT_FIELDBRUSH)) &&
  7138. (m_pbpoRightClickedPolygon != NULL) )
  7139. {
  7140. CBrushSector *pbscHitted = m_pbpoRightClickedPolygon->bpo_pbscSector;
  7141. CWorldEditorDoc *pDoc = GetDocument();
  7142. pDoc->m_selSectorSelection.Clear();
  7143. pDoc->m_selSectorSelection.Select( *pbscHitted);
  7144. }
  7145. }
  7146. LRESULT CWorldEditorView::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
  7147. {
  7148. CChildFrame *pCF = GetChildFrame();
  7149. // if test game is active
  7150. if( _pInput->IsInputEnabled())
  7151. { // repost some messages to thread
  7152. switch( message ) {
  7153. case WM_CANCELMODE:
  7154. case WM_KILLFOCUS:
  7155. case WM_ACTIVATEAPP:
  7156. case WM_LBUTTONUP:
  7157. ::PostMessage(NULL, message, wParam, lParam);
  7158. break;
  7159. case WM_MOUSEACTIVATE:
  7160. if( pCF->m_bTestGameOn)
  7161. {
  7162. return MA_ACTIVATEANDEAT;
  7163. }
  7164. break;
  7165. case WM_DESTROY:
  7166. PostQuitMessage(0);
  7167. break;
  7168. }
  7169. }
  7170. return CView::WindowProc(message, wParam, lParam);
  7171. }
  7172. void CWorldEditorView::OnRButtonDblClk(UINT nFlags, CPoint point)
  7173. {
  7174. m_iaInputAction = IA_NONE;
  7175. BOOL bSpace = (GetKeyState( VK_SPACE)&0x8000) != 0;
  7176. BOOL bCtrl = (GetKeyState( VK_CONTROL)&0x8000) != 0;
  7177. BOOL bShift = (GetKeyState( VK_SHIFT)&0x8000) != 0;
  7178. BOOL bLMB = nFlags & MK_LBUTTON;
  7179. BOOL bAlt = (GetKeyState( VK_MENU)&0x8000) != 0;
  7180. // space+ctrl+rmb zoomes out 2x
  7181. if( (bSpace) && (bCtrl) )
  7182. {
  7183. if( bLMB) return;
  7184. OnZoomLess();
  7185. return;
  7186. }
  7187. // RMB dblclick and ctrl select by texture in sector
  7188. CWorldEditorDoc* pDoc = GetDocument();
  7189. if( pDoc->GetEditingMode() == POLYGON_MODE)
  7190. {
  7191. // Alt+Ctrl requests that clicked polygon sizes its texture
  7192. if( bAlt && bCtrl)
  7193. {
  7194. MultiplyMappingOnPolygon( 2.0f);
  7195. }
  7196. else if( bCtrl && bShift && !bAlt)
  7197. {
  7198. OnSelectByColorInSector();
  7199. }
  7200. else if( bCtrl && !bAlt)
  7201. {
  7202. OnSelectByTextureAdjacent();
  7203. }
  7204. }
  7205. CView::OnRButtonDblClk(nFlags, point);
  7206. }
  7207. void CWorldEditorView::OnLastPrimitive()
  7208. {
  7209. CWorldEditorDoc* pDoc = GetDocument();
  7210. CTString strError;
  7211. BOOL bCutEnabled = IsCutEnabled( strError);
  7212. if( theApp.m_bCutModeOn)
  7213. {
  7214. if( !bCutEnabled)
  7215. {
  7216. // exit cut mode
  7217. theApp.m_bCutModeOn = FALSE;
  7218. WarningMessage( "%s", strError);
  7219. return;
  7220. }
  7221. pDoc->ApplyCut();
  7222. }
  7223. else
  7224. {
  7225. // exit cut mode
  7226. theApp.m_bCutModeOn = FALSE;
  7227. pDoc->StartPrimitiveCSG( theApp.m_vfpCurrent.vfp_plPrimitive, FALSE);
  7228. }
  7229. }
  7230. void CWorldEditorView::OnUpdateLastPrimitive(CCmdUI* pCmdUI)
  7231. {
  7232. pCmdUI->Enable( GetDocument()->m_pwoSecondLayer == NULL);
  7233. }
  7234. void CWorldEditorView::OnConusPrimitive()
  7235. {
  7236. // copy last used values for conus primitive as initial values for new primitive
  7237. theApp.m_vfpCurrent = theApp.m_vfpConus;
  7238. CWorldEditorDoc* pDoc = GetDocument();
  7239. pDoc->StartPrimitiveCSG( theApp.m_vfpCurrent.vfp_plPrimitive, FALSE);
  7240. }
  7241. void CWorldEditorView::OnTorusPrimitive()
  7242. {
  7243. // copy last used values for torus primitive as initial values for new primitive
  7244. theApp.m_vfpCurrent = theApp.m_vfpTorus;
  7245. // create primitive for the first time
  7246. CWorldEditorDoc* pDoc = GetDocument();
  7247. pDoc->StartPrimitiveCSG( theApp.m_vfpCurrent.vfp_plPrimitive, FALSE);
  7248. }
  7249. void CWorldEditorView::OnStaircasePrimitive()
  7250. {
  7251. // copy last used values for staircase primitive as initial values for new primitive
  7252. theApp.m_vfpCurrent = theApp.m_vfpStaircases;
  7253. // create primitive for the first time
  7254. CWorldEditorDoc* pDoc = GetDocument();
  7255. pDoc->StartPrimitiveCSG( theApp.m_vfpCurrent.vfp_plPrimitive, FALSE);
  7256. }
  7257. void CWorldEditorView::OnSpherePrimitive()
  7258. {
  7259. // copy last used values for sphere primitive as initial values for new primitive
  7260. theApp.m_vfpCurrent = theApp.m_vfpSphere;
  7261. // create primitive for the first time
  7262. CWorldEditorDoc* pDoc = GetDocument();
  7263. pDoc->StartPrimitiveCSG( theApp.m_vfpCurrent.vfp_plPrimitive, FALSE);
  7264. }
  7265. void CWorldEditorView::OnTerrainPrimitive()
  7266. {
  7267. // copy last used values for terrain primitive as initial values for new primitive
  7268. theApp.m_vfpCurrent = theApp.m_vfpTerrain;
  7269. // create primitive for the first time
  7270. CWorldEditorDoc* pDoc = GetDocument();
  7271. pDoc->StartPrimitiveCSG( theApp.m_vfpCurrent.vfp_plPrimitive, FALSE);
  7272. }
  7273. void CWorldEditorView::OnUpdateConusPrimitive(CCmdUI* pCmdUI)
  7274. {
  7275. pCmdUI->Enable( GetDocument()->m_pwoSecondLayer == NULL);
  7276. }
  7277. void CWorldEditorView::OnUpdateSpherePrimitive(CCmdUI* pCmdUI)
  7278. {
  7279. pCmdUI->Enable( GetDocument()->m_pwoSecondLayer == NULL);
  7280. }
  7281. void CWorldEditorView::OnUpdateTerrainPrimitive(CCmdUI* pCmdUI)
  7282. {
  7283. pCmdUI->Enable( GetDocument()->m_pwoSecondLayer == NULL);
  7284. }
  7285. void CWorldEditorView::OnUpdateTorusPrimitive(CCmdUI* pCmdUI)
  7286. {
  7287. pCmdUI->Enable( GetDocument()->m_pwoSecondLayer == NULL);
  7288. }
  7289. void CWorldEditorView::OnUpdateStaircasePrimitive(CCmdUI* pCmdUI)
  7290. {
  7291. pCmdUI->Enable( GetDocument()->m_pwoSecondLayer == NULL);
  7292. }
  7293. void CWorldEditorView::OnUpdateMoveDown(CCmdUI* pCmdUI)
  7294. {
  7295. CWorldEditorDoc* pDoc = GetDocument();
  7296. pCmdUI->Enable( (pDoc->m_pwoSecondLayer != NULL) &&
  7297. (pDoc->m_bPrimitiveMode) &&
  7298. (theApp.m_vfpCurrent.vfp_ttTriangularisationType != TT_NONE) );
  7299. }
  7300. void CWorldEditorView::OnUpdateMoveUp(CCmdUI* pCmdUI)
  7301. {
  7302. CWorldEditorDoc* pDoc = GetDocument();
  7303. pCmdUI->Enable( (pDoc->m_pwoSecondLayer != NULL) &&
  7304. (pDoc->m_bPrimitiveMode) &&
  7305. (theApp.m_vfpCurrent.vfp_ttTriangularisationType != TT_NONE) );
  7306. }
  7307. void CWorldEditorView::OnSelectLights()
  7308. {
  7309. CWorldEditorDoc* pDoc = GetDocument();
  7310. // obtain information about where mouse points into the world
  7311. CCastRay crRayHit = GetMouseHitInformation( m_ptMouse);
  7312. CBrushPolygon *pbpoPolygon = crRayHit.cr_pbpoBrushPolygon;
  7313. // if we hit brush entity
  7314. if( (crRayHit.cr_penHit == NULL) ||
  7315. (pbpoPolygon == NULL) ||
  7316. (pbpoPolygon->IsSelected(BPOF_SELECTED)) )
  7317. {
  7318. FOREACHINDYNAMICCONTAINER(pDoc->m_selPolygonSelection, CBrushPolygon, itbpo)
  7319. {
  7320. CBrushShadowMap &bsm = itbpo->bpo_smShadowMap;
  7321. FOREACHINLIST(CBrushShadowLayer, bsl_lnInShadowMap, bsm.bsm_lhLayers, itbsl)
  7322. {
  7323. CLightSource *plsLight = itbsl->bsl_plsLightSource;
  7324. CEntity *penLight = plsLight->ls_penEntity;
  7325. if( !pDoc->m_selEntitySelection.IsSelected( *penLight))
  7326. {
  7327. pDoc->m_selEntitySelection.Select( *penLight);
  7328. }
  7329. }
  7330. }
  7331. }
  7332. else
  7333. {
  7334. CBrushShadowMap &bsm = pbpoPolygon->bpo_smShadowMap;
  7335. FOREACHINLIST(CBrushShadowLayer, bsl_lnInShadowMap, bsm.bsm_lhLayers, itbsl)
  7336. {
  7337. CLightSource *plsLight = itbsl->bsl_plsLightSource;
  7338. CEntity *penLight = plsLight->ls_penEntity;
  7339. if( !pDoc->m_selEntitySelection.IsSelected( *penLight))
  7340. {
  7341. pDoc->m_selEntitySelection.Select( *penLight);
  7342. }
  7343. }
  7344. }
  7345. pDoc->SetEditingMode( ENTITY_MODE);
  7346. pDoc->m_chSelections.MarkChanged();
  7347. pDoc->UpdateAllViews( NULL);
  7348. }
  7349. void CWorldEditorView::OnDiscardShadows()
  7350. {
  7351. CWorldEditorDoc* pDoc = GetDocument();
  7352. CEntity *penEntity = NULL;
  7353. CBrushSector *pbscSector = NULL;
  7354. CBrushPolygon *pbpoPolygon = NULL;
  7355. CCastRay crRayHit = GetMouseHitInformation( m_ptMouse);
  7356. if( (crRayHit.cr_penHit != NULL) &&
  7357. (crRayHit.cr_pbpoBrushPolygon != NULL) )
  7358. {
  7359. penEntity = crRayHit.cr_penHit;
  7360. pbscSector = crRayHit.cr_pbpoBrushPolygon->bpo_pbscSector;
  7361. pbpoPolygon = crRayHit.cr_pbpoBrushPolygon;
  7362. }
  7363. if( pDoc->GetEditingMode() == ENTITY_MODE)
  7364. {
  7365. DiscardShadows( penEntity);
  7366. }
  7367. else if( pDoc->GetEditingMode() == SECTOR_MODE)
  7368. {
  7369. DiscardShadows( pbscSector);
  7370. }
  7371. else if( pDoc->GetEditingMode() == POLYGON_MODE)
  7372. {
  7373. DiscardShadows( pbpoPolygon);
  7374. }
  7375. }
  7376. void CWorldEditorView::OnCopySectorAmbient()
  7377. {
  7378. CWorldEditorDoc *pDoc = GetDocument();
  7379. CBrushSector *pbscHitted = NULL;
  7380. if( (m_penEntityHitOnContext != NULL) &&
  7381. (m_penEntityHitOnContext->GetRenderType() == CEntity::RT_BRUSH) &&
  7382. (m_pbpoRightClickedPolygon != NULL) )
  7383. {
  7384. CopySectorAmbient( m_pbpoRightClickedPolygon->bpo_pbscSector);
  7385. }
  7386. }
  7387. void CWorldEditorView::OnPasteSectorAmbient()
  7388. {
  7389. CWorldEditorDoc *pDoc = GetDocument();
  7390. CBrushSector *pbscHitted = NULL;
  7391. if( (m_penEntityHitOnContext != NULL) &&
  7392. (m_penEntityHitOnContext->GetRenderType() == CEntity::RT_BRUSH) &&
  7393. (m_pbpoRightClickedPolygon != NULL) )
  7394. {
  7395. PasteSectorAmbient( m_pbpoRightClickedPolygon->bpo_pbscSector);
  7396. }
  7397. }
  7398. void CWorldEditorView::OnSelectAllPolygons( void)
  7399. {
  7400. CWorldEditorDoc *pDoc = GetDocument();
  7401. CBrushSector *pbscHitted = NULL;
  7402. if( (m_penEntityHitOnContext != NULL) &&
  7403. (m_penEntityHitOnContext->GetRenderType() == CEntity::RT_BRUSH) &&
  7404. (m_pbpoRightClickedPolygon != NULL) )
  7405. {
  7406. pbscHitted = m_pbpoRightClickedPolygon->bpo_pbscSector;
  7407. }
  7408. if( (pbscHitted == NULL) || pbscHitted->IsSelected( BSCF_SELECTED) )
  7409. {
  7410. FOREACHINDYNAMICCONTAINER(pDoc->m_selSectorSelection, CBrushSector, itbsc)
  7411. {
  7412. FOREACHINSTATICARRAY(itbsc->bsc_abpoPolygons, CBrushPolygon, itbpo)
  7413. {
  7414. if( !itbpo->IsSelected(BPOF_SELECTED)) pDoc->m_selPolygonSelection.Select( *itbpo);
  7415. }
  7416. }
  7417. }
  7418. else
  7419. {
  7420. FOREACHINSTATICARRAY(pbscHitted->bsc_abpoPolygons, CBrushPolygon, itpo)
  7421. {
  7422. if( !itpo->IsSelected(BPOF_SELECTED)) pDoc->m_selPolygonSelection.Select( *itpo);
  7423. }
  7424. }
  7425. pDoc->SetEditingMode( POLYGON_MODE);
  7426. pDoc->m_chSelections.MarkChanged();
  7427. pDoc->UpdateAllViews( NULL);
  7428. }
  7429. void CWorldEditorView::OnSelectAllVertices()
  7430. {
  7431. CWorldEditorDoc *pDoc = GetDocument();
  7432. CBrushPolygon *pbpoHitted = NULL;
  7433. if( (m_penEntityHitOnContext != NULL) &&
  7434. (m_penEntityHitOnContext->GetRenderType() == CEntity::RT_BRUSH) &&
  7435. (m_pbpoRightClickedPolygon != NULL) )
  7436. {
  7437. pbpoHitted = m_pbpoRightClickedPolygon;
  7438. }
  7439. if( (pbpoHitted == NULL) || pbpoHitted->IsSelected( BPOF_SELECTED) )
  7440. {
  7441. FOREACHINDYNAMICCONTAINER(pDoc->m_selPolygonSelection, CBrushPolygon, itbpo)
  7442. {
  7443. FOREACHINSTATICARRAY(itbpo->bpo_apbvxTriangleVertices, CBrushVertex *, itpbvx)
  7444. {
  7445. if( !(*itpbvx)->IsSelected(BVXF_SELECTED)) pDoc->m_selVertexSelection.Select( **itpbvx);
  7446. }
  7447. }
  7448. }
  7449. else
  7450. {
  7451. FOREACHINSTATICARRAY(pbpoHitted->bpo_apbvxTriangleVertices, CBrushVertex *, itpbvx)
  7452. {
  7453. if( !(*itpbvx)->IsSelected(BVXF_SELECTED)) pDoc->m_selVertexSelection.Select( **itpbvx);
  7454. }
  7455. }
  7456. pDoc->SetEditingMode( VERTEX_MODE);
  7457. pDoc->m_chSelections.MarkChanged();
  7458. pDoc->UpdateAllViews( NULL);
  7459. }
  7460. void CWorldEditorView::OnCopySectors()
  7461. {
  7462. OnEditCopy();
  7463. }
  7464. void CWorldEditorView::OnPasteSectors()
  7465. {
  7466. OnEditPaste();
  7467. }
  7468. void CWorldEditorView::OnDeleteSectors()
  7469. {
  7470. OnDeleteEntities();
  7471. }
  7472. void CWorldEditorView::GetToolTipText( char *pToolTipText)
  7473. {
  7474. CWorldEditorDoc* pDoc = GetDocument();
  7475. CPoint CursorPos;
  7476. ::GetCursorPos(&CursorPos);
  7477. ScreenToClient(&CursorPos);
  7478. // obtain information about where mouse points into the world
  7479. BOOL bHitModels = pDoc->GetEditingMode() != POLYGON_MODE;
  7480. BOOL bHitFields = pDoc->GetEditingMode() == ENTITY_MODE;
  7481. CCastRay crRayHit = GetMouseHitInformation( m_ptMouse, FALSE, bHitModels, bHitFields);
  7482. CEntity *penEntity = crRayHit.cr_penHit;
  7483. CBrushPolygon *pbpoPolygon = crRayHit.cr_pbpoBrushPolygon;
  7484. CBrushSector *pbscSector = NULL;
  7485. if( pbpoPolygon != NULL) pbscSector = crRayHit.cr_pbpoBrushPolygon->bpo_pbscSector;
  7486. char *pchrCursor = pToolTipText;
  7487. INDEX iLongestLineLetters = 1;
  7488. CDLLEntityClass *pdecDLLClass;
  7489. if( (pDoc->GetEditingMode() == ENTITY_MODE) && (penEntity != NULL))
  7490. {
  7491. // get description line for all properties with name
  7492. pdecDLLClass = penEntity->GetClass()->ec_pdecDLLClass;
  7493. pchrCursor += sprintf(pchrCursor, "Class: %-24.24s\n", pdecDLLClass->dec_strName);
  7494. INDEX ctLetters = strlen("Class: ")+strlen(pdecDLLClass->dec_strName);
  7495. memset(pchrCursor, '�', ctLetters);
  7496. pchrCursor+=ctLetters;
  7497. *pchrCursor = '\n';
  7498. pchrCursor++;
  7499. }
  7500. INDEX ctMips = 0;
  7501. INDEX iMipIndex = 0;
  7502. INDEX ctEntities = 0;
  7503. INDEX ctSectors = 0;
  7504. INDEX ctPolygons = 0;
  7505. INDEX ctEdges = 0;
  7506. INDEX ctVertices = 0;
  7507. INDEX ctPlanes = 0;
  7508. // see if info should apply to whole selection
  7509. BOOL bCountSelection = TRUE;
  7510. if( (pDoc->GetEditingMode() == ENTITY_MODE) &&
  7511. (penEntity != NULL) &&
  7512. (!penEntity->IsSelected( ENF_SELECTED)) )
  7513. {
  7514. bCountSelection = FALSE;
  7515. }
  7516. if( (pDoc->GetEditingMode() == POLYGON_MODE) &&
  7517. (pbpoPolygon != NULL) &&
  7518. (!pbpoPolygon->IsSelected( BPOF_SELECTED)) )
  7519. {
  7520. bCountSelection = FALSE;
  7521. }
  7522. if( (pDoc->GetEditingMode() == SECTOR_MODE) &&
  7523. (pbscSector != NULL) &&
  7524. (!pbscSector->IsSelected( BSCF_SELECTED)) )
  7525. {
  7526. bCountSelection = FALSE;
  7527. }
  7528. if( pDoc->GetEditingMode() == TERRAIN_MODE)
  7529. {
  7530. CTerrain *ptrTerrain=GetTerrain();
  7531. if(ptrTerrain!=NULL)
  7532. {
  7533. pchrCursor += sprintf(pchrCursor, "%-24s %g x %g x %g\n%-24s %d x %d\n%-24s %d x %d\n%-24s %d x %d\n%-24s %d\n%-24s %d\n%-24s %g\n",
  7534. "Terrain size", ptrTerrain->tr_vTerrainSize(1),ptrTerrain->tr_vTerrainSize(2),ptrTerrain->tr_vTerrainSize(3),
  7535. "Height map size", ptrTerrain->tr_pixHeightMapWidth, ptrTerrain->tr_pixHeightMapHeight,
  7536. "Shadow map size", ptrTerrain->GetShadowMapWidth(), ptrTerrain->GetShadowMapHeight(),
  7537. "Model shading map size", ptrTerrain->GetShadingMapWidth(), ptrTerrain->GetShadingMapHeight(),
  7538. "Layers", ptrTerrain->tr_atlLayers.Count(),
  7539. "Tiles", ptrTerrain->tr_ctTiles,
  7540. "LOD switch distance", ptrTerrain->tr_fDistFactor);
  7541. }
  7542. else
  7543. {
  7544. pchrCursor += sprintf(pchrCursor, "Terrain not selected\n");
  7545. }
  7546. }
  7547. if( pDoc->GetEditingMode() == ENTITY_MODE)
  7548. {
  7549. FOREACHINDYNAMICCONTAINER(pDoc->m_woWorld.wo_cenEntities, CEntity, iten)
  7550. {
  7551. if( (bCountSelection && iten->IsSelected( ENF_SELECTED)) ||
  7552. (!bCountSelection && (iten ==penEntity)) )
  7553. {
  7554. ctEntities ++;
  7555. CEntity::RenderType rt = iten->GetRenderType();
  7556. if (rt==CEntity::RT_BRUSH || rt==CEntity::RT_FIELDBRUSH)
  7557. {
  7558. CBrush3D *pBrush3D = iten->GetBrush();
  7559. if(pBrush3D != NULL)
  7560. {
  7561. FLOAT fCurrentMipFactor = GetCurrentlyActiveMipFactor();
  7562. CBrush3D *pbrBrush = iten->GetBrush();
  7563. if( pbrBrush != NULL)
  7564. {
  7565. CBrushMip *pbmCurrentMip = pbrBrush->GetBrushMipByDistance( fCurrentMipFactor);
  7566. if( pbmCurrentMip != NULL)
  7567. {
  7568. ctSectors += pbmCurrentMip->bm_abscSectors.Count();
  7569. FOREACHINDYNAMICARRAY(pbmCurrentMip->bm_abscSectors, CBrushSector, itbsc)
  7570. {
  7571. ctPolygons += itbsc->bsc_abpoPolygons.Count();
  7572. ctEdges += itbsc->bsc_abedEdges.Count();
  7573. ctVertices+= itbsc->bsc_abvxVertices.Count();
  7574. ctPlanes += itbsc->bsc_abplPlanes.Count();
  7575. }
  7576. }
  7577. }
  7578. }
  7579. }
  7580. }
  7581. }
  7582. pchrCursor += sprintf(pchrCursor, "%-24s %d\n%-24s %d\n%-24s %d\n%-24s %d\n%-24s %d\n%-24s %d\n",
  7583. "No of entities:", ctEntities,
  7584. "No of sectors:", ctSectors,
  7585. "No of polygons:", ctPolygons,
  7586. "No of edges:", ctEdges,
  7587. "No of vertices:", ctVertices,
  7588. "No of planes:", ctPlanes);
  7589. pchrCursor += sprintf(pchrCursor, "%s\n", "������������������������������");
  7590. if( !bCountSelection)
  7591. {
  7592. CEntity::RenderType rt = penEntity->GetRenderType();
  7593. if (rt==CEntity::RT_BRUSH || rt==CEntity::RT_FIELDBRUSH)
  7594. {
  7595. CBrush3D *pBrush3D = penEntity->GetBrush();
  7596. if(pBrush3D != NULL)
  7597. {
  7598. INDEX iMip = 0;
  7599. FOREACHINLIST(CBrushMip, bm_lnInBrush, pBrush3D->br_lhBrushMips, itbm)
  7600. {
  7601. FLOAT fMipSwitchDistance = itbm->GetMipDistance();
  7602. CTString strTmp;
  7603. strTmp.PrintF("Mip %d is visible until ", iMip);
  7604. pchrCursor += sprintf(pchrCursor, "%-24s %g m\n", strTmp, fMipSwitchDistance);
  7605. iMip++;
  7606. }
  7607. pchrCursor += sprintf(pchrCursor, "%s\n", "������������������������������");
  7608. }
  7609. }
  7610. }
  7611. }
  7612. if( pDoc->GetEditingMode() == POLYGON_MODE)
  7613. {
  7614. if( bCountSelection)
  7615. {
  7616. INDEX ctEdges = 0;
  7617. ULONG ulShadowMemory = 0;
  7618. FOREACHINDYNAMICCONTAINER(pDoc->m_selPolygonSelection, CBrushPolygon, itbpo)
  7619. {
  7620. ctEdges += itbpo->bpo_abpePolygonEdges.Count();
  7621. ulShadowMemory += itbpo->bpo_smShadowMap.GetShadowSize();
  7622. }
  7623. pchrCursor += sprintf(pchrCursor, "Selection has %d polygons with %d edges\n", pDoc->m_selPolygonSelection.Count(), ctEdges);
  7624. pchrCursor += sprintf(pchrCursor, "Shadows on selected polygons occupy %g kb\n", ulShadowMemory/1024.0f);
  7625. }
  7626. if( pbpoPolygon != NULL)
  7627. {
  7628. CTextureData *ptd;
  7629. #define SET_MAPPING_INFO(mp, tex_name)\
  7630. ptd = (CTextureData*) mp.bpt_toTexture.GetData();\
  7631. if( ptd == NULL) pchrCursor += sprintf(pchrCursor, "%-24s None\n", tex_name);\
  7632. else {\
  7633. pchrCursor += sprintf(pchrCursor, "%-24s %.64s %s\n", tex_name, CTString(ptd->GetName()),\
  7634. ptd->GetDescription() );\
  7635. pchrCursor += sprintf(pchrCursor, "%-24s %s %s\n", " ",\
  7636. "Scroll: \""+pDoc->m_woWorld.wo_attTextureTransformations[mp.s.bpt_ubScroll].tt_strName+"\"",\
  7637. "Blend: \""+pDoc->m_woWorld.wo_atbTextureBlendings[mp.s.bpt_ubBlend].tb_strName+"\"");}
  7638. CBrushPolygon &bpo = *crRayHit.cr_pbpoBrushPolygon;
  7639. SET_MAPPING_INFO( bpo.bpo_abptTextures[0], "Texture 1");
  7640. SET_MAPPING_INFO( bpo.bpo_abptTextures[1], "Texture 2");
  7641. SET_MAPPING_INFO( bpo.bpo_abptTextures[2], "Texture 3");
  7642. pchrCursor += sprintf(pchrCursor, "Polygon under mouse has %d edges\n", bpo.bpo_abpePolygonEdges.Count());
  7643. pchrCursor += sprintf(pchrCursor, "Shadow on polygon under mouse occupies %g kb\n", bpo.bpo_smShadowMap.GetShadowSize()/1024.0f);
  7644. }
  7645. }
  7646. if( pDoc->GetEditingMode() == SECTOR_MODE)
  7647. {
  7648. if( bCountSelection)
  7649. {
  7650. ctSectors = pDoc->m_selSectorSelection.Count();
  7651. FOREACHINDYNAMICCONTAINER(pDoc->m_selSectorSelection, CBrushSector, itbsc)
  7652. {
  7653. ctPolygons += itbsc->bsc_abpoPolygons.Count();
  7654. ctEdges += itbsc->bsc_abedEdges.Count();
  7655. ctVertices+= itbsc->bsc_abvxVertices.Count();
  7656. ctPlanes += itbsc->bsc_abplPlanes.Count();
  7657. }
  7658. pchrCursor += sprintf(pchrCursor, "%-24s %d\n%-24s %d\n%-24s %d\n%-24s %d\n%-24s %d\n%",
  7659. "No of sectors:", ctSectors,
  7660. "No of polygons:", ctPolygons,
  7661. "No of edges:", ctEdges,
  7662. "No of vertices:", ctVertices,
  7663. "No of planes:", ctPlanes);
  7664. }
  7665. else
  7666. {
  7667. ctPolygons = pbscSector->bsc_abpoPolygons.Count();
  7668. ctEdges = pbscSector->bsc_abedEdges.Count();
  7669. ctVertices = pbscSector->bsc_abvxVertices.Count();
  7670. ctPlanes = pbscSector->bsc_abplPlanes.Count();
  7671. UBYTE ubR, ubG, ubB;
  7672. UBYTE ubH, ubS, ubV;
  7673. ColorToRGB( pbscSector->bsc_colAmbient, ubR, ubG, ubB);
  7674. ColorToHSV( pbscSector->bsc_colAmbient, ubH, ubS, ubV);
  7675. CTString strSectorName = pbscSector->bsc_strName;
  7676. if( strSectorName == "") strSectorName = "<not defined>";
  7677. INDEX iContentType = pbscSector->GetContentType();
  7678. CTString strContentType = pDoc->m_woWorld.wo_actContentTypes[iContentType].ct_strName;
  7679. if( strContentType == "") strContentType = "<not defined>";
  7680. INDEX iEnvironmentType = pbscSector->GetEnvironmentType();
  7681. CTString strEnvironmentType = pDoc->m_woWorld.wo_aetEnvironmentTypes[iEnvironmentType].et_strName;
  7682. if( strEnvironmentType == "") strEnvironmentType = "<not defined>";
  7683. INDEX iForceType = pbscSector->GetForceType();
  7684. CBrush3D *pbrBrush = pbscSector->bsc_pbmBrushMip->bm_pbrBrush;
  7685. CTString strForceType = pbrBrush->br_penEntity->GetForceName( iForceType);
  7686. if( strForceType == "") strForceType = "<not defined>";
  7687. pchrCursor += sprintf(pchrCursor, "%-24.24s %.64s\n%-24s %d\n%-24s %d\n%-24s %d\n%-24s %d\n%-24s"
  7688. "(R=%d G=%d B=%d) (H=%d S=%d V=%d)\n%-24.24s %.64s\n%-24.24s %.64s\n%-24.24s %.64s\n",
  7689. "Name:", strSectorName,
  7690. "No of polygons:", ctPolygons,
  7691. "No of edges:", ctEdges,
  7692. "No of vertices:", ctVertices,
  7693. "No of planes:", ctPlanes,
  7694. "Ambient color:", ubR, ubG, ubB, ubH, ubS, ubV,
  7695. "Content type:", strContentType,
  7696. "Environment type:", strEnvironmentType,
  7697. "Force type:", strForceType);
  7698. }
  7699. }
  7700. if( pDoc->GetEditingMode() == CSG_MODE)
  7701. {
  7702. FOREACHINDYNAMICCONTAINER(pDoc->m_pwoSecondLayer->wo_cenEntities, CEntity, iten)
  7703. {
  7704. CEntity::RenderType rt = iten->GetRenderType();
  7705. if (rt==CEntity::RT_BRUSH || rt==CEntity::RT_FIELDBRUSH)
  7706. {
  7707. CBrush3D *pBrush3D = iten->GetBrush();
  7708. if( pBrush3D != NULL)
  7709. {
  7710. FLOAT fCurrentMipFactor = GetCurrentlyActiveMipFactor();
  7711. CBrush3D *pbrBrush = iten->GetBrush();
  7712. if( pbrBrush != NULL)
  7713. {
  7714. CBrushMip *pbmCurrentMip = pbrBrush->GetBrushMipByDistance( fCurrentMipFactor);
  7715. if( pbmCurrentMip != NULL)
  7716. {
  7717. FOREACHINDYNAMICARRAY(pbmCurrentMip->bm_abscSectors, CBrushSector, itbsc)
  7718. {
  7719. ctPolygons += itbsc->bsc_abpoPolygons.Count();
  7720. ctEdges += itbsc->bsc_abedEdges.Count();
  7721. ctVertices+= itbsc->bsc_abvxVertices.Count();
  7722. ctPlanes += itbsc->bsc_abplPlanes.Count();
  7723. }
  7724. }
  7725. }
  7726. }
  7727. }
  7728. }
  7729. pchrCursor += sprintf(pchrCursor, "Primitive info:\n���������������\n%-24s %d\n%-24s %d\n%-24s %d\n%-24s %d",
  7730. "No of polygons:", ctPolygons,
  7731. "No of edges:", ctEdges,
  7732. "No of vertices:", ctVertices,
  7733. "No of planes:", ctPlanes);
  7734. }
  7735. if( (pDoc->GetEditingMode() == ENTITY_MODE) && (penEntity!=NULL) )
  7736. {
  7737. // add count of occupiing sectors and their names
  7738. INDEX ctIntersectingSectors = penEntity->en_rdSectors.Count();
  7739. INDEX ctWithName = 0;
  7740. {FOREACHSRCOFDST(penEntity->en_rdSectors, CBrushSector, bsc_rsEntities, pbsc)
  7741. if( pbsc->bsc_strName != "") ctWithName++;
  7742. ENDFOR}
  7743. INDEX ctLetters = sprintf(pchrCursor, "In %d sectors (%d with name):\n", ctIntersectingSectors, ctWithName);
  7744. if( ctLetters > iLongestLineLetters) iLongestLineLetters = ctLetters;
  7745. pchrCursor += ctLetters;
  7746. {FOREACHSRCOFDST(penEntity->en_rdSectors, CBrushSector, bsc_rsEntities, pbsc)
  7747. if( pbsc->bsc_strName != "")
  7748. {
  7749. INDEX ctLetters = sprintf(pchrCursor, "In: %-24.24s\n", pbsc->bsc_strName);
  7750. if( ctLetters > iLongestLineLetters) iLongestLineLetters = ctLetters;
  7751. pchrCursor += ctLetters;
  7752. }
  7753. ENDFOR}
  7754. for(;pdecDLLClass!=NULL; pdecDLLClass = pdecDLLClass->dec_pdecBase)
  7755. {
  7756. CTString strValue;
  7757. for(INDEX iProperty=0; iProperty<pdecDLLClass->dec_ctProperties; iProperty++)
  7758. {
  7759. CEntityProperty &epProperty = pdecDLLClass->dec_aepProperties[iProperty];
  7760. if( epProperty.ep_strName == CTString("")) continue;
  7761. strValue = "!!! Unkown property type";
  7762. switch( epProperty.ep_eptType)
  7763. {
  7764. case CEntityProperty::EPT_FLAGS:
  7765. {
  7766. strValue = "Flag array property";
  7767. }
  7768. case CEntityProperty::EPT_ENUM:
  7769. {
  7770. INDEX iCurrentEnum = ENTITYPROPERTY( &*penEntity, epProperty.ep_slOffset, INDEX);
  7771. CEntityPropertyEnumType *epEnum = epProperty.ep_pepetEnumType;
  7772. for( INDEX iEnum = 0; iEnum< epEnum->epet_ctValues; iEnum++)
  7773. {
  7774. INDEX iEnumID = epEnum->epet_aepevValues[ iEnum].epev_iValue;
  7775. if( iEnumID == iCurrentEnum)
  7776. strValue = (epEnum->epet_aepevValues[ iEnum].epev_strName);
  7777. }
  7778. break;
  7779. }
  7780. case CEntityProperty::EPT_BOOL:
  7781. {
  7782. if( ENTITYPROPERTY( &*penEntity, epProperty.ep_slOffset, BOOL))strValue = "TRUE";
  7783. else strValue = "FALSE";
  7784. break;
  7785. }
  7786. case CEntityProperty::EPT_FLOAT:
  7787. {
  7788. strValue.PrintF( "%g", ENTITYPROPERTY( &*penEntity, epProperty.ep_slOffset, FLOAT));
  7789. break;
  7790. }
  7791. case CEntityProperty::EPT_RANGE:
  7792. {
  7793. strValue.PrintF( "%g m", ENTITYPROPERTY( &*penEntity, epProperty.ep_slOffset, FLOAT));
  7794. break;
  7795. }
  7796. case CEntityProperty::EPT_COLOR:
  7797. {
  7798. COLOR colColor = ENTITYPROPERTY( &*penEntity, epProperty.ep_slOffset, COLOR);
  7799. UBYTE ubR, ubG, ubB, ubA;
  7800. UBYTE ubH, ubS, ubV;
  7801. ubA=colColor&0xFF;
  7802. ColorToRGB( colColor, ubR, ubG, ubB);
  7803. ColorToHSV( colColor, ubH, ubS, ubV);
  7804. strValue.PrintF( "RGBA(%d,%d,%d,%d) HSV(%d,%d,%d)", ubR,ubG,ubB,ubA,ubH,ubS,ubV);
  7805. break;
  7806. }
  7807. case CEntityProperty::EPT_STRING:
  7808. case CEntityProperty::EPT_STRINGTRANS:
  7809. case CEntityProperty::EPT_FILENAMENODEP:
  7810. {
  7811. strValue = ENTITYPROPERTY( &*penEntity, epProperty.ep_slOffset, CTString);
  7812. if( strValue == "") strValue = "<no value>";
  7813. break;
  7814. }
  7815. case CEntityProperty::EPT_ENTITYPTR:
  7816. {
  7817. CEntity *pen=ENTITYPROPERTY( &*penEntity, epProperty.ep_slOffset, CEntity *);
  7818. if( pen == NULL) strValue = "-> None";
  7819. else strValue = "-> "+pen->GetName();
  7820. break;
  7821. }
  7822. case CEntityProperty::EPT_PARENT:
  7823. {
  7824. CEntity *pen=penEntity->GetParent();
  7825. if( pen == NULL) strValue = "-> None";
  7826. else strValue = "-> "+pen->GetName();
  7827. break;
  7828. }
  7829. case CEntityProperty::EPT_FILENAME:
  7830. {
  7831. strValue = ENTITYPROPERTY( &*penEntity, epProperty.ep_slOffset, CTFileName);
  7832. if( strValue == "") strValue = "<no file>";
  7833. break;
  7834. }
  7835. case CEntityProperty::EPT_INDEX:
  7836. case CEntityProperty::EPT_ANGLE:
  7837. {
  7838. strValue.PrintF( "%d", ENTITYPROPERTY( &*penEntity, epProperty.ep_slOffset, INDEX) );
  7839. break;
  7840. }
  7841. case CEntityProperty::EPT_ANIMATION:
  7842. {
  7843. CAnimData *pAD = penEntity->GetAnimData( epProperty.ep_slOffset);
  7844. if( pAD == NULL)
  7845. {
  7846. strValue = "<no animation>";
  7847. }
  7848. else
  7849. {
  7850. CAnimInfo aiInfo;
  7851. INDEX iAnimation = ENTITYPROPERTY( &*penEntity, epProperty.ep_slOffset, INDEX);
  7852. pAD->GetAnimInfo( iAnimation, aiInfo);
  7853. strValue = aiInfo.ai_AnimName;
  7854. }
  7855. break;
  7856. }
  7857. case CEntityProperty::EPT_ILLUMINATIONTYPE:
  7858. {
  7859. INDEX iIllumination = ENTITYPROPERTY( &*penEntity, epProperty.ep_slOffset, INDEX);
  7860. strValue = pDoc->m_woWorld.wo_aitIlluminationTypes[iIllumination].it_strName;
  7861. break;
  7862. }
  7863. case CEntityProperty::EPT_FLOATAABBOX3D:
  7864. {
  7865. FLOATaabbox3D bbox = ENTITYPROPERTY( &*penEntity, epProperty.ep_slOffset, FLOATaabbox3D);
  7866. FLOAT3D vMin = bbox.Min();
  7867. FLOAT3D vMax = bbox.Max();
  7868. strValue.PrintF( "Min(%g,%g,%g), Max(%g,%g,%g)",
  7869. vMin(1), vMin(2), vMin(3), vMax(1), vMax(2), vMax(3));
  7870. break;
  7871. }
  7872. case CEntityProperty::EPT_FLOAT3D:
  7873. {
  7874. FLOAT3D vVector = ENTITYPROPERTY( &*penEntity, epProperty.ep_slOffset, FLOAT3D);
  7875. strValue.PrintF( "%g,%g,%g", vVector(1), vVector(2), vVector(3));
  7876. break;
  7877. }
  7878. case CEntityProperty::EPT_ANGLE3D:
  7879. {
  7880. ANGLE3D aAngle = ENTITYPROPERTY( &*penEntity, epProperty.ep_slOffset, ANGLE3D);
  7881. strValue.PrintF( "%g,%g,%g", DegAngle(aAngle(1)), DegAngle(aAngle(2)), DegAngle(aAngle(3)));
  7882. break;
  7883. }
  7884. }
  7885. INDEX ctLetters = sprintf(pchrCursor, "%-24.24s %.64s \n", epProperty.ep_strName, strValue);
  7886. if( ctLetters > iLongestLineLetters) iLongestLineLetters = ctLetters;
  7887. pchrCursor += ctLetters;
  7888. }
  7889. }
  7890. if( iLongestLineLetters>2)
  7891. {
  7892. iLongestLineLetters-=2;
  7893. memset(pchrCursor, '_', iLongestLineLetters);
  7894. pchrCursor+=iLongestLineLetters;
  7895. *pchrCursor = '\n';
  7896. pchrCursor++;
  7897. }
  7898. if( penEntity->GetParent() != NULL)
  7899. {
  7900. pchrCursor += sprintf(pchrCursor, "Parent: %s\n", penEntity->GetParent()->GetName());
  7901. }
  7902. else
  7903. {
  7904. pchrCursor += sprintf(pchrCursor, "No parent\n");
  7905. }
  7906. CTString strSpawn = "";
  7907. ULONG ulSpawn = penEntity->GetSpawnFlags();
  7908. ULONG ulAllways = SPF_EASY|SPF_NORMAL|SPF_HARD|SPF_EXTREME|SPF_SINGLEPLAYER|SPF_COOPERATIVE|SPF_DEATHMATCH;
  7909. if( (ulSpawn & ulAllways) == ulAllways)
  7910. {
  7911. pchrCursor += sprintf(pchrCursor, "%s", "Entity exists allways");
  7912. }
  7913. else
  7914. {
  7915. if( ulSpawn & SPF_EASY) strSpawn+="Easy,";
  7916. if( ulSpawn & SPF_NORMAL) strSpawn+="Normal,";
  7917. if( ulSpawn & SPF_HARD) strSpawn+="Hard,";
  7918. if( ulSpawn & SPF_EXTREME) strSpawn+="Extreme,";
  7919. if( ulSpawn & SPF_SINGLEPLAYER) strSpawn+="Single,";
  7920. if( ulSpawn & SPF_COOPERATIVE) strSpawn+="Cooperative,";
  7921. if( ulSpawn & SPF_DEATHMATCH) strSpawn+="Deathmatch,";
  7922. if( strSpawn != "")
  7923. {
  7924. pchrCursor += sprintf(pchrCursor, "%s", strSpawn);
  7925. *(pchrCursor-1) = 0;
  7926. }
  7927. else
  7928. {
  7929. pchrCursor += sprintf(pchrCursor, "%s", "Does not exist acording to spawn flags");
  7930. }
  7931. }
  7932. }
  7933. if( pDoc->GetEditingMode() == VERTEX_MODE)
  7934. {
  7935. pchrCursor += sprintf(pchrCursor, "%d %s", pDoc->m_selVertexSelection.Count(), "vertices");
  7936. }
  7937. }
  7938. void CWorldEditorView::OnMenuCopyMapping()
  7939. {
  7940. CWorldEditorDoc *pDoc = GetDocument();
  7941. ASSERT( m_pbpoRightClickedPolygon != NULL);
  7942. CopyMapping(m_pbpoRightClickedPolygon);
  7943. }
  7944. void CWorldEditorView::OnKeyPaste()
  7945. {
  7946. CWorldEditorDoc* pDoc = GetDocument();
  7947. if( pDoc->GetEditingMode() == TERRAIN_MODE)
  7948. {
  7949. theApp.m_iTerrainBrushMode=TBM_PAINT;
  7950. theApp.m_ctTerrainPageCanvas.MarkChanged();
  7951. pDoc->SetStatusLineModeInfoMessage();
  7952. }
  7953. else
  7954. {
  7955. CCastRay crRayHit = GetMouseHitInformation( m_ptMouse);
  7956. // if we hit brush entity
  7957. if( (crRayHit.cr_penHit != NULL) &&
  7958. (crRayHit.cr_pbpoBrushPolygon != NULL) )
  7959. {
  7960. // paste mapping
  7961. PasteMapping( crRayHit.cr_pbpoBrushPolygon, FALSE);
  7962. }
  7963. }
  7964. }
  7965. void CWorldEditorView::OnKeyPasteAsProjected()
  7966. {
  7967. CWorldEditorDoc* pDoc = GetDocument();
  7968. CCastRay crRayHit = GetMouseHitInformation( m_ptMouse);
  7969. // if we hit brush entity
  7970. if( (crRayHit.cr_penHit != NULL) &&
  7971. (crRayHit.cr_pbpoBrushPolygon != NULL) )
  7972. {
  7973. // paste mapping
  7974. PasteMapping( crRayHit.cr_pbpoBrushPolygon, TRUE);
  7975. }
  7976. }
  7977. void CWorldEditorView::OnMenuPasteMapping()
  7978. {
  7979. PasteMapping( m_pbpoRightClickedPolygon, FALSE);
  7980. }
  7981. void CWorldEditorView::OnMenuPasteAsProjectedMapping()
  7982. {
  7983. PasteMapping( m_pbpoRightClickedPolygon, TRUE);
  7984. }
  7985. void CWorldEditorView::CopyMapping(CBrushPolygon *pbpo)
  7986. {
  7987. CWorldEditorDoc *pDoc = GetDocument();
  7988. ASSERT(pbpo!=NULL);
  7989. CBrushPlane *pbpl = pbpo->bpo_pbplPlane;
  7990. CEntity *pen = pbpo->bpo_pbscSector->bsc_pbmBrushMip->bm_pbrBrush->br_penEntity;
  7991. ASSERT(pen!=NULL);
  7992. // get the mapping in absolute space
  7993. theApp.m_mdMapping = pbpo->bpo_abptTextures[pDoc->m_iTexture].bpt_mdMapping;
  7994. theApp.m_mdMapping.Transform(pbpl->bpl_plRelative, pen->GetPlacement(), _plOrigin);
  7995. theApp.m_plMapping = pbpl->bpl_plAbsolute;
  7996. theApp.m_mdMapping1 = pbpo->bpo_abptTextures[0].bpt_mdMapping;
  7997. theApp.m_mdMapping1.Transform(pbpl->bpl_plRelative, pen->GetPlacement(), _plOrigin);
  7998. theApp.m_plMapping1 = pbpl->bpl_plAbsolute;
  7999. theApp.m_mdMapping2 = pbpo->bpo_abptTextures[1].bpt_mdMapping;
  8000. theApp.m_mdMapping2.Transform(pbpl->bpl_plRelative, pen->GetPlacement(), _plOrigin);
  8001. theApp.m_plMapping2 = pbpl->bpl_plAbsolute;
  8002. theApp.m_mdMapping3 = pbpo->bpo_abptTextures[2].bpt_mdMapping;
  8003. theApp.m_mdMapping3.Transform(pbpl->bpl_plRelative, pen->GetPlacement(), _plOrigin);
  8004. theApp.m_plMapping3 = pbpl->bpl_plAbsolute;
  8005. }
  8006. void CWorldEditorView::PasteMappingOnOnePolygon(CBrushPolygon *pbpo, BOOL bAsProjected)
  8007. {
  8008. CWorldEditorDoc *pDoc = GetDocument();
  8009. PasteOneLayerMapping(pDoc->m_iTexture, theApp.m_mdMapping, theApp.m_plMapping, pbpo, bAsProjected);
  8010. pDoc->m_chSelections.MarkChanged();
  8011. pDoc->SetModifiedFlag( TRUE);
  8012. pDoc->UpdateAllViews( NULL);
  8013. }
  8014. void CWorldEditorView::PasteOneLayerMapping(INDEX iLayer, CMappingDefinition &md,
  8015. FLOATplane3D &pl, CBrushPolygon *pbpo, BOOL bAsProjected)
  8016. {
  8017. CWorldEditorDoc *pDoc = GetDocument();
  8018. // get the mapping in relative space of the brush polygon's entity
  8019. CEntity *pen = pbpo->bpo_pbscSector->bsc_pbmBrushMip->bm_pbrBrush->br_penEntity;
  8020. CSimpleProjection3D pr;
  8021. pr.ObjectPlacementL() = _plOrigin;
  8022. pr.ViewerPlacementL() = pen->GetPlacement();
  8023. pr.Prepare();
  8024. FLOATplane3D plRelative;
  8025. pr.Project(pl, plRelative);
  8026. CMappingDefinition mdRelative = md;
  8027. mdRelative.Transform(pl, _plOrigin, pen->GetPlacement());
  8028. // paste the mapping
  8029. if( bAsProjected)
  8030. {
  8031. pbpo->bpo_abptTextures[iLayer].bpt_mdMapping.ProjectMapping(
  8032. plRelative, mdRelative, pbpo->bpo_pbplPlane->bpl_plRelative);
  8033. }
  8034. else
  8035. {
  8036. pbpo->bpo_abptTextures[iLayer].bpt_mdMapping = mdRelative;
  8037. }
  8038. }
  8039. void CWorldEditorView::PasteMapping(CBrushPolygon *pbpo, BOOL bAsProjected)
  8040. {
  8041. CWorldEditorDoc *pDoc = GetDocument();
  8042. // paste mapping over selection if clicked polygon is selected
  8043. if( (pbpo == NULL) || (pbpo->IsSelected( BPOF_SELECTED)) )
  8044. {
  8045. FOREACHINDYNAMICCONTAINER(pDoc->m_selPolygonSelection, CBrushPolygon, itbpo)
  8046. {
  8047. PasteMappingOnOnePolygon(itbpo, bAsProjected);
  8048. }
  8049. }
  8050. else
  8051. {
  8052. PasteMappingOnOnePolygon(pbpo, bAsProjected);
  8053. }
  8054. pDoc->m_chSelections.MarkChanged();
  8055. pDoc->SetModifiedFlag( TRUE);
  8056. pDoc->UpdateAllViews( NULL);
  8057. }
  8058. void CWorldEditorView::OnSelectAllEntitiesInSectors()
  8059. {
  8060. CWorldEditorDoc *pDoc = GetDocument();
  8061. CBrushSector *pbscHitted = NULL;
  8062. if( (m_penEntityHitOnContext != NULL) &&
  8063. (m_penEntityHitOnContext->GetRenderType() == CEntity::RT_BRUSH) &&
  8064. (m_pbpoRightClickedPolygon != NULL) )
  8065. {
  8066. pbscHitted = m_pbpoRightClickedPolygon->bpo_pbscSector;
  8067. }
  8068. // if right clicked on nothing or selected sector
  8069. if( (pbscHitted == NULL) || pbscHitted->IsSelected( BSCF_SELECTED) )
  8070. {
  8071. FOREACHINDYNAMICCONTAINER(pDoc->m_selSectorSelection, CBrushSector, itbsc)
  8072. {
  8073. {FOREACHDSTOFSRC(itbsc->bsc_rsEntities, CEntity, en_rdSectors, pen)
  8074. if( !pen->IsSelected( ENF_SELECTED) )
  8075. {
  8076. pDoc->m_selEntitySelection.Select( *pen);
  8077. }
  8078. ENDFOR}
  8079. }
  8080. }
  8081. else
  8082. {
  8083. {FOREACHDSTOFSRC(pbscHitted->bsc_rsEntities, CEntity, en_rdSectors, pen)
  8084. if( !pen->IsSelected( ENF_SELECTED) )
  8085. {
  8086. pDoc->m_selEntitySelection.Select( *pen);
  8087. }
  8088. ENDFOR}
  8089. }
  8090. pDoc->SetEditingMode( ENTITY_MODE);
  8091. pDoc->m_chSelections.MarkChanged();
  8092. pDoc->UpdateAllViews( NULL);
  8093. }
  8094. void CWorldEditorView::OnSelectAllSectors()
  8095. {
  8096. CWorldEditorDoc *pDoc = GetDocument();
  8097. if( m_penEntityHitOnContext == NULL)
  8098. {
  8099. // in all entities in world
  8100. FOREACHINDYNAMICCONTAINER(pDoc->m_woWorld.wo_cenEntities, CEntity, iten)
  8101. {
  8102. CEntity::RenderType rt = iten->GetRenderType();
  8103. if (rt==CEntity::RT_BRUSH || rt==CEntity::RT_FIELDBRUSH)
  8104. {
  8105. // for each mip in its brush
  8106. FOREACHINLIST(CBrushMip, bm_lnInBrush, iten->GetBrush()->br_lhBrushMips, itbm)
  8107. {
  8108. // for all sectors in this mip
  8109. FOREACHINDYNAMICARRAY(itbm->bm_abscSectors, CBrushSector, itbsc)
  8110. {
  8111. // if sector is not hidden and not selected
  8112. if( !(itbsc->bsc_ulFlags & BSCF_HIDDEN) && !itbsc->IsSelected( BSCF_SELECTED) )
  8113. {
  8114. // select it
  8115. pDoc->m_selSectorSelection.Select( *itbsc);
  8116. }
  8117. }
  8118. }
  8119. }
  8120. }
  8121. }
  8122. // perform select sectors on whole entity selection
  8123. else if( m_penEntityHitOnContext->IsSelected( ENF_SELECTED))
  8124. {
  8125. FOREACHINDYNAMICCONTAINER(pDoc->m_selEntitySelection, CEntity, iten)
  8126. {
  8127. CEntity::RenderType rt = iten->GetRenderType();
  8128. if (rt==CEntity::RT_BRUSH || rt==CEntity::RT_FIELDBRUSH)
  8129. {
  8130. FOREACHINLIST(CBrushMip, bm_lnInBrush, iten->GetBrush()->br_lhBrushMips, itbm)
  8131. {
  8132. // for all sectors in this mip
  8133. FOREACHINDYNAMICARRAY(itbm->bm_abscSectors, CBrushSector, itbsc)
  8134. {
  8135. // if sector is not hidden and not selected
  8136. if( !(itbsc->bsc_ulFlags & BSCF_HIDDEN) && !itbsc->IsSelected( BSCF_SELECTED) )
  8137. {
  8138. // select it
  8139. pDoc->m_selSectorSelection.Select( *itbsc);
  8140. }
  8141. }
  8142. }
  8143. }
  8144. }
  8145. }
  8146. else if (m_penEntityHitOnContext->GetRenderType() == CEntity::RT_BRUSH)
  8147. {
  8148. // select all sectors in all mip levels
  8149. FOREACHINLIST(CBrushMip, bm_lnInBrush, m_penEntityHitOnContext->GetBrush()->br_lhBrushMips, itbm)
  8150. {
  8151. // select all sectors in current mip
  8152. FOREACHINDYNAMICARRAY(itbm->bm_abscSectors, CBrushSector, itbsc)
  8153. {
  8154. if( !(itbsc->bsc_ulFlags & BSCF_HIDDEN) && !itbsc->IsSelected( BSCF_SELECTED) )
  8155. {
  8156. pDoc->m_selSectorSelection.Select( *itbsc);
  8157. }
  8158. }
  8159. }
  8160. }
  8161. pDoc->SetEditingMode( SECTOR_MODE);
  8162. pDoc->m_chSelections.MarkChanged();
  8163. pDoc->UpdateAllViews( NULL);
  8164. }
  8165. void CWorldEditorView::CenterSelected(void)
  8166. {
  8167. CWorldEditorDoc *pDoc = GetDocument();
  8168. CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
  8169. CPropertyID *ppidProperty = pMainFrame->m_PropertyComboBar.GetSelectedProperty();
  8170. // bounding box of visible sectors
  8171. FLOATaabbox3D boxBoundingBox;
  8172. if( pDoc->GetEditingMode() == ENTITY_MODE && (pDoc->m_selEntitySelection.Count() != 0) )
  8173. {
  8174. FOREACHINDYNAMICCONTAINER(pDoc->m_selEntitySelection, CEntity, iten)
  8175. {
  8176. FLOAT3D vPos = iten->GetPlacement().pl_PositionVector;
  8177. FLOATaabbox3D boxEntity;
  8178. if( (ppidProperty != NULL) && (ppidProperty->pid_eptType == CEntityProperty::EPT_RANGE))
  8179. {
  8180. // obtain property ptr
  8181. CEntityProperty *penpProperty = iten->PropertyForName( ppidProperty->pid_strName);
  8182. // get editing range
  8183. FLOAT fRange = ENTITYPROPERTY( &*iten, penpProperty->ep_slOffset, FLOAT);
  8184. boxEntity |= FLOATaabbox3D( FLOAT3D(0.0f, 0.0f ,0.0f), fRange);
  8185. }
  8186. else
  8187. {
  8188. iten->GetSize( boxEntity);
  8189. }
  8190. boxEntity+=vPos;
  8191. boxBoundingBox |= boxEntity;
  8192. }
  8193. }
  8194. else if( pDoc->GetEditingMode() == TERRAIN_MODE)
  8195. {
  8196. CTerrain *ptrTerrain=GetTerrain();
  8197. if(ptrTerrain!=NULL)
  8198. {
  8199. ptrTerrain->GetAllTerrainBBox(boxBoundingBox);
  8200. }
  8201. }
  8202. else if( pDoc->GetEditingMode() == POLYGON_MODE && (pDoc->m_selPolygonSelection.Count() != 0) )
  8203. {
  8204. FOREACHINDYNAMICCONTAINER(pDoc->m_selPolygonSelection, CBrushPolygon, itbpo)
  8205. {
  8206. boxBoundingBox |= itbpo->bpo_boxBoundingBox;
  8207. }
  8208. }
  8209. else if( pDoc->GetEditingMode() == SECTOR_MODE && (pDoc->m_selSectorSelection.Count() != 0) )
  8210. {
  8211. FOREACHINDYNAMICCONTAINER(pDoc->m_selSectorSelection, CBrushSector, itbsc)
  8212. {
  8213. boxBoundingBox |= itbsc->bsc_boxBoundingBox;
  8214. }
  8215. }
  8216. else if( (pDoc->GetEditingMode() == VERTEX_MODE) && (pDoc->m_selVertexSelection.Count() != 0) )
  8217. {
  8218. FOREACHINDYNAMICCONTAINER(pDoc->m_selVertexSelection, CBrushVertex, itbvtx)
  8219. {
  8220. FLOATaabbox3D boxVtxBox = FLOATaabbox3D( itbvtx->bvx_vAbsolute);
  8221. boxVtxBox.Expand( 20);
  8222. boxBoundingBox |= boxVtxBox;
  8223. }
  8224. }
  8225. else
  8226. {
  8227. FOREACHINDYNAMICCONTAINER(pDoc->m_woWorld.wo_cenEntities, CEntity, iten)
  8228. {
  8229. CEntity::RenderType rt = iten->GetRenderType();
  8230. if (rt==CEntity::RT_BRUSH || rt==CEntity::RT_FIELDBRUSH)
  8231. {
  8232. // for each mip in its brush
  8233. FOREACHINLIST(CBrushMip, bm_lnInBrush, iten->GetBrush()->br_lhBrushMips, itbm)
  8234. {
  8235. // for all sectors in this mip
  8236. FOREACHINDYNAMICARRAY(itbm->bm_abscSectors, CBrushSector, itbsc)
  8237. {
  8238. // if sector is not hidden
  8239. if( !(itbsc->bsc_ulFlags & BSCF_HIDDEN))
  8240. {
  8241. boxBoundingBox |= itbsc->bsc_boxBoundingBox;
  8242. }
  8243. }
  8244. }
  8245. }
  8246. else
  8247. {
  8248. FLOAT3D vPos = iten->GetPlacement().pl_PositionVector;
  8249. FLOATaabbox3D boxEntity;
  8250. iten->GetSize( boxEntity);
  8251. boxEntity+=vPos;
  8252. boxBoundingBox |= boxEntity;
  8253. }
  8254. }
  8255. }
  8256. AllignBox( boxBoundingBox);
  8257. }
  8258. void CWorldEditorView::AllignBox( FLOATaabbox3D bbox)
  8259. {
  8260. CWorldEditorDoc *pDoc = GetDocument();
  8261. CChildFrame *pCF = GetChildFrame();
  8262. FLOAT3D vSize = bbox.Size();
  8263. if( vSize.Length() <= 1.0f)
  8264. vSize = FLOAT3D( 2.0f, 2.0f, 2.0f);
  8265. // width is alligned inside horizontal borders of draw port, height and lenght
  8266. // are alligned to height of draw port
  8267. FLOAT fDX = (FLOAT)m_pdpDrawPort->GetWidth()*9/10;
  8268. FLOAT fDY = (FLOAT)m_pdpDrawPort->GetHeight()*9/10;
  8269. FLOAT fWantedZoom = Min( Min( fDX/vSize(1), fDY/vSize(2)), fDY/vSize(3));
  8270. if( (fWantedZoom>1E-4) && (fWantedZoom<1E4) )
  8271. {
  8272. // create a slave viewer
  8273. CSlaveViewer svViewer(pCF->m_mvViewer, m_ptProjectionType, pDoc->m_plGrid,
  8274. m_pdpDrawPort);
  8275. pCF->m_mvViewer.mv_fTargetDistance = svViewer.GetDistanceForZoom(fWantedZoom);
  8276. pCF->m_mvViewer.SetTargetPlacement( bbox.Center());
  8277. }
  8278. pDoc->m_chSelections.MarkChanged();
  8279. pDoc->UpdateAllViews( NULL);
  8280. }
  8281. void CWorldEditorView::AllignPolygon( CBrushPolygon *pbpo)
  8282. {
  8283. CWorldEditorDoc *pDoc = GetDocument();
  8284. CChildFrame *pCF = GetChildFrame();
  8285. FLOATaabbox3D bbox = pbpo->bpo_boxBoundingBox;
  8286. FLOAT3D vSize = bbox.Size();
  8287. if( vSize.Length() <= 1.0f)
  8288. vSize = FLOAT3D( 2.0f, 2.0f, 2.0f);
  8289. // width is alligned inside horizontal borders of draw port, height and lenght
  8290. // are alligned to height of draw port
  8291. FLOAT fDX = (FLOAT)m_pdpDrawPort->GetWidth()*9/10;
  8292. FLOAT fDY = (FLOAT)m_pdpDrawPort->GetHeight()*9/10;
  8293. FLOAT fWantedZoom = Min( Min( fDX/vSize(1), fDY/vSize(2)), fDY/vSize(3));
  8294. if( (fWantedZoom>1E-4) && (fWantedZoom<1E4) )
  8295. {
  8296. // create a slave viewer
  8297. CSlaveViewer svViewer(pCF->m_mvViewer, m_ptProjectionType, pDoc->m_plGrid, m_pdpDrawPort);
  8298. pCF->m_mvViewer.mv_fTargetDistance = svViewer.GetDistanceForZoom(fWantedZoom);
  8299. FLOAT3D vDirection = pbpo->bpo_pbplPlane->bpl_plAbsolute;
  8300. DirectionVectorToAngles( -vDirection, pCF->m_mvViewer.mv_plViewer.pl_OrientationAngle);
  8301. pCF->m_mvViewer.SetTargetPlacement( bbox.Center());
  8302. }
  8303. pDoc->m_chSelections.MarkChanged();
  8304. pDoc->UpdateAllViews( NULL);
  8305. }
  8306. void CWorldEditorView::OnCloneToMorePreciseMip()
  8307. {
  8308. OnAddMorePreciseMip(TRUE);
  8309. }
  8310. void CWorldEditorView::OnCreateEmptyMorePreciseMip()
  8311. {
  8312. OnAddMorePreciseMip(FALSE);
  8313. }
  8314. void CWorldEditorView::OnCloneToRougherMipLevel()
  8315. {
  8316. OnAddRougherMipLevel( TRUE);
  8317. }
  8318. void CWorldEditorView::OnCreateEmptyRougherMip()
  8319. {
  8320. OnAddRougherMipLevel( FALSE);
  8321. }
  8322. void CWorldEditorView::OnAddMorePreciseMip(BOOL bClone)
  8323. {
  8324. // remember current time as time when last mip brushing option has been used
  8325. _fLastMipBrushingOptionUsed = _pTimer->GetRealTimeTick();
  8326. CWorldEditorDoc* pDoc = GetDocument();
  8327. pDoc->RememberUndo();
  8328. CBrushMip *pbmCurrentMip = GetCurrentBrushMip();
  8329. if (pbmCurrentMip==NULL) {
  8330. return;
  8331. }
  8332. CBrushMip *pbmAdded = pbmCurrentMip->bm_pbrBrush->NewBrushMipBefore(pbmCurrentMip, bClone);
  8333. GetChildFrame()->m_fManualMipBrushingFactor = pbmAdded->GetMipDistance()-0.01f;
  8334. // document has changed
  8335. pDoc->SetModifiedFlag();
  8336. // update all views
  8337. pDoc->UpdateAllViews( NULL);
  8338. // set text describing data that is edited
  8339. SetEditingDataPaneInfo( TRUE);
  8340. }
  8341. void CWorldEditorView::OnAddRougherMipLevel(BOOL bClone)
  8342. {
  8343. // remember current time as time when last mip brushing option has been used
  8344. _fLastMipBrushingOptionUsed = _pTimer->GetRealTimeTick();
  8345. CWorldEditorDoc* pDoc = GetDocument();
  8346. pDoc->RememberUndo();
  8347. CBrushMip *pbmCurrentMip = GetCurrentBrushMip();
  8348. if (pbmCurrentMip==NULL) {
  8349. return;
  8350. }
  8351. CBrushMip *pbmAdded = pbmCurrentMip->bm_pbrBrush->NewBrushMipAfter(pbmCurrentMip, bClone);
  8352. GetChildFrame()->m_fManualMipBrushingFactor = pbmAdded->GetMipDistance()-0.01f;
  8353. // document has changed
  8354. pDoc->SetModifiedFlag();
  8355. // update all views
  8356. pDoc->UpdateAllViews( NULL);
  8357. // set text describing data that is edited
  8358. SetEditingDataPaneInfo( TRUE);
  8359. }
  8360. // get current brush mip of current csg target brush
  8361. CBrushMip *CWorldEditorView::GetCurrentBrushMip(void)
  8362. {
  8363. CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
  8364. CEntity *penBrush = pMainFrame->m_CSGDesitnationCombo.GetSelectedBrushEntity();
  8365. if (penBrush==NULL) {
  8366. return NULL;
  8367. }
  8368. // get entity's brush
  8369. CBrush3D *pbrBrush = penBrush->GetBrush();
  8370. if( pbrBrush == NULL) {
  8371. return NULL;
  8372. }
  8373. // get currently active mip factor
  8374. FLOAT fCurrentMipFactor = GetCurrentlyActiveMipFactor();
  8375. return pbrBrush->GetBrushMipByDistance(fCurrentMipFactor);
  8376. }
  8377. void CWorldEditorView::OnDeleteMip()
  8378. {
  8379. // remember current time as time when last mip brushing option has been used
  8380. _fLastMipBrushingOptionUsed = _pTimer->GetRealTimeTick();
  8381. CBrushMip *pbmCurrentMip = GetCurrentBrushMip();
  8382. if (pbmCurrentMip==NULL) {
  8383. return;
  8384. }
  8385. // delete currently visible mip brush
  8386. pbmCurrentMip->bm_pbrBrush->DeleteBrushMip(pbmCurrentMip);
  8387. CWorldEditorDoc* pDoc = GetDocument();
  8388. // document has changed
  8389. pDoc->SetModifiedFlag();
  8390. // update all views
  8391. pDoc->UpdateAllViews( NULL);
  8392. // set text describing data that is edited
  8393. SetEditingDataPaneInfo( TRUE);
  8394. }
  8395. void CWorldEditorView::OnPreviousMipBrush()
  8396. {
  8397. CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
  8398. CEntity *penBrush = pMainFrame->m_CSGDesitnationCombo.GetSelectedBrushEntity();
  8399. if (penBrush == NULL) return;
  8400. CBrush3D &brBrush = *penBrush->en_pbrBrush;
  8401. // remember current time as time when last mip brushing option has been used
  8402. _fLastMipBrushingOptionUsed = _pTimer->GetRealTimeTick();
  8403. CBrushMip *pbmCurrentMip = GetCurrentBrushMip();
  8404. CBrushMip *pbmPrevMip = NULL;
  8405. if (pbmCurrentMip==NULL)
  8406. {
  8407. pbmPrevMip = brBrush.GetLastMip();
  8408. }
  8409. else
  8410. {
  8411. pbmPrevMip = pbmCurrentMip->GetPrev();
  8412. }
  8413. if (pbmPrevMip==NULL) return;
  8414. // set manual mip factor to show previous mip brush
  8415. GetChildFrame()->m_fManualMipBrushingFactor = pbmPrevMip->GetMipDistance()-0.01f;
  8416. // update all views
  8417. CWorldEditorDoc* pDoc = GetDocument();
  8418. pDoc->UpdateAllViews( NULL);
  8419. // set text describing data that is edited
  8420. SetEditingDataPaneInfo( TRUE);
  8421. }
  8422. void CWorldEditorView::OnNextMipBrush()
  8423. {
  8424. // remember current time as time when last mip brushing option has been used
  8425. _fLastMipBrushingOptionUsed = _pTimer->GetRealTimeTick();
  8426. CBrushMip *pbmCurrentMip = GetCurrentBrushMip();
  8427. if (pbmCurrentMip==NULL) {
  8428. return;
  8429. }
  8430. CBrushMip *pbmNextMip = pbmCurrentMip->GetNext();
  8431. if (pbmNextMip==NULL) {
  8432. return;
  8433. }
  8434. // set manual mip factor to show next mip brush
  8435. GetChildFrame()->m_fManualMipBrushingFactor = pbmNextMip->GetMipDistance()-0.01f;
  8436. // update all views
  8437. CWorldEditorDoc* pDoc = GetDocument();
  8438. pDoc->UpdateAllViews( NULL);
  8439. // set text describing data that is edited
  8440. SetEditingDataPaneInfo( TRUE);
  8441. }
  8442. void CWorldEditorView::OnUpdateCloneToMorePreciseMip(CCmdUI* pCmdUI)
  8443. {
  8444. pCmdUI->Enable( GetCurrentBrushMip()!=NULL && !GetChildFrame()->m_bAutoMipBrushingOn);
  8445. }
  8446. void CWorldEditorView::OnUpdateCloneToRougherMipLevel(CCmdUI* pCmdUI)
  8447. {
  8448. pCmdUI->Enable( GetCurrentBrushMip()!=NULL && !GetChildFrame()->m_bAutoMipBrushingOn);
  8449. }
  8450. void CWorldEditorView::OnUpdateCreateEmptyMorePreciseMip(CCmdUI* pCmdUI)
  8451. {
  8452. pCmdUI->Enable( GetCurrentBrushMip()!=NULL && !GetChildFrame()->m_bAutoMipBrushingOn);
  8453. }
  8454. void CWorldEditorView::OnUpdateCreateEmptyRougherMip(CCmdUI* pCmdUI)
  8455. {
  8456. pCmdUI->Enable( GetCurrentBrushMip()!=NULL && !GetChildFrame()->m_bAutoMipBrushingOn);
  8457. }
  8458. void CWorldEditorView::OnUpdateDeleteMip(CCmdUI* pCmdUI)
  8459. {
  8460. CBrushMip *pbm = GetCurrentBrushMip();
  8461. pCmdUI->Enable(
  8462. pbm!=NULL &&
  8463. pbm->bm_pbrBrush->br_lhBrushMips.Count()>1 &&
  8464. !GetChildFrame()->m_bAutoMipBrushingOn);
  8465. }
  8466. void CWorldEditorView::OnUpdatePreviousMipBrush(CCmdUI* pCmdUI)
  8467. {
  8468. CBrushMip *pbm = GetCurrentBrushMip();
  8469. pCmdUI->Enable(
  8470. ( (pbm==NULL) ||
  8471. (pbm->GetPrev()!=NULL) ) &&
  8472. !GetChildFrame()->m_bAutoMipBrushingOn);
  8473. }
  8474. void CWorldEditorView::OnUpdateNextMipBrush(CCmdUI* pCmdUI)
  8475. {
  8476. CBrushMip *pbm = GetCurrentBrushMip();
  8477. pCmdUI->Enable(
  8478. pbm!=NULL &&
  8479. pbm->GetNext()!=NULL &&
  8480. !GetChildFrame()->m_bAutoMipBrushingOn);
  8481. }
  8482. // paste polygon properties but don't paste mapping
  8483. void CWorldEditorView::OnEditPasteAlternative()
  8484. {
  8485. CWorldEditorDoc* pDoc = GetDocument();
  8486. CCastRay crRayHit = GetMouseHitInformation( m_ptMouse);
  8487. if( theApp.m_ctLastCopyType == CT_POLYGON_PROPERTIES)
  8488. {
  8489. // if mouse is over polygon
  8490. if( (crRayHit.cr_penHit != NULL) &&
  8491. (crRayHit.cr_pbpoBrushPolygon != NULL) )
  8492. {
  8493. if( crRayHit.cr_pbpoBrushPolygon->IsSelected( BPOF_SELECTED))
  8494. {
  8495. FOREACHINDYNAMICCONTAINER(pDoc->m_selPolygonSelection, CBrushPolygon, itbpo)
  8496. {
  8497. // apply all parameters from remembered
  8498. itbpo->CopyProperties( *theApp.m_pbpoClipboardPolygon);
  8499. }
  8500. }
  8501. else
  8502. {
  8503. // apply all parameters from remembered
  8504. crRayHit.cr_pbpoBrushPolygon->CopyProperties( *theApp.m_pbpoClipboardPolygon);
  8505. }
  8506. }
  8507. pDoc->m_chSelections.MarkChanged();
  8508. pDoc->SetModifiedFlag();
  8509. pDoc->UpdateAllViews( NULL);
  8510. }
  8511. if( theApp.m_ctLastCopyType == CT_POLYGON_PROPERTIES_ALTERNATIVE)
  8512. {
  8513. // if mouse is over polygon
  8514. if( (crRayHit.cr_penHit != NULL) &&
  8515. (crRayHit.cr_pbpoBrushPolygon != NULL) )
  8516. {
  8517. if( crRayHit.cr_pbpoBrushPolygon->IsSelected( BPOF_SELECTED))
  8518. {
  8519. FOREACHINDYNAMICCONTAINER(pDoc->m_selPolygonSelection, CBrushPolygon, itbpo)
  8520. {
  8521. // apply all parameters from remembered
  8522. itbpo->CopyProperties( *theApp.m_pbpoClipboardPolygon);
  8523. PasteOneLayerMapping(0, theApp.m_mdMapping1, theApp.m_plMapping1, &*itbpo, TRUE);
  8524. PasteOneLayerMapping(1, theApp.m_mdMapping2, theApp.m_plMapping2, &*itbpo, TRUE);
  8525. PasteOneLayerMapping(2, theApp.m_mdMapping3, theApp.m_plMapping3, &*itbpo, TRUE);
  8526. }
  8527. }
  8528. else
  8529. {
  8530. // apply all parameters from remembered
  8531. crRayHit.cr_pbpoBrushPolygon->CopyProperties( *theApp.m_pbpoClipboardPolygon);
  8532. PasteOneLayerMapping(0, theApp.m_mdMapping1, theApp.m_plMapping1, crRayHit.cr_pbpoBrushPolygon, TRUE);
  8533. PasteOneLayerMapping(1, theApp.m_mdMapping2, theApp.m_plMapping2, crRayHit.cr_pbpoBrushPolygon, TRUE);
  8534. PasteOneLayerMapping(2, theApp.m_mdMapping3, theApp.m_plMapping3, crRayHit.cr_pbpoBrushPolygon, TRUE);
  8535. }
  8536. }
  8537. pDoc->m_chSelections.MarkChanged();
  8538. pDoc->SetModifiedFlag();
  8539. pDoc->UpdateAllViews( NULL);
  8540. }
  8541. else if (theApp.m_ctLastCopyType == CT_ENTITY)
  8542. {
  8543. CWorldEditorDoc* pDoc = GetDocument();
  8544. CPlacement3D plPaste = GetMouseInWorldPlacement();
  8545. // load world from clipboard file and start template CSG
  8546. pDoc->StartTemplateCSG( plPaste, (CTString)"Temp\\ClipboardEntityWorld.wld");
  8547. // update all views
  8548. pDoc->UpdateAllViews( NULL);
  8549. }
  8550. }
  8551. void CWorldEditorView::OnUpdateEditPasteAlternative(CCmdUI* pCmdUI)
  8552. {
  8553. }
  8554. void CWorldEditorView::ToggleHittedPolygon( CCastRay &crRayHit)
  8555. {
  8556. CWorldEditorDoc* pDoc = GetDocument();
  8557. if( (crRayHit.cr_penHit == NULL) ||
  8558. (crRayHit.cr_pbpoBrushPolygon == NULL) )
  8559. {
  8560. return;
  8561. }
  8562. BOOL bShift = (GetKeyState( VK_SHIFT)&0x8000) != 0;
  8563. // remember if first clicked polygon is to be deselected
  8564. m_bWeDeselectedFirstPolygon = crRayHit.cr_pbpoBrushPolygon->IsSelected( BPOF_SELECTED) != 0;
  8565. INDEX ctPolygonsSelectedBefore = pDoc->m_selPolygonSelection.Count();
  8566. // if shift is not pressed
  8567. if( !bShift)
  8568. {
  8569. if( ctPolygonsSelectedBefore>1)
  8570. {
  8571. m_bWeDeselectedFirstPolygon = FALSE;
  8572. }
  8573. // deselect all selected polygons
  8574. pDoc->m_selPolygonSelection.Clear();
  8575. }
  8576. // if we have to deselect first polygon but we didn't deselect it with clear
  8577. if( (m_bWeDeselectedFirstPolygon) &&
  8578. (crRayHit.cr_pbpoBrushPolygon->IsSelected( BPOF_SELECTED)) )
  8579. {
  8580. // deselect clicked polygon
  8581. pDoc->m_selPolygonSelection.Deselect( *crRayHit.cr_pbpoBrushPolygon);
  8582. }
  8583. // if we must select first polygon
  8584. if( !m_bWeDeselectedFirstPolygon)
  8585. {
  8586. // select it
  8587. pDoc->m_selPolygonSelection.Select( *crRayHit.cr_pbpoBrushPolygon);
  8588. }
  8589. // mark that selections have been changed
  8590. pDoc->m_chSelections.MarkChanged();
  8591. // update all views
  8592. pDoc->UpdateAllViews( this);
  8593. }
  8594. void CWorldEditorView::ToggleHittedSector( CCastRay &crRayHit)
  8595. {
  8596. CWorldEditorDoc* pDoc = GetDocument();
  8597. // if any polygon hit toggle or add its sector
  8598. if( (crRayHit.cr_penHit == NULL) ||
  8599. (crRayHit.cr_pbscBrushSector == NULL) )
  8600. {
  8601. return;
  8602. }
  8603. BOOL bShift = (GetKeyState( VK_SHIFT)&0x8000) != 0;
  8604. // remember if first clicked sector is to be deselected
  8605. m_bWeDeselectedFirstSector = crRayHit.cr_pbscBrushSector->IsSelected( BSCF_SELECTED) != 0;
  8606. INDEX ctSectorsSelectedBefore = pDoc->m_selSectorSelection.Count();
  8607. // if shift is not pressed
  8608. if( !bShift)
  8609. {
  8610. if( ctSectorsSelectedBefore>1)
  8611. {
  8612. m_bWeDeselectedFirstSector = FALSE;
  8613. }
  8614. // deselect all selected sectors
  8615. pDoc->m_selSectorSelection.Clear();
  8616. }
  8617. // if we have to deselect first sector but we didn't deselect it with clear
  8618. if( (m_bWeDeselectedFirstSector) &&
  8619. (crRayHit.cr_pbscBrushSector->IsSelected( BSCF_SELECTED)) )
  8620. {
  8621. // deselect clicked sector
  8622. pDoc->m_selSectorSelection.Deselect( *crRayHit.cr_pbscBrushSector);
  8623. }
  8624. // if we must select first sector
  8625. if( !m_bWeDeselectedFirstSector)
  8626. {
  8627. // select it
  8628. pDoc->m_selSectorSelection.Select( *crRayHit.cr_pbscBrushSector);
  8629. }
  8630. // mark that selections have been changed
  8631. pDoc->m_chSelections.MarkChanged();
  8632. // update all views
  8633. pDoc->UpdateAllViews( this);
  8634. }
  8635. void CWorldEditorView::OnSelectAllEntitiesInWorld()
  8636. {
  8637. CWorldEditorDoc* pDoc = GetDocument();
  8638. // deselect all entities
  8639. pDoc->m_selEntitySelection.Clear();
  8640. // add each entity in world
  8641. FOREACHINDYNAMICCONTAINER(pDoc->m_woWorld.wo_cenEntities, CEntity, iten)
  8642. {
  8643. CBrushSector *pbscSector = iten->GetFirstSector();
  8644. BOOL bSectorVisible = (pbscSector == NULL) ||
  8645. !(pbscSector->bsc_ulFlags & BSCF_HIDDEN);
  8646. // if it isn't classified in hidden sector and is not hidden itself
  8647. if( bSectorVisible && !(iten->en_ulFlags&ENF_HIDDEN))
  8648. {
  8649. // add it to selection
  8650. pDoc->m_selEntitySelection.Select( *iten);
  8651. }
  8652. }
  8653. // mark that selections have been changed
  8654. pDoc->m_chSelections.MarkChanged();
  8655. // update all views
  8656. pDoc->UpdateAllViews( NULL);
  8657. }
  8658. void CWorldEditorView::OnSelectSectorsWithSameName()
  8659. {
  8660. CWorldEditorDoc* pDoc = GetDocument();
  8661. if( m_pbpoRightClickedPolygon == NULL) return;
  8662. // select all sectors in world with same name
  8663. CBrushSector *pbscSrc = m_pbpoRightClickedPolygon->bpo_pbscSector;
  8664. FOREACHINDYNAMICCONTAINER(pDoc->m_woWorld.wo_cenEntities, CEntity, iten)
  8665. {
  8666. CEntity::RenderType rt = iten->GetRenderType();
  8667. if (rt==CEntity::RT_BRUSH || rt==CEntity::RT_FIELDBRUSH)
  8668. {
  8669. // for each mip in its brush
  8670. FOREACHINLIST(CBrushMip, bm_lnInBrush, iten->GetBrush()->br_lhBrushMips, itbm)
  8671. {
  8672. // for all sectors in this mip
  8673. FOREACHINDYNAMICARRAY(itbm->bm_abscSectors, CBrushSector, itbsc)
  8674. {
  8675. // if sector is not hidden and has same name, select it
  8676. if( !(itbsc->bsc_ulFlags & BSCF_HIDDEN) &&
  8677. (itbsc->bsc_strName==pbscSrc->bsc_strName) )
  8678. {
  8679. if( !itbsc->IsSelected( BSCF_SELECTED))
  8680. {
  8681. pDoc->m_selSectorSelection.Select( *itbsc);
  8682. }
  8683. }
  8684. }
  8685. }
  8686. }
  8687. }
  8688. // mark that selections have been changed
  8689. pDoc->m_chSelections.MarkChanged();
  8690. // update all views
  8691. pDoc->UpdateAllViews( this);
  8692. }
  8693. void CWorldEditorView::OnSelectSectorsArroundEntity()
  8694. {
  8695. CWorldEditorDoc *pDoc = GetDocument();
  8696. // if none selected
  8697. if(pDoc->m_selEntitySelection.Count() == 0)
  8698. {
  8699. // perform on ray-hitted entity
  8700. BOOL bHitModels = pDoc->GetEditingMode() != POLYGON_MODE;
  8701. BOOL bHitFields = pDoc->GetEditingMode() == ENTITY_MODE;
  8702. CCastRay crRayHit = GetMouseHitInformation( m_ptMouse, FALSE, bHitModels, bHitFields);
  8703. // if none of entities is hitted
  8704. if(crRayHit.cr_penHit == NULL) return;
  8705. {FOREACHSRCOFDST(crRayHit.cr_penHit->en_rdSectors, CBrushSector, bsc_rsEntities, pbsc)
  8706. // if sector is not hidden and not selected
  8707. if( !(pbsc->bsc_ulFlags & BSCF_HIDDEN) && !pbsc->IsSelected( BSCF_SELECTED) )
  8708. {
  8709. // select it
  8710. pDoc->m_selSectorSelection.Select( *pbsc);
  8711. }
  8712. ENDFOR}
  8713. }
  8714. else
  8715. {
  8716. FOREACHINDYNAMICCONTAINER(pDoc->m_selEntitySelection, CEntity, iten)
  8717. {
  8718. {FOREACHSRCOFDST(iten->en_rdSectors, CBrushSector, bsc_rsEntities, pbsc)
  8719. // if sector is not hidden and not selected
  8720. if( !(pbsc->bsc_ulFlags & BSCF_HIDDEN) && !pbsc->IsSelected( BSCF_SELECTED) )
  8721. {
  8722. // select it
  8723. pDoc->m_selSectorSelection.Select( *pbsc);
  8724. }
  8725. ENDFOR}
  8726. }
  8727. }
  8728. pDoc->SetEditingMode( SECTOR_MODE);
  8729. pDoc->m_chSelections.MarkChanged();
  8730. pDoc->UpdateAllViews( NULL);
  8731. }
  8732. void CWorldEditorView::OnSelectSectorsArroundEntityOnContext()
  8733. {
  8734. CWorldEditorDoc *pDoc = GetDocument();
  8735. if( m_penEntityHitOnContext == NULL)
  8736. {
  8737. return;
  8738. }
  8739. // perform select sectors on whole entity selection
  8740. if( m_penEntityHitOnContext->IsSelected( ENF_SELECTED))
  8741. {
  8742. FOREACHINDYNAMICCONTAINER(pDoc->m_selEntitySelection, CEntity, iten)
  8743. {
  8744. {FOREACHSRCOFDST(iten->en_rdSectors, CBrushSector, bsc_rsEntities, pbsc)
  8745. // if sector is not hidden and not selected
  8746. if( !(pbsc->bsc_ulFlags & BSCF_HIDDEN) && !pbsc->IsSelected( BSCF_SELECTED) )
  8747. {
  8748. // select it
  8749. pDoc->m_selSectorSelection.Select( *pbsc);
  8750. }
  8751. ENDFOR}
  8752. }
  8753. }
  8754. else
  8755. {
  8756. {FOREACHSRCOFDST(m_penEntityHitOnContext->en_rdSectors, CBrushSector, bsc_rsEntities, pbsc)
  8757. // if sector is not hidden and not selected
  8758. if( !(pbsc->bsc_ulFlags & BSCF_HIDDEN) && !pbsc->IsSelected( BSCF_SELECTED) )
  8759. {
  8760. // select it
  8761. pDoc->m_selSectorSelection.Select( *pbsc);
  8762. }
  8763. ENDFOR}
  8764. }
  8765. pDoc->SetEditingMode( SECTOR_MODE);
  8766. pDoc->m_chSelections.MarkChanged();
  8767. pDoc->UpdateAllViews( NULL);
  8768. }
  8769. void CWorldEditorView::CopySectorAmbient( CBrushSector *pbscSector)
  8770. {
  8771. theApp.m_colSectorAmbientClipboard = pbscSector->bsc_colAmbient;
  8772. }
  8773. void CWorldEditorView::PasteSectorAmbient( CBrushSector *pbscSector)
  8774. {
  8775. CWorldEditorDoc* pDoc = GetDocument();
  8776. if( (pbscSector == NULL) || (pbscSector->IsSelected( BSCF_SELECTED)) )
  8777. {
  8778. FOREACHINDYNAMICCONTAINER(pDoc->m_selSectorSelection, CBrushSector, itbsc)
  8779. {
  8780. itbsc->bsc_colAmbient = theApp.m_colSectorAmbientClipboard;
  8781. itbsc->UncacheLightMaps();
  8782. }
  8783. }
  8784. else
  8785. {
  8786. pbscSector->bsc_colAmbient = theApp.m_colSectorAmbientClipboard;
  8787. pbscSector->UncacheLightMaps();
  8788. }
  8789. pDoc->SetModifiedFlag( TRUE);
  8790. pDoc->UpdateAllViews( NULL);
  8791. }
  8792. void CWorldEditorView::PasteTexture( CBrushPolygon *pbpoPolygon)
  8793. {
  8794. if( theApp.m_ptdActiveTexture==NULL) return;
  8795. CWorldEditorDoc* pDoc = GetDocument();
  8796. CTFileName fnTextureName = theApp.m_ptdActiveTexture->GetName();
  8797. try
  8798. {
  8799. if( (pbpoPolygon == NULL) || (pbpoPolygon->IsSelected( BPOF_SELECTED)) )
  8800. {
  8801. FOREACHINDYNAMICCONTAINER(pDoc->m_selPolygonSelection, CBrushPolygon, itbpo)
  8802. {
  8803. itbpo->bpo_abptTextures[pDoc->m_iTexture].bpt_toTexture.SetData_t( fnTextureName);
  8804. }
  8805. }
  8806. else
  8807. {
  8808. pbpoPolygon->bpo_abptTextures[pDoc->m_iTexture].bpt_toTexture.SetData_t( fnTextureName);
  8809. }
  8810. pDoc->m_chSelections.MarkChanged();
  8811. pDoc->SetModifiedFlag( TRUE);
  8812. }
  8813. catch( char *strError)
  8814. {
  8815. AfxMessageBox( CString(strError));
  8816. return;
  8817. }
  8818. pDoc->UpdateAllViews( NULL);
  8819. }
  8820. void CWorldEditorView::StorePolygonSelection(CBrushPolygonSelection &selPolygons,
  8821. CDynamicContainer<CBrushPolygon> &dcPolygons)
  8822. {
  8823. dcPolygons.Clear();
  8824. FOREACHINDYNAMICCONTAINER( selPolygons, CBrushPolygon, itbpo)
  8825. {
  8826. dcPolygons.Add( itbpo);
  8827. }
  8828. }
  8829. void CWorldEditorView::RestorePolygonSelection(CBrushPolygonSelection &selPolygons,
  8830. CDynamicContainer<CBrushPolygon> &dcPolygons)
  8831. {
  8832. selPolygons.Clear();
  8833. FOREACHINDYNAMICCONTAINER( dcPolygons, CBrushPolygon, itbpo)
  8834. {
  8835. selPolygons.Select( *itbpo);
  8836. }
  8837. }
  8838. void CWorldEditorView::DiscardShadows( CEntity *penEntity)
  8839. {
  8840. CWorldEditorDoc* pDoc = GetDocument();
  8841. CDynamicContainer<CBrushPolygon> dcPolygons;
  8842. StorePolygonSelection( pDoc->m_selPolygonSelection, dcPolygons);
  8843. pDoc->m_selPolygonSelection.Clear();
  8844. FLOATaabbox3D boxForDiscard;
  8845. if( (penEntity == NULL) || (penEntity->IsSelected( ENF_SELECTED)) )
  8846. {
  8847. FOREACHINDYNAMICCONTAINER(pDoc->m_selEntitySelection, CEntity, iten)
  8848. {
  8849. // if it is brush
  8850. if (iten->en_RenderType == CEntity::RT_BRUSH)
  8851. {
  8852. // for each mip in its brush
  8853. FOREACHINLIST(CBrushMip, bm_lnInBrush, iten->en_pbrBrush->br_lhBrushMips, itbm)
  8854. {
  8855. // for all sectors in this mip
  8856. FOREACHINDYNAMICARRAY(itbm->bm_abscSectors, CBrushSector, itbsc)
  8857. {
  8858. // for all polygons in sector
  8859. FOREACHINSTATICARRAY(itbsc->bsc_abpoPolygons, CBrushPolygon, itbpo)
  8860. {
  8861. boxForDiscard |= itbpo->bpo_boxBoundingBox;
  8862. itbpo->bpo_smShadowMap.DiscardAllLayers();
  8863. itbpo->InitializeShadowMap();
  8864. pDoc->m_selPolygonSelection.Select( *itbpo);
  8865. }
  8866. itbsc->UncacheLightMaps();
  8867. }
  8868. }
  8869. }
  8870. }
  8871. }
  8872. else
  8873. {
  8874. // if it is brush
  8875. if (penEntity->en_RenderType == CEntity::RT_BRUSH)
  8876. {
  8877. // for each mip in its brush
  8878. FOREACHINLIST(CBrushMip, bm_lnInBrush, penEntity->en_pbrBrush->br_lhBrushMips, itbm)
  8879. {
  8880. // for all sectors in this mip
  8881. FOREACHINDYNAMICARRAY(itbm->bm_abscSectors, CBrushSector, itbsc)
  8882. {
  8883. // for all polygons in sector
  8884. FOREACHINSTATICARRAY(itbsc->bsc_abpoPolygons, CBrushPolygon, itbpo)
  8885. {
  8886. boxForDiscard |= itbpo->bpo_boxBoundingBox;
  8887. itbpo->bpo_smShadowMap.DiscardAllLayers();
  8888. itbpo->InitializeShadowMap();
  8889. pDoc->m_selPolygonSelection.Select( *itbpo);
  8890. }
  8891. itbsc->UncacheLightMaps();
  8892. }
  8893. }
  8894. }
  8895. }
  8896. pDoc->m_woWorld.FindShadowLayers( boxForDiscard, TRUE);
  8897. pDoc->SetModifiedFlag( TRUE);
  8898. pDoc->UpdateAllViews( NULL);
  8899. RestorePolygonSelection( pDoc->m_selPolygonSelection, dcPolygons);
  8900. }
  8901. void CWorldEditorView::DiscardShadows( CBrushSector *pbscSector)
  8902. {
  8903. CWorldEditorDoc* pDoc = GetDocument();
  8904. CDynamicContainer<CBrushPolygon> dcPolygons;
  8905. StorePolygonSelection( pDoc->m_selPolygonSelection, dcPolygons);
  8906. pDoc->m_selPolygonSelection.Clear();
  8907. FLOATaabbox3D boxForDiscard;
  8908. if( (pbscSector == NULL) || (pbscSector->IsSelected( BSCF_SELECTED)) )
  8909. {
  8910. FOREACHINDYNAMICCONTAINER(pDoc->m_selSectorSelection, CBrushSector, itbsc)
  8911. {
  8912. FOREACHINSTATICARRAY(itbsc->bsc_abpoPolygons, CBrushPolygon, itbpo)
  8913. {
  8914. boxForDiscard |= itbpo->bpo_boxBoundingBox;
  8915. itbpo->bpo_smShadowMap.DiscardAllLayers();
  8916. itbpo->InitializeShadowMap();
  8917. pDoc->m_selPolygonSelection.Select( *itbpo);
  8918. }
  8919. itbsc->UncacheLightMaps();
  8920. }
  8921. }
  8922. else
  8923. {
  8924. FOREACHINSTATICARRAY(pbscSector->bsc_abpoPolygons, CBrushPolygon, itbpo)
  8925. {
  8926. boxForDiscard |= itbpo->bpo_boxBoundingBox;
  8927. itbpo->bpo_smShadowMap.DiscardAllLayers();
  8928. itbpo->InitializeShadowMap();
  8929. pDoc->m_selPolygonSelection.Select( *itbpo);
  8930. }
  8931. pbscSector->UncacheLightMaps();
  8932. }
  8933. pDoc->m_woWorld.FindShadowLayers( boxForDiscard, TRUE);
  8934. pDoc->SetModifiedFlag( TRUE);
  8935. pDoc->UpdateAllViews( NULL);
  8936. RestorePolygonSelection( pDoc->m_selPolygonSelection, dcPolygons);
  8937. }
  8938. void CWorldEditorView::DiscardShadows( CBrushPolygon *pbpoPolygon)
  8939. {
  8940. CWorldEditorDoc* pDoc = GetDocument();
  8941. CDynamicContainer<CBrushPolygon> dcPolygons;
  8942. StorePolygonSelection( pDoc->m_selPolygonSelection, dcPolygons);
  8943. FLOATaabbox3D boxForDiscard;
  8944. if( (pbpoPolygon == NULL) || (pbpoPolygon->IsSelected( BPOF_SELECTED)) )
  8945. {
  8946. FOREACHINDYNAMICCONTAINER(pDoc->m_selPolygonSelection, CBrushPolygon, itbpo)
  8947. {
  8948. // calculate bounding box for all polygons
  8949. boxForDiscard |= itbpo->bpo_boxBoundingBox;
  8950. itbpo->bpo_smShadowMap.DiscardAllLayers();
  8951. itbpo->InitializeShadowMap();
  8952. }
  8953. }
  8954. else
  8955. {
  8956. pbpoPolygon->bpo_smShadowMap.DiscardAllLayers();
  8957. pbpoPolygon->InitializeShadowMap();
  8958. boxForDiscard |= pbpoPolygon->bpo_boxBoundingBox;
  8959. pDoc->m_selPolygonSelection.Clear();
  8960. pDoc->m_selPolygonSelection.Select( *pbpoPolygon);
  8961. }
  8962. pDoc->m_woWorld.FindShadowLayers( boxForDiscard, TRUE);
  8963. pDoc->SetModifiedFlag( TRUE);
  8964. pDoc->UpdateAllViews( NULL);
  8965. RestorePolygonSelection( pDoc->m_selPolygonSelection, dcPolygons);
  8966. }
  8967. void CWorldEditorView::OnInsertVertex()
  8968. {
  8969. CWorldEditorDoc* pDoc = GetDocument();
  8970. MarkClosestVtxAndEdgeOnPrimitiveBase( m_ptMouse);
  8971. if( m_iDragEdge != -1) pDoc->InsertPrimitiveVertex( m_iDragEdge, m_vMouseDownSecondLayer);
  8972. }
  8973. void CWorldEditorView::OnDeleteVertex()
  8974. {
  8975. CWorldEditorDoc* pDoc = GetDocument();
  8976. MarkClosestVtxAndEdgeOnPrimitiveBase( m_ptMouse);
  8977. if( m_iDragVertice != -1) pDoc->DeletePrimitiveVertex( m_iDragVertice);
  8978. }
  8979. void CWorldEditorView::OnKeyBackslash()
  8980. {
  8981. CWorldEditorDoc* pDoc = GetDocument();
  8982. if( pDoc->GetEditingMode() == TERRAIN_MODE)
  8983. {
  8984. CPoint ptMouse;
  8985. GetCursorPos( &ptMouse);
  8986. if( theApp.m_iTerrainEditMode==TEM_LAYER)
  8987. {
  8988. CTerrainLayer *ptlLayer=GetLayer();
  8989. if(ptlLayer==NULL) return;
  8990. if( ptlLayer->tl_ltType==LT_TILE)
  8991. {
  8992. InvokeTerrainTilePalette(ptMouse.x, ptMouse.y);
  8993. return;
  8994. }
  8995. }
  8996. InvokeTerrainBrushPalette( ptMouse.x-BRUSH_PALETTE_WIDTH/2, ptMouse.y+BRUSH_PALETTE_HEIGHT/2);
  8997. }
  8998. else
  8999. {
  9000. CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
  9001. if( pDoc->m_selEntitySelection.Count() == 1)
  9002. {
  9003. pDoc->m_selEntitySelection.Lock();
  9004. CEntity *penOnlySelected = &pDoc->m_selEntitySelection[0];
  9005. pDoc->m_selEntitySelection.Unlock();
  9006. CEntity *penToSelect = NULL;
  9007. CPropertyID *ppidProperty = pMainFrame->m_PropertyComboBar.GetSelectedProperty();
  9008. if( ppidProperty == NULL) return;
  9009. if( ppidProperty->pid_eptType == CEntityProperty::EPT_PARENT)
  9010. {
  9011. penToSelect = penOnlySelected->GetParent();
  9012. }
  9013. else if( ppidProperty->pid_eptType == CEntityProperty::EPT_ENTITYPTR)
  9014. {
  9015. // obtain entity class ptr
  9016. CDLLEntityClass *pdecDLLClass = penOnlySelected->GetClass()->ec_pdecDLLClass;
  9017. // for all classes in hierarchy of this entity
  9018. for(;
  9019. pdecDLLClass!=NULL;
  9020. pdecDLLClass = pdecDLLClass->dec_pdecBase) {
  9021. // for all properties
  9022. for(INDEX iProperty=0; iProperty<pdecDLLClass->dec_ctProperties; iProperty++) {
  9023. CEntityProperty &epProperty = pdecDLLClass->dec_aepProperties[iProperty];
  9024. if( (ppidProperty->pid_strName == epProperty.ep_strName) &&
  9025. (ppidProperty->pid_eptType == epProperty.ep_eptType) )
  9026. {
  9027. // get target entity
  9028. penToSelect = ENTITYPROPERTY( &*penOnlySelected, epProperty.ep_slOffset, CEntityPointer);
  9029. }
  9030. }
  9031. }
  9032. }
  9033. if( penToSelect == NULL) return;
  9034. pDoc->m_selEntitySelection.Clear();
  9035. pDoc->m_selEntitySelection.Select( *penToSelect);
  9036. pMainFrame->m_PropertyComboBar.UpdateData( FALSE);
  9037. pDoc->m_chSelections.MarkChanged();
  9038. }
  9039. }
  9040. }
  9041. void CWorldEditorView::OnSavePicturesForEnvironment()
  9042. {
  9043. CWorldEditorDoc* pDoc = GetDocument();
  9044. pDoc->m_selEntitySelection.Lock();
  9045. CEntity *pen = &pDoc->m_selEntitySelection[0];
  9046. pDoc->m_selEntitySelection.Unlock();
  9047. CTFileName fnName = _EngineGUI.FileRequester( "Save pictures as ...",
  9048. FILTER_TGA FILTER_ALL FILTER_END,"Environment pictures directory", "Textures\\");
  9049. if( fnName == "") return;
  9050. CTFileName fnBase = fnName.NoExt();
  9051. CDrawPort *pdp;
  9052. CImageInfo II;
  9053. CTextureData TD;
  9054. CAnimData AD;
  9055. ULONG flags = NONE;
  9056. CChildFrame *pChild = GetChildFrame();
  9057. // create canvas to render picture
  9058. _pGfx->CreateWorkCanvas( 256, 256, &pdp);
  9059. if( pdp != NULL)
  9060. {
  9061. if( pdp->Lock())
  9062. {
  9063. CViewPrefs vpOld = m_vpViewPrefs;
  9064. // set rendering type for world
  9065. m_vpViewPrefs.m_wrpWorldRenderPrefs.SetHiddenLinesOn( FALSE);
  9066. m_vpViewPrefs.m_wrpWorldRenderPrefs.SetEditorModelsOn( FALSE);
  9067. m_vpViewPrefs.m_wrpWorldRenderPrefs.SetFieldBrushesOn( FALSE);
  9068. m_vpViewPrefs.m_wrpWorldRenderPrefs.SetBackgroundTextureOn( TRUE);
  9069. m_vpViewPrefs.m_wrpWorldRenderPrefs.SetVerticesFillType( CWorldRenderPrefs::FT_NONE);
  9070. m_vpViewPrefs.m_wrpWorldRenderPrefs.SetEdgesFillType( CWorldRenderPrefs::FT_NONE);
  9071. m_vpViewPrefs.m_wrpWorldRenderPrefs.SetPolygonsFillType( CWorldRenderPrefs::FT_TEXTURE);
  9072. m_vpViewPrefs.m_wrpWorldRenderPrefs.SetLensFlaresType( CWorldRenderPrefs::LFT_REFLECTIONS_AND_GLARE);
  9073. // for models
  9074. m_vpViewPrefs.m_mrpModelRenderPrefs.SetRenderType( RT_TEXTURE);
  9075. m_vpViewPrefs.m_mrpModelRenderPrefs.SetShadingType( RT_SHADING_PHONG);
  9076. m_vpViewPrefs.m_mrpModelRenderPrefs.SetShadowQuality( 0);
  9077. m_vpViewPrefs.m_mrpModelRenderPrefs.SetWire( FALSE);
  9078. m_vpViewPrefs.m_mrpModelRenderPrefs.SetHiddenLines( FALSE);
  9079. m_vpViewPrefs.m_mrpModelRenderPrefs.BBoxFrameShow( FALSE);
  9080. m_vpViewPrefs.m_mrpModelRenderPrefs.BBoxAllShow( FALSE);
  9081. // remember old viewer settings
  9082. CPlacement3D plOrgPlacement = pChild->m_mvViewer.mv_plViewer;
  9083. FLOAT fOldTargetDistance = pChild->m_mvViewer.mv_fTargetDistance;
  9084. enum CSlaveViewer::ProjectionType ptOld = m_ptProjectionType;
  9085. m_ptProjectionType = CSlaveViewer::PT_PERSPECTIVE;
  9086. // set new viewer settings
  9087. pChild->m_mvViewer.mv_plViewer = pen->GetPlacement();
  9088. pChild->m_mvViewer.mv_fTargetDistance = 10.0f;
  9089. #define GRAB_BCG( ext, angDelta) \
  9090. pChild->m_mvViewer.mv_plViewer = pen->GetPlacement();\
  9091. pChild->m_mvViewer.mv_plViewer.pl_OrientationAngle+=angDelta;\
  9092. RenderView( pdp);\
  9093. pdp->GrabScreen(II);\
  9094. try { II.SaveTGA_t( fnBase+ext); } \
  9095. catch (char *strError)\
  9096. { AfxMessageBox(CString(strError)); }
  9097. GRAB_BCG( "N.tga", ANGLE3D( 0, 0, 0));
  9098. GRAB_BCG( "W.tga", ANGLE3D( 90.0f, 0, 0));
  9099. GRAB_BCG( "S.tga", ANGLE3D( 180.0f, 0, 0));
  9100. GRAB_BCG( "E.tga", ANGLE3D( -90.0f, 0, 0));
  9101. GRAB_BCG( "C.tga", ANGLE3D( 0, 90.0f, 0));
  9102. GRAB_BCG( "F.tga", ANGLE3D( 0, -90.0f, 0));
  9103. // restore original settings
  9104. m_ptProjectionType = ptOld;
  9105. pChild->m_mvViewer.mv_plViewer = plOrgPlacement;
  9106. pChild->m_mvViewer.mv_fTargetDistance = fOldTargetDistance;
  9107. m_vpViewPrefs = vpOld;
  9108. pdp->Unlock();
  9109. }
  9110. _pGfx->DestroyWorkCanvas( pdp);
  9111. pdp = NULL;
  9112. }
  9113. }
  9114. void CWorldEditorView::OnUpdateSavePicturesForEnvironment(CCmdUI* pCmdUI)
  9115. {
  9116. CWorldEditorDoc* pDoc = GetDocument();
  9117. pCmdUI->Enable( pDoc->m_selEntitySelection.Count() == 1);
  9118. }
  9119. BOOL CWorldEditorView::OnEraseBkgnd(CDC* pDC)
  9120. {
  9121. return TRUE;
  9122. }
  9123. void CWorldEditorView::OnMenuAlignMappingU()
  9124. {
  9125. CWorldEditorDoc* pDoc = GetDocument();
  9126. if( pDoc->m_selPolygonSelection.Count() == 0) return;
  9127. FLOAT fLastU = 0;
  9128. // for each selected polygon
  9129. FOREACHINDYNAMICCONTAINER(pDoc->m_selPolygonSelection, CBrushPolygon, itbpo) {
  9130. CBrushPolygon &bpo = *itbpo;
  9131. CMappingDefinition &md = bpo.bpo_abptTextures[pDoc->m_iTexture].bpt_mdMapping;
  9132. // find min and max u for the polygon
  9133. md.md_fUOffset = 0;
  9134. FLOAT fMinU = UpperLimit(0.0f);
  9135. FLOAT fMaxU = LowerLimit(0.0f);
  9136. for(INDEX ibpe=0; ibpe<bpo.bpo_abpePolygonEdges.Count(); ibpe++) {
  9137. CBrushPolygonEdge &bpe = bpo.bpo_abpePolygonEdges[ibpe];
  9138. FLOAT3D v0, v1;
  9139. MEX2D(vTex0);
  9140. bpe.GetVertexCoordinatesRelative(v0, v1);
  9141. md.GetTextureCoordinates(
  9142. bpo.bpo_pbplPlane->bpl_pwplWorking->wpl_mvRelative, v0, vTex0);
  9143. FLOAT fU = vTex0(1)/1024.0f;
  9144. fMinU = Min(fMinU, fU);
  9145. fMaxU = Max(fMaxU, fU);
  9146. }
  9147. // add the offsets to its mapping
  9148. md.md_fUOffset=fMinU-fLastU;
  9149. fLastU += fMaxU-fMinU;
  9150. }
  9151. CPrintF("Total length u: %fm\n", fLastU);
  9152. pDoc->m_chSelections.MarkChanged();
  9153. pDoc->SetModifiedFlag( TRUE);
  9154. pDoc->UpdateAllViews( NULL);
  9155. }
  9156. void CWorldEditorView::OnKeyCtrlShiftK()
  9157. {
  9158. CWorldEditorDoc* pDoc = GetDocument();
  9159. if( pDoc->GetEditingMode() == TERRAIN_MODE)
  9160. {
  9161. ApplyRndNoiseOntoTerrain();
  9162. }
  9163. else
  9164. {
  9165. OnMenuAlignMappingV();
  9166. }
  9167. }
  9168. void CWorldEditorView::OnMenuAlignMappingV()
  9169. {
  9170. CWorldEditorDoc* pDoc = GetDocument();
  9171. if( pDoc->m_selPolygonSelection.Count() == 0) return;
  9172. FLOAT fLastV = 0;
  9173. // for each selected polygon
  9174. FOREACHINDYNAMICCONTAINER(pDoc->m_selPolygonSelection, CBrushPolygon, itbpo) {
  9175. CBrushPolygon &bpo = *itbpo;
  9176. CMappingDefinition &md = bpo.bpo_abptTextures[pDoc->m_iTexture].bpt_mdMapping;
  9177. // find min and max v for the polygon
  9178. md.md_fVOffset = 0;
  9179. FLOAT fMinV = UpperLimit(0.0f);
  9180. FLOAT fMaxV = LowerLimit(0.0f);
  9181. for(INDEX ibpe=0; ibpe<bpo.bpo_abpePolygonEdges.Count(); ibpe++) {
  9182. CBrushPolygonEdge &bpe = bpo.bpo_abpePolygonEdges[ibpe];
  9183. FLOAT3D v0, v1;
  9184. MEX2D(vTex0);
  9185. bpe.GetVertexCoordinatesRelative(v0, v1);
  9186. md.GetTextureCoordinates(
  9187. bpo.bpo_pbplPlane->bpl_pwplWorking->wpl_mvRelative, v0, vTex0);
  9188. FLOAT fV = vTex0(2)/1024.0f;
  9189. fMinV = Min(fMinV, fV);
  9190. fMaxV = Max(fMaxV, fV);
  9191. }
  9192. // add the offsets to its mapping
  9193. md.md_fVOffset=fMinV-fLastV;
  9194. fLastV += fMaxV-fMinV;
  9195. }
  9196. CPrintF("Total length v %fm\n", fLastV);
  9197. pDoc->m_chSelections.MarkChanged();
  9198. pDoc->SetModifiedFlag( TRUE);
  9199. pDoc->UpdateAllViews( NULL);
  9200. }
  9201. void CWorldEditorView::OnDestroy()
  9202. {
  9203. // destroy canvas that is currently used
  9204. _pGfx->DestroyWindowCanvas( m_pvpViewPort);
  9205. m_pvpViewPort = NULL;
  9206. CView::OnDestroy();
  9207. }
  9208. void CWorldEditorView::OnFallDown()
  9209. {
  9210. CWorldEditorDoc *pDoc = GetDocument();
  9211. FOREACHINDYNAMICCONTAINER(pDoc->m_selEntitySelection, CEntity, iten)
  9212. {
  9213. iten->FallDownToFloor();
  9214. }
  9215. pDoc->UpdateAllViews( NULL);
  9216. pDoc->SetModifiedFlag( TRUE);
  9217. }
  9218. void CWorldEditorView::OnUpdatePrevious(CCmdUI* pCmdUI)
  9219. {
  9220. CWorldEditorDoc *pDoc = GetDocument();
  9221. BOOL bShift = (GetKeyState( VK_SHIFT)&0x8000) != 0;
  9222. // for browsing trough properties
  9223. if( bShift && (pDoc->GetEditingMode() == ENTITY_MODE) && (pDoc->m_selEntitySelection.Count() != 0) )
  9224. {
  9225. pCmdUI->Enable( TRUE);
  9226. }
  9227. else if( (pDoc->GetEditingMode() == POLYGON_MODE) && (pDoc->m_selPolygonSelection.Count() != 0) )
  9228. {
  9229. pCmdUI->Enable( TRUE);
  9230. }
  9231. else if( pDoc->GetEditingMode() == TERRAIN_MODE)
  9232. {
  9233. pCmdUI->Enable( TRUE);
  9234. }
  9235. else if( (pDoc->m_bBrowseEntitiesMode) || (pDoc->m_cenEntitiesSelectedByVolume.Count()>0) )
  9236. {
  9237. pDoc->OnUpdatePreviousSelectedEntity(pCmdUI);
  9238. }
  9239. else
  9240. {
  9241. OnUpdatePreviousMipBrush( pCmdUI);
  9242. }
  9243. }
  9244. void CWorldEditorView::OnUpdateNext(CCmdUI* pCmdUI)
  9245. {
  9246. CWorldEditorDoc *pDoc = GetDocument();
  9247. BOOL bShift = (GetKeyState( VK_SHIFT)&0x8000) != 0;
  9248. // for browsing trough properties
  9249. if( bShift && (pDoc->GetEditingMode() == ENTITY_MODE) && (pDoc->m_selEntitySelection.Count() != 0) )
  9250. {
  9251. pCmdUI->Enable( TRUE);
  9252. }
  9253. else if( (pDoc->GetEditingMode() == POLYGON_MODE) && (pDoc->m_selPolygonSelection.Count() != 0) )
  9254. {
  9255. pCmdUI->Enable( TRUE);
  9256. }
  9257. else if( pDoc->GetEditingMode() == TERRAIN_MODE)
  9258. {
  9259. pCmdUI->Enable( TRUE);
  9260. }
  9261. else if( (pDoc->m_bBrowseEntitiesMode) || (pDoc->m_cenEntitiesSelectedByVolume.Count()>0) )
  9262. {
  9263. pDoc->OnUpdateNextSelectedEntity(pCmdUI);
  9264. }
  9265. else
  9266. {
  9267. OnUpdateNextMipBrush( pCmdUI);
  9268. }
  9269. }
  9270. void CWorldEditorView::OnPrevious()
  9271. {
  9272. CWorldEditorDoc *pDoc = GetDocument();
  9273. CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
  9274. CPropertyComboBar &dlgProperty = pMainFrame->m_PropertyComboBar;
  9275. BOOL bShift = (GetKeyState( VK_SHIFT)&0x8000) != 0;
  9276. BOOL bCtrl = (GetKeyState( VK_CONTROL)&0x8000) != 0;
  9277. // in entity mode use shift to select previous property
  9278. if( (pDoc->GetEditingMode() == ENTITY_MODE) && bShift )
  9279. {
  9280. // shift only is used to select previous empty target property
  9281. if( !bCtrl)
  9282. {
  9283. dlgProperty.SelectPreviousEmptyTarget();
  9284. }
  9285. // ctrl+shift is used to select previous property
  9286. else
  9287. {
  9288. dlgProperty.SelectPreviousProperty();
  9289. }
  9290. }
  9291. else if( (pDoc->GetEditingMode() == POLYGON_MODE) && (pDoc->m_selPolygonSelection.Count() != 0) )
  9292. {
  9293. OnPreviousPolygon();
  9294. }
  9295. else if( (pDoc->m_bBrowseEntitiesMode) || (pDoc->m_cenEntitiesSelectedByVolume.Count()>0) )
  9296. {
  9297. pDoc->OnPreviousSelectedEntity();
  9298. }
  9299. else if( pDoc->GetEditingMode() == TERRAIN_MODE)
  9300. {
  9301. CTerrainLayer *ptlLayer=GetLayer();
  9302. if(theApp.m_iTerrainEditMode==TEM_LAYER && ptlLayer!=NULL && ptlLayer->tl_ltType==LT_TILE)
  9303. {
  9304. CDynamicContainer<CTileInfo> dcTileInfo;
  9305. INDEX ctTilesPerRaw=0;
  9306. ObtainLayerTileInfo( &dcTileInfo, ptlLayer->tl_ptdTexture, ctTilesPerRaw);
  9307. INDEX ctTiles=dcTileInfo.Count();
  9308. ptlLayer->tl_iSelectedTile= Clamp( ptlLayer->tl_iSelectedTile+INDEX(1), (INDEX)0, INDEX(ctTiles-1) );
  9309. // free allocated tile info structures
  9310. for(INDEX i=0; i<dcTileInfo.Count(); i++)
  9311. {
  9312. delete &dcTileInfo[i];
  9313. }
  9314. dcTileInfo.Clear();
  9315. }
  9316. else
  9317. {
  9318. theApp.m_fCurrentTerrainBrush=ClampUp(theApp.m_fCurrentTerrainBrush+1.0f,FLOAT(CT_BRUSHES-1));
  9319. theApp.m_ctTerrainPageCanvas.MarkChanged();
  9320. }
  9321. }
  9322. else
  9323. {
  9324. OnPreviousMipBrush();
  9325. }
  9326. }
  9327. void CWorldEditorView::OnNext()
  9328. {
  9329. CWorldEditorDoc *pDoc = GetDocument();
  9330. CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
  9331. CPropertyComboBar &dlgProperty = pMainFrame->m_PropertyComboBar;
  9332. BOOL bShift = (GetKeyState( VK_SHIFT)&0x8000) != 0;
  9333. BOOL bCtrl = (GetKeyState( VK_CONTROL)&0x8000) != 0;
  9334. // in entity mode use shift to select next property
  9335. if( (pDoc->GetEditingMode() == ENTITY_MODE) && bShift )
  9336. {
  9337. // shift only is used to select next empty target property
  9338. if( !bCtrl)
  9339. {
  9340. dlgProperty.SelectNextEmptyTarget();
  9341. }
  9342. // ctrl+shift is used to select next property
  9343. else
  9344. {
  9345. dlgProperty.SelectNextProperty();
  9346. }
  9347. }
  9348. else if( (pDoc->GetEditingMode() == POLYGON_MODE) && (pDoc->m_selPolygonSelection.Count() != 0) )
  9349. {
  9350. OnNextPolygon();
  9351. }
  9352. else if( pDoc->GetEditingMode() == TERRAIN_MODE)
  9353. {
  9354. CTerrainLayer *ptlLayer=GetLayer();
  9355. if(theApp.m_iTerrainEditMode==TEM_LAYER && ptlLayer!=NULL && ptlLayer->tl_ltType==LT_TILE)
  9356. {
  9357. CDynamicContainer<CTileInfo> dcTileInfo;
  9358. INDEX ctTilesPerRaw=0;
  9359. ObtainLayerTileInfo( &dcTileInfo, ptlLayer->tl_ptdTexture, ctTilesPerRaw);
  9360. INDEX ctTiles=dcTileInfo.Count();
  9361. ptlLayer->tl_iSelectedTile= Clamp( ptlLayer->tl_iSelectedTile-INDEX(1), (INDEX)0, INDEX(ctTiles-1) );
  9362. // free allocated tile info structures
  9363. for(INDEX i=0; i<dcTileInfo.Count(); i++)
  9364. {
  9365. delete &dcTileInfo[i];
  9366. }
  9367. dcTileInfo.Clear();
  9368. }
  9369. else
  9370. {
  9371. theApp.m_fCurrentTerrainBrush=ClampDn(theApp.m_fCurrentTerrainBrush-1.0f,0.0f);
  9372. theApp.m_ctTerrainPageCanvas.MarkChanged();
  9373. }
  9374. }
  9375. else if( (pDoc->m_bBrowseEntitiesMode) || (pDoc->m_cenEntitiesSelectedByVolume.Count()>0) )
  9376. {
  9377. pDoc->OnNextSelectedEntity();
  9378. }
  9379. else
  9380. {
  9381. OnNextMipBrush();
  9382. }
  9383. }
  9384. void CWorldEditorView::OnPreviousPolygon(void)
  9385. {
  9386. CWorldEditorDoc *pDoc = GetDocument();
  9387. pDoc->m_selPolygonSelection.Lock();
  9388. ASSERT( pDoc->m_selPolygonSelection.Count() != 0);
  9389. INDEX iSelectedPolygon=0;
  9390. if( !pDoc->m_selPolygonSelection.IsMember( pDoc->m_pbpoLastCentered))
  9391. {
  9392. pDoc->m_pbpoLastCentered = &pDoc->m_selPolygonSelection[0];
  9393. iSelectedPolygon=0;
  9394. }
  9395. else
  9396. {
  9397. INDEX iCurrent = pDoc->m_selPolygonSelection.Index( pDoc->m_pbpoLastCentered);
  9398. INDEX iNext = (iCurrent+1) % pDoc->m_selPolygonSelection.Count();
  9399. pDoc->m_pbpoLastCentered = &pDoc->m_selPolygonSelection[iNext];
  9400. iSelectedPolygon=iNext;
  9401. }
  9402. AllignPolygon( pDoc->m_pbpoLastCentered);
  9403. CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
  9404. CTString strMessage;
  9405. strMessage.PrintF("Polygon %d/%d", iSelectedPolygon, pDoc->m_selPolygonSelection.Count());
  9406. pMainFrame->SetStatusBarMessage( strMessage, STATUS_LINE_PANE, 2);
  9407. pDoc->m_selPolygonSelection.Unlock();
  9408. }
  9409. void CWorldEditorView::OnNextPolygon(void)
  9410. {
  9411. CWorldEditorDoc *pDoc = GetDocument();
  9412. pDoc->m_selPolygonSelection.Lock();
  9413. ASSERT( pDoc->m_selPolygonSelection.Count() != 0);
  9414. INDEX iSelectedPolygon=0;
  9415. if( !pDoc->m_selPolygonSelection.IsMember( pDoc->m_pbpoLastCentered))
  9416. {
  9417. pDoc->m_pbpoLastCentered = &pDoc->m_selPolygonSelection[0];
  9418. iSelectedPolygon=0;
  9419. }
  9420. else
  9421. {
  9422. INDEX iCurrent = pDoc->m_selPolygonSelection.Index( pDoc->m_pbpoLastCentered);
  9423. INDEX iPrev = (iCurrent+pDoc->m_selPolygonSelection.Count()-1) % pDoc->m_selPolygonSelection.Count();
  9424. pDoc->m_pbpoLastCentered = &pDoc->m_selPolygonSelection[iPrev];
  9425. iSelectedPolygon=iPrev;
  9426. }
  9427. AllignPolygon( pDoc->m_pbpoLastCentered);
  9428. CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
  9429. CTString strMessage;
  9430. strMessage.PrintF("Polygon %d/%d", iSelectedPolygon, pDoc->m_selPolygonSelection.Count());
  9431. pMainFrame->SetStatusBarMessage( strMessage, STATUS_LINE_PANE, 2);
  9432. pDoc->m_selPolygonSelection.Unlock();
  9433. }
  9434. void CWorldEditorView::OnRemoveUnusedTextures()
  9435. {
  9436. CWorldEditorDoc *pDoc = GetDocument();
  9437. try
  9438. {
  9439. // for each entity in the world
  9440. FOREACHINDYNAMICCONTAINER(pDoc->m_woWorld.wo_cenEntities, CEntity, iten) {
  9441. // if it is brush entity
  9442. if (iten->en_RenderType == CEntity::RT_BRUSH) {
  9443. // for each mip in its brush
  9444. FOREACHINLIST(CBrushMip, bm_lnInBrush, iten->en_pbrBrush->br_lhBrushMips, itbm) {
  9445. // for all sectors in this mip
  9446. FOREACHINDYNAMICARRAY(itbm->bm_abscSectors, CBrushSector, itbsc) {
  9447. // for all polygons in sector
  9448. FOREACHINSTATICARRAY(itbsc->bsc_abpoPolygons, CBrushPolygon, itbpo)
  9449. {
  9450. // if it is non translucent portal same texture
  9451. if ( ((itbpo->bpo_ulFlags&BPOF_PORTAL) && !(itbpo->bpo_ulFlags&BPOF_TRANSLUCENT)) &&
  9452. (itbpo->bpo_bppProperties.bpp_uwPretenderDistance==0) )
  9453. {
  9454. itbpo->bpo_abptTextures[0].bpt_toTexture.SetData_t( CTString(""));
  9455. itbpo->bpo_abptTextures[1].bpt_toTexture.SetData_t( CTString(""));
  9456. itbpo->bpo_abptTextures[2].bpt_toTexture.SetData_t( CTString(""));
  9457. }
  9458. }
  9459. }
  9460. }
  9461. }
  9462. }
  9463. }
  9464. // if failed
  9465. catch( char *err_str)
  9466. {
  9467. // report error
  9468. AfxMessageBox( CString(err_str));
  9469. return;
  9470. }
  9471. }
  9472. void CWorldEditorView::OnRotate()
  9473. {
  9474. Rotate(90.0f, 0.0f);
  9475. }
  9476. void CWorldEditorView::OnRotateBack()
  9477. {
  9478. Rotate(-90.0f, 0.0f);
  9479. }
  9480. #define ANGLE_KEY_DELTA 15.0f
  9481. void CWorldEditorView::OnRotateLeft()
  9482. {
  9483. BOOL bShift = (GetKeyState( VK_SHIFT)&0x8000) != 0;
  9484. Rotate(ANGLE_KEY_DELTA, 0.0f, bShift);
  9485. }
  9486. void CWorldEditorView::OnRotateRight()
  9487. {
  9488. BOOL bShift = (GetKeyState( VK_SHIFT)&0x8000) != 0;
  9489. Rotate(-ANGLE_KEY_DELTA, 0.0f, bShift);
  9490. }
  9491. void CWorldEditorView::OnRotateUp()
  9492. {
  9493. BOOL bShift = (GetKeyState( VK_SHIFT)&0x8000) != 0;
  9494. CWorldEditorDoc *pDoc = GetDocument();
  9495. if( (pDoc->m_pwoSecondLayer != NULL) &&
  9496. (pDoc->m_bPrimitiveMode) &&
  9497. (theApp.m_vfpCurrent.vfp_ttTriangularisationType != TT_NONE) )
  9498. {
  9499. OnMoveUp();
  9500. }
  9501. else
  9502. {
  9503. Rotate(0.0f,-ANGLE_KEY_DELTA, bShift);
  9504. }
  9505. }
  9506. void CWorldEditorView::OnRotateDown()
  9507. {
  9508. BOOL bShift = (GetKeyState( VK_SHIFT)&0x8000) != 0;
  9509. CWorldEditorDoc *pDoc = GetDocument();
  9510. if( (pDoc->m_pwoSecondLayer != NULL) &&
  9511. (pDoc->m_bPrimitiveMode) &&
  9512. (theApp.m_vfpCurrent.vfp_ttTriangularisationType != TT_NONE) )
  9513. {
  9514. OnMoveDown();
  9515. }
  9516. else
  9517. {
  9518. Rotate(0.0f,ANGLE_KEY_DELTA, bShift);
  9519. }
  9520. }
  9521. void CWorldEditorView::Rotate( FLOAT fAngleLR, FLOAT fAngleUD, BOOL bSmooth/*=FALSE*/)
  9522. {
  9523. if( bSmooth && Abs(fAngleLR)!=90.0f)
  9524. {
  9525. fAngleLR/=10;
  9526. fAngleUD/=10;
  9527. }
  9528. CWorldEditorDoc *pDoc = GetDocument();
  9529. ANGLE3D a3dForRotation = ANGLE3D(0.0f, 0.0f, 0.0f);
  9530. switch( m_ptProjectionType)
  9531. {
  9532. case CSlaveViewer::PT_ISOMETRIC_FRONT:
  9533. case CSlaveViewer::PT_ISOMETRIC_BACK:
  9534. {
  9535. a3dForRotation(3) = fAngleLR;
  9536. a3dForRotation(2) = fAngleUD;
  9537. break;
  9538. }
  9539. case CSlaveViewer::PT_ISOMETRIC_RIGHT:
  9540. case CSlaveViewer::PT_ISOMETRIC_LEFT:
  9541. {
  9542. a3dForRotation(2) = fAngleLR;
  9543. a3dForRotation(3) = -fAngleUD;
  9544. break;
  9545. }
  9546. default:
  9547. {
  9548. a3dForRotation(1) = fAngleLR;
  9549. a3dForRotation(2) = fAngleUD;
  9550. }
  9551. }
  9552. if( (pDoc->GetEditingMode() == POLYGON_MODE))
  9553. {
  9554. if( Abs(fAngleLR)!=90.0f)
  9555. {
  9556. fAngleLR/=50;
  9557. fAngleUD/=50;
  9558. }
  9559. CCastRay crRayHit = GetMouseHitInformation( m_ptMouse);
  9560. // if mouse is over polygon
  9561. if( (crRayHit.cr_penHit != NULL) &&
  9562. (crRayHit.cr_pbpoBrushPolygon != NULL) )
  9563. {
  9564. CBrushPolygon &bpo = *crRayHit.cr_pbpoBrushPolygon;
  9565. FLOAT3D vCenter=bpo.bpo_boxBoundingBox.Center();
  9566. vCenter=bpo.bpo_pbplPlane->bpl_plAbsolute.ProjectPoint( vCenter);
  9567. CEntity *pen = bpo.bpo_pbscSector->bsc_pbmBrushMip->bm_pbrBrush->br_penEntity;
  9568. CSimpleProjection3D pr;
  9569. pr.ObjectPlacementL() = _plOrigin;
  9570. pr.ViewerPlacementL() = pen->GetPlacement();
  9571. pr.Prepare();
  9572. FLOATplane3D vRelative;
  9573. pr.ProjectCoordinate(vCenter, vRelative);
  9574. // rotate it
  9575. ANGLE3D angMappingRotation=ANGLE3D(0,0,0);
  9576. angMappingRotation(1)=fAngleLR;
  9577. bpo.bpo_abptTextures[pDoc->m_iTexture].bpt_mdMapping.Rotate(
  9578. bpo.bpo_pbplPlane->bpl_pwplWorking->wpl_mvRelative,
  9579. vRelative, angMappingRotation(1));
  9580. }
  9581. }
  9582. else if( (pDoc->GetEditingMode() == CSG_MODE))
  9583. {
  9584. pDoc->m_plSecondLayer.pl_OrientationAngle += a3dForRotation;
  9585. }
  9586. else if( (pDoc->GetEditingMode() == ENTITY_MODE))
  9587. {
  9588. CEntity *penBrush = NULL;
  9589. {FOREACHINDYNAMICCONTAINER(pDoc->m_selEntitySelection, CEntity, iten)
  9590. {
  9591. if (iten->en_RenderType == CEntity::RT_BRUSH) {
  9592. penBrush = &*iten;
  9593. }
  9594. if( !(iten->GetFlags() & ENF_ANCHORED) ||
  9595. GetChildFrame()->m_bAncoredMovingAllowed)
  9596. {
  9597. CPlacement3D plEntity = iten->GetPlacement();
  9598. plEntity.pl_OrientationAngle += a3dForRotation;
  9599. iten->SetPlacement( plEntity);
  9600. }
  9601. }}
  9602. // check for terrain updating
  9603. {FOREACHINDYNAMICCONTAINER(pDoc->m_selEntitySelection, CEntity, iten)
  9604. {
  9605. CLightSource *pls = iten->GetLightSource();
  9606. if (pls!=NULL)
  9607. {
  9608. // if light is directional
  9609. if(pls->ls_ulFlags &LSF_DIRECTIONAL)
  9610. {
  9611. CTerrain *ptrTerrain=GetTerrain();
  9612. if(ptrTerrain!=NULL) ptrTerrain->UpdateShadowMap();
  9613. }
  9614. }
  9615. }}
  9616. if( penBrush != NULL)
  9617. {
  9618. DiscardShadows( penBrush);
  9619. }
  9620. }
  9621. pDoc->m_chSelections.MarkChanged();
  9622. pDoc->SetModifiedFlag( TRUE);
  9623. pDoc->UpdateAllViews( NULL);
  9624. }
  9625. void CWorldEditorView::MultiplyMappingOnPolygon( FLOAT fFactor)
  9626. {
  9627. CWorldEditorDoc *pDoc = GetDocument();
  9628. CCastRay crRayHit = GetMouseHitInformation( m_ptMouse);
  9629. // if mouse is over polygon
  9630. if( (crRayHit.cr_penHit != NULL) &&
  9631. (crRayHit.cr_pbpoBrushPolygon != NULL) )
  9632. {
  9633. CMappingDefinitionUI mdui;
  9634. CBrushPolygon *pbpo = crRayHit.cr_pbpoBrushPolygon;
  9635. pbpo->bpo_abptTextures[pDoc->m_iTexture].bpt_mdMapping.ToUI( mdui);
  9636. mdui.mdui_fUStretch *= fFactor;
  9637. mdui.mdui_fVStretch *= fFactor;
  9638. pbpo->bpo_abptTextures[pDoc->m_iTexture].bpt_mdMapping.FromUI( mdui);
  9639. pDoc->m_chSelections.MarkChanged();
  9640. pDoc->SetModifiedFlag( TRUE);
  9641. pDoc->UpdateAllViews( NULL);
  9642. }
  9643. }
  9644. void CWorldEditorView::OnSelectVisibleSectors()
  9645. {
  9646. CWorldEditorDoc *pDoc = GetDocument();
  9647. pDoc->m_selSectorSelection.Clear();
  9648. FOREACHINDYNAMICCONTAINER(pDoc->m_woWorld.wo_cenEntities, CEntity, iten)
  9649. {
  9650. // don't select for hidden entities
  9651. if( !(iten->en_ulFlags & ENF_HIDDEN))
  9652. {
  9653. continue;
  9654. }
  9655. CEntity::RenderType rt = iten->GetRenderType();
  9656. if (rt==CEntity::RT_BRUSH || rt==CEntity::RT_FIELDBRUSH)
  9657. {
  9658. CBrush3D *pBrush3D = iten->GetBrush();
  9659. if(pBrush3D != NULL)
  9660. {
  9661. FLOAT fCurrentMipFactor = GetCurrentlyActiveMipFactor();
  9662. CBrush3D *pbrBrush = iten->GetBrush();
  9663. if( pbrBrush != NULL)
  9664. {
  9665. CBrushMip *pbmCurrentMip = pbrBrush->GetBrushMipByDistance( fCurrentMipFactor);
  9666. if( pbmCurrentMip != NULL)
  9667. {
  9668. FOREACHINDYNAMICARRAY(pbmCurrentMip->bm_abscSectors, CBrushSector, itbsc)
  9669. {
  9670. if( !(itbsc->bsc_ulFlags & BSCF_HIDDEN))
  9671. {
  9672. // add it to selection
  9673. pDoc->m_selSectorSelection.Select( *itbsc);
  9674. }
  9675. }
  9676. }
  9677. }
  9678. }
  9679. }
  9680. }
  9681. pDoc->m_chSelections.MarkChanged();
  9682. pDoc->UpdateAllViews( NULL);
  9683. }
  9684. void CWorldEditorView::OnEditCopyAlternative()
  9685. {
  9686. EditCopy( TRUE);
  9687. }
  9688. /*
  9689. * Draw a line for arrow drawing.
  9690. */
  9691. static inline void DrawArrowLine(CDrawPort &dp, const FLOAT2D &vPoint0,
  9692. const FLOAT2D &vPoint1, COLOR color, ULONG ulLineType)
  9693. {
  9694. PIX x0 = (PIX)vPoint0(1);
  9695. PIX x1 = (PIX)vPoint1(1);
  9696. PIX y0 = (PIX)vPoint0(2);
  9697. PIX y1 = (PIX)vPoint1(2);
  9698. dp.DrawLine(x0, y0, x1, y1, color, ulLineType);
  9699. }
  9700. /*
  9701. * Draw an arrow for debugging edge directions.
  9702. */
  9703. static inline void DrawArrow(CDrawPort &dp, PIX i0, PIX j0, PIX i1, PIX j1, COLOR color,
  9704. ULONG ulLineType)
  9705. {
  9706. FLOAT2D vPoint0 = FLOAT2D((FLOAT)i0, (FLOAT)j0);
  9707. FLOAT2D vPoint1 = FLOAT2D((FLOAT)i1, (FLOAT)j1);
  9708. FLOAT2D vDelta = vPoint1-vPoint0;
  9709. FLOAT fDelta = vDelta.Length();
  9710. FLOAT2D vArrowLen, vArrowWidth;
  9711. if (fDelta>0.01) {
  9712. vArrowLen = vDelta/fDelta*FLOAT(10.0);
  9713. vArrowWidth = vDelta/fDelta*FLOAT(2.0);
  9714. } else {
  9715. vArrowWidth = vArrowLen = FLOAT2D(0.0f, 0.0f);
  9716. }
  9717. // FLOAT3D vArrowLen = vDelta/5.0f;
  9718. // FLOAT3D vArrowWidth = vDelta/30.0f;
  9719. Swap(vArrowWidth(1), vArrowWidth(2));
  9720. //vArrowWidth(2) *= -1.0f;
  9721. DrawArrowLine(dp, vPoint0, vPoint1, color, ulLineType);
  9722. DrawArrowLine(dp, vPoint1-vArrowLen+vArrowWidth, vPoint1, color, ulLineType);
  9723. DrawArrowLine(dp, vPoint1-vArrowLen-vArrowWidth, vPoint1, color, ulLineType);
  9724. //DrawArrowLine(dp, vPoint0+vArrowWidth, vPoint0-vArrowWidth, color, ulLineType);
  9725. }
  9726. void CWorldEditorView::DrawAxis(const PIX2D &pixC, PIX len, COLOR colAxisColor, COLOR colTextColor,
  9727. CTString strU, CTString strV)
  9728. {
  9729. if( strU=="" || strV=="") return;
  9730. // draw arrow-headed axis
  9731. DrawArrow( *m_pdpDrawPort, pixC(1), pixC(2), pixC(1)+len, pixC(2), colAxisColor, _FULL_);
  9732. DrawArrow( *m_pdpDrawPort, pixC(1), pixC(2), pixC(1), pixC(2)-len, colAxisColor, _FULL_);
  9733. // type axis text line
  9734. m_pdpDrawPort->SetFont( _pfdConsoleFont);
  9735. m_pdpDrawPort->SetTextAspect( 1.0f);
  9736. m_pdpDrawPort->SetTextScaling( 1.0f);
  9737. m_pdpDrawPort->PutTextCXY( strU, pixC(1)+len+8, pixC(2), colTextColor);
  9738. m_pdpDrawPort->PutTextCXY( strV, pixC(1), pixC(2)-len-8, colTextColor);
  9739. }
  9740. void CWorldEditorView::DrawArrowAndTypeText( CProjection3D &prProjection,
  9741. const FLOAT3D &v0, const FLOAT3D &v1, COLOR colColor, CTString strText)
  9742. {
  9743. // get transformed end vertices
  9744. FLOAT3D tv0, tv1;
  9745. prProjection.PreClip(v0, tv0);
  9746. prProjection.PreClip(v1, tv1);
  9747. // clip the edge line
  9748. FLOAT3D vClipped0 = tv0;
  9749. FLOAT3D vClipped1 = tv1;
  9750. ULONG ulClipFlags = prProjection.ClipLine(vClipped0, vClipped1);
  9751. // if the edge remains after clipping to front plane
  9752. if (ulClipFlags != LCF_EDGEREMOVED) {
  9753. // project the vertices
  9754. FLOAT3D v3d0, v3d1;
  9755. prProjection.PostClip(vClipped0, v3d0);
  9756. prProjection.PostClip(vClipped1, v3d1);
  9757. // make 2d vertices
  9758. FLOAT2D v2d0, v2d1;
  9759. v2d0(1) = v3d0(1); v2d0(2) = v3d0(2);
  9760. v2d1(1) = v3d1(1); v2d1(2) = v3d1(2);
  9761. if( (Abs(v2d1(1)-v2d0(1)) > 8) || (Abs(v2d1(2)-v2d0(2)) > 8) )
  9762. {
  9763. // draw arrow-headed line between vertices
  9764. DrawArrow( *m_pdpDrawPort, (PIX)v2d0(1), (PIX)v2d0(2),
  9765. (PIX)v2d1(1), (PIX)v2d1(2), colColor, _FULL_);
  9766. // type text over line
  9767. if( strText != "")
  9768. m_pdpDrawPort->PutTextCXY( strText, (v2d0(1)+v2d1(1))/2, (v2d0(2)+v2d1(2))/2);
  9769. }
  9770. }
  9771. }
  9772. void CWorldEditorView::SelectWhoTargets( CDynamicContainer<CEntity> &dcTargetedEntities)
  9773. {
  9774. CWorldEditorDoc *pDoc = GetDocument();
  9775. pDoc->m_selEntitySelection.Clear();
  9776. CEntityProperty *pepSelected = NULL;
  9777. // for each that can be targeted
  9778. FOREACHINDYNAMICCONTAINER(dcTargetedEntities, CEntity, itenTargets)
  9779. {
  9780. // for each entity in world
  9781. FOREACHINDYNAMICCONTAINER(pDoc->m_woWorld.wo_cenEntities, CEntity, iten)
  9782. {
  9783. // obtain entity class ptr
  9784. CDLLEntityClass *pdecDLLClass = iten->GetClass()->ec_pdecDLLClass;
  9785. // for all classes in hierarchy of this entity
  9786. for(;pdecDLLClass!=NULL; pdecDLLClass = pdecDLLClass->dec_pdecBase)
  9787. {
  9788. // for all properties
  9789. for(INDEX iProperty=0; iProperty<pdecDLLClass->dec_ctProperties; iProperty++)
  9790. {
  9791. CEntityProperty *pepProperty = &pdecDLLClass->dec_aepProperties[iProperty];
  9792. if( pepProperty->ep_eptType == CEntityProperty::EPT_ENTITYPTR)
  9793. {
  9794. // obtain property ptr
  9795. CEntity *penCurrentPtr = ENTITYPROPERTY( &*iten, pepProperty->ep_slOffset, CEntityPointer);
  9796. if( (penCurrentPtr == &*itenTargets) && !iten->IsSelected( ENF_SELECTED) )
  9797. {
  9798. pepSelected = pepProperty;
  9799. pDoc->m_selEntitySelection.Select( *iten);
  9800. }
  9801. }
  9802. }
  9803. }
  9804. }
  9805. }
  9806. pDoc->m_chSelections.MarkChanged();
  9807. // if only one entity targets
  9808. if( pDoc->m_selEntitySelection.Count() == 1)
  9809. {
  9810. CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
  9811. pMainFrame->m_PropertyComboBar.SelectProperty( pepSelected);
  9812. }
  9813. pDoc->UpdateAllViews( NULL);
  9814. }
  9815. void CWorldEditorView::OnSelectWhoTargetsOnContext()
  9816. {
  9817. CWorldEditorDoc *pDoc = GetDocument();
  9818. // to hold entities for selecting
  9819. CDynamicContainer<CEntity> dcEntities;
  9820. // if right-clicked on void or selected entity
  9821. if( (m_penEntityHitOnContext == NULL) ||
  9822. (m_penEntityHitOnContext->IsSelected( ENF_SELECTED)) )
  9823. {
  9824. // perform on whole selection
  9825. {FOREACHINDYNAMICCONTAINER(pDoc->m_selEntitySelection, CEntity, iten)
  9826. {
  9827. dcEntities.Add( iten);
  9828. }}
  9829. }
  9830. else
  9831. {
  9832. // perform only on right-clicked entity
  9833. dcEntities.Add( m_penEntityHitOnContext);
  9834. }
  9835. // select all entities that target ones from dynamic container
  9836. SelectWhoTargets( dcEntities);
  9837. }
  9838. void CWorldEditorView::OnSelectWhoTargets()
  9839. {
  9840. CWorldEditorDoc *pDoc = GetDocument();
  9841. // to hold entities for selecting
  9842. CDynamicContainer<CEntity> dcEntities;
  9843. // perform on whole selection
  9844. {FOREACHINDYNAMICCONTAINER(pDoc->m_selEntitySelection, CEntity, iten)
  9845. {
  9846. dcEntities.Add( iten);
  9847. }}
  9848. // select all entities that target ones from dynamic container
  9849. SelectWhoTargets( dcEntities);
  9850. }
  9851. void CWorldEditorView::OnSelectAllTargetsOnContext()
  9852. {
  9853. CEntity *pen = m_penEntityHitOnContext;
  9854. if( pen==NULL || pen->IsSelected( ENF_SELECTED))
  9855. {
  9856. SelectAllTargetsOfSelectedEntities();
  9857. return;
  9858. }
  9859. else
  9860. {
  9861. SelectAllTargetsOfEntity(pen);
  9862. }
  9863. }
  9864. void CWorldEditorView::OnSelectAllTargets()
  9865. {
  9866. SelectAllTargetsOfSelectedEntities();
  9867. }
  9868. void CWorldEditorView::SelectAllTargetsOfEntity(CEntity *pen)
  9869. {
  9870. ASSERT( pen!= NULL);
  9871. CWorldEditorDoc *pDoc = GetDocument();
  9872. // obtain entity class ptr
  9873. CDLLEntityClass *pdecDLLClass = pen->GetClass()->ec_pdecDLLClass;
  9874. // to hold entities for selecting
  9875. CDynamicContainer<CEntity> dcEntities;
  9876. // for all classes in hierarchy of this entity
  9877. for(;pdecDLLClass!=NULL; pdecDLLClass = pdecDLLClass->dec_pdecBase)
  9878. {
  9879. // for all properties
  9880. for(INDEX iProperty=0; iProperty<pdecDLLClass->dec_ctProperties; iProperty++)
  9881. {
  9882. CEntityProperty &epProperty = pdecDLLClass->dec_aepProperties[iProperty];
  9883. if( epProperty.ep_eptType == CEntityProperty::EPT_ENTITYPTR &&
  9884. epProperty.ep_strName!=NULL &&
  9885. CTString(epProperty.ep_strName)!="")
  9886. {
  9887. // obtain property ptr
  9888. CEntity *penTarget = ENTITYPROPERTY( &*pen, epProperty.ep_slOffset, CEntityPointer);
  9889. if( penTarget != NULL)
  9890. {
  9891. // add it to container
  9892. dcEntities.Add( penTarget);
  9893. }
  9894. }
  9895. }
  9896. }
  9897. // for all entities in dynamic container
  9898. FOREACHINDYNAMICCONTAINER(dcEntities, CEntity, iten)
  9899. {
  9900. // if not yet selected
  9901. if( !iten->IsSelected( ENF_SELECTED))
  9902. {
  9903. // select it
  9904. pDoc->m_selEntitySelection.Select( *iten);
  9905. }
  9906. }
  9907. pDoc->m_chSelections.MarkChanged();
  9908. pDoc->UpdateAllViews( NULL);
  9909. }
  9910. void CWorldEditorView::SelectAllTargetsOfSelectedEntities(void)
  9911. {
  9912. CWorldEditorDoc *pDoc = GetDocument();
  9913. // to hold entities for selecting
  9914. CDynamicContainer<CEntity> dcEntities;
  9915. {FOREACHINDYNAMICCONTAINER(pDoc->m_selEntitySelection, CEntity, iten)
  9916. {
  9917. // obtain entity class ptr
  9918. CDLLEntityClass *pdecDLLClass = iten->GetClass()->ec_pdecDLLClass;
  9919. // for all classes in hierarchy of this entity
  9920. for(;pdecDLLClass!=NULL; pdecDLLClass = pdecDLLClass->dec_pdecBase)
  9921. {
  9922. // for all properties
  9923. for(INDEX iProperty=0; iProperty<pdecDLLClass->dec_ctProperties; iProperty++)
  9924. {
  9925. CEntityProperty &epProperty = pdecDLLClass->dec_aepProperties[iProperty];
  9926. if(epProperty.ep_eptType==CEntityProperty::EPT_ENTITYPTR &&
  9927. epProperty.ep_strName!=NULL &&
  9928. CTString(epProperty.ep_strName)!="")
  9929. {
  9930. // obtain property ptr
  9931. CEntity *penTarget = ENTITYPROPERTY( &*iten, epProperty.ep_slOffset, CEntityPointer);
  9932. if( penTarget != NULL)
  9933. {
  9934. // add it to container
  9935. dcEntities.Add( penTarget);
  9936. }
  9937. }
  9938. }
  9939. }
  9940. }}
  9941. // for all entities in dynamic container
  9942. FOREACHINDYNAMICCONTAINER( dcEntities, CEntity, iten)
  9943. {
  9944. // if not yet selected
  9945. if( !iten->IsSelected( ENF_SELECTED))
  9946. {
  9947. // select it
  9948. pDoc->m_selEntitySelection.Select( *iten);
  9949. }
  9950. }
  9951. pDoc->m_chSelections.MarkChanged();
  9952. pDoc->UpdateAllViews( NULL);
  9953. return;
  9954. }
  9955. void CWorldEditorView::OnSelectInvalidTris()
  9956. {
  9957. CWorldEditorDoc *pDoc = GetDocument();
  9958. // for each entity in the world
  9959. FOREACHINDYNAMICCONTAINER(pDoc->m_woWorld.wo_cenEntities, CEntity, iten) {
  9960. // if it is brush entity
  9961. if (iten->en_RenderType == CEntity::RT_BRUSH) {
  9962. // for each mip in its brush
  9963. FOREACHINLIST(CBrushMip, bm_lnInBrush, iten->en_pbrBrush->br_lhBrushMips, itbm) {
  9964. // for all sectors in this mip
  9965. FOREACHINDYNAMICARRAY(itbm->bm_abscSectors, CBrushSector, itbsc) {
  9966. // for all polygons in sector
  9967. FOREACHINSTATICARRAY(itbsc->bsc_abpoPolygons, CBrushPolygon, itbpo) {
  9968. // if it has invalid triangles
  9969. if ((itbpo->bpo_ulFlags&BPOF_INVALIDTRIANGLES)&&
  9970. !(itbpo->IsSelected(BPOF_SELECTED))) {
  9971. // select it
  9972. pDoc->m_selPolygonSelection.Select( *itbpo);
  9973. }
  9974. }
  9975. }
  9976. }
  9977. }
  9978. }
  9979. pDoc->m_chSelections.MarkChanged();
  9980. pDoc->UpdateAllViews( NULL);
  9981. }
  9982. BOOL CWorldEditorView::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
  9983. {
  9984. INDEX iCount = zDelta/120;
  9985. BOOL bSpace = (GetKeyState( ' ') & 128) != 0;
  9986. BOOL bCtrl = nFlags & MK_CONTROL;
  9987. BOOL bAlt = (GetKeyState( VK_MENU)&0x8000) != 0;
  9988. BOOL bShift = (GetKeyState( VK_SHIFT)&0x8000) != 0;
  9989. CWorldEditorDoc* pDoc = GetDocument();
  9990. ASSERT_VALID(pDoc);
  9991. // ctrl + mouse wheel toggle modes
  9992. /*
  9993. if( bCtrl && !bSpace && !bShift && !bAlt)
  9994. {
  9995. for( INDEX iKnee=0; iKnee<Abs(iCount); iKnee++)
  9996. {
  9997. if(iCount<0)
  9998. {
  9999. switch(pDoc->GetEditingMode())
  10000. {
  10001. case( ENTITY_MODE):
  10002. {
  10003. pDoc->SetEditingMode( SECTOR_MODE);
  10004. break;
  10005. }
  10006. case( SECTOR_MODE):
  10007. {
  10008. pDoc->SetEditingMode( POLYGON_MODE);
  10009. break;
  10010. }
  10011. case( POLYGON_MODE):
  10012. {
  10013. pDoc->SetEditingMode( VERTEX_MODE);
  10014. break;
  10015. }
  10016. case( VERTEX_MODE):
  10017. {
  10018. pDoc->SetEditingMode( TERRAIN_MODE);
  10019. break;
  10020. }
  10021. case( TERRAIN_MODE):
  10022. {
  10023. pDoc->SetEditingMode( ENTITY_MODE);
  10024. break;
  10025. }
  10026. }
  10027. }
  10028. else
  10029. {
  10030. switch(pDoc->GetEditingMode())
  10031. {
  10032. case( ENTITY_MODE):
  10033. {
  10034. pDoc->SetEditingMode( TERRAIN_MODE);
  10035. break;
  10036. }
  10037. case( SECTOR_MODE):
  10038. {
  10039. pDoc->SetEditingMode( ENTITY_MODE);
  10040. break;
  10041. }
  10042. case( POLYGON_MODE):
  10043. {
  10044. pDoc->SetEditingMode( SECTOR_MODE);
  10045. break;
  10046. }
  10047. case( VERTEX_MODE):
  10048. {
  10049. pDoc->SetEditingMode( POLYGON_MODE);
  10050. break;
  10051. }
  10052. case( TERRAIN_MODE):
  10053. {
  10054. pDoc->SetEditingMode( VERTEX_MODE);
  10055. break;
  10056. }
  10057. }
  10058. }
  10059. pDoc->m_chSelections.MarkChanged();
  10060. pDoc->UpdateAllViews( NULL);
  10061. }
  10062. }
  10063. */
  10064. // space+ctrl+lmb zoomes in 2x
  10065. if( bSpace && bCtrl)
  10066. {
  10067. BOOL bHitModels = (pDoc->GetEditingMode() == ENTITY_MODE) || bSpace;
  10068. BOOL bHitFields = (pDoc->GetEditingMode() == ENTITY_MODE) || bSpace;
  10069. // obtain information about where mouse points into the world
  10070. CCastRay crRayHit = GetMouseHitInformation( m_ptMouse, FALSE, bHitModels, bHitFields);
  10071. // set new target
  10072. GetChildFrame()->m_mvViewer.SetTargetPlacement( crRayHit.cr_vHit);
  10073. // move mouse to center of screen
  10074. CPoint ptCenter = CPoint( m_pdpDrawPort->GetWidth()/2, m_pdpDrawPort->GetHeight()/2);
  10075. ClientToScreen( &ptCenter);
  10076. SetCursorPos(ptCenter.x, ptCenter.y);
  10077. OnZoomMore();
  10078. pDoc->UpdateAllViews( NULL);
  10079. m_ptMouseDown = ptCenter;
  10080. for( INDEX iKnee=0; iKnee<Abs(iCount); iKnee++)
  10081. {
  10082. if(iCount<0) OnZoomLess();
  10083. else OnZoomMore();
  10084. }
  10085. }
  10086. else
  10087. {
  10088. for( INDEX iKnee=0; iKnee<Abs(iCount); iKnee++)
  10089. {
  10090. if(iCount<0) PostMessage( WM_COMMAND, ID_PREVIOUS, 0);
  10091. else PostMessage( WM_COMMAND, ID_NEXT, 0);
  10092. }
  10093. }
  10094. return CView::OnMouseWheel(nFlags, zDelta, pt);
  10095. }
  10096. void CWorldEditorView::OnSelectSectorsOtherSide()
  10097. {
  10098. CWorldEditorDoc* pDoc = GetDocument();
  10099. // obtain information about where mouse points into the world
  10100. CCastRay crRayHit = GetMouseHitInformation( m_ptMouse);
  10101. // if we hit brush entity
  10102. if( (crRayHit.cr_penHit != NULL) &&
  10103. (crRayHit.cr_pbpoBrushPolygon != NULL) &&
  10104. (crRayHit.cr_pbpoBrushPolygon->bpo_ulFlags & BPOF_PORTAL))
  10105. {
  10106. CBrushPolygon &bpo = *crRayHit.cr_pbpoBrushPolygon;
  10107. // for all sectors behind portal
  10108. {FOREACHDSTOFSRC(bpo.bpo_rsOtherSideSectors, CBrushSector, bsc_rdOtherSidePortals, pbsc)
  10109. if( !pbsc->IsSelected( BSCF_SELECTED))
  10110. {
  10111. pDoc->m_selSectorSelection.Select( *pbsc);
  10112. }
  10113. ENDFOR}
  10114. pDoc->SetEditingMode( SECTOR_MODE);
  10115. pDoc->m_chSelections.MarkChanged();
  10116. pDoc->UpdateAllViews( NULL);
  10117. }
  10118. }
  10119. void CWorldEditorView::OnSelectLinksToSector()
  10120. {
  10121. CWorldEditorDoc* pDoc = GetDocument();
  10122. // obtain information about where mouse points into the world
  10123. CCastRay crRayHit = GetMouseHitInformation( m_ptMouse);
  10124. // if we hit brush entity
  10125. if( (crRayHit.cr_penHit != NULL) &&
  10126. (crRayHit.cr_pbpoBrushPolygon != NULL))
  10127. {
  10128. CBrushSector &bsc = *crRayHit.cr_pbpoBrushPolygon->bpo_pbscSector;
  10129. // for all sectors behind portal
  10130. {FOREACHSRCOFDST(bsc.bsc_rdOtherSidePortals, CBrushPolygon, bpo_rsOtherSideSectors, pbpo)
  10131. if( !pbpo->IsSelected( BPOF_SELECTED))
  10132. {
  10133. pDoc->m_selPolygonSelection.Select( *pbpo);
  10134. }
  10135. ENDFOR}
  10136. pDoc->SetEditingMode( POLYGON_MODE);
  10137. pDoc->m_chSelections.MarkChanged();
  10138. pDoc->UpdateAllViews( NULL);
  10139. }
  10140. }
  10141. void CWorldEditorView::OnRemainSelectedByOrientation()
  10142. {
  10143. OnRemainSelectedByOrientation(TRUE);
  10144. }
  10145. void CWorldEditorView::OnRemainSelectedbyOrientationSingle()
  10146. {
  10147. OnRemainSelectedByOrientation(FALSE);
  10148. }
  10149. void CWorldEditorView::OnRemainSelectedByOrientation(BOOL bBothSides)
  10150. {
  10151. CWorldEditorDoc* pDoc = GetDocument();
  10152. // obtain information about where mouse points into the world
  10153. CCastRay crRayHit = GetMouseHitInformation( m_ptMouse);
  10154. CBrushPolygon *pbpoPolygon = crRayHit.cr_pbpoBrushPolygon;
  10155. // if we hit brush entity
  10156. if( (crRayHit.cr_penHit != NULL) &&
  10157. (pbpoPolygon != NULL) )
  10158. {
  10159. FLOAT3D vReference = pbpoPolygon->bpo_pbplPlane->bpl_plAbsolute;
  10160. // copy polygon selection to container
  10161. CDynamicContainer<CBrushPolygon> dcTemp;
  10162. {FOREACHINDYNAMICCONTAINER(pDoc->m_selPolygonSelection, CBrushPolygon, itbpo)
  10163. {
  10164. dcTemp.Add( itbpo);
  10165. }}
  10166. pDoc->m_selPolygonSelection.Clear();
  10167. {FOREACHINDYNAMICCONTAINER( dcTemp, CBrushPolygon, itbpo)
  10168. {
  10169. FLOAT fCos;
  10170. if( bBothSides)
  10171. {
  10172. fCos = Abs(vReference % itbpo->bpo_pbplPlane->bpl_plAbsolute);
  10173. }
  10174. else
  10175. {
  10176. fCos = vReference % itbpo->bpo_pbplPlane->bpl_plAbsolute;
  10177. }
  10178. if( fCos > CosFast(360.0f/8.0f))
  10179. {
  10180. pDoc->m_selPolygonSelection.Select( *itbpo);
  10181. }
  10182. }}
  10183. pDoc->m_chSelections.MarkChanged();
  10184. pDoc->UpdateAllViews( NULL);
  10185. }
  10186. }
  10187. void CWorldEditorView::OnDeselectByOrientation()
  10188. {
  10189. CWorldEditorDoc* pDoc = GetDocument();
  10190. // obtain information about where mouse points into the world
  10191. CCastRay crRayHit = GetMouseHitInformation( m_ptMouse);
  10192. CBrushPolygon *pbpoPolygon = crRayHit.cr_pbpoBrushPolygon;
  10193. // if we hit brush entity
  10194. if( (crRayHit.cr_penHit != NULL) &&
  10195. (pbpoPolygon != NULL) )
  10196. {
  10197. FLOAT3D vReference = pbpoPolygon->bpo_pbplPlane->bpl_plAbsolute;
  10198. // copy polygon selection to container
  10199. CDynamicContainer<CBrushPolygon> dcTemp;
  10200. {FOREACHINDYNAMICCONTAINER(pDoc->m_selPolygonSelection, CBrushPolygon, itbpo)
  10201. {
  10202. dcTemp.Add( itbpo);
  10203. }}
  10204. pDoc->m_selPolygonSelection.Clear();
  10205. {FOREACHINDYNAMICCONTAINER( dcTemp, CBrushPolygon, itbpo)
  10206. {
  10207. FLOAT fCos = Abs(vReference % itbpo->bpo_pbplPlane->bpl_plAbsolute);
  10208. if( fCos < CosFast(360.0f/8.0f))
  10209. {
  10210. pDoc->m_selPolygonSelection.Select( *itbpo);
  10211. }
  10212. }}
  10213. pDoc->m_chSelections.MarkChanged();
  10214. pDoc->UpdateAllViews( NULL);
  10215. }
  10216. }
  10217. void CWorldEditorView::OnReoptimizeBrushes()
  10218. {
  10219. CWorldEditorDoc* pDoc = GetDocument();
  10220. CWaitCursor wc;
  10221. CCastRay crRayHit = GetMouseHitInformation( m_ptMouse);
  10222. if( (crRayHit.cr_penHit != NULL) &&
  10223. (crRayHit.cr_pbpoBrushPolygon != NULL) )
  10224. {
  10225. pDoc->ClearSelections();
  10226. pDoc->m_chSelections.MarkChanged();
  10227. CEntity *penEntityHit = crRayHit.cr_penHit;
  10228. BOOL bSelected = crRayHit.cr_penHit->IsSelected( ENF_SELECTED);
  10229. if( bSelected && (pDoc->GetEditingMode() == ENTITY_MODE))
  10230. {
  10231. {FOREACHINDYNAMICCONTAINER(pDoc->m_selEntitySelection, CEntity, iten)
  10232. {
  10233. if (iten->en_RenderType == CEntity::RT_BRUSH)
  10234. {
  10235. CBrush3D *pbrBrush = iten->GetBrush();
  10236. // for each mip in the brush
  10237. FOREACHINLIST(CBrushMip, bm_lnInBrush, pbrBrush->br_lhBrushMips, itbm)
  10238. {
  10239. // reoptimize it
  10240. itbm->Reoptimize();
  10241. }
  10242. DiscardShadows( &*iten);
  10243. if( iten->GetFlags() & ENF_ZONING)
  10244. {
  10245. pbrBrush->SwitchToZoning();
  10246. }
  10247. else
  10248. {
  10249. pbrBrush->SwitchToNonZoning();
  10250. }
  10251. }
  10252. }}
  10253. }
  10254. else
  10255. {
  10256. if (penEntityHit->en_RenderType == CEntity::RT_BRUSH)
  10257. {
  10258. CBrush3D *pbrBrush = penEntityHit->GetBrush();
  10259. // for each mip in the brush
  10260. FOREACHINLIST(CBrushMip, bm_lnInBrush, pbrBrush->br_lhBrushMips, itbm)
  10261. {
  10262. // reoptimize it
  10263. itbm->Reoptimize();
  10264. }
  10265. DiscardShadows( penEntityHit);
  10266. if( penEntityHit->GetFlags() & ENF_ZONING)
  10267. {
  10268. pbrBrush->SwitchToZoning();
  10269. }
  10270. else
  10271. {
  10272. pbrBrush->SwitchToNonZoning();
  10273. }
  10274. }
  10275. }
  10276. // automaticly update portal links
  10277. pDoc->m_woWorld.RebuildLinks();
  10278. pDoc->UpdateAllViews( NULL);
  10279. pDoc->SetModifiedFlag();
  10280. }
  10281. // ray-hit didn't hit any entity, reoptimize the whole world
  10282. else
  10283. {
  10284. // for each entity in the world
  10285. FOREACHINDYNAMICCONTAINER(pDoc->m_woWorld.wo_cenEntities, CEntity, iten)
  10286. {
  10287. // if it is brush entity
  10288. if (iten->en_RenderType == CEntity::RT_BRUSH)
  10289. {
  10290. CBrush3D *pbrBrush = iten->GetBrush();
  10291. // for each mip in the brush
  10292. FOREACHINLIST(CBrushMip, bm_lnInBrush, pbrBrush->br_lhBrushMips, itbm)
  10293. {
  10294. // reoptimize it
  10295. itbm->Reoptimize();
  10296. }
  10297. DiscardShadows( iten);
  10298. if( iten->GetFlags() & ENF_ZONING)
  10299. {
  10300. pbrBrush->SwitchToZoning();
  10301. }
  10302. else
  10303. {
  10304. pbrBrush->SwitchToNonZoning();
  10305. }
  10306. }
  10307. }
  10308. }
  10309. }
  10310. void CWorldEditorView::OnMergeVertices()
  10311. {
  10312. CWorldEditorDoc* pDoc = GetDocument();
  10313. pDoc->RememberUndo();
  10314. pDoc->ClearSelections( ST_VERTEX);
  10315. CDynamicContainer<CBrushVertex> cbvxAllreadyDone;
  10316. DOUBLE3D vMergeToVertex;
  10317. {FOREACHINDYNAMICCONTAINER( pDoc->m_selVertexSelection, CBrushVertex, itbvx)
  10318. {
  10319. vMergeToVertex = FLOATtoDOUBLE(itbvx->bvx_vAbsolute);
  10320. }}
  10321. // deselect vertices that are on right spot, to avoid unnecessary triangularisation
  10322. {FOREACHINDYNAMICCONTAINER( pDoc->m_selVertexSelection, CBrushVertex, itbvx)
  10323. {
  10324. if( FLOATtoDOUBLE(itbvx->bvx_vAbsolute) == vMergeToVertex)
  10325. {
  10326. cbvxAllreadyDone.Add(itbvx);
  10327. }
  10328. }}
  10329. {FOREACHINDYNAMICCONTAINER( cbvxAllreadyDone, CBrushVertex, itbvx)
  10330. {
  10331. pDoc->m_selVertexSelection.Deselect( *itbvx);
  10332. }}
  10333. // triangularize all influenced polygons
  10334. pDoc->m_woWorld.TriangularizeForVertices( pDoc->m_selVertexSelection);
  10335. // for each vertex
  10336. {FOREACHINDYNAMICCONTAINER( pDoc->m_selVertexSelection, CBrushVertex, itbvx)
  10337. {
  10338. // set its new position
  10339. itbvx->SetAbsolutePosition( vMergeToVertex);
  10340. }}
  10341. // reselect vertices
  10342. {FOREACHINDYNAMICCONTAINER( cbvxAllreadyDone, CBrushVertex, itbvx)
  10343. {
  10344. pDoc->m_selVertexSelection.Select( *itbvx);
  10345. }}
  10346. // update sectors
  10347. pDoc->m_woWorld.UpdateSectorsDuringVertexChange( pDoc->m_selVertexSelection);
  10348. pDoc->m_woWorld.UpdateSectorsAfterVertexChange( pDoc->m_selVertexSelection);
  10349. pDoc->UpdateAllViews( NULL);
  10350. pDoc->SetModifiedFlag();
  10351. }
  10352. void CWorldEditorView::OnExportDisplaceMap()
  10353. {
  10354. CImageInfo ii;
  10355. CDlgDisplaceMapSize dlgDisplaceMapSize;
  10356. if( dlgDisplaceMapSize.DoModal() != IDOK)
  10357. {
  10358. return;
  10359. }
  10360. CWorldEditorDoc* pDoc = GetDocument();
  10361. // find bounding box of all selected polygons
  10362. FLOATaabbox3D boxSelection;
  10363. FOREACHINDYNAMICCONTAINER(pDoc->m_selPolygonSelection, CBrushPolygon, itbpo)
  10364. {
  10365. // calculate bounding box for all polygons
  10366. boxSelection |= itbpo->bpo_boxBoundingBox;
  10367. }
  10368. PIX pixWidth = dlgDisplaceMapSize.m_pixWidth;
  10369. PIX pixHeight = dlgDisplaceMapSize.m_pixHeight;
  10370. FLOAT fMinX = boxSelection.Min()(1);
  10371. FLOAT fMaxX = boxSelection.Max()(1);
  10372. FLOAT fMinY = boxSelection.Min()(2);
  10373. FLOAT fMaxY = boxSelection.Max()(2);
  10374. FLOAT fSizeY = boxSelection.Size()(2);
  10375. FLOAT fMinZ = boxSelection.Min()(3);
  10376. FLOAT fMaxZ = boxSelection.Max()(3);
  10377. FLOAT fDeltaX;
  10378. FLOAT fDeltaZ;
  10379. if (dlgDisplaceMapSize.m_bMidPixSample)
  10380. {
  10381. fDeltaX = (fMaxX-fMinX)/pixWidth;
  10382. fDeltaZ = (fMaxZ-fMinZ)/pixHeight;
  10383. }
  10384. else
  10385. {
  10386. fDeltaX = (fMaxX-fMinX-0.5f)/pixWidth;
  10387. fDeltaZ = (fMaxZ-fMinZ-0.5f)/pixHeight;
  10388. }
  10389. CPrintF("Export displace map...\n");
  10390. CPrintF("Min: (%gf, %gf, %gf), Max: (%gf, %gf, %gf), Delta X=%g, Delta Z=%g\n",
  10391. fMinX, fMinY, fMinZ,
  10392. fMaxX, fMaxY, fMaxZ,
  10393. fDeltaX, fDeltaZ);
  10394. CTFileName fnDocName = CTString(CStringA(pDoc->GetPathName()));
  10395. CTFileName fnDirectory = fnDocName.FileDir();
  10396. CTFileName fnDefaultSelected = fnDocName.FileName()+CTString("DisplaceMap.tga");
  10397. try
  10398. {
  10399. fnDirectory.RemoveApplicationPath_t();
  10400. }
  10401. catch( char *str_err)
  10402. {
  10403. AfxMessageBox( CString(str_err));
  10404. return;
  10405. }
  10406. // note: NULL given instead of profile string name, to avoid using last directory
  10407. CTFileName fnDisplaceMap =
  10408. _EngineGUI.FileRequester( "Select name to export displace map",
  10409. "Pictures (*.tga)\0*.tga\0" FILTER_END,
  10410. NULL, fnDirectory, fnDefaultSelected, NULL, FALSE);
  10411. if( fnDisplaceMap == "") return;
  10412. ULONG ulSize = pixWidth*pixHeight*3;
  10413. UBYTE *pubPicture = (UBYTE *) AllocMemory( ulSize);
  10414. // initializes structure members and attaches pointer to image
  10415. ii.Attach( pubPicture, pixWidth, pixHeight, 24);
  10416. // for each line of pixels in height map
  10417. for( INDEX iY=0; iY<pixHeight; iY++)
  10418. {
  10419. // for each horizontal pixel in height map
  10420. for( INDEX iX=0; iX<pixWidth; iX++)
  10421. {
  10422. FLOAT fX;
  10423. FLOAT fZ;
  10424. // calculate coordinate in world
  10425. if (dlgDisplaceMapSize.m_bMidPixSample)
  10426. {
  10427. fX = fMinX+fDeltaX*iX+fDeltaX/2;
  10428. fZ = fMinZ+fDeltaZ*iY+fDeltaZ/2;
  10429. }
  10430. else
  10431. {
  10432. fX = fMinX+fDeltaX*iX+0.1;
  10433. fZ = fMinZ+fDeltaZ*iY+0.1;
  10434. }
  10435. // cast ray to recive height
  10436. CCastRay crRayHit = CCastRay( NULL, CPlacement3D(FLOAT3D(fX, fMaxY+1.0f, fZ), ANGLE3D(0,-90,0)) );
  10437. crRayHit.cr_bAllowOverHit = TRUE;
  10438. crRayHit.cr_bHitPortals = FALSE;
  10439. crRayHit.cr_ttHitModels = CCastRay::TT_NONE;
  10440. // cast ray, go for hit data
  10441. pDoc->m_woWorld.CastRay( crRayHit);
  10442. if (!dlgDisplaceMapSize.m_bHighResolution){
  10443. // set black pixel if nothing hit
  10444. UBYTE ubPixelColor = 0;
  10445. if( crRayHit.cr_penHit != NULL)
  10446. {
  10447. FLOAT fYHit = crRayHit.cr_vHit(2);
  10448. ubPixelColor = (UBYTE) ((fYHit-fMinY)/fSizeY*255.0f);
  10449. }
  10450. UBYTE *pPixel=pubPicture+iY*pixWidth*3+iX*3;
  10451. *(pPixel+0) = ubPixelColor;
  10452. *(pPixel+1) = ubPixelColor;
  10453. *(pPixel+2) = ubPixelColor;
  10454. }
  10455. else
  10456. {
  10457. // set black pixel if nothing hit
  10458. unsigned short usPixelColor = 0;
  10459. if( crRayHit.cr_penHit != NULL)
  10460. {
  10461. FLOAT fYHit = crRayHit.cr_vHit(2);
  10462. usPixelColor = (unsigned short) ((fYHit-fMinY)/fSizeY*65535);
  10463. }
  10464. UBYTE *pPixel=pubPicture+iY*pixWidth*3+iX*3;
  10465. *(pPixel+0) = 0;
  10466. *(pPixel+1) = usPixelColor>>8;
  10467. *(pPixel+2) = usPixelColor&0xFF;
  10468. }
  10469. }
  10470. }
  10471. // try to
  10472. try {
  10473. // save displace map as TGA
  10474. ii.SaveTGA_t( fnDisplaceMap);
  10475. } // if failed
  10476. catch (char *strError) {
  10477. // report error
  10478. AfxMessageBox(CString(strError));
  10479. }
  10480. }
  10481. void CWorldEditorView::OnCutMode()
  10482. {
  10483. // if we should enter cut mode
  10484. if( !theApp.m_bCutModeOn)
  10485. {
  10486. CTString strError;
  10487. BOOL bCutEnabled = IsCutEnabled( strError);
  10488. if( !bCutEnabled)
  10489. {
  10490. // warn user
  10491. WarningMessage( "%s", strError);
  10492. return;
  10493. }
  10494. }
  10495. theApp.m_bCutModeOn = !theApp.m_bCutModeOn;
  10496. theApp.m_bMeasureModeOn = FALSE;
  10497. }
  10498. void CWorldEditorView::OnUpdateCutMode(CCmdUI* pCmdUI)
  10499. {
  10500. CWorldEditorDoc* pDoc = GetDocument();
  10501. // cut is enabled only in sector and polygon mode
  10502. if( (pDoc->GetEditingMode() == POLYGON_MODE) ||
  10503. (pDoc->GetEditingMode() == ENTITY_MODE) ||
  10504. (pDoc->GetEditingMode() == SECTOR_MODE) )
  10505. {
  10506. pCmdUI->Enable( TRUE);
  10507. }
  10508. else
  10509. {
  10510. pCmdUI->Enable( FALSE);
  10511. }
  10512. pCmdUI->SetCheck( theApp.m_bCutModeOn);
  10513. //pDoc->UpdateAllViews( NULL); !!!!!!!!!!!!!!!!!!!!! unbelievable !!!!!!!!!!!!!!!!!
  10514. }
  10515. BOOL CWorldEditorView::IsCutEnabled(CTString &strError)
  10516. {
  10517. CWorldEditorDoc* pDoc = GetDocument();
  10518. if( pDoc->GetEditingMode() == ENTITY_MODE)
  10519. {
  10520. // there must be at least one entity in selection
  10521. if( pDoc->m_selEntitySelection.Count() == 0)
  10522. {
  10523. strError = "You must select entity(s) that you want to mirror!";
  10524. return FALSE;
  10525. }
  10526. }
  10527. else if( pDoc->GetEditingMode() == POLYGON_MODE)
  10528. {
  10529. // there must be at least one polygon in selection
  10530. if( pDoc->m_selPolygonSelection.Count() == 0)
  10531. {
  10532. strError = "You must select polygon(s) that you want to cut!";
  10533. return FALSE;
  10534. }
  10535. // all polygons must be of the same brush
  10536. CBrush3D *pbrBrush = NULL;
  10537. FOREACHINDYNAMICCONTAINER(pDoc->m_selPolygonSelection, CBrushPolygon, itbpo)
  10538. {
  10539. // remember first polygon's brush
  10540. if( pbrBrush == NULL)
  10541. {
  10542. pbrBrush = itbpo->bpo_pbscSector->bsc_pbmBrushMip->bm_pbrBrush;
  10543. }
  10544. else
  10545. {
  10546. // if any of the other polygons are not from same brush
  10547. if( pbrBrush != itbpo->bpo_pbscSector->bsc_pbmBrushMip->bm_pbrBrush)
  10548. {
  10549. // don't allow cut
  10550. strError = "All polygons must be from the same brush to be able to cut them!";
  10551. return FALSE;
  10552. }
  10553. }
  10554. }
  10555. }
  10556. else if(pDoc->GetEditingMode() == SECTOR_MODE)
  10557. {
  10558. // there must be at least one sector in selection
  10559. if( pDoc->m_selSectorSelection.Count() == 0)
  10560. {
  10561. strError = "You must select sector(s) that you want to cut!";
  10562. return FALSE;
  10563. }
  10564. // all sectors must be of the same brush
  10565. CBrush3D *pbrBrush = NULL;
  10566. FOREACHINDYNAMICCONTAINER(pDoc->m_selSectorSelection, CBrushSector, itbsc)
  10567. {
  10568. // remember first sector's brush
  10569. if( pbrBrush == NULL)
  10570. {
  10571. pbrBrush = itbsc->bsc_pbmBrushMip->bm_pbrBrush;
  10572. }
  10573. else
  10574. {
  10575. // if any of the other sectors are not from same brush
  10576. if( pbrBrush != itbsc->bsc_pbmBrushMip->bm_pbrBrush)
  10577. {
  10578. // don't allow cut
  10579. strError = "All sector must be from the same brush to be able to cut them!";
  10580. return FALSE;
  10581. }
  10582. }
  10583. }
  10584. }
  10585. return TRUE;
  10586. }
  10587. void CWorldEditorView::OnUpdateSelectClones(CCmdUI* pCmdUI)
  10588. {
  10589. CWorldEditorDoc* pDoc = GetDocument();
  10590. // allow clone selecting only if we have only one entity selected
  10591. if( pDoc->m_selEntitySelection.Count() == 1)
  10592. {
  10593. pCmdUI->Enable( TRUE);
  10594. return;
  10595. }
  10596. pCmdUI->Enable( FALSE);
  10597. }
  10598. void CWorldEditorView::OnSelectClones()
  10599. {
  10600. CWorldEditorDoc* pDoc = GetDocument();
  10601. CEntity *pen = pDoc->m_selEntitySelection.GetFirstInSelection();
  10602. // for each entity in the world
  10603. FOREACHINDYNAMICCONTAINER(pDoc->m_woWorld.wo_cenEntities, CEntity, iten)
  10604. {
  10605. // if has same name
  10606. if( pen->GetName() == iten->GetName() )
  10607. {
  10608. // if is not yet selected
  10609. if( !iten->IsSelected( ENF_SELECTED))
  10610. {
  10611. // select it
  10612. pDoc->m_selEntitySelection.Select( *iten);
  10613. }
  10614. }
  10615. }
  10616. // mark that selections have been changed
  10617. pDoc->m_chSelections.MarkChanged();
  10618. pDoc->UpdateAllViews( NULL);
  10619. }
  10620. BOOL CWorldEditorView::IsSelectClonesOnContextEnabled( void)
  10621. {
  10622. CCastRay crRayHit = GetMouseHitInformation( m_ptMouse);
  10623. if( crRayHit.cr_penHit != NULL)
  10624. {
  10625. return TRUE;
  10626. }
  10627. return FALSE;
  10628. }
  10629. void CWorldEditorView::OnSelectClonesOnContext()
  10630. {
  10631. CWorldEditorDoc* pDoc = GetDocument();
  10632. CCastRay crRayHit = GetMouseHitInformation( m_ptMouse);
  10633. if( crRayHit.cr_penHit != NULL)
  10634. {
  10635. // get hitted entity
  10636. CEntity *pen = crRayHit.cr_penHit;
  10637. // for each entity in the world
  10638. FOREACHINDYNAMICCONTAINER(pDoc->m_woWorld.wo_cenEntities, CEntity, iten)
  10639. {
  10640. // if has same name
  10641. if( pen->GetName() == iten->GetName() )
  10642. {
  10643. // if is not yet selected
  10644. if( !iten->IsSelected( ENF_SELECTED))
  10645. {
  10646. // select it
  10647. pDoc->m_selEntitySelection.Select( *iten);
  10648. }
  10649. }
  10650. }
  10651. }
  10652. // mark that selections have been changed
  10653. pDoc->m_chSelections.MarkChanged();
  10654. pDoc->UpdateAllViews( NULL);
  10655. }
  10656. void CWorldEditorView::OnKeyCtrlShiftE()
  10657. {
  10658. CWorldEditorDoc* pDoc = GetDocument();
  10659. if(pDoc->GetEditingMode()==TERRAIN_MODE)
  10660. {
  10661. ApplyEqualizeOntoTerrain();
  10662. }
  10663. else
  10664. {
  10665. OnSelectOfSameClass();
  10666. }
  10667. }
  10668. void CWorldEditorView::OnSelectOfSameClass()
  10669. {
  10670. CWorldEditorDoc* pDoc = GetDocument();
  10671. CEntity *pen = pDoc->m_selEntitySelection.GetFirstInSelection();
  10672. // to hold entities for selecting
  10673. CDynamicContainer<CEntity> dcEntities;
  10674. // for all selected entities
  10675. {FOREACHINDYNAMICCONTAINER(pDoc->m_selEntitySelection, CEntity, iten)
  10676. {
  10677. dcEntities.Add( &*iten);
  10678. }}
  10679. // for each non-hidden entity in the world
  10680. {FOREACHINDYNAMICCONTAINER(pDoc->m_woWorld.wo_cenEntities, CEntity, iten)
  10681. {
  10682. CBrushSector *pbscSector = iten->GetFirstSector();
  10683. BOOL bSectorVisible = (pbscSector == NULL) ||
  10684. !(pbscSector->bsc_ulFlags & BSCF_HIDDEN);
  10685. // if it isn't classified in hidden sector and is not hidden itself
  10686. if( !bSectorVisible || (iten->en_ulFlags&ENF_HIDDEN) )
  10687. {
  10688. continue;
  10689. }
  10690. // obtain this entity's class ptr
  10691. CEntityClass *pdecClass = iten->GetClass();
  10692. // test all classes
  10693. {FOREACHINDYNAMICCONTAINER(dcEntities, CEntity, itenClass)
  10694. {
  10695. CEntityClass *pdecClassTest = itenClass->GetClass();
  10696. // if of same class
  10697. if( pdecClassTest == pdecClass)
  10698. {
  10699. // if not yet selected
  10700. if( !iten->IsSelected( ENF_SELECTED))
  10701. {
  10702. // select it
  10703. pDoc->m_selEntitySelection.Select( *iten);
  10704. }
  10705. }
  10706. }}
  10707. }}
  10708. // mark that selections have been changed
  10709. pDoc->m_chSelections.MarkChanged();
  10710. pDoc->UpdateAllViews( NULL);
  10711. }
  10712. void CWorldEditorView::OnSelectOfSameClassOnContext()
  10713. {
  10714. CWorldEditorDoc* pDoc = GetDocument();
  10715. CCastRay crRayHit = GetMouseHitInformation( m_ptMouse);
  10716. if( crRayHit.cr_penHit != NULL)
  10717. {
  10718. // get hitted entity
  10719. CEntity *pen = crRayHit.cr_penHit;
  10720. // obtain this entity's class ptr
  10721. CEntityClass *pdecClassTest = pen->GetClass();
  10722. // for each non-hidden entity in the world
  10723. {FOREACHINDYNAMICCONTAINER(pDoc->m_woWorld.wo_cenEntities, CEntity, iten)
  10724. {
  10725. CBrushSector *pbscSector = iten->GetFirstSector();
  10726. BOOL bSectorVisible = (pbscSector == NULL) ||
  10727. !(pbscSector->bsc_ulFlags & BSCF_HIDDEN);
  10728. // if it isn't classified in hidden sector and is not hidden itself
  10729. if( !bSectorVisible || (iten->en_ulFlags&ENF_HIDDEN) )
  10730. {
  10731. continue;
  10732. }
  10733. CEntityClass *pdecClass = iten->GetClass();
  10734. // if of same class
  10735. if( pdecClassTest == pdecClass)
  10736. {
  10737. // if not yet selected
  10738. if( !iten->IsSelected( ENF_SELECTED))
  10739. {
  10740. // select it
  10741. pDoc->m_selEntitySelection.Select( *iten);
  10742. }
  10743. }
  10744. }}
  10745. }
  10746. // mark that selections have been changed
  10747. pDoc->m_chSelections.MarkChanged();
  10748. pDoc->UpdateAllViews( NULL);
  10749. }
  10750. BOOL CWorldEditorView::IsSelectOfSameClassOnContextEnabled( void)
  10751. {
  10752. CCastRay crRayHit = GetMouseHitInformation( m_ptMouse);
  10753. if( crRayHit.cr_penHit != NULL)
  10754. {
  10755. return TRUE;
  10756. }
  10757. return FALSE;
  10758. }
  10759. // limit current frame rate if neeeded
  10760. void LimitFrameRate(void)
  10761. {
  10762. // measure passed time for each loop
  10763. /*
  10764. static CTimerValue tvLast(-1.0f);
  10765. CTimerValue tvNow = _pTimer->GetHighPrecisionTimer();
  10766. TIME tmCurrentDelta = (tvNow-tvLast).GetSeconds();
  10767. // limit maximum frame rate
  10768. wed_iMaxFPSActive = ClampDn( (INDEX)wed_iMaxFPSActive, 1L);
  10769. TIME tmWantedDelta = 1.0f / wed_iMaxFPSActive;
  10770. if( tmCurrentDelta<tmWantedDelta) Sleep( (tmWantedDelta-tmCurrentDelta)*1000.0f);
  10771. // remember new time
  10772. tvLast = _pTimer->GetHighPrecisionTimer();*/
  10773. }
  10774. void CWorldEditorView::ApplyFreeModeControls( CPlacement3D &pl, ANGLE3D &aAbs, FLOAT &fSpeedMultiplier, BOOL bPrescan)
  10775. {
  10776. CChildFrame *pcf = GetChildFrame();
  10777. CWorldEditorDoc* pDoc = GetDocument();
  10778. #define FB_SPEED 1.0f
  10779. #define LR_SPEED 1.0f
  10780. #define UD_SPEED 1.0f
  10781. #define ROT_SPEED 0.75f
  10782. FLOAT fFB = 0.0f; // forward/backward movement
  10783. FLOAT fLR = 0.0f; // left/right movement
  10784. FLOAT fUD = 0.0f; // up/down movement
  10785. FLOAT fRLR = 0.0f; // rotate left/right
  10786. FLOAT fRUD = 0.0f; // rotate up/down
  10787. _pInput->GetInput(bPrescan);
  10788. if (!bPrescan) {
  10789. // additional key indentifiers are not on
  10790. BOOL bShift = _pInput->GetButtonState( KID_LSHIFT) || _pInput->GetButtonState( KID_RSHIFT);
  10791. BOOL bAlt = _pInput->GetButtonState( KID_LALT) || _pInput->GetButtonState( KID_RALT);
  10792. BOOL bCtrl = _pInput->GetButtonState( KID_LCONTROL) || _pInput->GetButtonState( KID_RCONTROL);
  10793. // apply view configuration from first perspective view of child configuration
  10794. if(_pInput->GetButtonState( KID_NUM0)) pcf->ApplySettingsFromPerspectiveView( this, 0);
  10795. if(_pInput->GetButtonState( KID_NUM1)) pcf->ApplySettingsFromPerspectiveView( this, 1);
  10796. if(_pInput->GetButtonState( KID_NUM2)) pcf->ApplySettingsFromPerspectiveView( this, 2);
  10797. if(_pInput->GetButtonState( KID_NUM3)) pcf->ApplySettingsFromPerspectiveView( this, 3);
  10798. if(_pInput->GetButtonState( KID_NUM4)) pcf->ApplySettingsFromPerspectiveView( this, 4);
  10799. if(_pInput->GetButtonState( KID_NUM5)) pcf->ApplySettingsFromPerspectiveView( this, 5);
  10800. if(_pInput->GetButtonState( KID_NUM6)) pcf->ApplySettingsFromPerspectiveView( this, 6);
  10801. if(_pInput->GetButtonState( KID_NUM7)) pcf->ApplySettingsFromPerspectiveView( this, 7);
  10802. if(_pInput->GetButtonState( KID_NUM8)) pcf->ApplySettingsFromPerspectiveView( this, 8);
  10803. if(_pInput->GetButtonState( KID_NUM9)) pcf->ApplySettingsFromPerspectiveView( this, 9);
  10804. // apply view configuration from available buffers
  10805. if(_pInput->GetButtonState( KID_0)) OnKeyBuffer( ID_BUFFER10);
  10806. if(_pInput->GetButtonState( KID_1)) OnKeyBuffer( ID_BUFFER01);
  10807. if(_pInput->GetButtonState( KID_2)) OnKeyBuffer( ID_BUFFER02);
  10808. if(_pInput->GetButtonState( KID_3)) OnKeyBuffer( ID_BUFFER03);
  10809. if(_pInput->GetButtonState( KID_4)) OnKeyBuffer( ID_BUFFER04);
  10810. if(_pInput->GetButtonState( KID_5)) OnKeyBuffer( ID_BUFFER05);
  10811. if(_pInput->GetButtonState( KID_6)) OnKeyBuffer( ID_BUFFER06);
  10812. if(_pInput->GetButtonState( KID_7)) OnKeyBuffer( ID_BUFFER07);
  10813. if(_pInput->GetButtonState( KID_8)) OnKeyBuffer( ID_BUFFER08);
  10814. if(_pInput->GetButtonState( KID_9)) OnKeyBuffer( ID_BUFFER09);
  10815. // ---------- Simulate moving as in fly mode
  10816. // forward
  10817. if(
  10818. _pInput->GetButtonState( KID_W) ||
  10819. _pInput->GetButtonState( KID_MOUSE2) ||
  10820. _pInput->GetButtonState( KID_ARROWUP))
  10821. {
  10822. fFB = -FB_SPEED*fSpeedMultiplier;
  10823. }
  10824. // backward
  10825. if(
  10826. _pInput->GetButtonState( KID_S) ||
  10827. _pInput->GetButtonState( KID_MOUSE1) ||
  10828. _pInput->GetButtonState( KID_ARROWDOWN) )
  10829. {
  10830. fFB = +FB_SPEED*fSpeedMultiplier;
  10831. }
  10832. /*
  10833. if( _pInput->GetButtonState( KID_MOUSE1))
  10834. {
  10835. fLR = -_pInput->GetAxisRelative(1)/15.0f;
  10836. }*/
  10837. // strife left
  10838. if(
  10839. _pInput->GetButtonState( KID_Q) ||
  10840. _pInput->GetButtonState( KID_A) ||
  10841. _pInput->GetButtonState( KID_ARROWLEFT) )
  10842. {
  10843. fLR = -LR_SPEED*fSpeedMultiplier;
  10844. }
  10845. // strife right
  10846. if(
  10847. _pInput->GetButtonState( KID_E) ||
  10848. _pInput->GetButtonState( KID_D) ||
  10849. _pInput->GetButtonState( KID_ARROWRIGHT) )
  10850. {
  10851. fLR = +LR_SPEED*fSpeedMultiplier;
  10852. }
  10853. // up
  10854. if( (_pInput->GetButtonState( KID_R) && !bAlt) ||
  10855. _pInput->GetButtonState( KID_SPACE) )
  10856. {
  10857. fUD = +UD_SPEED*fSpeedMultiplier;
  10858. }
  10859. // down
  10860. if( _pInput->GetButtonState( KID_F))
  10861. {
  10862. fUD = -UD_SPEED*fSpeedMultiplier;
  10863. }
  10864. // drop marker here
  10865. if( _pInput->GetButtonState( KID_C))
  10866. {
  10867. CTFileName fnDropClass;
  10868. CTString strTargetProperty;
  10869. if(pDoc->m_selEntitySelection.Count() == 1)
  10870. {
  10871. CEntity &enOnly = pDoc->m_selEntitySelection.GetFirst();
  10872. if(enOnly.DropsMarker( fnDropClass, strTargetProperty))
  10873. {
  10874. OnDropMarker(pl);
  10875. }
  10876. }
  10877. }
  10878. static BOOL bLastTurboDown = FALSE;
  10879. static FLOAT fSpeedMultiplierBeforeTurbo = 1.0f;
  10880. if( _pInput->GetButtonState( KID_TAB))
  10881. {
  10882. if( !bLastTurboDown)
  10883. {
  10884. fSpeedMultiplierBeforeTurbo = fSpeedMultiplier;
  10885. }
  10886. bLastTurboDown = TRUE;
  10887. fSpeedMultiplier = Clamp( fSpeedMultiplier+0.5f, 1.0f, 20.0f);
  10888. }
  10889. else if( bLastTurboDown)
  10890. {
  10891. bLastTurboDown = FALSE;
  10892. fSpeedMultiplier = fSpeedMultiplierBeforeTurbo;
  10893. }
  10894. }
  10895. // get current rotation
  10896. fRLR = _pInput->GetAxisValue(1)*ROT_SPEED;
  10897. fRUD = -_pInput->GetAxisValue(2)*ROT_SPEED;
  10898. // apply translation
  10899. if (!bPrescan) {
  10900. pl.Translate_OwnSystem( FLOAT3D(fLR, fUD, fFB));
  10901. // apply rotation
  10902. pl.pl_OrientationAngle = aAbs;//.Rotate_HPB( ANGLE3D(-fRLR, -fRUD, 0));
  10903. }
  10904. aAbs+=ANGLE3D(-fRLR, -fRUD, 0);
  10905. }
  10906. // placements and orientation used in free fly mode
  10907. static CPlacement3D _plNew;
  10908. static CPlacement3D _plOld;
  10909. static ANGLE3D _aAbs;
  10910. void CWorldEditorView::PumpWindowsMessagesInFreeMode(BOOL &bRunning, FLOAT &fSpeedMultiplier)
  10911. {
  10912. CChildFrame *pcf = GetChildFrame();
  10913. CWorldEditorDoc* pDoc = GetDocument();
  10914. // additional key indentifiers are not on
  10915. BOOL bShift = _pInput->GetButtonState( KID_LSHIFT) || _pInput->GetButtonState( KID_RSHIFT);
  10916. BOOL bAlt = _pInput->GetButtonState( KID_LALT) || _pInput->GetButtonState( KID_RALT);
  10917. BOOL bCtrl = _pInput->GetButtonState( KID_LCONTROL) || _pInput->GetButtonState( KID_RCONTROL);
  10918. // while there are any messages in the message queue
  10919. MSG msg;
  10920. while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
  10921. {
  10922. // process scripts that are invoked on shortcuts from within WED
  10923. ProcesWEDConsoleShortcuts( &msg);
  10924. if(msg.message==_uiMessengerMsg)
  10925. {
  10926. // if one application allready started
  10927. HWND hwndMessenger = ::FindWindow(NULL, L"Croteam Messenger");
  10928. if(hwndMessenger != NULL)
  10929. {
  10930. // force messenger to popup
  10931. ::PostMessage( hwndMessenger, _uiMessengerForcePopup, 0, 0);
  10932. }
  10933. }
  10934. // ---------- Simulate some important commands of wed
  10935. if( msg.message==WM_KEYDOWN || msg.message==WM_SYSKEYDOWN)
  10936. {
  10937. // 'G' links on/off
  10938. if( msg.wParam=='G' && !bCtrl) pcf->OnRenderTargets();
  10939. // 'G' links on/off
  10940. if( msg.wParam=='G' && bCtrl) pcf->OnToggleEntityNames();
  10941. // 'H' shadow on off
  10942. if( msg.wParam=='H') pcf->OnViewShadowsOnoff();
  10943. // 'Num -' toggle frame rate
  10944. if( msg.wParam == VK_SUBTRACT) pcf->OnSceneRenderingTime();
  10945. // 'B' toggle auto mip leveling
  10946. if( msg.wParam=='B') pcf->OnAutoMipLeveling();
  10947. // 'Alt+R' toggle frame rate
  10948. if( msg.wParam=='R' && bAlt) pcf->OnSceneRenderingTime();
  10949. // 'Shift+Backspace' center background viewer
  10950. if( (msg.wParam == VK_BACK) && bShift)
  10951. {
  10952. OnCenterBcgViewer();
  10953. _plNew = pcf->m_mvViewer.mv_plViewer;
  10954. _plOld = _plNew;
  10955. _aAbs = _plNew.pl_OrientationAngle;
  10956. }
  10957. // 'Backspace' center to 0
  10958. else if( msg.wParam == VK_BACK)
  10959. {
  10960. OnResetViewer();
  10961. _plNew = pcf->m_mvViewer.mv_plViewer;
  10962. _plOld = _plNew;
  10963. _aAbs = _plNew.pl_OrientationAngle;
  10964. }
  10965. // 'F5, F6, F7, F8' type of projections
  10966. if( (msg.wParam == VK_F5) && bShift) OnIsometricBottom();
  10967. else if( msg.wParam == VK_F5) OnIsometricTop();
  10968. if( (msg.wParam == VK_F6) && bShift) OnIsometricLeft();
  10969. else if( msg.wParam == VK_F6) OnIsometricRight();
  10970. if( (msg.wParam == VK_F7) && bShift) OnIsometricBack();
  10971. else if( msg.wParam == VK_F7) OnIsometricFront();
  10972. if( (msg.wParam == VK_F8)) OnPerspective();
  10973. // 'Home', 'End', 'Page Up', 'Page Dn' 'Ctrl+' combinations for storing and restoring positions
  10974. if( (msg.wParam == VK_HOME) && bCtrl) pcf->OnStorePosition01();
  10975. else if( msg.wParam == VK_HOME)
  10976. {
  10977. pcf->OnRestorePosition01();
  10978. _plNew = pcf->m_mvViewer.mv_plViewer;
  10979. _plOld = _plNew;
  10980. _aAbs = _plNew.pl_OrientationAngle;
  10981. }
  10982. if( (msg.wParam == VK_END) && bCtrl) pcf->OnStorePosition02();
  10983. else if( msg.wParam == VK_END)
  10984. {
  10985. pcf->OnRestorePosition02();
  10986. _plNew = pcf->m_mvViewer.mv_plViewer;
  10987. _plOld = _plNew;
  10988. _aAbs = _plNew.pl_OrientationAngle;
  10989. }
  10990. if( (msg.wParam == VK_PRIOR) && bCtrl) pcf->OnStorePosition03();
  10991. else if( msg.wParam == VK_PRIOR)
  10992. {
  10993. pcf->OnRestorePosition03();
  10994. _plNew = pcf->m_mvViewer.mv_plViewer;
  10995. _plOld = _plNew;
  10996. _aAbs = _plNew.pl_OrientationAngle;
  10997. }
  10998. if( (msg.wParam == VK_NEXT) && bCtrl) pcf->OnStorePosition04();
  10999. else if( msg.wParam == VK_NEXT)
  11000. {
  11001. pcf->OnRestorePosition04();
  11002. _plNew = pcf->m_mvViewer.mv_plViewer;
  11003. _plOld = _plNew;
  11004. _aAbs = _plNew.pl_OrientationAngle;
  11005. }
  11006. // 'X', 'Alt+X', 'Alt+A' hide selected, unselected, show all
  11007. if( (msg.wParam == 'X') && bAlt) pDoc->OnHideUnselected();
  11008. else if( msg.wParam == 'X') pDoc->OnHideSelected();
  11009. if( (msg.wParam == 'A') && bAlt) pDoc->OnShowAll();
  11010. // 'Z' for toggle view selection
  11011. if( msg.wParam == 'Z') pcf->OnViewSelection();
  11012. }
  11013. // use mouse wheel to increase/decrease moving speed
  11014. if( msg.message==WM_MOUSEWHEEL)
  11015. {
  11016. short zDelta = (short) HIWORD(msg.wParam);
  11017. INDEX iCount = zDelta/120;
  11018. for( INDEX iKnee=0; iKnee<Abs(iCount); iKnee++)
  11019. {
  11020. if(iCount<0) fSpeedMultiplier/=2;
  11021. else fSpeedMultiplier*=2;
  11022. }
  11023. }
  11024. // if it is not a mouse message
  11025. if(!(msg.message>=WM_MOUSEFIRST&&msg.message<=WM_MOUSELAST))
  11026. {
  11027. // if not system key messages
  11028. if (!(msg.message==WM_KEYDOWN && msg.wParam==VK_F10
  11029. ||msg.message==WM_SYSKEYDOWN))
  11030. {
  11031. // translate it
  11032. TranslateMessage(&msg);
  11033. }
  11034. // if paint message
  11035. if (msg.message==WM_PAINT)
  11036. {
  11037. // dispatch it
  11038. DispatchMessage(&msg);
  11039. }
  11040. }
  11041. // if should stop
  11042. if( (msg.message==WM_KEYDOWN && msg.wParam==VK_ESCAPE)
  11043. ||(msg.message==WM_ACTIVATE)
  11044. ||(msg.message==WM_CANCELMODE)
  11045. ||(msg.message==WM_KILLFOCUS)
  11046. ||(msg.message==WM_ACTIVATEAPP))
  11047. {
  11048. // stop running
  11049. bRunning = FALSE;
  11050. break;
  11051. }
  11052. }
  11053. }
  11054. void CWorldEditorView::OnAlternativeMovingMode()
  11055. {
  11056. INDEX iAllowMouseAcceleration = _pShell->GetINDEX("inp_bAllowMouseAcceleration");
  11057. INDEX iFilterMouse = _pShell->GetINDEX("inp_bFilterMouse");
  11058. _pShell->SetINDEX("inp_bAllowMouseAcceleration", 1);
  11059. _pShell->SetINDEX("inp_bFilterMouse", 1);
  11060. CWorldEditorDoc* pDoc = GetDocument();
  11061. CViewPrefs vpOrg = m_vpViewPrefs;
  11062. // obtain child frame ptr
  11063. CChildFrame *pcf = GetChildFrame();
  11064. _plNew = pcf->m_mvViewer.mv_plViewer;
  11065. _plOld = _plNew;
  11066. _aAbs = _plNew.pl_OrientationAngle;
  11067. BOOL bAutoMipBrushingBefore = pcf->m_bAutoMipBrushingOn;
  11068. BOOL bDisableVisibilityTweaksBefore = pcf->m_bDisableVisibilityTweaks;
  11069. // enable input
  11070. _pInput->EnableInput(m_pvpViewPort);
  11071. // initialy, game is running
  11072. BOOL bRunning = TRUE;
  11073. INDEX iLastTick = 0;
  11074. CTimerValue tvStart = _pTimer->GetHighPrecisionTimer();
  11075. // while it is still running
  11076. while( bRunning)
  11077. {
  11078. // process all windows messages
  11079. PumpWindowsMessagesInFreeMode( bRunning, _fFlyModeSpeedMultiplier);
  11080. CTimerValue tvNow = _pTimer->GetHighPrecisionTimer();
  11081. FLOAT fPassed = (tvNow-tvStart).GetSeconds();
  11082. INDEX iNowTick = INDEX(fPassed/_pTimer->TickQuantum);
  11083. // apply controls for frame rates below tick quantum
  11084. while(iLastTick<iNowTick-1)
  11085. {
  11086. _plOld = _plNew;
  11087. ApplyFreeModeControls( _plNew, _aAbs, _fFlyModeSpeedMultiplier, FALSE);
  11088. iLastTick++;
  11089. }
  11090. ApplyFreeModeControls( _plNew, _aAbs, _fFlyModeSpeedMultiplier, TRUE);
  11091. // set new viewer position
  11092. FLOAT fLerpFactor = (fPassed-iNowTick*_pTimer->TickQuantum)/_pTimer->TickQuantum;
  11093. ASSERT(fLerpFactor>0 && fLerpFactor<1.0f);
  11094. pcf->m_mvViewer.mv_plViewer.Lerp( _plOld, _plNew, Clamp(fLerpFactor, 0.0f, 1.0f));
  11095. pcf->m_mvViewer.mv_plViewer.pl_OrientationAngle = _aAbs;
  11096. // disable auto rendering range
  11097. m_vpViewPrefs.m_bAutoRenderingRange = FALSE;
  11098. m_vpViewPrefs.m_fRenderingRange = 2.0f;
  11099. pcf->m_bAutoMipBrushingOn = TRUE;
  11100. pcf->m_bDisableVisibilityTweaks=FALSE;
  11101. // render view again
  11102. CDC *pDC = GetDC();
  11103. OnDraw( pDC);
  11104. ReleaseDC( pDC);
  11105. // smooth frame rate
  11106. LimitFrameRate();
  11107. }
  11108. _pInput->DisableInput();
  11109. // restore rendering range settings from remembered stat view prefs
  11110. m_vpViewPrefs.m_bAutoRenderingRange = vpOrg.m_bAutoRenderingRange;
  11111. m_vpViewPrefs.m_wrpWorldRenderPrefs.SetMinimumRenderRange(vpOrg.m_wrpWorldRenderPrefs.GetMinimumRenderRange());
  11112. pcf->m_bAutoMipBrushingOn = bAutoMipBrushingBefore;
  11113. pcf->m_bDisableVisibilityTweaks=bDisableVisibilityTweaksBefore;
  11114. _pShell->SetINDEX("inp_bAllowMouseAcceleration", iAllowMouseAcceleration);
  11115. _pShell->SetINDEX("inp_bFilterMouse", iFilterMouse);
  11116. }
  11117. void CWorldEditorView::OnReTriple()
  11118. {
  11119. CWorldEditorDoc* pDoc = GetDocument();
  11120. CBrushPolygon *pbpo = pDoc->m_selPolygonSelection.GetFirstInSelection();
  11121. pbpo->bpo_pbscSector->ReTriple( pDoc->m_selPolygonSelection);
  11122. }
  11123. void CWorldEditorView::OnClearAllTargets(void)
  11124. {
  11125. CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
  11126. CWorldEditorDoc* pDoc = GetDocument();
  11127. if( m_bEntityHitedOnContext && m_penEntityHitOnContext != NULL)
  11128. {
  11129. if( ::MessageBoxA( pMainFrame->m_hWnd, "Are you sure that you want to clear all targets?",
  11130. "Warning !", MB_YESNO | MB_ICONWARNING | MB_DEFBUTTON2|
  11131. MB_SYSTEMMODAL | MB_TOPMOST) != IDYES)
  11132. {
  11133. return;
  11134. }
  11135. // clear all targets of right-clicked entity
  11136. pMainFrame->m_PropertyComboBar.ClearAllTargets( m_penEntityHitOnContext);
  11137. pDoc->UpdateAllViews( NULL);
  11138. pDoc->SetModifiedFlag();
  11139. }
  11140. }
  11141. void CWorldEditorView::OnSelectCsgTarget()
  11142. {
  11143. CWorldEditorDoc* pDoc = GetDocument();
  11144. CBrushMip *pbmCurrentMip = GetCurrentBrushMip();
  11145. if (pbmCurrentMip!=NULL)
  11146. {
  11147. // obtain entity
  11148. CEntity *pen = pbmCurrentMip->bm_pbrBrush->br_penEntity;
  11149. if( !pen->IsSelected( ENF_SELECTED))
  11150. {
  11151. pDoc->m_selEntitySelection.Select( *pen);
  11152. pDoc->m_chSelections.MarkChanged();
  11153. pDoc->UpdateAllViews( NULL);
  11154. }
  11155. }
  11156. }
  11157. void CWorldEditorView::OnUpdateSelectCsgTarget(CCmdUI* pCmdUI)
  11158. {
  11159. CWorldEditorDoc* pDoc = GetDocument();
  11160. CBrushMip *pbmCurrentMip = GetCurrentBrushMip();
  11161. pCmdUI->Enable(pbmCurrentMip!=NULL);
  11162. }
  11163. void CWorldEditorView::OnUpdateReTriple(CCmdUI* pCmdUI)
  11164. {
  11165. BOOL bEnableRetripling = FALSE;
  11166. CWorldEditorDoc* pDoc = GetDocument();
  11167. if( pDoc->m_selPolygonSelection.Count() != 0)
  11168. {
  11169. CBrushPolygon *pbpo = pDoc->m_selPolygonSelection.GetFirstInSelection();
  11170. bEnableRetripling = pbpo->bpo_pbscSector->IsReTripleAvailable( pDoc->m_selPolygonSelection);
  11171. }
  11172. pCmdUI->Enable(bEnableRetripling);
  11173. }
  11174. void CWorldEditorView::OnTriangularizePolygon()
  11175. {
  11176. CWorldEditorDoc *pDoc = GetDocument();
  11177. CBrushPolygon *pbpoHitted = NULL;
  11178. if( (m_penEntityHitOnContext != NULL) &&
  11179. (m_penEntityHitOnContext->GetRenderType() == CEntity::RT_BRUSH) &&
  11180. (m_pbpoRightClickedPolygon != NULL) )
  11181. {
  11182. pbpoHitted = m_pbpoRightClickedPolygon;
  11183. }
  11184. if( pbpoHitted != NULL)
  11185. {
  11186. pDoc->m_selVertexSelection.Clear();
  11187. if( pbpoHitted->IsSelected(BPOF_SELECTED))
  11188. {
  11189. OnTriangularizeSelection();
  11190. return;
  11191. }
  11192. else
  11193. {
  11194. pDoc->m_selVertexSelection.Clear();
  11195. pDoc->m_selPolygonSelection.Clear();
  11196. pbpoHitted->bpo_pbscSector->TriangularizePolygon( pbpoHitted);
  11197. }
  11198. }
  11199. pDoc->m_chSelections.MarkChanged();
  11200. pDoc->SetModifiedFlag();
  11201. pDoc->UpdateAllViews( NULL);
  11202. }
  11203. void CWorldEditorView::OnEntityContextHelp()
  11204. {
  11205. if( m_penEntityHitOnContext != NULL)
  11206. {
  11207. theApp.DisplayHelp(m_penEntityHitOnContext->GetClass()->GetName(), HH_DISPLAY_TOPIC, NULL);
  11208. }
  11209. }
  11210. void CWorldEditorView::AutoFitMapping(CBrushPolygon *pbpo, BOOL bInvert/*=FALSE*/, BOOL bFitBoth/*=FALSE*/)
  11211. {
  11212. CWorldEditorDoc* pDoc = GetDocument();
  11213. if( pbpo==NULL) return;
  11214. if( pbpo->IsSelected(BPOF_SELECTED))
  11215. {
  11216. // for each selected polygon
  11217. FOREACHINDYNAMICCONTAINER(pDoc->m_selPolygonSelection, CBrushPolygon, itbpo)
  11218. {
  11219. AutoFitMappingOnPolygon(*itbpo, bInvert, bFitBoth);
  11220. }
  11221. }
  11222. else
  11223. {
  11224. AutoFitMappingOnPolygon(*pbpo, bInvert, bFitBoth);
  11225. }
  11226. pDoc->m_chSelections.MarkChanged();
  11227. pDoc->SetModifiedFlag( TRUE);
  11228. pDoc->UpdateAllViews( NULL);
  11229. }
  11230. void CWorldEditorView::AutoFitMappingOnPolygon(CBrushPolygon &bpo, BOOL bInvert/*=FALSE*/, BOOL bFitBoth/*=FALSE*/)
  11231. {
  11232. CWorldEditorDoc* pDoc = GetDocument();
  11233. CMappingDefinition &md = bpo.bpo_abptTextures[pDoc->m_iTexture].bpt_mdMapping;
  11234. // reset u,v stretches
  11235. CMappingDefinitionUI mdui;
  11236. md.ToUI(mdui);
  11237. mdui.mdui_fUStretch = 1.0f;
  11238. mdui.mdui_fVStretch = 1.0f;
  11239. mdui.mdui_fUOffset = 0.0f;
  11240. mdui.mdui_fVOffset = 0.0f;
  11241. md.FromUI(mdui);
  11242. // find min and max u and v for the polygon
  11243. FLOAT fMinU = UpperLimit(0.0f);
  11244. FLOAT fMaxU = LowerLimit(0.0f);
  11245. FLOAT fMinV = UpperLimit(0.0f);
  11246. FLOAT fMaxV = LowerLimit(0.0f);
  11247. INDEX ibpe=0;
  11248. for(; ibpe<bpo.bpo_abpePolygonEdges.Count(); ibpe++)
  11249. {
  11250. CBrushPolygonEdge &bpe = bpo.bpo_abpePolygonEdges[ibpe];
  11251. FLOAT3D v0, v1;
  11252. MEX2D(vTex0);
  11253. bpe.GetVertexCoordinatesRelative(v0, v1);
  11254. md.GetTextureCoordinates( bpo.bpo_pbplPlane->bpl_pwplWorking->wpl_mvRelative, v0, vTex0);
  11255. FLOAT fU = vTex0(1)/1024.0f;
  11256. FLOAT fV = vTex0(2)/1024.0f;
  11257. fMinU = Min(fMinU, fU);
  11258. fMaxU = Max(fMaxU, fU);
  11259. fMinV = Min(fMinV, fV);
  11260. fMaxV = Max(fMaxV, fV);
  11261. }
  11262. // calculate u,v fit stretches
  11263. FLOAT fFitStretchU = fMaxU-fMinU;
  11264. FLOAT fFitStretchV = fMaxV-fMinV;
  11265. // get fit stretch
  11266. FLOAT fFitStretch;
  11267. if( !bInvert)
  11268. {
  11269. fFitStretch = Min(fFitStretchV,fFitStretchU);
  11270. }
  11271. else
  11272. {
  11273. fFitStretch = Max(fFitStretchV,fFitStretchU);
  11274. }
  11275. // adjust stretch for texture size
  11276. CTextureData *ptd = (CTextureData *)bpo.bpo_abptTextures[pDoc->m_iTexture].bpt_toTexture.GetData();
  11277. if( ptd!=NULL)
  11278. {
  11279. MEX mexW=ptd->GetWidth();
  11280. MEX mexH=ptd->GetHeight();
  11281. // if fitting U
  11282. if( fFitStretch==fFitStretchU)
  11283. {
  11284. fFitStretch/=mexW/1024.0f;
  11285. }
  11286. // if fitting V
  11287. else
  11288. {
  11289. fFitStretch/=mexH/1024.0f;
  11290. }
  11291. fFitStretchU/=mexW/1024.0f;
  11292. fFitStretchV/=mexH/1024.0f;
  11293. }
  11294. if( bFitBoth)
  11295. {
  11296. mdui.mdui_fUStretch=fFitStretchU;
  11297. mdui.mdui_fVStretch=fFitStretchV;
  11298. }
  11299. else
  11300. {
  11301. mdui.mdui_fUStretch=fFitStretch;
  11302. mdui.mdui_fVStretch=fFitStretch;
  11303. }
  11304. md.FromUI(mdui);
  11305. CMappingVectors &mv = bpo.bpo_pbplPlane->bpl_pwplWorking->wpl_mvRelative;
  11306. // find vtx that has min u and v
  11307. fMinU = UpperLimit(0.0f);
  11308. fMaxV = LowerLimit(0.0f);
  11309. FLOAT3D vMinU, vMaxV;
  11310. for(ibpe=0; ibpe<bpo.bpo_abpePolygonEdges.Count(); ibpe++)
  11311. {
  11312. CBrushPolygonEdge &bpe = bpo.bpo_abpePolygonEdges[ibpe];
  11313. FLOAT3D v0, v1, va0, va1;
  11314. MEX2D(vTex0);
  11315. bpe.GetVertexCoordinatesRelative(v0, v1);
  11316. bpe.GetVertexCoordinatesAbsolute(va0, va1);
  11317. md.GetTextureCoordinates( mv, v0, vTex0);
  11318. FLOAT fU = vTex0(1)/1024.0f;
  11319. FLOAT fV = vTex0(2)/1024.0f;
  11320. if( fU<fMinU)
  11321. {
  11322. vMinU=v0;
  11323. fMinU=fU;
  11324. }
  11325. if( fV>fMaxV)
  11326. {
  11327. vMaxV=v0;
  11328. fMaxV=fV;
  11329. }
  11330. }
  11331. // remember u offset
  11332. md.Center(mv, vMinU);
  11333. md.ToUI(mdui);
  11334. fMinU = mdui.mdui_fUOffset;
  11335. // remember v offset
  11336. md.Center(mv, vMaxV);
  11337. md.ToUI(mdui);
  11338. fMaxV = mdui.mdui_fVOffset;
  11339. // set offsets
  11340. mdui.mdui_fUOffset=fMinU;
  11341. mdui.mdui_fVOffset=fMaxV;
  11342. md.FromUI(mdui);
  11343. }
  11344. void CWorldEditorView::OnTriangularizeSelection()
  11345. {
  11346. CWorldEditorDoc* pDoc = GetDocument();
  11347. CDynamicContainer<CBrushPolygon> dcPolygons;
  11348. // copy polygon selection
  11349. FOREACHINDYNAMICCONTAINER(pDoc->m_selPolygonSelection, CBrushPolygon, itbpo)
  11350. {
  11351. dcPolygons.Add(&*itbpo);
  11352. }
  11353. // clear selections
  11354. pDoc->m_selPolygonSelection.Clear();
  11355. pDoc->m_selVertexSelection.Clear();
  11356. // apply triangularisation
  11357. pDoc->m_woWorld.TriangularizePolygons( dcPolygons);
  11358. pDoc->m_chSelections.MarkChanged();
  11359. pDoc->SetModifiedFlag();
  11360. pDoc->UpdateAllViews( NULL);
  11361. }
  11362. void CWorldEditorView::OnUpdateTriangularizeSelection(CCmdUI* pCmdUI)
  11363. {
  11364. CWorldEditorDoc* pDoc = GetDocument();
  11365. pCmdUI->Enable(pDoc->m_selPolygonSelection.Count()!=0);
  11366. }
  11367. void CWorldEditorView::OnPopupAutoFitMapping()
  11368. {
  11369. if(m_pbpoRightClickedPolygon != NULL)
  11370. {
  11371. AutoFitMapping( m_pbpoRightClickedPolygon);
  11372. }
  11373. }
  11374. void CWorldEditorView::OnPopupAutoFitMappingSmall()
  11375. {
  11376. if(m_pbpoRightClickedPolygon != NULL)
  11377. {
  11378. AutoFitMapping( m_pbpoRightClickedPolygon, TRUE);
  11379. }
  11380. }
  11381. void CWorldEditorView::OnPopupAutoFitMappingBoth()
  11382. {
  11383. if(m_pbpoRightClickedPolygon != NULL)
  11384. {
  11385. AutoFitMapping( m_pbpoRightClickedPolygon, TRUE, TRUE);
  11386. }
  11387. }
  11388. void CWorldEditorView::ApplyDefaultMapping(CBrushPolygon *pbpo, BOOL bRotation, BOOL bOffset, BOOL bStretch)
  11389. {
  11390. if(m_pbpoRightClickedPolygon == NULL) return;
  11391. CWorldEditorDoc* pDoc = GetDocument();
  11392. // if is selected
  11393. if( m_pbpoRightClickedPolygon->IsSelected(BPOF_SELECTED))
  11394. {
  11395. FOREACHINDYNAMICCONTAINER(pDoc->m_selPolygonSelection, CBrushPolygon, itbpo)
  11396. {
  11397. CBrushPolygon &po=*itbpo;
  11398. CMappingDefinition &md=po.bpo_abptTextures[pDoc->m_iTexture].bpt_mdMapping;
  11399. CMappingDefinitionUI mdui;
  11400. md.ToUI(mdui);
  11401. if( bRotation)
  11402. {
  11403. mdui.mdui_aURotation=0.0f;
  11404. mdui.mdui_aVRotation=0.0f;
  11405. }
  11406. if( bStretch)
  11407. {
  11408. mdui.mdui_fUStretch = 1.0f;
  11409. mdui.mdui_fVStretch = 1.0f;
  11410. }
  11411. if( bOffset)
  11412. {
  11413. mdui.mdui_fUOffset = 0.0f;
  11414. mdui.mdui_fVOffset = 0.0f;
  11415. }
  11416. md.FromUI(mdui);
  11417. }
  11418. }
  11419. else
  11420. {
  11421. CMappingDefinition &md=m_pbpoRightClickedPolygon->bpo_abptTextures[pDoc->m_iTexture].bpt_mdMapping;
  11422. CMappingDefinitionUI mdui;
  11423. md.ToUI(mdui);
  11424. if( bRotation)
  11425. {
  11426. mdui.mdui_aURotation=0.0f;
  11427. mdui.mdui_aVRotation=0.0f;
  11428. }
  11429. if( bStretch)
  11430. {
  11431. mdui.mdui_fUStretch = 1.0f;
  11432. mdui.mdui_fVStretch = 1.0f;
  11433. }
  11434. if( bOffset)
  11435. {
  11436. mdui.mdui_fUOffset = 0.0f;
  11437. mdui.mdui_fVOffset = 0.0f;
  11438. }
  11439. md.FromUI(mdui);
  11440. }
  11441. }
  11442. void CWorldEditorView::OnResetMappingOffset()
  11443. {
  11444. ApplyDefaultMapping( m_pbpoRightClickedPolygon, FALSE, TRUE, FALSE);
  11445. }
  11446. void CWorldEditorView::OnResetMappingRotation()
  11447. {
  11448. ApplyDefaultMapping( m_pbpoRightClickedPolygon, TRUE, FALSE, FALSE);
  11449. }
  11450. void CWorldEditorView::OnResetMappingStretch()
  11451. {
  11452. ApplyDefaultMapping( m_pbpoRightClickedPolygon, FALSE, FALSE, TRUE);
  11453. }
  11454. void CWorldEditorView::ShowLinkTree(CEntity *pen, BOOL bWhoTargets/*=FALSE*/, BOOL bPropertyNames/*=FALSE*/)
  11455. {
  11456. CWorldEditorDoc* pDoc = GetDocument();
  11457. CPoint ptScr=m_ptMouse;
  11458. ClientToScreen( &ptScr);
  11459. if( pen!=NULL || (pDoc->m_selEntitySelection.Count() != 0))
  11460. {
  11461. CDlgLinkTree dlg( pen, ptScr, bWhoTargets, bPropertyNames);
  11462. dlg.DoModal();
  11463. }
  11464. }
  11465. void CWorldEditorView::OnCrossroadForL()
  11466. {
  11467. CWorldEditorDoc* pDoc = GetDocument();
  11468. if( pDoc->GetEditingMode() == ENTITY_MODE)
  11469. {
  11470. ShowLinkTree(NULL);
  11471. }
  11472. else if(pDoc->m_pwoSecondLayer != NULL)
  11473. {
  11474. pDoc->OnJoinLayers();
  11475. }
  11476. else if( pDoc->GetEditingMode() == TERRAIN_MODE)
  11477. {
  11478. theApp.m_iTerrainEditMode=TEM_LAYER;
  11479. theApp.m_ctTerrainPageCanvas.MarkChanged();
  11480. GetDocument()->SetStatusLineModeInfoMessage();
  11481. }
  11482. }
  11483. void CWorldEditorView::OnSelectUsingTargetTree()
  11484. {
  11485. ShowLinkTree(m_penEntityHitOnContext);
  11486. }
  11487. void CWorldEditorView::OnTargetTree()
  11488. {
  11489. ShowLinkTree(NULL);
  11490. }
  11491. void CWorldEditorView::OnUpdateTargetTree(CCmdUI* pCmdUI)
  11492. {
  11493. CWorldEditorDoc* pDoc = GetDocument();
  11494. pCmdUI->Enable(pDoc->m_selEntitySelection.Count() != 0);
  11495. }
  11496. void SwapLayers( CBrushPolygon &bpo, INDEX il1, INDEX il2)
  11497. {
  11498. CBrushPolygonTexture bptTemp;
  11499. bptTemp.CopyTextureProperties(bpo.bpo_abptTextures[il1], TRUE);
  11500. bpo.bpo_abptTextures[il1].CopyTextureProperties(bpo.bpo_abptTextures[il2], TRUE);
  11501. bpo.bpo_abptTextures[il2].CopyTextureProperties(bptTemp, TRUE);
  11502. }
  11503. void CWorldEditorView::OnSwapLayers12()
  11504. {
  11505. CWorldEditorDoc* pDoc = GetDocument();
  11506. FOREACHINDYNAMICCONTAINER(pDoc->m_selPolygonSelection, CBrushPolygon, itbpo)
  11507. {
  11508. SwapLayers( *itbpo, 0, 1);
  11509. }
  11510. pDoc->m_chSelections.MarkChanged();
  11511. pDoc->UpdateAllViews( NULL);
  11512. }
  11513. void CWorldEditorView::OnSwapLayers23()
  11514. {
  11515. CWorldEditorDoc* pDoc = GetDocument();
  11516. FOREACHINDYNAMICCONTAINER(pDoc->m_selPolygonSelection, CBrushPolygon, itbpo)
  11517. {
  11518. SwapLayers( *itbpo, 1, 2);
  11519. }
  11520. pDoc->m_chSelections.MarkChanged();
  11521. pDoc->UpdateAllViews( NULL);
  11522. }
  11523. void CWorldEditorView::OnSelectDescendants()
  11524. {
  11525. CWorldEditorDoc* pDoc = GetDocument();
  11526. FOREACHINDYNAMICCONTAINER(pDoc->m_selEntitySelection, CEntity, iten)
  11527. {
  11528. SelectDescendents( pDoc->m_selEntitySelection, *iten);
  11529. }
  11530. pDoc->m_chSelections.MarkChanged();
  11531. pDoc->UpdateAllViews( NULL);
  11532. }
  11533. void CWorldEditorView::OnRotateToTargetOrigin()
  11534. {
  11535. if(m_penEntityHitOnContext != NULL)
  11536. {
  11537. CWorldEditorDoc* pDoc = GetDocument();
  11538. FOREACHINDYNAMICCONTAINER(pDoc->m_selEntitySelection, CEntity, iten)
  11539. {
  11540. const CPlacement3D &plDst=iten->GetPlacement();
  11541. const CPlacement3D &plSrc=m_penEntityHitOnContext->GetPlacement();
  11542. FLOAT3D vDir=plSrc.pl_PositionVector-plDst.pl_PositionVector;
  11543. vDir.Normalize();
  11544. ANGLE3D ang;
  11545. DirectionVectorToAngles(vDir, ang);
  11546. CPlacement3D plNew=plDst;
  11547. plNew.pl_OrientationAngle=ang;
  11548. iten->SetPlacement(plNew);
  11549. }
  11550. pDoc->SetModifiedFlag( TRUE);
  11551. pDoc->UpdateAllViews( NULL);
  11552. }
  11553. }
  11554. void CWorldEditorView::OnRotateToTargetCenter()
  11555. {
  11556. if(m_penEntityHitOnContext != NULL)
  11557. {
  11558. CWorldEditorDoc* pDoc = GetDocument();
  11559. FOREACHINDYNAMICCONTAINER(pDoc->m_selEntitySelection, CEntity, iten)
  11560. {
  11561. const CPlacement3D &plDst=iten->GetPlacement();
  11562. FLOATaabbox3D box;
  11563. m_penEntityHitOnContext->GetSize(box);
  11564. FLOAT3D vTarget=box.Center();
  11565. FLOAT3D vDir=vTarget-plDst.pl_PositionVector;
  11566. vDir.Normalize();
  11567. ANGLE3D ang;
  11568. DirectionVectorToAngles(vDir, ang);
  11569. CPlacement3D plNew=plDst;
  11570. plNew.pl_OrientationAngle=ang;
  11571. iten->SetPlacement(plNew);
  11572. }
  11573. pDoc->SetModifiedFlag( TRUE);
  11574. pDoc->UpdateAllViews( NULL);
  11575. }
  11576. }
  11577. void CWorldEditorView::OnCopyPlacement()
  11578. {
  11579. if(m_penEntityHitOnContext==NULL) return;
  11580. theApp.m_plClipboard2=m_penEntityHitOnContext->GetPlacement();
  11581. }
  11582. void CWorldEditorView::OnCopyOrientation()
  11583. {
  11584. if(m_penEntityHitOnContext==NULL) return;
  11585. theApp.m_plClipboard1.pl_OrientationAngle=m_penEntityHitOnContext->GetPlacement().pl_OrientationAngle;
  11586. }
  11587. void CWorldEditorView::OnCopyPosition()
  11588. {
  11589. if(m_penEntityHitOnContext==NULL) return;
  11590. theApp.m_plClipboard1.pl_PositionVector=m_penEntityHitOnContext->GetPlacement().pl_PositionVector;
  11591. }
  11592. void CWorldEditorView::OnPastePlacement()
  11593. {
  11594. CWorldEditorDoc* pDoc = GetDocument();
  11595. if(m_penEntityHitOnContext==NULL) return;
  11596. if( m_penEntityHitOnContext->IsSelected(ENF_SELECTED))
  11597. {
  11598. FOREACHINDYNAMICCONTAINER(pDoc->m_selEntitySelection, CEntity, iten)
  11599. {
  11600. iten->SetPlacement(theApp.m_plClipboard2);
  11601. }
  11602. }
  11603. else
  11604. {
  11605. m_penEntityHitOnContext->SetPlacement(theApp.m_plClipboard2);
  11606. }
  11607. pDoc->SetModifiedFlag( TRUE);
  11608. pDoc->UpdateAllViews( NULL);
  11609. }
  11610. void CWorldEditorView::OnPasteOrientation()
  11611. {
  11612. CWorldEditorDoc* pDoc = GetDocument();
  11613. if(m_penEntityHitOnContext==NULL) return;
  11614. if( m_penEntityHitOnContext->IsSelected(ENF_SELECTED))
  11615. {
  11616. FOREACHINDYNAMICCONTAINER(pDoc->m_selEntitySelection, CEntity, iten)
  11617. {
  11618. CPlacement3D pl=iten->GetPlacement();
  11619. pl.pl_OrientationAngle=theApp.m_plClipboard1.pl_OrientationAngle;
  11620. iten->SetPlacement(pl);
  11621. }
  11622. }
  11623. else
  11624. {
  11625. CPlacement3D pl=m_penEntityHitOnContext->GetPlacement();
  11626. pl.pl_OrientationAngle=theApp.m_plClipboard1.pl_OrientationAngle;
  11627. m_penEntityHitOnContext->SetPlacement(pl);
  11628. }
  11629. pDoc->SetModifiedFlag( TRUE);
  11630. pDoc->UpdateAllViews( NULL);
  11631. }
  11632. void CWorldEditorView::OnPastePosition()
  11633. {
  11634. CWorldEditorDoc* pDoc = GetDocument();
  11635. if(m_penEntityHitOnContext==NULL) return;
  11636. if( m_penEntityHitOnContext->IsSelected(ENF_SELECTED))
  11637. {
  11638. FOREACHINDYNAMICCONTAINER(pDoc->m_selEntitySelection, CEntity, iten)
  11639. {
  11640. CPlacement3D pl=iten->GetPlacement();
  11641. pl.pl_PositionVector=theApp.m_plClipboard1.pl_PositionVector;
  11642. iten->SetPlacement(pl);
  11643. }
  11644. }
  11645. else
  11646. {
  11647. CPlacement3D pl=m_penEntityHitOnContext->GetPlacement();
  11648. pl.pl_PositionVector=theApp.m_plClipboard1.pl_PositionVector;
  11649. m_penEntityHitOnContext->SetPlacement(pl);
  11650. }
  11651. pDoc->SetModifiedFlag( TRUE);
  11652. pDoc->UpdateAllViews( NULL);
  11653. }
  11654. void CWorldEditorView::Align(BOOL bX,BOOL bY,BOOL bZ,BOOL bH,BOOL bP,BOOL bB)
  11655. {
  11656. CWorldEditorDoc* pDoc = GetDocument();
  11657. INDEX ctSelected=pDoc->m_woWorld.wo_cenEntities.Count();
  11658. CEntity *penLast=NULL;
  11659. {FOREACHINDYNAMICCONTAINER(pDoc->m_selEntitySelection, CEntity, iten)
  11660. {
  11661. penLast=&*iten;
  11662. }}
  11663. CPlacement3D penSrc=penLast->GetPlacement();
  11664. {FOREACHINDYNAMICCONTAINER(pDoc->m_selEntitySelection, CEntity, iten)
  11665. {
  11666. CPlacement3D pl=iten->GetPlacement();
  11667. if( bX) {pl.pl_PositionVector(1)=penSrc.pl_PositionVector(1);};
  11668. if( bY) {pl.pl_PositionVector(2)=penSrc.pl_PositionVector(2);};
  11669. if( bZ) {pl.pl_PositionVector(3)=penSrc.pl_PositionVector(3);};
  11670. if( bH) {pl.pl_OrientationAngle(1)=penSrc.pl_OrientationAngle(1);};
  11671. if( bP) {pl.pl_OrientationAngle(2)=penSrc.pl_OrientationAngle(2);};
  11672. if( bB) {pl.pl_OrientationAngle(3)=penSrc.pl_OrientationAngle(3);};
  11673. iten->SetPlacement(pl);
  11674. }}
  11675. pDoc->SetModifiedFlag( TRUE);
  11676. pDoc->UpdateAllViews( NULL);
  11677. }
  11678. void CWorldEditorView::OnAlignB()
  11679. {
  11680. Align(FALSE,FALSE,FALSE,FALSE,FALSE,TRUE);
  11681. }
  11682. void CWorldEditorView::OnAlignH()
  11683. {
  11684. Align(FALSE,FALSE,FALSE,TRUE,FALSE,FALSE);
  11685. }
  11686. void CWorldEditorView::OnAlignP()
  11687. {
  11688. Align(FALSE,FALSE,FALSE,FALSE,TRUE,FALSE);
  11689. }
  11690. void CWorldEditorView::OnAlignX()
  11691. {
  11692. Align(TRUE,FALSE,FALSE,FALSE,FALSE,FALSE);
  11693. }
  11694. void CWorldEditorView::OnAlignY()
  11695. {
  11696. Align(FALSE,TRUE,FALSE,FALSE,FALSE,FALSE);
  11697. }
  11698. void CWorldEditorView::OnAlignZ()
  11699. {
  11700. Align(FALSE,FALSE,TRUE,FALSE,FALSE,FALSE);
  11701. }
  11702. struct CameraProjectionInfo {
  11703. FLOAT cpi_fOffsetRatioX;
  11704. FLOAT cpi_fOffsetRatioY;
  11705. FLOAT cpi_fOffsetRatioZ;
  11706. ANGLE cpi_angH;
  11707. ANGLE cpi_angP;
  11708. ANGLE cpi_angB;
  11709. double cpi_rMinI;
  11710. double cpi_rMinJ;
  11711. double cpi_rSizeI;
  11712. double cpi_rSizeJ;
  11713. };
  11714. CameraProjectionInfo *_pacpi=NULL;
  11715. INDEX _ctProjections=0;
  11716. CameraProjectionInfo acpiF[] =
  11717. {
  11718. { 0, 0, 1, 0, 0, 0, 0, 0, 1, 1}
  11719. };
  11720. CameraProjectionInfo acpi2x2[] =
  11721. {
  11722. { 0, 0, 1, 0, 0, 0, 0, 0, 0.5, 0.5},
  11723. { 1, 0, 0, 90, 0, 0, 0.5, 0, 0.5, 0.5},
  11724. { 0, 0, -1, 180, 0, 0, 0, 0.5, 0.5, 0.5},
  11725. {-1, 0, 0, 270, 0, 0, 0.5, 0.5, 0.5, 0.5}
  11726. };
  11727. CameraProjectionInfo acpi3x2[] =
  11728. {
  11729. { 0, 0, 1, 0, 0, 0, 0, 0, 0.3, 0.3},
  11730. { 1, 0, 0, 90, 0, 0, 0.3, 0, 0.3, 0.3},
  11731. { 0, 0, -1, 180, 0, 0, 0.6, 0, 0.3, 0.3},
  11732. {-1, 0, 0, 270, 0, 0, 0, 0.3, 0.3, 0.3},
  11733. { 0, 1, 0, 0,-90, 0, 0.3, 0.3, 0.3, 0.3},
  11734. { 0,-1, 0, 0, 90, 0, 0.6, 0.3, 0.3, 0.3},
  11735. };
  11736. // setup viewing parameters for saving pretender textures
  11737. void SetupView(INDEX iFrame, CDrawPort *pdp, CAnyProjection3D &apr, FLOATaabbox3D box)
  11738. {
  11739. // init projection parameters
  11740. CIsometricProjection3D prIsometricProjection;
  11741. prIsometricProjection.ScreenBBoxL() = FLOATaabbox2D(
  11742. FLOAT2D(0.0f, 0.0f),
  11743. FLOAT2D((FLOAT)pdp->GetWidth(), (FLOAT)pdp->GetHeight())
  11744. );
  11745. prIsometricProjection.NearClipDistanceL() = 0.0f;
  11746. // determine far clip plane
  11747. FLOAT3D vSize=box.Size();
  11748. FLOAT3D vHSize=vSize/2.0f;
  11749. FLOAT3D vRatio=FLOAT3D(
  11750. _pacpi[iFrame].cpi_fOffsetRatioX,
  11751. _pacpi[iFrame].cpi_fOffsetRatioY,
  11752. _pacpi[iFrame].cpi_fOffsetRatioZ);
  11753. ANGLE3D ang=ANGLE3D(
  11754. _pacpi[iFrame].cpi_angH,
  11755. _pacpi[iFrame].cpi_angP,
  11756. _pacpi[iFrame].cpi_angB);
  11757. FLOAT fFCD=Max(
  11758. Abs(vRatio(1))*vSize(1), Max(
  11759. Abs(vRatio(2))*vSize(2),
  11760. Abs(vRatio(3))*vSize(3)));
  11761. prIsometricProjection.FarClipDistanceL() = fFCD;
  11762. prIsometricProjection.AspectRatioL() = 1.0f;
  11763. // set up viewer position
  11764. apr = prIsometricProjection;
  11765. FLOAT3D vPos=FLOAT3D(
  11766. vRatio(1)*vHSize(1),
  11767. vRatio(2)*vHSize(2),
  11768. vRatio(3)*vHSize(3))+box.Center();
  11769. FLOAT fMaxSize;
  11770. if( vRatio(1)!=0)
  11771. {
  11772. fMaxSize=Max(vSize(2),vSize(3));
  11773. }
  11774. else if( vRatio(2)!=0)
  11775. {
  11776. fMaxSize=Max(vSize(1),vSize(3));
  11777. }
  11778. else
  11779. {
  11780. fMaxSize=Max(vSize(1),vSize(2));
  11781. }
  11782. prIsometricProjection.ZoomFactorL()=pdp->GetWidth()/fMaxSize;
  11783. CPlacement3D plViewer=CPlacement3D(vPos, ang);
  11784. //plViewer.RelativeToAbsolute(plEntity);
  11785. apr=prIsometricProjection;
  11786. apr->ViewerPlacementL() = plViewer;
  11787. apr->ObjectPlacementL() = CPlacement3D(FLOAT3D(0,0,0), ANGLE3D(0,0,0));
  11788. apr->Prepare();
  11789. }
  11790. BOOL CWorldEditorView::SaveAutoTexture(FLOATaabbox3D boxBrush, CTFileName &fnTex)
  11791. {
  11792. CWorldEditorDoc* pDoc = GetDocument();
  11793. CDlgAutTexturize dlg;
  11794. if( dlg.DoModal()!=IDOK) return FALSE;
  11795. // call file requester for pretender texture name
  11796. CTFileName fnPretenderTexture = _EngineGUI.FileRequester( "Pretender texture name",
  11797. FILTER_TGA FILTER_END, "Auto save texture", "", "", NULL, TRUE);
  11798. if( fnPretenderTexture == "") return FALSE;
  11799. switch( dlg.m_iPretenderStyle)
  11800. {
  11801. case 0: _pacpi=acpiF; _ctProjections=1; break;
  11802. case 1: _pacpi=acpi2x2; _ctProjections=4; break;
  11803. case 2: _pacpi=acpi3x2; _ctProjections=6; break;
  11804. default: _pacpi=acpi3x2; _ctProjections=6; break;
  11805. }
  11806. CDrawPort *pdp;
  11807. CImageInfo II;
  11808. CTextureData TD;
  11809. CAnimData AD;
  11810. ULONG flags = NONE;
  11811. CChildFrame *pChild = GetChildFrame();
  11812. // create canvas to render picture
  11813. _pGfx->CreateWorkCanvas( dlg.m_pixWidth, dlg.m_pixHeight, &pdp);
  11814. if( pdp != NULL)
  11815. {
  11816. FLOAT3D vSize=boxBrush.Size();
  11817. for(INDEX iFrame=0; iFrame<_ctProjections; iFrame++)
  11818. {
  11819. CameraProjectionInfo &cpi=_pacpi[iFrame];
  11820. CDrawPort dpClone( pdp, cpi.cpi_rMinI, cpi.cpi_rMinJ, cpi.cpi_rSizeI, cpi.cpi_rSizeJ);
  11821. // clone draw port
  11822. if( dpClone.Lock())
  11823. {
  11824. dpClone.FillZBuffer(ZBUF_BACK);
  11825. CAnyProjection3D apr;
  11826. SetupView(iFrame, &dpClone, apr, boxBrush);
  11827. // store rendering preferences
  11828. BOOL bWasBcgOn = _wrpWorldRenderPrefs.IsBackgroundTextureOn();
  11829. CWorldRenderPrefs::SelectionType stBefore=_wrpWorldRenderPrefs.GetSelectionType();
  11830. _wrpWorldRenderPrefs.SetBackgroundTextureOn( FALSE);
  11831. _wrpWorldRenderPrefs.SetSelectionType( CWorldRenderPrefs::ST_NONE);
  11832. COLOR colOld=pDoc->m_woWorld.GetBackgroundColor();
  11833. pDoc->m_woWorld.SetBackgroundColor(dlg.m_colBcg.GetColor());
  11834. // render view
  11835. ::RenderView(pDoc->m_woWorld, *(CEntity*)NULL, apr, dpClone);
  11836. // restore rendering preferences
  11837. pDoc->m_woWorld.SetBackgroundColor(colOld);
  11838. _wrpWorldRenderPrefs.SetSelectionType(stBefore);
  11839. _wrpWorldRenderPrefs.SetBackgroundTextureOn( bWasBcgOn);
  11840. }
  11841. dpClone.Unlock();
  11842. }
  11843. pdp->GrabScreen( II, 2);
  11844. if( dlg.m_bExpandEdges)
  11845. {
  11846. II.ExpandEdges();
  11847. }
  11848. // try to
  11849. try {
  11850. // save screen shot as TGA
  11851. II.SaveTGA_t( fnPretenderTexture);
  11852. fnTex=fnPretenderTexture.NoExt()+".tex";
  11853. // create temporary texture
  11854. CreateTexture_t( fnPretenderTexture, fnTex,
  11855. dlg.m_pixWidth, MAX_MEX_LOG2+1, FALSE);
  11856. _EngineGUI.CreateTexture( fnTex);
  11857. } // if failed
  11858. catch (char *strError) {
  11859. // report error
  11860. AfxMessageBox(CString(strError));
  11861. }
  11862. }
  11863. return TRUE;
  11864. }
  11865. INDEX _aiMinMax[] =
  11866. {
  11867. 0,0,1,
  11868. 1,0,1,
  11869. 1,0,0,
  11870. 0,0,0,
  11871. 0,1,1,
  11872. 1,1,1,
  11873. 1,1,0,
  11874. 0,1,0
  11875. };
  11876. INDEX _aiPlaneVtx[] =
  11877. {
  11878. 4,0,1,5,
  11879. 5,1,2,6,
  11880. 6,2,3,7,
  11881. 7,3,0,4,
  11882. 7,4,5,6,
  11883. 0,3,2,1,
  11884. };
  11885. FLOAT3D _avBoxVtx[8];
  11886. struct BoxPlaneParams {
  11887. FLOATplane3D bpp_plPlane;
  11888. CMappingVectors bpp_mvDefault;
  11889. CMappingVectors bpp_mvVectors;
  11890. CMappingDefinition bpp_mdMappingDefinition;
  11891. };
  11892. BoxPlaneParams _abpp[6];
  11893. BOOL CWorldEditorView::SetAutoTextureBoxParams(FLOATaabbox3D boxBrush, CTFileName &fnTex)
  11894. {
  11895. CTextureData *pTD=NULL;
  11896. try
  11897. {
  11898. pTD=_pTextureStock->Obtain_t( fnTex);
  11899. }
  11900. catch (char *strError)
  11901. {
  11902. WarningMessage(strError);
  11903. return FALSE;
  11904. }
  11905. // create box vertices
  11906. FLOAT3D vMin=boxBrush.Min();
  11907. FLOAT3D vMax=boxBrush.Max();
  11908. FLOAT3D vSize=boxBrush.Size();
  11909. for( INDEX iVtx=0; iVtx<8; iVtx++)
  11910. {
  11911. FLOAT fX=_aiMinMax[iVtx*3+0]*vSize(1)+vMin(1);
  11912. FLOAT fY=_aiMinMax[iVtx*3+1]*vSize(2)+vMin(2);
  11913. FLOAT fZ=_aiMinMax[iVtx*3+2]*vSize(3)+vMin(3);
  11914. _avBoxVtx[iVtx]=FLOAT3D(fX,fY,fZ);
  11915. }
  11916. // create box planes
  11917. for( INDEX iPlane=0; iPlane<_ctProjections; iPlane++)
  11918. {
  11919. CameraProjectionInfo &cpi=_pacpi[iPlane];
  11920. // create plane
  11921. BoxPlaneParams &bpp=_abpp[iPlane];
  11922. FLOAT3D &vVtx0=_avBoxVtx[_aiPlaneVtx[iPlane*4+0]];
  11923. FLOAT3D &vVtx1=_avBoxVtx[_aiPlaneVtx[iPlane*4+1]];
  11924. FLOAT3D &vVtx2=_avBoxVtx[_aiPlaneVtx[iPlane*4+2]];
  11925. FLOAT3D &vVtx3=_avBoxVtx[_aiPlaneVtx[iPlane*4+3]];
  11926. bpp.bpp_plPlane=FLOATplane3D(vVtx0, vVtx1, vVtx2);
  11927. // create mapping vectors
  11928. bpp.bpp_mvDefault.FromPlane(bpp.bpp_plPlane);
  11929. bpp.bpp_mvVectors.mv_vO=(vVtx0+vVtx2)/2.0f;
  11930. FLOAT3D vDeltaU=vVtx3-vVtx0;
  11931. FLOAT3D vDeltaV=vVtx1-vVtx0;
  11932. FLOAT fStretch = Max(vDeltaU.Length(), vDeltaV.Length())/(pTD->GetWidth()/1024.0f*cpi.cpi_rSizeI);
  11933. bpp.bpp_mvVectors.mv_vU=vDeltaU.Normalize()*fStretch;
  11934. bpp.bpp_mvVectors.mv_vV=vDeltaV.Normalize()*fStretch;
  11935. bpp.bpp_mdMappingDefinition.FromMappingVectors(bpp.bpp_mvDefault, bpp.bpp_mvVectors);
  11936. MEX mexOffsetU = pTD->GetWidth() *(cpi.cpi_rMinI+cpi.cpi_rSizeI/2);
  11937. MEX mexOffsetV = pTD->GetHeight()*(cpi.cpi_rMinJ+cpi.cpi_rSizeJ/2);
  11938. bpp.bpp_mdMappingDefinition.md_fUOffset-=mexOffsetU/1024.0f;
  11939. bpp.bpp_mdMappingDefinition.md_fVOffset-=mexOffsetV/1024.0f;
  11940. }
  11941. return TRUE;
  11942. }
  11943. void CWorldEditorView::AutoApplyTextureOntoPolygon(CBrushPolygon &bpo, FLOATaabbox3D boxBrush, CTFileName &fnTex)
  11944. {
  11945. // get box polygon that has smallest scalar product with our polygon
  11946. FLOAT fMaxScalar=-1e6f;
  11947. INDEX iMaxPlane=0;
  11948. FLOATplane3D &plPlaneAbs=bpo.bpo_pbplPlane->bpl_plAbsolute;
  11949. FLOATplane3D &plPlaneRel=bpo.bpo_pbplPlane->bpl_plRelative;
  11950. for(INDEX iPlane=0; iPlane<6; iPlane++)
  11951. {
  11952. BoxPlaneParams &bpp=_abpp[iPlane];
  11953. FLOAT fScalar=plPlaneAbs%bpp.bpp_plPlane;
  11954. if( fScalar>fMaxScalar)
  11955. {
  11956. iMaxPlane=iPlane;
  11957. fMaxScalar=fScalar;
  11958. }
  11959. }
  11960. BoxPlaneParams &bpp=_abpp[iMaxPlane];
  11961. CBrushPolygonTexture &bbpt0=bpo.bpo_abptTextures[0];
  11962. CBrushPolygonTexture &bbpt1=bpo.bpo_abptTextures[1];
  11963. CBrushPolygonTexture &bbpt2=bpo.bpo_abptTextures[2];
  11964. try
  11965. {
  11966. bbpt0.CopyTextureProperties(CBrushPolygonTexture(),TRUE);
  11967. bbpt0.bpt_toTexture.SetData_t(fnTex);
  11968. bbpt1.bpt_toTexture.SetData(NULL);
  11969. bbpt2.bpt_toTexture.SetData(NULL);
  11970. // get the mapping in relative space of the brush polygon's entity
  11971. CEntity *pen = bpo.bpo_pbscSector->bsc_pbmBrushMip->bm_pbrBrush->br_penEntity;
  11972. CSimpleProjection3D pr;
  11973. pr.ObjectPlacementL() = _plOrigin;
  11974. pr.ViewerPlacementL() = pen->GetPlacement();
  11975. pr.Prepare();
  11976. FLOATplane3D plRelative;
  11977. pr.Project(bpp.bpp_plPlane, plRelative);
  11978. CMappingDefinition mdRelative = bpp.bpp_mdMappingDefinition;
  11979. mdRelative.Transform(bpp.bpp_plPlane, _plOrigin, pen->GetPlacement());
  11980. bbpt0.bpt_mdMapping.ProjectMapping(plRelative, mdRelative, plPlaneRel);
  11981. bpo.bpo_ulFlags |= BPOF_FULLBRIGHT;
  11982. bpo.bpo_smShadowMap.Uncache();
  11983. bpo.DiscardShadows();
  11984. }
  11985. catch (char *strError)
  11986. {
  11987. WarningMessage(strError);
  11988. }
  11989. }
  11990. void CWorldEditorView::AutoApplyTexture(FLOATaabbox3D boxBrush, CTFileName &fnTex)
  11991. {
  11992. if( !SetAutoTextureBoxParams(boxBrush, fnTex)) return;
  11993. CWorldEditorDoc* pDoc = GetDocument();
  11994. // textureize mip levels
  11995. FOREACHINDYNAMICCONTAINER(pDoc->m_selEntitySelection, CEntity, iten)
  11996. {
  11997. CEntity *pen=&*iten;
  11998. if( pen->GetRenderType() == CEntity::RT_BRUSH)
  11999. {
  12000. CBrush3D *pbrBrush=pen->GetBrush();
  12001. // for each mip in the brush
  12002. BOOL bFirstMip=TRUE;
  12003. FOREACHINLIST(CBrushMip, bm_lnInBrush, pbrBrush->br_lhBrushMips, itbm)
  12004. {
  12005. if( bFirstMip)
  12006. {
  12007. bFirstMip=FALSE;
  12008. continue;
  12009. }
  12010. // for all sectors in this mip
  12011. FOREACHINDYNAMICARRAY(itbm->bm_abscSectors, CBrushSector, itbsc) {
  12012. // for each polygon in sector
  12013. FOREACHINSTATICARRAY(itbsc->bsc_abpoPolygons, CBrushPolygon, itbpo) {
  12014. CBrushPolygon &bpo = *itbpo;
  12015. AutoApplyTextureOntoPolygon(bpo, boxBrush, fnTex);
  12016. }
  12017. }
  12018. }
  12019. }
  12020. }
  12021. }
  12022. void CWorldEditorView::OnAutotexturizeMips()
  12023. {
  12024. CWorldEditorDoc* pDoc = GetDocument();
  12025. FLOATaabbox3D boxBrush;
  12026. // for each entity in the world
  12027. {FOREACHINDYNAMICCONTAINER(pDoc->m_selEntitySelection, CEntity, iten)
  12028. {
  12029. CEntity *pen=&*iten;
  12030. if( pen->GetRenderType() == CEntity::RT_BRUSH)
  12031. {
  12032. CBrush3D *pbrBrush=pen->GetBrush();
  12033. CBrushMip *pbrMip=pbrBrush->GetFirstMip();
  12034. boxBrush|=pbrMip->bm_boxBoundingBox;
  12035. }
  12036. }}
  12037. CTFileName fnTex;
  12038. BOOL bSuccess=SaveAutoTexture( boxBrush, fnTex);
  12039. if( !bSuccess) return;
  12040. AutoApplyTexture( boxBrush, fnTex);
  12041. // mark that selections have been changed
  12042. pDoc->UpdateAllViews( NULL);
  12043. pDoc->SetModifiedFlag();
  12044. }
  12045. void CWorldEditorView::OnUpdateAutotexturizeMips(CCmdUI* pCmdUI)
  12046. {
  12047. CWorldEditorDoc* pDoc = GetDocument();
  12048. pCmdUI->Enable(pDoc->m_selEntitySelection.Count()!=0);
  12049. }
  12050. void CWorldEditorView::OnRandomOffsetU()
  12051. {
  12052. CWorldEditorDoc* pDoc = GetDocument();
  12053. // for each selected polygon
  12054. FOREACHINDYNAMICCONTAINER(pDoc->m_selPolygonSelection, CBrushPolygon, itbpo)
  12055. {
  12056. CTextureData *pTD = (CTextureData *) itbpo->bpo_abptTextures[pDoc->m_iTexture].bpt_toTexture.GetData();
  12057. if( pTD != NULL)
  12058. {
  12059. // add rnd offsets to mapping
  12060. itbpo->bpo_abptTextures[pDoc->m_iTexture].bpt_mdMapping.md_fUOffset+=((FLOAT)rand())/RAND_MAX*pTD->GetWidth();
  12061. }
  12062. }
  12063. }
  12064. void CWorldEditorView::OnRandomOffsetV()
  12065. {
  12066. CWorldEditorDoc* pDoc = GetDocument();
  12067. // for each selected polygon
  12068. FOREACHINDYNAMICCONTAINER(pDoc->m_selPolygonSelection, CBrushPolygon, itbpo)
  12069. {
  12070. CTextureData *pTD = (CTextureData *) itbpo->bpo_abptTextures[pDoc->m_iTexture].bpt_toTexture.GetData();
  12071. if( pTD != NULL)
  12072. {
  12073. // add rnd offsets to mapping
  12074. itbpo->bpo_abptTextures[pDoc->m_iTexture].bpt_mdMapping.md_fVOffset+=((FLOAT)rand())/RAND_MAX*pTD->GetHeight();
  12075. }
  12076. }
  12077. }
  12078. void CWorldEditorView::OnStretchRelativeOffset()
  12079. {
  12080. CWorldEditorDoc* pDoc = GetDocument();
  12081. if(m_penEntityHitOnContext==NULL) return;
  12082. CDlgStretchChildOffset dlg;
  12083. if( dlg.DoModal()!=IDOK) return;
  12084. if( m_penEntityHitOnContext->IsSelected(ENF_SELECTED))
  12085. {
  12086. FOREACHINDYNAMICCONTAINER(pDoc->m_selEntitySelection, CEntity, iten)
  12087. {
  12088. if( iten->GetParent()!=NULL)
  12089. {
  12090. CPlacement3D pl=iten->GetPlacement();
  12091. CPlacement3D plParent=iten->GetParent()->GetPlacement();
  12092. pl.AbsoluteToRelative(plParent);
  12093. FLOAT3D vRelPos=pl.pl_PositionVector;
  12094. vRelPos*=dlg.m_fStretchValue;
  12095. // set stretched offset
  12096. pl.pl_PositionVector=vRelPos;
  12097. pl.RelativeToAbsolute(plParent);
  12098. iten->SetPlacement(pl);
  12099. }
  12100. }
  12101. }
  12102. else
  12103. {
  12104. if( m_penEntityHitOnContext->GetParent()!=NULL)
  12105. {
  12106. CPlacement3D pl=m_penEntityHitOnContext->GetPlacement();
  12107. CPlacement3D plParent=m_penEntityHitOnContext->GetParent()->GetPlacement();
  12108. pl.AbsoluteToRelative(plParent);
  12109. FLOAT3D vRelPos=pl.pl_PositionVector;
  12110. vRelPos*=dlg.m_fStretchValue;
  12111. // set stretched offset
  12112. pl.pl_PositionVector=vRelPos;
  12113. pl.RelativeToAbsolute(plParent);
  12114. m_penEntityHitOnContext->SetPlacement(pl);
  12115. }
  12116. }
  12117. pDoc->SetModifiedFlag( TRUE);
  12118. pDoc->UpdateAllViews( NULL);
  12119. }
  12120. void CWorldEditorView::OnDeselectHidden()
  12121. {
  12122. CWorldEditorDoc* pDoc = GetDocument();
  12123. // for all of the world's entities
  12124. FOREACHINDYNAMICCONTAINER(pDoc->m_woWorld.wo_cenEntities, CEntity, iten)
  12125. {
  12126. // if the entity is hidden and selected
  12127. if (iten->en_ulFlags&ENF_HIDDEN && iten->IsSelected( ENF_SELECTED))
  12128. {
  12129. // deselect it
  12130. pDoc->m_selEntitySelection.Deselect( *iten);
  12131. }
  12132. }
  12133. pDoc->UpdateAllViews( NULL);
  12134. }
  12135. void CWorldEditorView::OnSelectHidden()
  12136. {
  12137. CWorldEditorDoc* pDoc = GetDocument();
  12138. // for all of the world's entities
  12139. FOREACHINDYNAMICCONTAINER(pDoc->m_woWorld.wo_cenEntities, CEntity, iten)
  12140. {
  12141. // if the entity is hidden and selected
  12142. if (iten->en_ulFlags&ENF_HIDDEN && !iten->IsSelected( ENF_SELECTED))
  12143. {
  12144. // select it
  12145. pDoc->m_selEntitySelection.Select( *iten);
  12146. }
  12147. }
  12148. pDoc->UpdateAllViews( NULL);
  12149. }
  12150. void CWorldEditorView::OnSectorsToBrush()
  12151. {
  12152. CBrushPolygonSelection selPolygons;
  12153. CWorldEditorDoc* pDoc = GetDocument();
  12154. if(pDoc->m_selSectorSelection.Count()==0) return;
  12155. pDoc->RememberUndo();
  12156. pDoc->ClearSelections(ST_SECTOR);
  12157. // make polygon selection
  12158. FOREACHINDYNAMICCONTAINER(pDoc->m_selSectorSelection, CBrushSector, itbsc)
  12159. {
  12160. FOREACHINSTATICARRAY(itbsc->bsc_abpoPolygons, CBrushPolygon, itbpo)
  12161. {
  12162. selPolygons.Select( *itbpo);
  12163. }
  12164. }
  12165. PolygonsToBrush(selPolygons, FALSE, TRUE);
  12166. selPolygons.CDynamicContainer<CBrushPolygon>::Clear();
  12167. }
  12168. void CWorldEditorView::PolygonsToBrush(CBrushPolygonSelection &selPolygons, BOOL bDeleteSectors, BOOL bZoning)
  12169. {
  12170. CWorldEditorDoc* pDoc = GetDocument();
  12171. FLOATaabbox3D boxPolygons;
  12172. // get bbox of selected polygons
  12173. FOREACHINDYNAMICCONTAINER(selPolygons, CBrushPolygon, itbpo)
  12174. {
  12175. boxPolygons |= itbpo->bpo_boxBoundingBox;
  12176. }
  12177. CPlacement3D plCenterDown=CPlacement3D(FLOAT3D(0,0,0), ANGLE3D(0,0,0));
  12178. plCenterDown.pl_PositionVector=FLOAT3D(boxPolygons.Center()(1),boxPolygons.Min()(2),boxPolygons.Center()(3));
  12179. CEntity *penwb=theApp.CreateWorldBaseEntity(pDoc->m_woWorld, bZoning, plCenterDown);
  12180. if( penwb==NULL) return;
  12181. pDoc->m_woWorld.CopyPolygonsToBrush(selPolygons, penwb);
  12182. if(bDeleteSectors)
  12183. {
  12184. // delete old sectors
  12185. pDoc->m_woWorld.DeleteSectors( pDoc->m_selSectorSelection, FALSE);
  12186. }
  12187. pDoc->ClearSelections();
  12188. pDoc->m_chSelections.MarkChanged();
  12189. pDoc->SetModifiedFlag( TRUE);
  12190. pDoc->UpdateAllViews( NULL);
  12191. }
  12192. void CWorldEditorView::OnPolygonsToBrush()
  12193. {
  12194. CWorldEditorDoc* pDoc = GetDocument();
  12195. if( pDoc->m_selPolygonSelection.Count()==0) return;
  12196. pDoc->RememberUndo();
  12197. CDynamicContainer<CBrushPolygon> dcPolygons;
  12198. StorePolygonSelection( pDoc->m_selPolygonSelection, dcPolygons);
  12199. PolygonsToBrush(pDoc->m_selPolygonSelection, FALSE, FALSE);
  12200. pDoc->m_woWorld.DeletePolygons(dcPolygons);
  12201. }
  12202. void CWorldEditorView::OnClonePolygons()
  12203. {
  12204. CWorldEditorDoc* pDoc = GetDocument();
  12205. if( pDoc->m_selPolygonSelection.Count()==0) return;
  12206. pDoc->RememberUndo();
  12207. PolygonsToBrush(pDoc->m_selPolygonSelection, FALSE, FALSE);
  12208. }
  12209. void CWorldEditorView::OnDeletePolygons()
  12210. {
  12211. CDynamicContainer<CBrushPolygon> dcPolygons;
  12212. CWorldEditorDoc* pDoc = GetDocument();
  12213. if( pDoc->m_selPolygonSelection.Count()==0) return;
  12214. pDoc->RememberUndo();
  12215. StorePolygonSelection( pDoc->m_selPolygonSelection, dcPolygons);
  12216. pDoc->ClearSelections();
  12217. pDoc->m_woWorld.DeletePolygons(dcPolygons);
  12218. pDoc->SetModifiedFlag( TRUE);
  12219. pDoc->UpdateAllViews( NULL);
  12220. }
  12221. void CWorldEditorView::OnKeyU()
  12222. {
  12223. CWorldEditorDoc* pDoc = GetDocument();
  12224. if( pDoc->GetEditingMode() == POLYGON_MODE)
  12225. {
  12226. OnKeyPasteAsProjected();
  12227. }
  12228. else if( pDoc->GetEditingMode() == TERRAIN_MODE)
  12229. {
  12230. theApp.m_iTerrainEditMode=TEM_HEIGHTMAP;
  12231. theApp.m_ctTerrainPageCanvas.MarkChanged();
  12232. GetDocument()->SetStatusLineModeInfoMessage();
  12233. }
  12234. }
  12235. void CWorldEditorView::OnKeyD()
  12236. {
  12237. CWorldEditorDoc* pDoc = GetDocument();
  12238. if( pDoc->GetEditingMode() == ENTITY_MODE)
  12239. {
  12240. OnDropMarker();
  12241. }
  12242. if( (pDoc->GetEditingMode() == POLYGON_MODE) ||
  12243. (pDoc->GetEditingMode() == VERTEX_MODE) )
  12244. {
  12245. OnFlipPolygon();
  12246. }
  12247. if( pDoc->GetEditingMode() == TERRAIN_MODE)
  12248. {
  12249. theApp.m_iTerrainBrushMode=TBM_ERASE;
  12250. theApp.m_ctTerrainPageCanvas.MarkChanged();
  12251. pDoc->SetStatusLineModeInfoMessage();
  12252. }
  12253. }
  12254. void CWorldEditorView::OnFlipPolygon()
  12255. {
  12256. CWorldEditorDoc* pDoc = GetDocument();
  12257. BOOL bSelection=TRUE;
  12258. // obtain information about where mouse points into the world
  12259. CCastRay crRayHit = GetMouseHitInformation( m_ptMouse, FALSE, FALSE, FALSE);
  12260. CBrushPolygon *pbpoHit=crRayHit.cr_pbpoBrushPolygon;
  12261. if( (pbpoHit!=NULL) && !pbpoHit->IsSelected( BPOF_SELECTED) )
  12262. {
  12263. bSelection=FALSE;
  12264. }
  12265. CDynamicContainer<CBrushPolygon> dcPolygons;
  12266. CDynamicContainer<CBrushSector> dcSectors;
  12267. if( bSelection)
  12268. {
  12269. FOREACHINDYNAMICCONTAINER( pDoc->m_selPolygonSelection, CBrushPolygon, itbpo)
  12270. {
  12271. dcPolygons.Add( itbpo);
  12272. if( !dcSectors.IsMember(itbpo->bpo_pbscSector))
  12273. {
  12274. dcSectors.Add(itbpo->bpo_pbscSector);
  12275. }
  12276. }
  12277. }
  12278. else
  12279. {
  12280. pDoc->m_selPolygonSelection.Clear();
  12281. dcPolygons.Add( pbpoHit);
  12282. dcSectors.Add(pbpoHit->bpo_pbscSector);
  12283. }
  12284. pDoc->ClearSelections();
  12285. FOREACHINDYNAMICCONTAINER(dcPolygons, CBrushPolygon, itbpo)
  12286. {
  12287. CBrushPolygon &bpo = *itbpo;
  12288. pDoc->m_woWorld.FlipPolygon(bpo);
  12289. }
  12290. FOREACHINDYNAMICCONTAINER( dcSectors, CBrushSector, itbsc)
  12291. {
  12292. itbsc->UpdateSector();
  12293. }
  12294. {FOREACHINDYNAMICCONTAINER(dcPolygons, CBrushPolygon, itbpo)
  12295. {
  12296. CBrushPolygon &bpo = *itbpo;
  12297. INDEX iTriVtx=bpo.bpo_aiTriangleElements.Count();
  12298. INDEX tmpa=0;
  12299. }}
  12300. pDoc->SetModifiedFlag( TRUE);
  12301. pDoc->UpdateAllViews( NULL);
  12302. }
  12303. void CWorldEditorView::OnKeyM()
  12304. {
  12305. CWorldEditorDoc* pDoc = GetDocument();
  12306. if( pDoc->GetEditingMode() == POLYGON_MODE)
  12307. {
  12308. // obtain information about where mouse points into the world
  12309. CCastRay crRayHit = GetMouseHitInformation( m_ptMouse);
  12310. // if we hit brush entity
  12311. if( (crRayHit.cr_penHit != NULL) &&
  12312. (crRayHit.cr_pbpoBrushPolygon != NULL) )
  12313. {
  12314. CopyMapping(crRayHit.cr_pbpoBrushPolygon);
  12315. }
  12316. }
  12317. else if( pDoc->GetEditingMode() == VERTEX_MODE)
  12318. {
  12319. OnMergeVertices();
  12320. }
  12321. else if( pDoc->GetEditingMode() == TERRAIN_MODE)
  12322. {
  12323. theApp.m_iTerrainBrushMode=TBM_MINIMUM;
  12324. theApp.m_ctTerrainPageCanvas.MarkChanged();
  12325. pDoc->SetStatusLineModeInfoMessage();
  12326. }
  12327. }
  12328. void CWorldEditorView::OnSelectBrush()
  12329. {
  12330. CPoint ptMouse;
  12331. GetCursorPos( &ptMouse);
  12332. InvokeTerrainBrushPalette( ptMouse.x-BRUSH_PALETTE_WIDTH/2, ptMouse.y+BRUSH_PALETTE_HEIGHT/2);
  12333. }
  12334. void CWorldEditorView::OnSelectTerrain()
  12335. {
  12336. CWorldEditorDoc* pDoc = GetDocument();
  12337. CCastRay crRayHit = GetMouseHitInformation( m_ptMouse);
  12338. if( (crRayHit.cr_penHit!=NULL) && (crRayHit.cr_penHit->GetRenderType() == CEntity::RT_TERRAIN) &&
  12339. (crRayHit.cr_penHit!=GetTerrainEntity()) )
  12340. {
  12341. pDoc->m_ptrSelectedTerrain=crRayHit.cr_penHit->GetTerrain();
  12342. theApp.m_ctTerrainPage.MarkChanged();
  12343. }
  12344. }
  12345. void CWorldEditorView::OnAltitudeEditMode()
  12346. {
  12347. theApp.m_iTerrainEditMode=TEM_HEIGHTMAP;
  12348. theApp.m_ctTerrainPageCanvas.MarkChanged();
  12349. GetDocument()->SetStatusLineModeInfoMessage();
  12350. }
  12351. void CWorldEditorView::OnLayerTextureEditMode()
  12352. {
  12353. theApp.m_iTerrainEditMode=TEM_LAYER;
  12354. theApp.m_ctTerrainPageCanvas.MarkChanged();
  12355. GetDocument()->SetStatusLineModeInfoMessage();
  12356. }
  12357. void CWorldEditorView::OnOptimizeTerrain()
  12358. {
  12359. OptimizeLayers();
  12360. }
  12361. void CWorldEditorView::OnRecalculateTerrainShadows()
  12362. {
  12363. CTerrain *ptrTerrain=GetTerrain();
  12364. if( ptrTerrain==NULL) return;
  12365. ptrTerrain->UpdateShadowMap();
  12366. }
  12367. void CWorldEditorView::OnViewHeightmap()
  12368. {
  12369. POINT pt;
  12370. GetCursorPos(&pt);
  12371. pt.x-=32;
  12372. pt.y+=32;
  12373. DisplayHeightMapWindow(pt);
  12374. }
  12375. void CWorldEditorView::OnImportHeightmap()
  12376. {
  12377. ApplyImportExport(0);
  12378. }
  12379. void CWorldEditorView::OnImportHeightmap16()
  12380. {
  12381. ApplyImportExport(1);
  12382. }
  12383. void CWorldEditorView::OnExportHeightmap()
  12384. {
  12385. ApplyImportExport(2);
  12386. }
  12387. void CWorldEditorView::OnExportHeightmap16()
  12388. {
  12389. ApplyImportExport(3);
  12390. }
  12391. void CWorldEditorView::OnSelectLayer()
  12392. {
  12393. InvokeSelectLayerCombo();
  12394. }
  12395. void CWorldEditorView::OnPickLayer()
  12396. {
  12397. CWorldEditorDoc* pDoc = GetDocument();
  12398. CCastRay crRayHit=GetMouseHitInformation( m_ptMouse);
  12399. if( (crRayHit.cr_penHit!=NULL) && (crRayHit.cr_penHit->GetRenderType() == CEntity::RT_TERRAIN))
  12400. {
  12401. CTerrain *ptrTerrain=crRayHit.cr_penHit->GetTerrain();
  12402. Point pt=Calculate2dHitPoint(ptrTerrain, crRayHit.cr_vHit);
  12403. // in altitude mode
  12404. if(theApp.m_iTerrainEditMode==TEM_HEIGHTMAP)
  12405. {
  12406. // pick altitude
  12407. INDEX iWidth=ptrTerrain->tr_pixHeightMapWidth;
  12408. UWORD *puw=ptrTerrain->tr_auwHeightMap+iWidth*pt.pt_iY+pt.pt_iX;
  12409. theApp.m_uwEditAltitude=*puw;
  12410. }
  12411. // in layer mode
  12412. else
  12413. {
  12414. // pick layer
  12415. INDEX ctLayers=ptrTerrain->tr_atlLayers.Count();
  12416. for(INDEX iLayer=ctLayers-1; iLayer>=0; iLayer--)
  12417. {
  12418. UBYTE ubPower=GetValueFromMask(ptrTerrain, iLayer, crRayHit.cr_vHit);
  12419. if(ubPower>0)
  12420. {
  12421. SelectLayer(iLayer);
  12422. CTerrainLayer *ptlLayer=&ptrTerrain->tr_atlLayers[iLayer];
  12423. if(ptlLayer->tl_ltType==LT_TILE)
  12424. {
  12425. CDynamicContainer<CTileInfo> dcTileInfo;
  12426. INDEX ctTilesPerRaw=0;
  12427. ObtainLayerTileInfo( &dcTileInfo, ptlLayer->tl_ptdTexture, ctTilesPerRaw);
  12428. INDEX ctTiles=dcTileInfo.Count();
  12429. for(INDEX iTile=0; iTile<ctTiles; iTile++)
  12430. {
  12431. CTileInfo &ti=dcTileInfo[iTile];
  12432. if( ((ubPower&TL_TILE_INDEX)==(ti.ti_iy*ptlLayer->tl_ctTilesInRow+ti.ti_ix) ) &&
  12433. (ubPower&TL_VISIBLE) &&
  12434. (!(ubPower&TL_FLIPX) == !ti.ti_bFlipX) &&
  12435. (!(ubPower&TL_FLIPY) == !ti.ti_bFlipY) &&
  12436. (!(ubPower&TL_SWAPXY) == !ti.ti_bSwapXY) )
  12437. {
  12438. ptlLayer->tl_iSelectedTile=iTile;
  12439. break;
  12440. }
  12441. }
  12442. }
  12443. else
  12444. {
  12445. theApp.m_ctTerrainPageCanvas.MarkChanged();
  12446. }
  12447. break;
  12448. }
  12449. }
  12450. }
  12451. }
  12452. }
  12453. void CWorldEditorView::OnIdle(void)
  12454. {
  12455. POINT point;
  12456. GetCursorPos(&point);
  12457. HWND hwndUnderMouse = ::WindowFromPoint(point);
  12458. if( ::GetParent(hwndUnderMouse)==m_hWnd)
  12459. {
  12460. UpdateCursor();
  12461. }
  12462. CWorldEditorDoc* pDoc = GetDocument();
  12463. if( pDoc->GetEditingMode()==TERRAIN_MODE && m_iaInputAction==IA_NONE)
  12464. {
  12465. UpdateLayerDistribution();
  12466. }
  12467. }
  12468. void CWorldEditorView::OnPosterize()
  12469. {
  12470. CWorldEditorDoc* pDoc = GetDocument();
  12471. if( pDoc->GetEditingMode() == TERRAIN_MODE)
  12472. {
  12473. theApp.m_iTerrainBrushMode=TBM_POSTERIZE;
  12474. theApp.m_ctTerrainPageCanvas.MarkChanged();
  12475. GetDocument()->SetStatusLineModeInfoMessage();
  12476. }
  12477. }
  12478. void CWorldEditorView::OnFlatten()
  12479. {
  12480. CWorldEditorDoc* pDoc = GetDocument();
  12481. if( pDoc->GetEditingMode() == TERRAIN_MODE)
  12482. {
  12483. theApp.m_iTerrainBrushMode=TBM_FLATTEN;
  12484. theApp.m_ctTerrainPageCanvas.MarkChanged();
  12485. GetDocument()->SetStatusLineModeInfoMessage();
  12486. }
  12487. }
  12488. void CWorldEditorView::OnApplyFilter()
  12489. {
  12490. ApplyFilterOntoTerrain();
  12491. }
  12492. void CWorldEditorView::OnTeSmooth()
  12493. {
  12494. ApplySmoothOntoTerrain();
  12495. }
  12496. void CWorldEditorView::OnEditTerrainPrefs()
  12497. {
  12498. CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
  12499. CDlgTEOperationSettings dlg(pMainFrame);
  12500. dlg.DoModal();
  12501. }
  12502. void CWorldEditorView::OnUpdateEditTerrainPrefs(CCmdUI* pCmdUI)
  12503. {
  12504. CWorldEditorDoc* pDoc = GetDocument();
  12505. pCmdUI->Enable( pDoc->GetEditingMode()==TERRAIN_MODE);
  12506. }
  12507. void CWorldEditorView::OnKeyCtrlShiftG()
  12508. {
  12509. CWorldEditorDoc* pDoc = GetDocument();
  12510. if(pDoc->GetEditingMode()==TERRAIN_MODE)
  12511. {
  12512. RandomizeWhiteNoise();
  12513. ApplyGenerateTerrain();
  12514. }
  12515. else
  12516. {
  12517. GetChildFrame()->OnGridOnOff();
  12518. }
  12519. }
  12520. void CWorldEditorView::OnUpdateKeyCtrlShiftG(CCmdUI* pCmdUI)
  12521. {
  12522. CWorldEditorDoc* pDoc = GetDocument();
  12523. if(pDoc->GetEditingMode()==TERRAIN_MODE)
  12524. {
  12525. pCmdUI->Enable( TRUE);
  12526. }
  12527. else
  12528. {
  12529. GetChildFrame()->OnUpdateGridOnOff(pCmdUI);
  12530. }
  12531. }
  12532. void CWorldEditorView::OnTerrainLayerOptions()
  12533. {
  12534. CTerrainLayer *ptlLayer=GetLayer();
  12535. if(ptlLayer==NULL) return;
  12536. CDlgEditTerrainLayer dlg;
  12537. if( dlg.DoModal()==IDOK)
  12538. {
  12539. INDEX iLayer=GetLayerIndex();
  12540. GenerateLayerDistribution(iLayer);
  12541. }
  12542. }
  12543. void CWorldEditorView::OnUpdateTerrainLayerOptions(CCmdUI* pCmdUI)
  12544. {
  12545. CWorldEditorDoc* pDoc = GetDocument();
  12546. pCmdUI->Enable( pDoc->GetEditingMode()==TERRAIN_MODE);
  12547. }
  12548. void CWorldEditorView::OnApplyContinousNoise()
  12549. {
  12550. CWorldEditorDoc* pDoc = GetDocument();
  12551. if( pDoc->GetEditingMode()==TERRAIN_MODE && GetTerrain()!=NULL)
  12552. {
  12553. ApplyContinousNoiseOntoTerrain();
  12554. }
  12555. }
  12556. void CWorldEditorView::OnApplyMinimum()
  12557. {
  12558. CWorldEditorDoc* pDoc = GetDocument();
  12559. if( pDoc->GetEditingMode()==TERRAIN_MODE && GetTerrain()!=NULL)
  12560. {
  12561. ApplyMinimumOntoTerrain();
  12562. }
  12563. }
  12564. void CWorldEditorView::OnApplyMaximum()
  12565. {
  12566. CWorldEditorDoc* pDoc = GetDocument();
  12567. if( pDoc->GetEditingMode()==TERRAIN_MODE && GetTerrain()!=NULL)
  12568. {
  12569. ApplyMaximumOntoTerrain();
  12570. }
  12571. }
  12572. void CWorldEditorView::OnApplyFlatten()
  12573. {
  12574. CWorldEditorDoc* pDoc = GetDocument();
  12575. if( pDoc->GetEditingMode()==TERRAIN_MODE && GetTerrain()!=NULL)
  12576. {
  12577. ApplyFlattenOntoTerrain();
  12578. }
  12579. }
  12580. void CWorldEditorView::OnApplyPosterize()
  12581. {
  12582. CWorldEditorDoc* pDoc = GetDocument();
  12583. if( pDoc->GetEditingMode()==TERRAIN_MODE && GetTerrain()!=NULL)
  12584. {
  12585. ApplyPosterizeOntoTerrain();
  12586. }
  12587. }
  12588. void CWorldEditorView::OnOptimizeLayers()
  12589. {
  12590. CWorldEditorDoc* pDoc = GetDocument();
  12591. if( pDoc->GetEditingMode()==TERRAIN_MODE && GetTerrain()!=NULL)
  12592. {
  12593. OptimizeLayers();
  12594. }
  12595. }
  12596. void CWorldEditorView::OnTbrushAltitude()
  12597. {
  12598. theApp.m_iTerrainBrushMode=TBM_PAINT;
  12599. theApp.m_ctTerrainPageCanvas.MarkChanged();
  12600. GetDocument()->SetStatusLineModeInfoMessage();
  12601. }
  12602. void CWorldEditorView::OnTbrushSmooth()
  12603. {
  12604. theApp.m_iTerrainBrushMode=TBM_SMOOTH;
  12605. theApp.m_ctTerrainPageCanvas.MarkChanged();
  12606. GetDocument()->SetStatusLineModeInfoMessage();
  12607. }
  12608. void CWorldEditorView::OnTbrushEquilaze()
  12609. {
  12610. theApp.m_iTerrainBrushMode=TBM_FLATTEN;
  12611. theApp.m_ctTerrainPageCanvas.MarkChanged();
  12612. GetDocument()->SetStatusLineModeInfoMessage();
  12613. }
  12614. void CWorldEditorView::OnTbrushErase()
  12615. {
  12616. theApp.m_iTerrainBrushMode=TBM_ERASE;
  12617. theApp.m_ctTerrainPageCanvas.MarkChanged();
  12618. GetDocument()->SetStatusLineModeInfoMessage();
  12619. }
  12620. void CWorldEditorView::OnTbrushNoise()
  12621. {
  12622. theApp.m_iTerrainBrushMode=TBM_RND_NOISE;
  12623. theApp.m_ctTerrainPageCanvas.MarkChanged();
  12624. GetDocument()->SetStatusLineModeInfoMessage();
  12625. }
  12626. void CWorldEditorView::OnTbrushContinousNoise()
  12627. {
  12628. theApp.m_iTerrainBrushMode=TBM_CONTINOUS_NOISE;
  12629. theApp.m_ctTerrainPageCanvas.MarkChanged();
  12630. GetDocument()->SetStatusLineModeInfoMessage();
  12631. }
  12632. void CWorldEditorView::OnTbrushFilter()
  12633. {
  12634. theApp.m_iTerrainBrushMode=TBM_FILTER;
  12635. theApp.m_ctTerrainPageCanvas.MarkChanged();
  12636. GetDocument()->SetStatusLineModeInfoMessage();
  12637. }
  12638. void CWorldEditorView::OnTbrushFlatten()
  12639. {
  12640. theApp.m_iTerrainBrushMode=TBM_FLATTEN;
  12641. theApp.m_ctTerrainPageCanvas.MarkChanged();
  12642. GetDocument()->SetStatusLineModeInfoMessage();
  12643. }
  12644. void CWorldEditorView::OnTbrushMaximum()
  12645. {
  12646. theApp.m_iTerrainBrushMode=TBM_MAXIMUM;
  12647. theApp.m_ctTerrainPageCanvas.MarkChanged();
  12648. GetDocument()->SetStatusLineModeInfoMessage();
  12649. }
  12650. void CWorldEditorView::OnTbrushMinimum()
  12651. {
  12652. theApp.m_iTerrainBrushMode=TBM_MINIMUM;
  12653. theApp.m_ctTerrainPageCanvas.MarkChanged();
  12654. GetDocument()->SetStatusLineModeInfoMessage();
  12655. }
  12656. void CWorldEditorView::OnTbrushPosterize()
  12657. {
  12658. theApp.m_iTerrainBrushMode=TBM_POSTERIZE;
  12659. theApp.m_ctTerrainPageCanvas.MarkChanged();
  12660. GetDocument()->SetStatusLineModeInfoMessage();
  12661. }
  12662. void CWorldEditorView::OnTerrainProperties()
  12663. {
  12664. CWorldEditorDoc* pDoc = GetDocument();
  12665. if( pDoc->GetEditingMode()==TERRAIN_MODE && GetTerrain()!=NULL)
  12666. {
  12667. CDlgTerrainProperties dlg;
  12668. dlg.DoModal();
  12669. }
  12670. }