1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668 |
- /* Copyright (c) 2002-2012 Croteam Ltd.
- This program is free software; you can redistribute it and/or modify
- it under the terms of version 2 of the GNU General Public License as published by
- the Free Software Foundation
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License along
- with this program; if not, write to the Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
- // WorldEditorDoc.cpp : implementation of the CWorldEditorDoc class
- //
- #include "stdafx.h"
- #include "WorldEditor.h"
- #include "WorldEditorDoc.h"
- #include <Engine/Base/Profiling.h>
- #include <Engine/Build.h>
- #include <direct.h>
- #ifdef _DEBUG
- #undef new
- #define new DEBUG_NEW
- #undef THIS_FILE
- static char THIS_FILE[] = __FILE__;
- #endif
- #pragma optimize("p", on) // this is in effect for entire file!
- extern COLOR acol_ColorizePallete[];
- /////////////////////////////////////////////////////////////////////////////
- // CWorldEditorDoc
- IMPLEMENT_DYNCREATE(CWorldEditorDoc, CDocument)
- BEGIN_MESSAGE_MAP(CWorldEditorDoc, CDocument)
- //{{AFX_MSG_MAP(CWorldEditorDoc)
- ON_COMMAND(ID_CSG_SPLIT_SECTORS, OnCsgSplitSectors)
- ON_UPDATE_COMMAND_UI(ID_CSG_SPLIT_SECTORS, OnUpdateCsgSplitSectors)
- ON_COMMAND(ID_CSG_CANCEL, OnCsgCancel)
- ON_COMMAND(ID_SHOW_ORIENTATION, OnShowOrientation)
- ON_UPDATE_COMMAND_UI(ID_SHOW_ORIENTATION, OnUpdateShowOrientation)
- ON_COMMAND(ID_EDIT_UNDO, OnEditUndo)
- ON_COMMAND(ID_EDIT_REDO, OnEditRedo)
- ON_UPDATE_COMMAND_UI(ID_EDIT_UNDO, OnUpdateEditUndo)
- ON_UPDATE_COMMAND_UI(ID_EDIT_REDO, OnUpdateEditRedo)
- ON_COMMAND(ID_WORLD_SETTINGS, OnWorldSettings)
- ON_COMMAND(ID_CSG_JOIN_SECTORS, OnCsgJoinSectors)
- ON_UPDATE_COMMAND_UI(ID_CSG_JOIN_SECTORS, OnUpdateCsgJoinSectors)
- ON_COMMAND(ID_AUTO_SNAP, OnAutoSnap)
- ON_COMMAND(ID_CSG_ADD, OnCsgAdd)
- ON_UPDATE_COMMAND_UI(ID_CSG_ADD, OnUpdateCsgAdd)
- ON_COMMAND(ID_CSG_REMOVE, OnCsgRemove)
- ON_UPDATE_COMMAND_UI(ID_CSG_REMOVE, OnUpdateCsgRemove)
- ON_COMMAND(ID_CSG_SPLIT_POLYGONS, OnCsgSplitPolygons)
- ON_UPDATE_COMMAND_UI(ID_CSG_SPLIT_POLYGONS, OnUpdateCsgSplitPolygons)
- ON_COMMAND(ID_CSG_JOIN_POLYGONS, OnCsgJoinPolygons)
- ON_UPDATE_COMMAND_UI(ID_CSG_JOIN_POLYGONS, OnUpdateCsgJoinPolygons)
- ON_COMMAND(ID_CALCULATESHADOWS, OnCalculateShadows)
- ON_COMMAND(ID_BROWSE_ENTITIES_MODE, OnBrowseEntitiesMode)
- ON_UPDATE_COMMAND_UI(ID_BROWSE_ENTITIES_MODE, OnUpdateBrowseEntitiesMode)
- ON_COMMAND(ID_PREVIOUS_SELECTED_ENTITY, OnPreviousSelectedEntity)
- ON_UPDATE_COMMAND_UI(ID_PREVIOUS_SELECTED_ENTITY, OnUpdatePreviousSelectedEntity)
- ON_COMMAND(ID_NEXT_SELECTED_ENTITY, OnNextSelectedEntity)
- ON_UPDATE_COMMAND_UI(ID_NEXT_SELECTED_ENTITY, OnUpdateNextSelectedEntity)
- ON_COMMAND(ID_JOIN_LAYERS, OnJoinLayers)
- ON_UPDATE_COMMAND_UI(ID_AUTO_SNAP, OnUpdateAutoSnap)
- ON_COMMAND(ID_SELECT_BY_CLASS, OnSelectByClass)
- ON_UPDATE_COMMAND_UI(ID_SELECT_BY_CLASS, OnUpdateSelectByClass)
- ON_COMMAND(ID_CSG_JOIN_ALL_POLYGONS, OnCsgJoinAllPolygons)
- ON_UPDATE_COMMAND_UI(ID_CSG_JOIN_ALL_POLYGONS, OnUpdateCsgJoinAllPolygons)
- ON_COMMAND(ID_TEXTURE_1, OnTexture1)
- ON_UPDATE_COMMAND_UI(ID_TEXTURE_1, OnUpdateTexture1)
- ON_COMMAND(ID_TEXTURE_2, OnTexture2)
- ON_UPDATE_COMMAND_UI(ID_TEXTURE_2, OnUpdateTexture2)
- ON_COMMAND(ID_TEXTURE_3, OnTexture3)
- ON_UPDATE_COMMAND_UI(ID_TEXTURE_3, OnUpdateTexture3)
- ON_COMMAND(ID_TEXTURE_MODE_1, OnTextureMode1)
- ON_COMMAND(ID_TEXTURE_MODE_2, OnTextureMode2)
- ON_COMMAND(ID_TEXTURE_MODE_3, OnTextureMode3)
- ON_COMMAND(ID_SAVE_THUMBNAIL, OnSaveThumbnail)
- ON_COMMAND(ID_UPDATE_LINKS, OnUpdateLinks)
- ON_COMMAND(ID_SNAPSHOT, OnSnapshot)
- ON_COMMAND(ID_MIRROR_AND_STRETCH, OnMirrorAndStretch)
- ON_COMMAND(ID_FLIP_LAYER, OnFlipLayer)
- ON_UPDATE_COMMAND_UI(ID_FLIP_LAYER, OnUpdateFlipLayer)
- ON_COMMAND(ID_FILTER_SELECTION, OnFilterSelection)
- ON_COMMAND(ID_UPDATE_CLONES, OnUpdateClones)
- ON_UPDATE_COMMAND_UI(ID_UPDATE_CLONES, OnUpdateUpdateClones)
- ON_COMMAND(ID_HIDE_SELECTED, OnHideSelected)
- ON_UPDATE_COMMAND_UI(ID_HIDE_SELECTED, OnUpdateHideSelected)
- ON_COMMAND(ID_HIDE_UNSELECTED, OnHideUnselected)
- ON_COMMAND(ID_SHOW_ALL, OnShowAll)
- ON_COMMAND(ID_CHECK_EDIT, OnCheckEdit)
- ON_COMMAND(ID_CHECK_ADD, OnCheckAdd)
- ON_COMMAND(ID_CHECK_DELETE, OnCheckDelete)
- ON_UPDATE_COMMAND_UI(ID_CHECK_EDIT, OnUpdateCheckEdit)
- ON_UPDATE_COMMAND_UI(ID_CHECK_ADD, OnUpdateCheckAdd)
- ON_UPDATE_COMMAND_UI(ID_CHECK_DELETE, OnUpdateCheckDelete)
- ON_COMMAND(ID_UPDATE_BRUSHES, OnUpdateBrushes)
- ON_COMMAND(ID_SELECT_BY_CLASS_IMPORTANT, OnSelectByClassImportant)
- ON_COMMAND(ID_INSERT_3D_OBJECT, OnInsert3dObject)
- ON_COMMAND(ID_EXPORT_3D_OBJECT, OnExport3dObject)
- ON_UPDATE_COMMAND_UI(ID_EXPORT_3D_OBJECT, OnUpdateExport3dObject)
- ON_COMMAND(ID_CROSSROAD_FOR_N, OnCrossroadForN)
- ON_COMMAND(ID_POPUP_VTX_ALLIGN, OnPopupVtxAllign)
- ON_COMMAND(ID_POPUP_VTX_FILTER, OnPopupVtxFilter)
- ON_COMMAND(ID_POPUP_VTX_NUMERIC, OnPopupVtxNumeric)
- ON_COMMAND(ID_HIDE_SELECTED_SECTORS, OnHideSelectedSectors)
- ON_COMMAND(ID_HIDE_UNSELECTED_SECTORS, OnHideUnselectedSectors)
- ON_COMMAND(ID_SHOW_ALL_SECTORS, OnShowAllSectors)
- ON_COMMAND(ID_TEXTURE_MODE_4, OnTextureMode4)
- ON_COMMAND(ID_TEXTURE_MODE_5, OnTextureMode5)
- ON_COMMAND(ID_TEXTURE_MODE_6, OnTextureMode6)
- ON_COMMAND(ID_TEXTURE_MODE_7, OnTextureMode7)
- ON_COMMAND(ID_TEXTURE_MODE_8, OnTextureMode8)
- ON_COMMAND(ID_TEXTURE_MODE_9, OnTextureMode9)
- ON_COMMAND(ID_TEXTURE_MODE_10, OnTextureMode10)
- //}}AFX_MSG_MAP
- ON_COMMAND(ID_EXPORT_PLACEMENTS, OnExportPlacements)
- ON_COMMAND(ID_EXPORT_ENTITIES, OnExportEntities)
- END_MESSAGE_MAP()
- /////////////////////////////////////////////////////////////////////////////
- // CWorldEditorDoc construction/destruction
- CWorldEditorDoc::CWorldEditorDoc()
- {
- m_iCurrentTerrainUndo=-1;
- m_ptrSelectedTerrain=NULL;
- m_slDisplaceTexTime=0;
- m_bAskedToCheckOut = FALSE;
- m_pCutLineView = NULL;
- m_iMirror = 0;
- m_bWasEverSaved = FALSE;
- m_iSelectedEntityInVolume = 0;
- m_iTexture = 0;
- m_ctLastPrimitiveVertices = -1;
- m_bPrimitiveCreatedFirstTime = TRUE;
- m_fLastPrimitiveWidth = 0.0;
- m_fLastPrimitiveLenght = 0.0;
- m_bLastIfOuter = FALSE;
- m_ttLastTriangularisationType = theApp.m_vfpCurrent.vfp_ttTriangularisationType;
- m_bAutoSnap = TRUE;
- m_bPrimitiveMode = FALSE;
- m_pwoSecondLayer = NULL;
- m_penPrimitive = NULL;
- m_bOrientationIcons=AfxGetApp()->GetProfileInt( L"World editor", L"Orientation icons", FALSE);
- m_bBrowseEntitiesMode = FALSE;
- m_bReadOnly = FALSE;
- m_csgtLastUsedCSGOperation = CSG_ILLEGAL;
- m_csgtPreLastUsedCSGOperation = CSG_ILLEGAL;
- m_bPreLastUsedPrimitiveMode = TRUE;
- m_bLastUsedPrimitiveMode = TRUE;
- m_fnLastDroppedTemplate = CTString("");
- // initialize grid placement
- m_plGrid.pl_PositionVector = FLOAT3D(0.0f,0.0f,0.0f);
- m_plGrid.pl_OrientationAngle = ANGLE3D(0,0,0);
- // initialize delta placement
- m_plDeltaPlacement.pl_PositionVector = FLOAT3D(0.0f,0.0f,0.0f);
- m_plDeltaPlacement.pl_OrientationAngle = ANGLE3D(0,0,0);
- // initialize last placement
- m_plLastPlacement.pl_PositionVector = FLOAT3D(0.0f,0.0f,0.0f);
- m_plLastPlacement.pl_OrientationAngle = ANGLE3D(0,0,0);
- // initialize create box vertices
- char strIni[ 128];
- strcpy( strIni, CStringA(theApp.GetProfileString( L"World editor", L"Volume box min", L"0.0 0.0 0.0")));
- sscanf( strIni, "%f %f %f",
- &m_vCreateBoxVertice0(1), &m_vCreateBoxVertice0(2), &m_vCreateBoxVertice0(3));
- strcpy( strIni, CStringA(theApp.GetProfileString( L"World editor", L"Volume box max", L"1.0 1.0 1.0")));
- sscanf( strIni, "%f %f %f",
- &m_vCreateBoxVertice1(1), &m_vCreateBoxVertice1(2), &m_vCreateBoxVertice1(3));
- // set default editing mode - polygon mode
- INDEX iMode=AfxGetApp()->GetProfileInt( L"World editor", L"Last editing mode", POLYGON_MODE);
- if(iMode==POLYGON_MODE || iMode==VERTEX_MODE || iMode==SECTOR_MODE || iMode==ENTITY_MODE || iMode==TERRAIN_MODE)
- {
- SetEditingMode( iMode);
- }
- else
- {
- SetEditingMode( POLYGON_MODE);
- }
- }
- CWorldEditorDoc::~CWorldEditorDoc()
- {
- DeleteTerrainUndo(this);
- if(m_iMode==POLYGON_MODE || m_iMode==VERTEX_MODE || m_iMode==SECTOR_MODE || m_iMode==ENTITY_MODE || m_iMode==TERRAIN_MODE)
- {
- theApp.WriteProfileInt(L"World editor", L"Last editing mode", m_iMode);
- }
- else
- {
- theApp.WriteProfileInt(L"World editor", L"Last editing mode", POLYGON_MODE);
- }
- if( m_pwoSecondLayer != NULL)
- delete m_pwoSecondLayer;
- // delete stored undo members
- FORDELETELIST(CUndo, m_lnListNode, m_lhUndo, itUndo)
- {
- delete &itUndo.Current();
- }
- // delete redo
- FORDELETELIST(CUndo, m_lnListNode, m_lhRedo, itRedo)
- {
- delete &itRedo.Current();
- }
- }
- void CWorldEditorDoc::ClearSelections(ESelectionType stExcept /*=ST_NONE*/)
- {
- if( stExcept != ST_VERTEX) { m_selVertexSelection.Clear(); m_chSelections.MarkChanged();}
- if( stExcept != ST_ENTITY) { m_selEntitySelection.Clear(); m_chSelections.MarkChanged();}
- if( stExcept != ST_VOLUME) { m_cenEntitiesSelectedByVolume.Clear(); m_chSelections.MarkChanged();}
- if( stExcept != ST_SECTOR) { m_selSectorSelection.Clear(); m_chSelections.MarkChanged();}
- if( stExcept != ST_POLYGON) { m_selPolygonSelection.Clear(); m_chSelections.MarkChanged();}
- }
- /*
- * Sets message about current mode and selected members
- */
- void CWorldEditorDoc::SetStatusLineModeInfoMessage( void)
- {
- BOOL bAlt = (GetKeyState( VK_MENU)&0x8000) != 0;
- BOOL bCtrl = (GetKeyState( VK_CONTROL)&0x8000) != 0;
- // initialy, we are in polygon edit mode
- CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
-
- HICON hIcon;
- char strModeName[ 32];
- // write mode change on status line
- switch( m_iMode)
- {
- case POLYGON_MODE:
- {
- sprintf( strModeName, "%d polys, layer %d", m_selPolygonSelection.Count(), m_iTexture+1);
- hIcon = theApp.LoadIcon( IDR_ICON_PANE_POLYGON);
- break;
- };
- case SECTOR_MODE:
- {
- sprintf( strModeName, "%d sectors", m_selSectorSelection.Count());
- hIcon = theApp.LoadIcon( IDR_ICON_PANE_SECTOR);
- break;
- };
- case ENTITY_MODE:
- {
- if( m_bBrowseEntitiesMode)
- {
- sprintf( strModeName, "%d in volume", m_cenEntitiesSelectedByVolume.Count());
- }
- else
- {
- sprintf( strModeName, "%d entities", m_selEntitySelection.Count());
- };
- hIcon = theApp.LoadIcon( IDR_ICON_PANE_ENTITY);
- break;
- }
- case CSG_MODE:
- {
- sprintf( strModeName, "CSG mode");
- hIcon = theApp.LoadIcon( IDR_ICON_PANE_CSG);
- break;
- };
- case VERTEX_MODE:
- {
- sprintf( strModeName, "%d vertices", m_selVertexSelection.Count());
- hIcon = theApp.LoadIcon( IDR_ICON_PANE_VERTEX);
- break;
- };
- case TERRAIN_MODE:
- {
- if(bCtrl&&bAlt)
- {
- if(theApp.m_iTerrainEditMode==TEM_HEIGHTMAP)
- {
- sprintf( strModeName, "%s", "Pick altitude");
- }
- else
- {
- sprintf( strModeName, "%s", "Pick layer");
- }
- }
- else if(theApp.m_iTerrainEditMode==TEM_HEIGHTMAP)
- {
- INDEX iIcon;
- CTString strText;
- if(theApp.m_iTerrainBrushMode==TBM_FILTER)
- {
- sprintf( strModeName, "%s", GetFilterName(theApp.m_iFilter));
- }
- else
- {
- GetBrushModeInfo(INDEX(theApp.m_iTerrainBrushMode), iIcon, strText);
- sprintf( strModeName, "%s", strText);
- }
- }
- else
- {
- sprintf( strModeName, "Layer %d", GetLayerIndex());
- }
- hIcon = theApp.LoadIcon( IDR_ICON_PANE_TERRAIN);
- break;
- };
- default: { FatalError("Unknown editing mode."); break;};
- }
- pMainFrame->m_wndStatusBar.GetStatusBarCtrl().SetIcon( EDITING_MODE_ICON_PANE, hIcon);
- pMainFrame->m_wndStatusBar.SetPaneText( EDITING_MODE_PANE, CString(strModeName), TRUE);
- }
- /*
- * Changes editing mode
- */
- void CWorldEditorDoc::SetEditingMode( INDEX iNewMode)
- {
- #if !ALLOW_TERRAINS
- if(iNewMode==TERRAIN_MODE)
- {
- return;
- }
- #endif
- // exit cut mode
- theApp.m_bCutModeOn = FALSE;
- // cancel browse entities mode
- if( m_bBrowseEntitiesMode)
- {
- OnBrowseEntitiesMode();
- }
- // set new mode
- m_iMode = iNewMode;
-
- SetStatusLineModeInfoMessage();
- UpdateAllViews( NULL);
- // send message for mode change
- PostThreadMessage( GetCurrentThreadId(), WM_CHANGE_EDITING_MODE, TRUE, 0);
- }
- BOOL CWorldEditorDoc::OnNewDocument()
- {
- if (!CDocument::OnNewDocument())
- return FALSE;
- // create the World entity
- CPlacement3D plWorld;
- plWorld.pl_PositionVector = FLOAT3D(0.0f,0.0f,0.0f);
- plWorld.pl_OrientationAngle = ANGLE3D(0,0,0);
- CEntity *penWorldBase;
- try
- {
- penWorldBase = m_woWorld.CreateEntity_t(plWorld, CTFILENAME("Classes\\WorldBase.ecl"));
- }
- catch( char *err_str)
- {
- AfxMessageBox( CString(err_str));
- return FALSE;
- }
- // prepare the entity
- penWorldBase->Initialize();
- EFirstWorldBase eFirstWorldBase;
- penWorldBase->SendEvent( eFirstWorldBase);
- CEntity::HandleSentEvents();
- return TRUE;
- }
- /////////////////////////////////////////////////////////////////////////////
- // CWorldEditorDoc serialization
- void CWorldEditorDoc::Serialize(CArchive& ar)
- {
- // must not get here
- ASSERT(FALSE);
- }
- /////////////////////////////////////////////////////////////////////////////
- // CWorldEditorDoc diagnostics
- #ifdef _DEBUG
- void CWorldEditorDoc::AssertValid() const
- {
- CDocument::AssertValid();
- }
- void CWorldEditorDoc::Dump(CDumpContext& dc) const
- {
- CDocument::Dump(dc);
- }
- #endif //_DEBUG
- /////////////////////////////////////////////////////////////////////////////
- // CWorldEditorDoc commands
- /////////////////////////////////////////////////////////////////////////////
- void CWorldEditorDoc::SetupBackdropTextureObject( CTFileName fnPicture, CTextureObject &to)
- {
- CImageInfo iiImageInfo;
- try
- {
- iiImageInfo.LoadAnyGfxFormat_t( fnPicture);
- // both dimension must be potentions of 2
- if( (iiImageInfo.ii_Width == 1<<((int)Log2( (FLOAT)iiImageInfo.ii_Width))) &&
- (iiImageInfo.ii_Height == 1<<((int)Log2( (FLOAT)iiImageInfo.ii_Height))) )
- {
- CTFileName fnTexture = fnPicture.FileDir()+fnPicture.FileName()+".tex";
- // creates new texture with one frame
- CTextureData tdPicture;
- tdPicture.Create_t( &iiImageInfo, iiImageInfo.ii_Width, 1, FALSE);
- tdPicture.Save_t( fnTexture);
- to.SetData_t( fnTexture);
- }
- }
- catch( char *strError)
- {
- (void) strError;
- }
- }
- BOOL CWorldEditorDoc::OnOpenDocument(LPCTSTR lpszPathName)
- {
- CTFileName fnOpenFileName;
- // open the world
- fnOpenFileName = CTString(CStringA(lpszPathName));
- if( fnOpenFileName.FileExt()!=".wld") return FALSE;
- try
- {
- fnOpenFileName.RemoveApplicationPath_t();
- // if the file is read only
- if(IsFileReadOnly(fnOpenFileName))
- {
- // warn user about it
- WarningMessage("'%s' is read only. You have to check it out to be able to save it.",
- (const char*)fnOpenFileName);
- // remember it
- m_bReadOnly = TRUE;
- }
- _pfWorldEditingProfile.Reset();
- m_woWorld.Load_t( fnOpenFileName);
- m_woWorld.ReinitializeEntities();
- _pfWorldEditingProfile.Report( theApp.m_strCSGAndShadowStatistics);
- theApp.m_strCSGAndShadowStatistics.SaveVar(CTString("Temp\\Profile_Open.txt"));
- // try to load textures for backdrops
- if( m_woWorld.wo_strBackdropUp != "")
- {
- SetupBackdropTextureObject( m_woWorld.wo_strBackdropUp, m_toBackdropUp);
- }
- if( m_woWorld.wo_strBackdropFt != "")
- {
- SetupBackdropTextureObject( m_woWorld.wo_strBackdropFt, m_toBackdropFt);
- }
- if( m_woWorld.wo_strBackdropRt != "")
- {
- SetupBackdropTextureObject( m_woWorld.wo_strBackdropRt, m_toBackdropRt);
- }
- POSITION pos = GetFirstViewPosition();
- CWorldEditorView *pWedView = (CWorldEditorView *) GetNextView(pos);
- ASSERT( pWedView != NULL);
- CChildFrame *pWedChild = pWedView->GetChildFrame();
- ASSERT( pWedChild != NULL);
- pWedChild->m_mvViewer.mv_plViewer = m_woWorld.wo_plFocus;
- pWedChild->m_mvViewer.mv_fTargetDistance = m_woWorld.wo_fTargetDistance;
- }
- catch( char *strError)
- {
- AfxMessageBox( CString(strError));
- return FALSE;
- }
- // try to load object for backdrops
- if( m_woWorld.wo_strBackdropObject != "")
- {
- // try to
- try
- {
- // load 3D lightwawe object
- FLOATmatrix3D mStretch;
- mStretch.Diagonal(1.0f);
- m_o3dBackdropObject.LoadAny3DFormat_t( m_woWorld.wo_strBackdropObject, mStretch);
- }
- // catch and
- catch( char *strError)
- {
- // report errors
- AfxMessageBox( CString(strError));
- }
- }
- if( theApp.m_Preferences.ap_bShowAllOnOpen)
- {
- OnShowAllEntities();
- OnShowAllSectors();
- }
- // flush stale caches
- _pShell->Execute("FreeUnusedStock();");
- return TRUE;
- }
- // overridden from mfc
- void CWorldEditorDoc::SetModifiedFlag( BOOL bModified /*= TRUE*/ )
- {
- CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
- CDocument::SetModifiedFlag(bModified);
- if (!bModified) {
- return;
- }
- try
- {
- if (IsFileReadOnly(m_woWorld.wo_fnmFileName) && !m_bAskedToCheckOut)
- {
- // ask for check out
- if( ::MessageBoxA( pMainFrame->m_hWnd, "Do you want to open the world for edit?",
- "Warning !", MB_YESNO | MB_ICONWARNING | MB_DEFBUTTON1 |
- MB_TASKMODAL | MB_TOPMOST) == IDYES)
- {
- m_bAskedToCheckOut = TRUE;
- OnCheckEdit();
- }
- }
- }
- catch( char *strError)
- {
- AfxMessageBox( CString(strError));
- return;
- }
- }
- BOOL CWorldEditorDoc::OnSaveDocument(LPCTSTR lpszPathName)
- {
- CTFileName fnSaveFileName;
- // save the world
- fnSaveFileName = CTString(CStringA(lpszPathName));
- try
- {
- fnSaveFileName.RemoveApplicationPath_t();
- // if the file is read only
- if(IsFileReadOnly(fnSaveFileName))
- {
- // don't allow saving
- WarningMessage( "World file is read-only. You can't save it.");
- return FALSE;
- }
- POSITION pos = GetFirstViewPosition();
- CWorldEditorView *pWedView = (CWorldEditorView *) GetNextView(pos);
- CChildFrame *pWedChild = pWedView->GetChildFrame();
- m_woWorld.wo_plFocus = pWedChild->m_mvViewer.mv_plViewer;
- m_woWorld.wo_fTargetDistance = pWedChild->m_mvViewer.mv_fTargetDistance;
- m_woWorld.Save_t( fnSaveFileName);
- SetModifiedFlag(FALSE);
- }
- catch( char *strError)
- {
- AfxMessageBox( CString(strError));
- return FALSE;
- }
- // write file's directory into application's .ini file
- theApp.WriteProfileString(L"World editor", L"Open directory",
- CString(_fnmApplicationPath+fnSaveFileName.FileDir()));
- // save thumbnail
- SaveThumbnail();
- m_bWasEverSaved = TRUE;
- return TRUE;
- }
- static BOOL _bDontRecalculateBase = FALSE;
- // start creating primitive from current application's primitive, don't recreate base
- void CWorldEditorDoc::ApplyCurrentPrimitiveSettings(void)
- {
- ASSERT( m_pwoSecondLayer != NULL);
- // destroy second layer world
- delete m_pwoSecondLayer;
- m_pwoSecondLayer = NULL;
- INDEX iPreCSGMode = m_iPreCSGMode;
- // force not recreation of primitive base
- _bDontRecalculateBase = TRUE;
- StartPrimitiveCSG( theApp.m_vfpCurrent.vfp_plPrimitive, FALSE);
- CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
- pMainFrame->m_TriangularisationCombo.SetCurSel( (int)theApp.m_vfpCurrent.vfp_ttTriangularisationType);
- m_iPreCSGMode = iPreCSGMode;
- }
- // start creating primitive
- void CWorldEditorDoc::StartPrimitiveCSG( CPlacement3D plPrimitive, BOOL bResetAngles/*=TRUE*/)
- {
- ApplyAutoColorize();
- if( theApp.m_ptdActiveTexture == NULL)
- {
- AfxMessageBox( L"You have to select active texture first (double click on texture in browser).");
- return;
- }
- if( !((theApp.m_vfpCurrent.vfp_ptPrimitiveType == PT_CONUS) ||
- (theApp.m_vfpCurrent.vfp_ptPrimitiveType == PT_TORUS) ||
- (theApp.m_vfpCurrent.vfp_ptPrimitiveType == PT_STAIRCASES) ||
- (theApp.m_vfpCurrent.vfp_ptPrimitiveType == PT_SPHERE) ||
- (theApp.m_vfpCurrent.vfp_ptPrimitiveType == PT_TERRAIN) ) )
- {
- WarningMessage( "This type of primitive not yet supported. Please be patient !!!");
- return;
- }
- POSITION pos = GetFirstViewPosition();
- CWorldEditorView *pWedView = (CWorldEditorView *) GetNextView(pos);
- CChildFrame *pWedChild = pWedView->GetChildFrame();
- // remember auto mip brushing flag
- pWedChild->m_bLastAutoMipBrushingOn = pWedChild->m_bAutoMipBrushingOn;
- // turn off auto mip brushing
- pWedChild->m_bAutoMipBrushingOn = FALSE;
- m_pwoSecondLayer = new CWorld;
- m_bPrimitiveMode = TRUE;
- // position the second layer
- m_plSecondLayer = plPrimitive;
- // if angle reset requested
- if( bResetAngles)
- {
- // reset angles so they are alligned to current grid
- m_plSecondLayer.pl_OrientationAngle = m_plGrid.pl_OrientationAngle;
- }
- // create the World entity
- CPlacement3D plPrimitiveEntity;
- plPrimitiveEntity.pl_PositionVector = FLOAT3D(0.0f,0.0f,0.0f);
- plPrimitiveEntity.pl_OrientationAngle = ANGLE3D(0,0,0);
- try
- {
- m_penPrimitive = m_pwoSecondLayer->CreateEntity_t( plPrimitiveEntity,
- CTFILENAME("Classes\\WorldBase.ecl"));
- }
- catch( char *err_str)
- {
- AfxMessageBox( CString(err_str));
- // discard initialized variables needed for CSG
- delete m_pwoSecondLayer;
- m_pwoSecondLayer = NULL;
- m_bPrimitiveMode = FALSE;
- return;
- }
- // prepare the entity
- m_penPrimitive->Initialize();
- // store current mode
- m_iPreCSGMode = m_iMode;
- // start CSG mode
- SetEditingMode( CSG_MODE);
- // create primitive for the first time
- //m_bPrimitiveCreatedFirstTime = TRUE;
- CreatePrimitive();
- // if preferences say so, show info
- if( theApp.m_Preferences.ap_AutomaticInfo)
- {
- CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
- pMainFrame->ShowInfoWindow();
- }
- // invalidate document (i.e. all views)
- UpdateAllViews( NULL);
- }
- // start CSG with world template
- void CWorldEditorDoc::StartTemplateCSG( CPlacement3D plTemplate,
- const CTFileName &fnWorld, BOOL bResetAngles/*=TRUE*/)
- {
- POSITION pos = GetFirstViewPosition();
- CWorldEditorView *pWedView = (CWorldEditorView *) GetNextView(pos);
- CChildFrame *pWedChild = pWedView->GetChildFrame();
- // remember auto mip brushing flag
- pWedChild->m_bLastAutoMipBrushingOn = pWedChild->m_bAutoMipBrushingOn;
- // turn off auto mip brushing
- pWedChild->m_bAutoMipBrushingOn = FALSE;
- m_pwoSecondLayer = new CWorld;
- m_bPrimitiveMode = FALSE;
- // remember name of last template used for CSG
- m_fnLastDroppedTemplate = fnWorld;
- // position the second layer
- m_plSecondLayer = plTemplate;
- // if angle reset was requested
- if( bResetAngles)
- {
- // reset angles so they are alligned to current grid
- m_plSecondLayer.pl_OrientationAngle = m_plGrid.pl_OrientationAngle;
- }
- try
- {
- // load the World
- m_pwoSecondLayer->Load_t( fnWorld);
- }
- catch( char *err_str)
- {
- AfxMessageBox( CString(err_str));
- delete m_pwoSecondLayer;
- m_pwoSecondLayer = NULL;
- return;
- }
- // invalidate document (i.e. all views)
- UpdateAllViews( NULL);
- // store current mode
- m_iPreCSGMode = m_iMode;
- // start CSG mode
- SetEditingMode( CSG_MODE);
- // update position property page for the first time
- m_chSelections.MarkChanged();
- // if preferences say so, show info
- if( theApp.m_Preferences.ap_AutomaticInfo)
- {
- CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
- pMainFrame->ShowInfoWindow();
- }
- // don't join layers !!!!
- /*
- // if none of entities in dropped world has brush rendering type
- // for all of the world's entities
- {FOREACHINDYNAMICCONTAINER(m_pwoSecondLayer->wo_cenEntities, CEntity, iten)
- {
- CEntity::RenderType rt = iten->GetRenderType();
- // if the entity is brush and it is not empty
- if( (rt==CEntity::RT_BRUSH || rt==CEntity::RT_FIELDBRUSH) && ( !iten->IsEmptyBrush()) &&
- (CTString(iten->GetClass()->ec_pdecDLLClass->dec_strName) == "WorldBase") )
- {
- // if preferences say so, show info
- if( theApp.m_Preferences.ap_AutomaticInfo)
- {
- CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
- pMainFrame->ShowInfoWindow();
- }
- // don't join layers
- return;
- }
- }}
- // call join layers
- OnJoinLayers();
- */
- }
- #define CT_PRIMITIVES_IN_HISTORY_BUFFER 1024
- // apply current CSG operation
- void CWorldEditorDoc::ApplyCSG(enum CSGType CSGType)
- {
- if((CSGType==CSG_ADD ||
- CSGType==CSG_ADD_REVERSE ||
- CSGType==CSG_REMOVE ||
- CSGType==CSG_REMOVE_REVERSE ||
- CSGType==CSG_ADD_ENTITIES ||
- CSGType==CSG_SPLIT_POLYGONS ||
- CSGType==CSG_JOIN_LAYERS) && (m_pwoSecondLayer==NULL)) return;
- POSITION pos = GetFirstViewPosition();
- CWorldEditorView *pWedView = (CWorldEditorView *) GetNextView(pos);
- CChildFrame *pWedChild = pWedView->GetChildFrame();
- // restore auto mip brushing flag
- pWedChild->m_bAutoMipBrushingOn = pWedChild->m_bLastAutoMipBrushingOn;
- // set wait cursor
- CWaitCursor StartWaitCursor;
- if( theApp.m_bCSGReportEnabled)
- {
- _pfWorldEditingProfile.Reset();
- }
- RememberUndo();
- // remember last used CSG operation
- m_csgtPreLastUsedCSGOperation = m_csgtLastUsedCSGOperation;
- m_csgtLastUsedCSGOperation = CSGType;
- // set flag telling is last used CSG was primitive
- m_bPreLastUsedPrimitiveMode = m_bLastUsedPrimitiveMode;
- m_bLastUsedPrimitiveMode = m_bPrimitiveMode;
- // invalving entities
- CEntity *penThis;
- CEntity *penOther;
- BOOL bThisFound = FALSE;
- BOOL bOtherFound = FALSE;
- // calculate delta placement
- m_plDeltaPlacement = m_plSecondLayer;
- // convert it into absolute space of last used placement (delta calculated)
- m_plDeltaPlacement.AbsoluteToRelative( m_plLastPlacement);
- // remember position of last applied CSG
- m_plLastPlacement = m_plSecondLayer;
- theApp.m_vfpCurrent.vfp_plPrimitive = m_plSecondLayer;
- // calculate width, height, sheer,... delta to be able to use it for next clone CSG
- theApp.m_vfpDelta = theApp.m_vfpCurrent - theApp.m_vfpLast;
- // remember last values for primitive as prelast used ones
- theApp.m_vfpPreLast = theApp.m_vfpLast;
- // remember current values for primitive as last used ones
- theApp.m_vfpLast = theApp.m_vfpCurrent;
- if( m_bPrimitiveMode)
- {
- // if there are too many primitives in history buffer
- if( theApp.m_lhPrimitiveHistory.Count() >= CT_PRIMITIVES_IN_HISTORY_BUFFER)
- {
- // remove last used one
- CPrimitiveInHistoryBuffer *ppihbLast =
- LIST_TAIL( theApp.m_lhPrimitiveHistory, CPrimitiveInHistoryBuffer, pihb_lnNode);
- theApp.m_lhPrimitiveHistory.RemTail();
- delete ppihbLast;
- }
- // add this primtive into history buffer
- CPrimitiveInHistoryBuffer *ppihbMember = new CPrimitiveInHistoryBuffer;
- ppihbMember->pihb_vfpPrimitive = theApp.m_vfpCurrent;
- ppihbMember->pihb_vfpPrimitive.vfp_csgtCSGOperation = CSGType;
- theApp.m_lhPrimitiveHistory.AddHead( ppihbMember->pihb_lnNode);
- // save primitives history buffer
- CTFileStream strmFile;
- try
- {
- strmFile.Create_t( CTString("Data\\PrimitivesHistory.pri"));
- INDEX ctHistory = theApp.m_lhPrimitiveHistory.Count();
- strmFile << ctHistory;
- // write history primitives list
- FOREACHINLIST( CPrimitiveInHistoryBuffer, pihb_lnNode, theApp.m_lhPrimitiveHistory, itPrim)
- {
- itPrim->pihb_vfpPrimitive.Write_t( strmFile);
- }
- }
- catch( char *strError)
- {
- WarningMessage( strError);
- }
- // remember used values for primitive to be used as default values for next primitive
- // of same type
- switch( theApp.m_vfpCurrent.vfp_ptPrimitiveType)
- {
- case PT_CONUS:{ theApp.m_vfpConus = theApp.m_vfpCurrent; break;}
- case PT_TORUS:{ theApp.m_vfpTorus = theApp.m_vfpCurrent; break;}
- case PT_STAIRCASES:{ theApp.m_vfpStaircases = theApp.m_vfpCurrent; break;}
- case PT_SPHERE:{ theApp.m_vfpSphere = theApp.m_vfpCurrent; break;}
- case PT_TERRAIN:{ theApp.m_vfpTerrain = theApp.m_vfpCurrent; break;}
- default: ASSERTALWAYS( "Wrong primitive type occured");
- }
- }
- CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
- // join operations are not really CSG operations because we do not have second layer
- BOOL bJoinOperation = (
- CSGType==CSG_JOIN_LAYERS ||
- CSGType==CSG_JOIN_SECTORS ||
- CSGType==CSG_JOIN_POLYGONS ||
- CSGType==CSG_JOIN_POLYGONS_KEEP_TEXTURES ||
- CSGType==CSG_JOIN_ALL_POLYGONS ||
- CSGType==CSG_JOIN_ALL_POLYGONS_KEEP_TEXTURES);
- if( !bJoinOperation)
- {
- // for real CSG operations search for invalving entities
- penThis = pMainFrame->m_CSGDesitnationCombo.GetSelectedBrushEntity();
- if( penThis != NULL)
- {
- bThisFound = TRUE;
- }
- if( !bThisFound)
- {
- WarningMessage( "Destination for CSG can't be optained, canceling CSG.");
- StopCSG();
- return;
- }
- // find other entity
- {FOREACHINDYNAMICCONTAINER(m_pwoSecondLayer->wo_cenEntities, CEntity, itenOther) {
- if (CTString(itenOther->GetClass()->ec_pdecDLLClass->dec_strName) == "WorldBase") {
- penOther = &itenOther.Current();
- bOtherFound = TRUE;
- break;
- }
- }}
- // if other entity can't be obtained, switch to join layers mode
- if( !bOtherFound)
- {
- CSGType = CSG_JOIN_LAYERS;
- }
- }
- // act acording requested CSG operation
- switch( CSGType)
- {
- case CSG_ADD:
- {
- ClearSelections();
- // apply "add"
- m_woWorld.CSGAdd(*penThis, *m_pwoSecondLayer, *penOther, m_plSecondLayer);
- break;
- }
- case CSG_ADD_REVERSE:
- {
- ClearSelections();
- // apply "add reverse"
- m_woWorld.CSGAddReverse(*penThis, *m_pwoSecondLayer, *penOther, m_plSecondLayer);
- break;
- }
- case CSG_REMOVE:
- {
- ClearSelections();
- // apply "remove"
- m_woWorld.CSGRemove(*penThis, *m_pwoSecondLayer, *penOther, m_plSecondLayer);
- break;
- }
- case CSG_REMOVE_REVERSE:
- {
- //ClearSelections();
- // apply "remove reverse"
- // m_woWorld.CSGRemoveReverse(*penThis, *m_pwoSecondLayer, *penOther, m_plSecondLayer);
- break;
- }
- case CSG_SPLIT_SECTORS:
- {
- // clear all selections except sector seletion
- ClearSelections( ST_SECTOR);
- // apply "split sectors"
- m_woWorld.SplitSectors(*penThis, m_selSectorSelection,
- *m_pwoSecondLayer, *penOther, m_plSecondLayer);
- break;
- }
- case CSG_JOIN_SECTORS:
- {
- // clear all selections except sector seletion
- ClearSelections( ST_SECTOR);
- // join selected sectors
- m_woWorld.JoinSectors( m_selSectorSelection);
- // store current mode
- m_iPreCSGMode = m_iMode;
- break;
- }
- case CSG_SPLIT_POLYGONS:
- {
- // clear all selections except polygon seletion
- ClearSelections( ST_POLYGON);
- // apply "split polygons"
- m_woWorld.SplitPolygons(*penThis, m_selPolygonSelection,
- *m_pwoSecondLayer, *penOther, m_plSecondLayer);
- break;
- }
- case CSG_JOIN_POLYGONS:
- case CSG_JOIN_POLYGONS_KEEP_TEXTURES:
- {
- // clear all selections except polygon seletion
- ClearSelections( ST_POLYGON);
- // join selected polygons
- m_woWorld.JoinPolygons(m_selPolygonSelection);
- // store current mode
- m_iPreCSGMode = m_iMode;
- break;
- }
- case CSG_JOIN_ALL_POLYGONS:
- case CSG_JOIN_ALL_POLYGONS_KEEP_TEXTURES:
- {
- // clear all selections except polygon seletion
- ClearSelections( ST_POLYGON);
- // join selected polygons
- m_woWorld.JoinAllPossiblePolygons(
- m_selPolygonSelection, CSGType==CSG_JOIN_ALL_POLYGONS_KEEP_TEXTURES, m_iTexture);
- // store current mode
- m_iPreCSGMode = m_iMode;
- break;
- }
- case CSG_JOIN_LAYERS:
- {
- theApp.m_vfpCurrent.vfp_csgtCSGOperation = CSG_JOIN_LAYERS;
- // clear entity selections
- m_selEntitySelection.Clear();
- m_cenEntitiesSelectedByVolume.Clear();
- // mark that selections have been changed
- m_chSelections.MarkChanged();
- // make container of entities to copy
- CDynamicContainer<CEntity> cenToCopy;
- cenToCopy = m_pwoSecondLayer->wo_cenEntities;
- // remove empty brushes from it
- {FOREACHINDYNAMICCONTAINER(m_pwoSecondLayer->wo_cenEntities, CEntity, iten)
- {
- if( iten->IsEmptyBrush() && (iten->GetFlags()&ENF_ZONING))
- {
- cenToCopy.Remove(iten);
- }
- }}
- // copy entities in container
- m_woWorld.CopyEntities( *m_pwoSecondLayer, cenToCopy,
- m_selEntitySelection, m_plSecondLayer);
- m_iPreCSGMode = ENTITY_MODE;
- break;
- }
- default:
- {
- ASSERTALWAYS( "Illegal CSG operation type requested!");
- }
- }
- // increase auto colorize color's index
- theApp.m_iLastAutoColorizeColor=(theApp.m_iLastAutoColorizeColor+1)%32;
- m_chSelections.MarkChanged();
- SetModifiedFlag(TRUE);
- m_chDocument.MarkChanged();
- StopCSG();
- if( theApp.m_bCSGReportEnabled)
- {
- // create CSG report
- _pfWorldEditingProfile.Report( theApp.m_strCSGAndShadowStatistics);
- theApp.m_strCSGAndShadowStatistics.SaveVar(CTString("Temp\\Profile_CSG.txt"));
- }
- m_iMirror = 0;
- }
- // clean up after doing a CSG
- void CWorldEditorDoc::StopCSG(void)
- {
- if( m_pwoSecondLayer == NULL) return;
- CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
- // destroy second layer world
- delete m_pwoSecondLayer;
- m_pwoSecondLayer = NULL;
- m_bPrimitiveMode = FALSE;
- // if preferences say so, hide info
- if( theApp.m_Preferences.ap_AutomaticInfo)
- {
- pMainFrame->HideInfoWindow();
- }
- // restore mode
- SetEditingMode( m_iPreCSGMode);
- // if info frame exist
- if( pMainFrame->m_pInfoFrame != NULL)
- {
- // force immidiate page refilling
- pMainFrame->m_pInfoFrame->m_pInfoSheet->OnIdle( 0);
- }
- // invalidate document (i.e. all views)
- UpdateAllViews( NULL);
- }
- // cancel current CSG operation
- void CWorldEditorDoc::CancelCSG(void)
- {
- StopCSG();
- }
- void CWorldEditorDoc::OnIdle(void)
- {
- CValuesForPrimitive &vfp=theApp.m_vfpCurrent;
- if( m_pwoSecondLayer!=NULL && m_bPrimitiveMode &&
- vfp.vfp_ptPrimitiveType==PT_TERRAIN &&
- vfp.vfp_fnDisplacement!="" &&
- theApp.m_Preferences.ap_bAutoUpdateDisplaceMap)
- {
- try
- {
- SLONG slFileTime=GetFileTimeStamp_t(vfp.vfp_fnDisplacement);
- if(slFileTime>m_slDisplaceTexTime)
- {
- CreatePrimitive();
- UpdateAllViews( NULL);
- }
- }
- catch(char *strError)
- {
- (void) strError;
- }
- }
-
- POSITION pos = GetFirstViewPosition();
- CWorldEditorView *pWedView;
- FOREVER
- {
- pWedView = (CWorldEditorView *) GetNextView(pos);
- if( pWedView == NULL) break;
- pWedView->OnIdle();
- }
- if( GetEditingMode()==TERRAIN_MODE)
- {
- UpdateAllViews( NULL);
- }
- }
- // does "snap to grid" for given coordinate
- void CWorldEditorDoc::SnapFloat( FLOAT &fDest, FLOAT fStep /* SNAP_FLOAT_GRID */)
- {
- // this must use floor() to get proper snapping of negative values.
- FLOAT fDiv = fDest/fStep;
- FLOAT fRound = fDiv + 0.5f;
- int iSnap = int( floor(fRound));
- FLOAT fRes = iSnap * fStep;
- fDest = fRes;
- }
- // does "snap to grid" for given angle
- void CWorldEditorDoc::SnapAngle( ANGLE &angDest, ANGLE angStep /* SNAP_ANGLE_GRID */)
- {
- /* Watch out for unsigned-signed mixing!
- All sub-expression and arguments must be unsigned for this to work correctly!
- Unfortunately, ANGLE is not an unsigned type by default, so we must cast it.
- Also, angStep must be a divisor of ANGLE_180!
- */
-
- SnapFloat( angDest, angStep);
- /*
- ASSERT(ANGLE_180%angStep == 0); // don't test with ANGLE_360 ,since it is 0!
- angDest = ANGLE( ((UWORD(angDest)+UWORD(angStep)/2U)/UWORD(angStep))*UWORD(angStep) );
- */
- }
- // does "snap to grid" for given placement
- void CWorldEditorDoc::SnapToGrid( CPlacement3D &plPlacement, FLOAT fSnapValue)
- {
- FLOAT fAngleSnap = SNAP_ANGLE_GRID;
- if( fSnapValue < SNAP_FLOAT_CM) fSnapValue = SNAP_FLOAT_CM;
- if( !m_bAutoSnap)
- {
- fSnapValue = SNAP_FLOAT_CM;
- fAngleSnap = ANGLE_SNAP/32.0f;
- }
- // snap X coordinate
- SnapFloat( plPlacement.pl_PositionVector(1), fSnapValue);
- // snap Y coordinate
- SnapFloat( plPlacement.pl_PositionVector(2), fSnapValue);
- // snap Z coordinate
- SnapFloat( plPlacement.pl_PositionVector(3), fSnapValue);
-
- /*
- // snap H angle
- SnapAngle( plPlacement.pl_OrientationAngle(1));
- // snap P angle
- SnapAngle( plPlacement.pl_OrientationAngle(2));
- // snap B angle
- SnapAngle( plPlacement.pl_OrientationAngle(3));
- */
-
- // snap X coordinate
- SnapFloat( plPlacement.pl_PositionVector(1), SNAP_FLOAT_CM);
- // snap Y coordinate
- SnapFloat( plPlacement.pl_PositionVector(2), SNAP_FLOAT_CM);
- // snap Z coordinate
- SnapFloat( plPlacement.pl_PositionVector(3), SNAP_FLOAT_CM);
-
- // snap H angle
- SnapAngle( plPlacement.pl_OrientationAngle(1), fAngleSnap);
- // snap P angle
- SnapAngle( plPlacement.pl_OrientationAngle(2), fAngleSnap);
- // snap B angle
- SnapAngle( plPlacement.pl_OrientationAngle(3), fAngleSnap);
- }
- // static vars used for polygon creation in primitives
- static BOOL _bAutoCreateMipBrushes;
- static BOOL _bClosed;
- static CObjectMaterial *_pomMaterial;
- static CObjectSector *_poscSector;
- static CTextureData *_pPrimitiveTexture;
- static DOUBLE _fTextureWidth;
- static DOUBLE _fTextureHeight;
- void DisplaceVertex( DOUBLE3D &vVtx, CImageInfo *pII,
- DOUBLE fMinX, DOUBLE fMaxX, DOUBLE fMinZ, DOUBLE fMaxZ,
- INDEX iSlicesPerW, INDEX iSlicesPerL, FLOAT fAmplitude)
- {
- if( pII == NULL) return;
- FLOAT fPix = (fMaxX-fMinX)/(pII->ii_Width-1);
- FLOAT fDelta = (vVtx(1)-fMinX);
- FLOAT fMaxDelta = (fMaxX-fMinX);
- FLOAT fTmp = ((pII->ii_Width-1) / fMaxDelta * fDelta);
- PIX pixX = (PIX)((pII->ii_Width-1) /(fMaxX-fMinX) * (vVtx(1) + fPix/2.0f -fMinX) );
- PIX pixY = (PIX)((pII->ii_Height-1)/(fMaxZ-fMinZ) * (vVtx(3) + fPix/2.0f -fMinZ) );
- if( pixX >= pII->ii_Width) pixX = pII->ii_Width -1;
- if( pixY >= pII->ii_Height) pixY = pII->ii_Height-1;
- SLONG slPicPosition = (pII->ii_Width*pixY +pixX) * (pII->ii_BitsPerPixel/8);
- vVtx(2) += fAmplitude/256.0f * pII->ii_Picture[slPicPosition];
- }
- #define HEIGHT_EPSILON 0.001
- void AddPolygon(INDEX vtxCt, DOUBLE3D *avVtx, BOOL bInvert,
- DOUBLE3D f3dMappingTranslation = DOUBLE3D(0.0f,0.0f,0.0f),
- CImageInfo *pII=NULL,
- DOUBLE fMinX=0.0f, DOUBLE fMaxX=0.0f,
- DOUBLE fMinZ=0.0f, DOUBLE fMaxZ=0.0f,
- INDEX iSlicesPerW=0, INDEX iSlicesPerL=0,
- FLOAT fAmplitude=0.0f,
- DOUBLE fRaiseHeight=0.0f)
- {
- // copy array of vertices
- DOUBLE3D *avVtxCopy = new DOUBLE3D[vtxCt];
-
- for( INDEX iCopy=0; iCopy<vtxCt; iCopy++)
- {
- avVtxCopy[iCopy] = avVtx[iCopy];
- }
-
- // displace all vertices
- if( pII != NULL)
- {
- for( INDEX iVtx=0; iVtx<vtxCt; iVtx++)
- {
- if( Abs(avVtxCopy[iVtx](2)-fRaiseHeight)<HEIGHT_EPSILON)
- {
- DisplaceVertex( avVtxCopy[iVtx], pII, fMinX, fMaxX, fMinZ, fMaxZ,
- iSlicesPerW, iSlicesPerL, fAmplitude);
- }
- }
- }
- /*
- // report it
- _RPT1(_CRT_WARN, "\n%d:", vtxCt);
- for(INDEX ivx=0; ivx<vtxCt; ivx++) {
- // report it
- _RPT3(_CRT_WARN, " (%f, %f, %f)",
- avVtx[ivx](1),
- avVtx[ivx](2),
- avVtx[ivx](3));
- }
- */
-
- switch( theApp.m_vfpCurrent.vfp_ttTriangularisationType)
- {
- case TT_NONE:
- {
- // create polygon
- CObjectPolygon *pObjectPolygon = _poscSector->CreatePolygon(
- vtxCt, avVtxCopy, *_pomMaterial, NULL, bInvert);
- if( pObjectPolygon != NULL) {
- // set shadow cluster size to 2m
- ((CBrushPolygonProperties&)(pObjectPolygon->opo_ubUserData)).bpp_sbShadowClusterSize=2;
- }
- break;
- }
- case TT_CENTER_VERTEX:
- {
- // calculate center vertex
- DOUBLE3D vCenter = DOUBLE3D( 0.0, 0.0, 0.0);
- INDEX iVtx=0;
- for( ; iVtx<vtxCt; iVtx++)
- {
- vCenter+=avVtxCopy[iVtx];
- }
- vCenter /= vtxCt;
- // create polygons
- DOUBLE3D avPolygon[ 3];
- for( iVtx=0; iVtx<vtxCt; iVtx++)
- {
- INDEX iNextVtx = (iVtx+1)%vtxCt;
- avPolygon[ 0] = avVtxCopy[iVtx];
- avPolygon[ 1] = avVtxCopy[iNextVtx];
- avPolygon[ 2] = vCenter;
- CObjectPolygon *pObjectPolygon = _poscSector->CreatePolygon(
- 3, avPolygon, *_pomMaterial, NULL, bInvert);
- if( pObjectPolygon != NULL) {
- // set shadow cluster size to 2m
- ((CBrushPolygonProperties&)(pObjectPolygon->opo_ubUserData)).bpp_sbShadowClusterSize=2;
- }
- }
- break;
- }
- default:
- {
- INDEX iStartVtx = 0;
- if( theApp.m_vfpCurrent.vfp_ttTriangularisationType == TT_FROM_VTX00) iStartVtx = 0;
- if( theApp.m_vfpCurrent.vfp_ttTriangularisationType == TT_FROM_VTX01) iStartVtx = 1;
- if( theApp.m_vfpCurrent.vfp_ttTriangularisationType == TT_FROM_VTX02) iStartVtx = 2;
- if( theApp.m_vfpCurrent.vfp_ttTriangularisationType == TT_FROM_VTX03) iStartVtx = 3;
- if( theApp.m_vfpCurrent.vfp_ttTriangularisationType == TT_FROM_VTX04) iStartVtx = 4;
- if( theApp.m_vfpCurrent.vfp_ttTriangularisationType == TT_FROM_VTX05) iStartVtx = 5;
- if( theApp.m_vfpCurrent.vfp_ttTriangularisationType == TT_FROM_VTX06) iStartVtx = 6;
- if( theApp.m_vfpCurrent.vfp_ttTriangularisationType == TT_FROM_VTX07) iStartVtx = 7;
- if( theApp.m_vfpCurrent.vfp_ttTriangularisationType == TT_FROM_VTX08) iStartVtx = 8;
- if( theApp.m_vfpCurrent.vfp_ttTriangularisationType == TT_FROM_VTX09) iStartVtx = 9;
- if( theApp.m_vfpCurrent.vfp_ttTriangularisationType == TT_FROM_VTX10) iStartVtx =10;
- if( theApp.m_vfpCurrent.vfp_ttTriangularisationType == TT_FROM_VTX11) iStartVtx =11;
- if( theApp.m_vfpCurrent.vfp_ttTriangularisationType == TT_FROM_VTX12) iStartVtx =12;
- if( theApp.m_vfpCurrent.vfp_ttTriangularisationType == TT_FROM_VTX13) iStartVtx =13;
- if( theApp.m_vfpCurrent.vfp_ttTriangularisationType == TT_FROM_VTX14) iStartVtx =14;
- if( theApp.m_vfpCurrent.vfp_ttTriangularisationType == TT_FROM_VTX15) iStartVtx =15;
- iStartVtx %= vtxCt;
- // create polygons
- DOUBLE3D avPolygon[ 3];
- for( INDEX iVtx=iStartVtx; iVtx<iStartVtx+vtxCt-2; iVtx++)
- {
- INDEX iNextVtx = (iVtx+1)%vtxCt;
- INDEX iNextNextVtx = (iNextVtx+1)%vtxCt;
- avPolygon[ 0] = avVtxCopy[iStartVtx];
- avPolygon[ 1] = avVtxCopy[iNextVtx];
- avPolygon[ 2] = avVtxCopy[iNextNextVtx];
- CObjectPolygon *pObjectPolygon = _poscSector->CreatePolygon(
- 3, avPolygon, *_pomMaterial, NULL, bInvert);
- if( pObjectPolygon != NULL) {
- // set shadow cluster size to 2m
- ((CBrushPolygonProperties&)(pObjectPolygon->opo_ubUserData)).bpp_sbShadowClusterSize=2;
- }
- }
- break;
- }
- }
- delete[] avVtxCopy;
- }
- void CWorldEditorDoc::ConvertObject3DToBrush(CObject3D &ob, BOOL bApplyProjectedMapping/*=FALSE*/,
- INDEX iMipBrush/*=0*/, FLOAT fSwitchFactor/*=1E6f*/,
- BOOL bApplyDefaultPolygonProperties/*=TRUE*/)
- {
- CObject3D obTmp = ob;
- obTmp.RecalculatePlanes();
- // try to
- try
- {
- // turn this on to dump all primitives
- #ifndef NDEBUG
- //theApp.m_vfpCurrent.vfp_o3dPrimitive.DebugDump();
- #endif //NDEBUG
- if( !obTmp.ArePolygonsPlanar())
- {
- throw( "ERROR: Primitive that You want to use has non planar polygons.\n"
- "Make sure that stretch x and stretch y are same or use triangularisation.");
- }
- if( bApplyProjectedMapping)
- {
- DOUBLE xMin = theApp.m_vfpCurrent.vfp_fXMin;
- DOUBLE xMax = theApp.m_vfpCurrent.vfp_fXMax;
- DOUBLE zMin = theApp.m_vfpCurrent.vfp_fZMin;
- DOUBLE zMax = theApp.m_vfpCurrent.vfp_fZMax;
- // create mapping to be stretched over the top of primitive
- FLOATplane3D plHorizontal(FLOAT3D(0,1,0),0);
- CMappingDefinitionUI mduiHorizontal;
- mduiHorizontal.mdui_aURotation = mduiHorizontal.mdui_aVRotation = AngleDeg(90.0f);
- mduiHorizontal.mdui_fUStretch = FLOAT((xMax-xMin)/_fTextureWidth);
- mduiHorizontal.mdui_fVStretch = FLOAT((zMax-zMin)/_fTextureHeight);
- mduiHorizontal.mdui_fUOffset = FLOAT(xMin)/mduiHorizontal.mdui_fUStretch;
- mduiHorizontal.mdui_fVOffset = FLOAT(zMin)/mduiHorizontal.mdui_fVStretch;
- CMappingDefinition mdHorizontal;
- mdHorizontal.FromUI(mduiHorizontal);
- // for each polygon in primitive
- CObject3D &ob = obTmp;
- ob.ob_aoscSectors.Lock();
- CObjectSector &osc = ob.ob_aoscSectors[0];
- osc.osc_aopoPolygons.Lock();
- FOREACHINDYNAMICARRAY( osc.osc_aopoPolygons, CObjectPolygon, itopo) {
- CObjectPolygon &opo = *itopo;
- // project mapping to the polygon
- opo.opo_amdMappings[0].ProjectMapping(plHorizontal, mdHorizontal,
- DOUBLEtoFLOAT(*opo.opo_Plane));
- opo.opo_amdMappings[1] = opo.opo_amdMappings[0];
- opo.opo_amdMappings[2] = opo.opo_amdMappings[0];
- }
- osc.osc_aopoPolygons.Unlock();
- ob.ob_aoscSectors.Unlock();
- }
- // convert it into brush
- CBrush3D *pbr = m_penPrimitive->GetBrush();
- if( iMipBrush == 0)
- {
- pbr->Clear();
- }
- pbr->AddMipBrushFromObject3D_t(obTmp, fSwitchFactor);
-
- if( bApplyDefaultPolygonProperties)
- {
- // --- Apply default values for primitive polygons ---
- // for each mip in its brush
- FOREACHINLIST(CBrushMip, bm_lnInBrush, pbr->br_lhBrushMips, itbm) {
- // for all sectors in this mip
- FOREACHINDYNAMICARRAY(itbm->bm_abscSectors, CBrushSector, itbsc) {
- // for all polygons in sector
- FOREACHINSTATICARRAY(itbsc->bsc_abpoPolygons, CBrushPolygon, itbpo)
- {
- itbpo->CopyPropertiesWithoutTexture( *theApp.m_pbpoPolygonWithDeafultValues);
- }
- }
- }
- }
- pbr->CalculateBoundingBoxes();
- }
- // report errors
- catch( char *err_str)
- {
- AfxMessageBox( CString(err_str));
- }
- }
- void CWorldEditorDoc::ApplyAutoColorize(void)
- {
- // if primitive auto colorization is on
- if( theApp.m_Preferences.ap_bAutoColorize)
- {
- theApp.m_vfpCurrent.vfp_colPolygonsColor = acol_ColorizePallete[theApp.m_iLastAutoColorizeColor];
- theApp.m_vfpCurrent.vfp_colSectorsColor = theApp.m_vfpCurrent.vfp_colPolygonsColor;
- }
- }
- void CWorldEditorDoc::CreateConusPrimitive(void)
- {
- /*
- // report it
- _RPT0(_CRT_WARN, "\nConus\n");
- */
- // calculate height
- DOUBLE fHeight = theApp.m_vfpCurrent.vfp_fYMax-theApp.m_vfpCurrent.vfp_fYMin;
- if( fHeight < SNAP_FLOAT_GRID) fHeight = SNAP_FLOAT_GRID;
- // get count of vertices on the base
- INDEX vtxCt = theApp.m_vfpCurrent.vfp_avVerticesOnBaseOfPrimitive.Count();
- // get shear values
- DOUBLE dx = theApp.m_vfpCurrent.vfp_fShearX;
- DOUBLE dz = theApp.m_vfpCurrent.vfp_fShearZ;
- // get stretch value for top-base vertices
- DOUBLE fStretchX = theApp.m_vfpCurrent.vfp_fStretchX;
- DOUBLE fStretchY = theApp.m_vfpCurrent.vfp_fStretchY;
- // base polygon
- DOUBLE3D *avBottomPolygon = new DOUBLE3D[ vtxCt];
- for(INDEX iVtxBottom=0; iVtxBottom<vtxCt; iVtxBottom++)
- {
- avBottomPolygon[ iVtxBottom] = theApp.m_vfpCurrent.vfp_avVerticesOnBaseOfPrimitive[ iVtxBottom];
- avBottomPolygon[ iVtxBottom](2) = theApp.m_vfpCurrent.vfp_fYMin;
- }
- AddPolygon( vtxCt, avBottomPolygon, _bClosed);
- // top polygon
- DOUBLE3D *avTopPolygon = new DOUBLE3D[ vtxCt];
- for(INDEX iVtxTop=0; iVtxTop<vtxCt; iVtxTop++)
- {
- avTopPolygon[ iVtxTop] = DOUBLE3D(
- theApp.m_vfpCurrent.vfp_avVerticesOnBaseOfPrimitive[ iVtxTop](1) * fStretchX + dx,
- theApp.m_vfpCurrent.vfp_fYMax,
- theApp.m_vfpCurrent.vfp_avVerticesOnBaseOfPrimitive[ iVtxTop](3) * fStretchY + dz);
- }
- if( (fStretchX != 0.0f) && (fStretchY != 0.0f) )
- {
- AddPolygon( vtxCt, avTopPolygon, !_bClosed);
- }
- // side polygons
- DOUBLE3D *avSidePolygon = new DOUBLE3D[ 4];
- for( INDEX iBaseVtx=0; iBaseVtx<vtxCt; iBaseVtx++)
- {
- INDEX iNextVtx = (iBaseVtx+1) % vtxCt;
- avSidePolygon[ 0] = avBottomPolygon[ iBaseVtx];
- avSidePolygon[ 0](2) = theApp.m_vfpCurrent.vfp_fYMin;
- avSidePolygon[ 1] = avTopPolygon[ iBaseVtx];
- avSidePolygon[ 1](2) = theApp.m_vfpCurrent.vfp_fYMax;
- avSidePolygon[ 2] = avTopPolygon[ iNextVtx];
- avSidePolygon[ 2](2) = theApp.m_vfpCurrent.vfp_fYMax;
- avSidePolygon[ 3] = avBottomPolygon[ iNextVtx];
- avSidePolygon[ 3](2) = theApp.m_vfpCurrent.vfp_fYMin;
- // get lenght of base edge
- DOUBLE fEdgeLenght =
- (theApp.m_vfpCurrent.vfp_avVerticesOnBaseOfPrimitive[ 1] -
- theApp.m_vfpCurrent.vfp_avVerticesOnBaseOfPrimitive[ 0]).Length();
- // calculate how many times we wrapped (tiled) one texture
- INDEX iWrappedTimes = INDEX( (iBaseVtx * fEdgeLenght) / _fTextureWidth);
- // prepare vector of mapping translation (allign to left)
- DOUBLE3D f3dMappingTranslation = avSidePolygon[ 0];
- // add primitive-texture height difference to start from top
- f3dMappingTranslation -= DOUBLE3D( 0.0f, fHeight-_fTextureHeight, 0.0f);
- // calculate last edge's mapping remainings for "continous" mapping
- DOUBLE fMappingRemaining = iBaseVtx*fEdgeLenght - iWrappedTimes*_fTextureWidth;
- // calculate edge vector going from end toward start vertice of base edge
- DOUBLE3D f3dEdge = avSidePolygon[ 3] - avSidePolygon[ 0];
- // normalize it
- f3dEdge.Normalize();
- // multiply it with mapping remaining value
- f3dEdge *= fMappingRemaining;
- // add its influence into mapping translation vector
- f3dMappingTranslation += f3dEdge;
- // create polygons on side of conus
- AddPolygon( 4, avSidePolygon, _bClosed, f3dMappingTranslation);
- }
- delete avBottomPolygon;
- delete avTopPolygon;
- delete avSidePolygon;
- theApp.m_vfpCurrent.vfp_o3dPrimitive.Optimize();
- ConvertObject3DToBrush(theApp.m_vfpCurrent.vfp_o3dPrimitive);
- }
- void CWorldEditorDoc::CreateTorusPrimitive(void)
- {
- /*
- // report it
- _RPT0(_CRT_WARN, "\nTorus\n");
- */
- // get count of vertices that will be used for creating base polygon
- INDEX vtxCt = theApp.m_vfpCurrent.vfp_avVerticesOnBaseOfPrimitive.Count();
- // get torus parameters
- INDEX iSlicesIn360 = theApp.m_vfpCurrent.vfp_iSlicesIn360;
- INDEX iNoOfSlices = theApp.m_vfpCurrent.vfp_iNoOfSlices;
- FLOAT fHeight = theApp.m_vfpCurrent.vfp_fYMax-theApp.m_vfpCurrent.vfp_fYMin;
- // clamp no of slices
- if(iNoOfSlices<1) iNoOfSlices=1;
- //if(iNoOfSlices>iSlicesIn360) iNoOfSlices=iSlicesIn360;
- DOUBLE3D **papvBases = new DOUBLE3D *[iNoOfSlices+1];
- DOUBLE3D vCenter = DOUBLE3D( theApp.m_vfpCurrent.vfp_fRadius, 0.0f, 0.0f);
- BOOL bInvert = _bClosed;
- // rotate base vertices to calculate torus slices
- INDEX iSlice=0;
- for( ; iSlice<iNoOfSlices+1; iSlice++)
- {
- // create rotation matrix
- ANGLE3D angSlice = ANGLE3D( 0, 0, AngleDeg( (360.0f/iSlicesIn360)*iSlice));
- if( theApp.m_vfpCurrent.vfp_fRadius>0.0f)
- {
- angSlice(3) = -angSlice(3);
- }
- DOUBLEmatrix3D matrixRot;
- matrixRot ^= angSlice;
- papvBases[iSlice] = new DOUBLE3D[vtxCt];
- // calculate vertex coordinates for each slice
- for(INDEX iBaseVtx=0; iBaseVtx<vtxCt; iBaseVtx++)
- {
- // create vector from center to rotating vertex
- DOUBLE3D vCT = theApp.m_vfpCurrent.vfp_avVerticesOnBaseOfPrimitive[ iBaseVtx]-vCenter;
- papvBases[iSlice][iBaseVtx] = vCT*matrixRot+vCenter;
- papvBases[iSlice][iBaseVtx](3) += iSlice*fHeight;
- }
- }
- if(iNoOfSlices!=iSlicesIn360 || fHeight!=0)
- {
- // create torus starting polygon
- AddPolygon( vtxCt, papvBases[0], bInvert);
- // create torus ending polygon
- AddPolygon( vtxCt, papvBases[iNoOfSlices], !bInvert);
- }
- DOUBLE3D avPolygonVertices[4];
- // create polygons on sides
- for(iSlice=0; iSlice<iNoOfSlices; iSlice++)
- {
- INDEX iNextSlice = (iSlice+1)%(iNoOfSlices+1);
- for(INDEX iVtx=0; iVtx<vtxCt; iVtx++)
- {
- INDEX iNextVtx = (iVtx+1)%vtxCt;
- avPolygonVertices[0] = papvBases[iSlice][iVtx];
- avPolygonVertices[1] = papvBases[iSlice][iNextVtx];
- avPolygonVertices[2] = papvBases[iNextSlice][iNextVtx];
- avPolygonVertices[3] = papvBases[iNextSlice][iVtx];
- AddPolygon( 4, avPolygonVertices, !bInvert);
- }
- }
- // free allocated arrays
- for( INDEX iFree=0; iFree<iNoOfSlices+1; iFree++)
- {
- delete papvBases[iFree];
- }
- delete papvBases;
- theApp.m_vfpCurrent.vfp_o3dPrimitive.Optimize();
- ConvertObject3DToBrush(theApp.m_vfpCurrent.vfp_o3dPrimitive);
- }
- void CWorldEditorDoc::CreateStaircasesPrimitive(void)
- {
- /*
- // report it
- _RPT0(_CRT_WARN, "\nStaircases\n");
- */
- // calculate height
- DOUBLE fWidth = theApp.m_vfpCurrent.vfp_fXMax-theApp.m_vfpCurrent.vfp_fXMin;
- if( fWidth < SNAP_FLOAT_GRID) fWidth = SNAP_FLOAT_GRID;
- DOUBLE fHeight = theApp.m_vfpCurrent.vfp_fYMax-theApp.m_vfpCurrent.vfp_fYMin;
- if( fHeight < SNAP_FLOAT_GRID) fHeight = SNAP_FLOAT_GRID;
- DOUBLE fLenght = (theApp.m_vfpCurrent.vfp_fZMax-theApp.m_vfpCurrent.vfp_fZMin);
- if( fLenght < SNAP_FLOAT_12) fLenght = SNAP_FLOAT_12;
-
- // get parameters for staircases
- INDEX iStairsIn360 = theApp.m_vfpCurrent.vfp_iSlicesIn360;
- INDEX iNoOfStairs = theApp.m_vfpCurrent.vfp_iNoOfSlices;
- DOUBLE fRadius = theApp.m_vfpCurrent.vfp_fRadius;
- DOUBLE angle = 360.0/iStairsIn360;
- DOUBLE angleAdd = 0.0;
- // if base is created inside circle
- if( theApp.m_vfpCurrent.vfp_bOuter && !theApp.m_vfpCurrent.vfp_bLinearStaircases)
- {
- fRadius = fRadius/Cos(FLOAT(angle/2));
- angleAdd = -angle/2.0;
- fWidth = fWidth/Cos(FLOAT(angle/2));
- }
- BOOL bTopSlope = theApp.m_vfpCurrent.vfp_iTopShape == 1;
- BOOL bTopCeiling = theApp.m_vfpCurrent.vfp_iTopShape == 2;
- BOOL bBottomSlope = theApp.m_vfpCurrent.vfp_iBottomShape == 1;
- BOOL bBottomFloor = theApp.m_vfpCurrent.vfp_iBottomShape == 2;
- DOUBLE3D **papvBases = new DOUBLE3D *[iNoOfStairs];
- DOUBLE3D vCenter = DOUBLE3D( 0.0f, 0.0f, 0.0f);
- BOOL bInvert = _bClosed;
- // rotate base vertices to calculate rotating staircases
- INDEX iStair=0;
- for( ; iStair<iNoOfStairs; iStair++)
- {
- // create rotation matrix
- ANGLE3D angRotation1;
- ANGLE3D angRotation2;
-
- if( fRadius>0.0f)
- {
- angRotation1 = ANGLE3D( -AngleDeg( FLOAT((angle)*iStair+angleAdd)), 0, 0);
- angRotation2 = ANGLE3D( -AngleDeg( FLOAT((angle)*(iStair+1)+angleAdd)), 0, 0);
- }
- else
- {
- angRotation1 = ANGLE3D( AngleDeg( FLOAT((angle)*iStair+angleAdd)), 0, 0);
- angRotation2 = ANGLE3D( AngleDeg( FLOAT((angle)*(iStair+1)+angleAdd)), 0, 0);
- }
-
- DOUBLEmatrix3D matrixRot1;
- matrixRot1 ^= angRotation1;
- DOUBLEmatrix3D matrixRot2;
- matrixRot2 ^= angRotation2;
- papvBases[iStair] = new DOUBLE3D[4];
- if( theApp.m_vfpCurrent.vfp_bLinearStaircases)
- {
- papvBases[iStair][0] = DOUBLE3D( -fWidth/2.0f, fHeight*iStair, -fLenght*iStair);
- papvBases[iStair][1] = DOUBLE3D( -fWidth/2.0f, fHeight*iStair, -fLenght*(iStair+1));
- papvBases[iStair][2] = DOUBLE3D( fWidth/2.0f, fHeight*iStair, -fLenght*(iStair+1));
- papvBases[iStair][3] = DOUBLE3D( fWidth/2.0f, fHeight*iStair, -fLenght*iStair);
- }
- else
- {
- // calculate vertex coordinates for each rotating stair base
- for(INDEX iBaseVtx=0; iBaseVtx<4; iBaseVtx++)
- {
- DOUBLE3D vCT1, vCT2;
- // create vector from center to rotating vertex
- if( fRadius>0.0f)
- {
- vCT1 = DOUBLE3D(-fRadius,0.0,0.0)-vCenter;
- vCT2 = DOUBLE3D(-fRadius+fWidth,0.0,0.0)-vCenter;
- }
- else
- {
- vCT1 = DOUBLE3D(-fRadius-fWidth,0.0,0.0)-vCenter;
- vCT2 = DOUBLE3D(-fRadius,0.0,0.0)-vCenter;
- }
- papvBases[iStair][3] = vCT2*matrixRot1+vCenter;
- papvBases[iStair][3](2) = fHeight*iStair;
- papvBases[iStair][2] = vCT2*matrixRot2+vCenter;
- papvBases[iStair][2](2) = fHeight*iStair;
- papvBases[iStair][1] = vCT1*matrixRot2+vCenter;
- papvBases[iStair][1](2) = fHeight*iStair;
- papvBases[iStair][0] = vCT1*matrixRot1+vCenter;
- papvBases[iStair][0](2) = fHeight*iStair;
- }
- }
- }
- DOUBLE3D avVtx[8];
- // create polygons of stairs
- for(iStair=0; iStair<iNoOfStairs; iStair++)
- {
- // add only first front polygon if rest are eaten by stairs material
- BOOL bAddFrontVerticalPolygon = TRUE;
- if( (bTopSlope || bTopCeiling) && (iStair != 0) )
- bAddFrontVerticalPolygon = FALSE;
- // add only last back polygon if rest are eaten by stairs material
- BOOL bAddBackVerticalPolygon = TRUE;
- if( (bBottomSlope || bBottomFloor) && (iStair != (iNoOfStairs-1)) )
- bAddBackVerticalPolygon = FALSE;
- avVtx[0] = papvBases[iStair][0];
- avVtx[1] = papvBases[iStair][1];
- avVtx[2] = papvBases[iStair][2];
- avVtx[3] = papvBases[iStair][3];
- avVtx[4] = papvBases[iStair][0];
- avVtx[4](2) += fHeight;
- avVtx[5] = papvBases[iStair][1];
- avVtx[5](2) += fHeight;
- avVtx[6] = papvBases[iStair][2];
- avVtx[6](2) += fHeight;
- avVtx[7] = papvBases[iStair][3];
- avVtx[7](2) += fHeight;
- // if bottom shape is slope
- if( bBottomSlope)
- {
- avVtx[1](2) += fHeight;
- avVtx[2](2) += fHeight;
- }
- // if top shape is slope
- if( bTopSlope)
- {
- avVtx[5](2) += fHeight;
- avVtx[6](2) += fHeight;
- }
- DOUBLE3D avPolygon[4];
- avPolygon[0] = avVtx[0];
- avPolygon[1] = avVtx[1];
- avPolygon[2] = avVtx[5];
- avPolygon[3] = avVtx[4];
- // if bottom shape is floor
- if( bBottomFloor)
- {
- avPolygon[0](2) = 0.0;
- avPolygon[1](2) = 0.0;
- }
- // if top shape is ceiling
- if( bTopCeiling)
- {
- avPolygon[2](2) = fHeight*iNoOfStairs;
- avPolygon[3](2) = fHeight*iNoOfStairs;
- }
- AddPolygon( 4, avPolygon, !bInvert);
- avPolygon[0] = avVtx[3];
- avPolygon[1] = avVtx[2];
- avPolygon[2] = avVtx[6];
- avPolygon[3] = avVtx[7];
- // if bottom shape is floor
- if( bBottomFloor)
- {
- avPolygon[0](2) = 0.0;
- avPolygon[1](2) = 0.0;
- }
- // if top shape is ceiling
- if( bTopCeiling)
- {
- avPolygon[2](2) = fHeight*iNoOfStairs;
- avPolygon[3](2) = fHeight*iNoOfStairs;
- }
- AddPolygon( 4, avPolygon, bInvert);
- if( bAddFrontVerticalPolygon)
- {
- avPolygon[0] = avVtx[0];
- avPolygon[1] = avVtx[4];
- avPolygon[2] = avVtx[7];
- avPolygon[3] = avVtx[3];
- // if top shape is ceiling
- if( bTopCeiling)
- {
- avPolygon[1](2) = fHeight*iNoOfStairs;
- avPolygon[2](2) = fHeight*iNoOfStairs;
- }
- AddPolygon( 4, avPolygon, !bInvert);
- }
- // if bottom shape is slope, top is stairs, don't create polygon because its area is 0
- if( !(bBottomSlope && !bTopSlope) && bAddBackVerticalPolygon)
- {
- avPolygon[0] = avVtx[1];
- avPolygon[1] = avVtx[5];
- avPolygon[2] = avVtx[6];
- avPolygon[3] = avVtx[2];
- if( bBottomFloor)
- {
- avPolygon[0](2) = 0.0;
- avPolygon[3](2) = 0.0;
- }
- AddPolygon( 4, avPolygon, bInvert);
- }
- // if top shape is slope
- if( bTopSlope == 1)
- {
- avPolygon[0] = avVtx[4];
- avPolygon[1] = avVtx[6];
- avPolygon[2] = avVtx[7];
- AddPolygon( 3, avPolygon, !bInvert);
- avPolygon[0] = avVtx[4];
- avPolygon[1] = avVtx[5];
- avPolygon[2] = avVtx[6];
- AddPolygon( 3, avPolygon, !bInvert);
- }
- else
- {
- avPolygon[0] = avVtx[4];
- avPolygon[1] = avVtx[5];
- avPolygon[2] = avVtx[6];
- avPolygon[3] = avVtx[7];
- // if top shape is ceiling
- if( bTopCeiling)
- {
- avPolygon[0](2) = fHeight*iNoOfStairs;
- avPolygon[1](2) = fHeight*iNoOfStairs;
- avPolygon[2](2) = fHeight*iNoOfStairs;
- avPolygon[3](2) = fHeight*iNoOfStairs;
- }
- AddPolygon( 4, avPolygon, !bInvert);
- }
- // if bottom shape is slope
- if( bBottomSlope == 1)
- {
- avPolygon[0] = avVtx[0];
- avPolygon[1] = avVtx[2];
- avPolygon[2] = avVtx[3];
- AddPolygon( 3, avPolygon, bInvert);
- avPolygon[0] = avVtx[0];
- avPolygon[1] = avVtx[1];
- avPolygon[2] = avVtx[2];
- AddPolygon( 3, avPolygon, bInvert);
- }
- else
- {
- avPolygon[0] = avVtx[0];
- avPolygon[1] = avVtx[1];
- avPolygon[2] = avVtx[2];
- avPolygon[3] = avVtx[3];
- // if bottom shape is floor
- if( bBottomFloor)
- {
- avPolygon[0](2) = 0.0;
- avPolygon[1](2) = 0.0;
- avPolygon[2](2) = 0.0;
- avPolygon[3](2) = 0.0;
- }
- AddPolygon( 4, avPolygon, bInvert);
- }
- }
- // free allocated arrays
- for( INDEX iFree=0; iFree<iNoOfStairs; iFree++)
- {
- delete papvBases[iFree];
- }
- delete papvBases;
- theApp.m_vfpCurrent.vfp_o3dPrimitive.Optimize();
- ConvertObject3DToBrush(theApp.m_vfpCurrent.vfp_o3dPrimitive);
- }
- void CWorldEditorDoc::CreateSpherePrimitive(void)
- {
- // calculate width, lenght and height but as radiuses !!! (divided by 2)
- DOUBLE fWidth = (theApp.m_vfpCurrent.vfp_fXMax-theApp.m_vfpCurrent.vfp_fXMin)/2.0;
- if( fWidth < SNAP_FLOAT_GRID) fWidth = SNAP_FLOAT_GRID;
- DOUBLE fHeight = (theApp.m_vfpCurrent.vfp_fYMax-theApp.m_vfpCurrent.vfp_fYMin)/2.0;
- if( fHeight < SNAP_FLOAT_GRID) fHeight = SNAP_FLOAT_GRID;
- DOUBLE fLenght = (theApp.m_vfpCurrent.vfp_fZMax-theApp.m_vfpCurrent.vfp_fZMin)/2.0;
- if( fLenght < SNAP_FLOAT_12) fLenght = SNAP_FLOAT_12;
- // get parameters for staircases
- INDEX iMeridians = theApp.m_vfpCurrent.vfp_iMeridians;
- INDEX iParalels = theApp.m_vfpCurrent.vfp_iParalels;
- BOOL bInvert = _bClosed;
-
- // calculate bases
- DOUBLE3D **papvSlices = new DOUBLE3D *[iParalels+1];
- ANGLE angleSliceDelta = AngleDeg(180.0f)/iParalels;
- ANGLE angleSlice = -90.0f;
- // calculate all slices on sphere
- INDEX iSlice=0;
- for( ; iSlice<iParalels+1; iSlice++)
- {
- DOUBLE fSliceHeight, dA, dB;
- // if equal slices
- if( theApp.m_vfpCurrent.vfp_bLinearStaircases)
- {
- fSliceHeight = -fHeight + (fHeight*2/iParalels*iSlice);
- }
- else
- {
- fSliceHeight = Sin( angleSlice) * fHeight;
- }
- // snap X coordinate (1 cm)
- //Snap(fSliceHeight, SNAP_DOUBLE_CM);
- // calculate width and lenght of elipse for current slice
- dA = sqrt((fWidth*fWidth*fHeight*fHeight-
- fWidth*fWidth*fSliceHeight*fSliceHeight)/(fHeight*fHeight));
- dB = sqrt((fLenght*fLenght*fHeight*fHeight-
- fLenght*fLenght*fSliceHeight*fSliceHeight)/(fHeight*fHeight));
-
- // array for vertices of this slice
- papvSlices[iSlice] = new DOUBLE3D[iMeridians];
- ANGLE angle = AngleDeg(360.0f)/iMeridians;
- ANGLE angleCt = 0;
- for( INDEX iVtx=0; iVtx<iMeridians; iVtx++)
- {
- DOUBLE x = Cos( angleCt) * dA + (theApp.m_vfpCurrent.vfp_fXMin+theApp.m_vfpCurrent.vfp_fXMax)/2.0f;
- DOUBLE z = Sin( angleCt) * dB + (theApp.m_vfpCurrent.vfp_fZMin+theApp.m_vfpCurrent.vfp_fZMax)/2.0f;
- // snap X coordinate (1 cm)
- //Snap(x, SNAP_DOUBLE_CM);
- // snap Y coordinate (1 cm)
- //Snap(z, SNAP_DOUBLE_CM);
- papvSlices[iSlice][iVtx] = DOUBLE3D( x, fSliceHeight, z);
- angleCt += angle;
- }
- angleSlice += angleSliceDelta;
- }
- DOUBLE3D avPolygon[4];
- // create polygons
- for( iSlice=0; iSlice<iParalels; iSlice++)
- {
- INDEX iNextSlice = iSlice+1;
- for( INDEX iVtx=0; iVtx<iMeridians; iVtx++)
- {
- INDEX iNextVtx = (iVtx+1)%iMeridians;
- if (iSlice == 0) {
- avPolygon[0] = papvSlices[iNextSlice][iVtx];
- avPolygon[1] = papvSlices[iNextSlice][iNextVtx];
- avPolygon[2] = papvSlices[iSlice][0];
- AddPolygon( 3, avPolygon, bInvert);
- } else if (iSlice == iParalels-1) {
- avPolygon[0] = papvSlices[iNextSlice][0];
- avPolygon[1] = papvSlices[iSlice][iNextVtx];
- avPolygon[2] = papvSlices[iSlice][iVtx];
- AddPolygon( 3, avPolygon, bInvert);
- } else {
- avPolygon[0] = papvSlices[iNextSlice][iVtx];
- avPolygon[1] = papvSlices[iNextSlice][iNextVtx];
- avPolygon[2] = papvSlices[iSlice][iNextVtx];
- avPolygon[3] = papvSlices[iSlice][iVtx];
- AddPolygon( 4, avPolygon, bInvert);
- }
- }
- }
- // free allocated arrays
- for( INDEX iFree=0; iFree<iParalels+1; iFree++)
- {
- delete papvSlices[iFree];
- }
- delete papvSlices;
- theApp.m_vfpCurrent.vfp_o3dPrimitive.Optimize();
- ConvertObject3DToBrush(theApp.m_vfpCurrent.vfp_o3dPrimitive);
- }
- void InitializeObject3DForPrimitive(void)
- {
- // clear Object3D that will be used for creating primitive
- theApp.m_vfpCurrent.vfp_o3dPrimitive.Clear();
- // create sector
- _poscSector = theApp.m_vfpCurrent.vfp_o3dPrimitive.ob_aoscSectors.New(1);
- _poscSector->osc_colColor = theApp.m_vfpCurrent.vfp_colSectorsColor;
- // create material
- _pomMaterial = _poscSector->osc_aomtMaterials.New(1);
- _pPrimitiveTexture = theApp.m_ptdActiveTexture;
- _fTextureWidth = METERS_MEX( _pPrimitiveTexture->GetWidth());
- _fTextureHeight = METERS_MEX( _pPrimitiveTexture->GetHeight());
- *_pomMaterial = CObjectMaterial( _pPrimitiveTexture->GetName());
- _pomMaterial->SetColor( theApp.m_vfpCurrent.vfp_colPolygonsColor);
- // Pick up primitive-related variables
- _bClosed = theApp.m_vfpCurrent.vfp_bClosed;
- _bAutoCreateMipBrushes = theApp.m_vfpCurrent.vfp_bAutoCreateMipBrushes;
- }
- void GetTerrainPolygonEdges(CObjectSector &osec, INDEX iPolygon, INDEX iSlicesX, INDEX iSlicesZ,
- CObjectEdge *&poe0, CObjectEdge *&poe1, CObjectEdge *&poe2,
- CObjectEdge *&poe3, CObjectEdge *&poe4);
- void CWorldEditorDoc::CreateTerrainPrimitive(void)
- {
- CImageInfo iiDisplace;
- CImageInfo *piiDisplace = &iiDisplace;
- if( theApp.m_vfpCurrent.vfp_fnDisplacement != "")
- {
- try
- {
- iiDisplace.LoadAnyGfxFormat_t( theApp.m_vfpCurrent.vfp_fnDisplacement);
- m_slDisplaceTexTime=GetFileTimeStamp_t(theApp.m_vfpCurrent.vfp_fnDisplacement);
- }
- catch( char *strError)
- {
- (void) strError;
- piiDisplace = NULL;
- }
- }
- else
- {
- piiDisplace = NULL;
- }
-
- // get parameters for slices
- INDEX iSlicesX = theApp.m_vfpCurrent.vfp_iSlicesPerWidth;
- if( iSlicesX < 1) iSlicesX = 1;
- INDEX iSlicesZ = theApp.m_vfpCurrent.vfp_iSlicesPerHeight;
- if( iSlicesZ < 1) iSlicesZ = 1;
- INDEX iMip=0;
- // auto create mip brushes
- while( iSlicesX>=1 && iSlicesZ>=1 && ((iMip==0)||_bAutoCreateMipBrushes))
- {
- CreateTerrainObject3D( piiDisplace, iSlicesX, iSlicesZ, iMip);
- ConvertObject3DToBrush(theApp.m_vfpCurrent.vfp_o3dPrimitive, TRUE, iMip, 5.0f+iMip*1.5, FALSE);
- iSlicesX /= 2;
- iSlicesZ /= 2;
- iMip++;
- }
- }
- void CWorldEditorDoc::CreateTerrainObject3D( CImageInfo *piiDisplace, INDEX iSlicesX, INDEX iSlicesZ, INDEX iMip)
- {
- // calculate width, lenght and heigth
- DOUBLE fWidth = (theApp.m_vfpCurrent.vfp_fXMax-theApp.m_vfpCurrent.vfp_fXMin);
- if( fWidth < SNAP_FLOAT_GRID) fWidth = SNAP_FLOAT_GRID;
- DOUBLE fHeight = (theApp.m_vfpCurrent.vfp_fYMax-theApp.m_vfpCurrent.vfp_fYMin);
- if( fHeight < SNAP_FLOAT_GRID) fHeight = SNAP_FLOAT_GRID;
- DOUBLE fLenght = (theApp.m_vfpCurrent.vfp_fZMax-theApp.m_vfpCurrent.vfp_fZMin);
- if( fLenght < SNAP_FLOAT_12) fLenght = SNAP_FLOAT_12;
-
- DOUBLE fMinX = theApp.m_vfpCurrent.vfp_fXMin;
- DOUBLE fMaxX = theApp.m_vfpCurrent.vfp_fXMax;
- DOUBLE fMinY = theApp.m_vfpCurrent.vfp_fYMin;
- DOUBLE fMaxY = theApp.m_vfpCurrent.vfp_fYMax;
- DOUBLE fMinZ = theApp.m_vfpCurrent.vfp_fZMin;
- DOUBLE fMaxZ = theApp.m_vfpCurrent.vfp_fZMax;
- DOUBLE fDX = fWidth/iSlicesX;
- DOUBLE fDZ = fLenght/iSlicesZ;
- FLOAT fAmplitude = theApp.m_vfpCurrent.vfp_fAmplitude;
- ULONG ulNonFllorPolygonFlags = BPOF_FULLBRIGHT|BPOF_DETAILPOLYGON|BPOF_PORTAL;
- if( !_bClosed)
- {
- // swap min and max y coordinates
- FLOAT fTemp = fMinY;
- fMinY = fMaxY;
- fMaxY = fTemp;
- ulNonFllorPolygonFlags = BPOF_FULLBRIGHT|BPOF_DETAILPOLYGON;
- }
- // initialize object 3D
- InitializeObject3DForPrimitive();
- // get sector reference
- CObjectSector &osec = *_poscSector;
- INDEX ctVertices = (iSlicesX+1)*(iSlicesZ+1)+4;
- osec.osc_aovxVertices.New(ctVertices);
- osec.osc_aovxVertices.Lock();
- // create 'floor' vertices
- {for( INDEX iz=0; iz<=iSlicesZ; iz++) {
- {for( INDEX ix=0; ix<=iSlicesX; ix++) {
- INDEX iVtx = iz*(iSlicesX+1)+ix;
- CObjectVertex &ov = osec.osc_aovxVertices[iVtx];
- ov = DOUBLE3D(fMinX+fDX*ix, fMinY, fMinZ+fDZ*iz);
- DisplaceVertex( ov, piiDisplace, fMinX, fMaxX, fMinZ, fMaxZ, iSlicesX, iSlicesZ, fAmplitude);
- }}
- }}
- // create four 'ceiling' vertices
- #define START_OF_CEILING_VERTICES ((iSlicesX+1)*(iSlicesZ+1))
- INDEX iVtx = START_OF_CEILING_VERTICES;
- osec.osc_aovxVertices[iVtx+0] = DOUBLE3D(fMinX, fMaxY, fMaxZ);
- osec.osc_aovxVertices[iVtx+1] = DOUBLE3D(fMaxX, fMaxY, fMaxZ);
- osec.osc_aovxVertices[iVtx+2] = DOUBLE3D(fMaxX, fMaxY, fMinZ);
- osec.osc_aovxVertices[iVtx+3] = DOUBLE3D(fMinX, fMaxY, fMinZ);
- // allocate edges
- INDEX ctEdges = iSlicesX*(iSlicesZ+1)+iSlicesZ*(iSlicesX+1)+iSlicesX*iSlicesZ+8;
- osec.osc_aoedEdges.New(ctEdges);
-
- // create edges from vertices
- osec.osc_aoedEdges.Lock();
- // create horizontal edges
- {for( INDEX iz=0; iz<iSlicesZ+1; iz++)
- {
- {for( INDEX ix=0; ix<iSlicesX; ix++)
- {
- INDEX iVtx1 = iz*(iSlicesX+1)+ix;
- INDEX iEdg = iz*iSlicesX+ix;
- CObjectEdge &oedg = osec.osc_aoedEdges[iEdg];
- oedg.oed_Vertex0 = &osec.osc_aovxVertices[iVtx1];
- oedg.oed_Vertex1 = &osec.osc_aovxVertices[iVtx1+1];
- }
- }
- }}
- // create vertical edges
- #define START_OF_VERTICAL_EDGES (iSlicesX*(iSlicesZ+1))
- {for( INDEX iz=0; iz<iSlicesZ; iz++)
- {
- {for( INDEX ix=0; ix<iSlicesX+1; ix++)
- {
- INDEX iVtx1 = iz*(iSlicesX+1)+ix;
- INDEX iEdg = START_OF_VERTICAL_EDGES + iz*(iSlicesX+1)+ix;
- CObjectEdge &oedg = osec.osc_aoedEdges[iEdg];
- oedg.oed_Vertex0 = &osec.osc_aovxVertices[iVtx1];
- oedg.oed_Vertex1 = &osec.osc_aovxVertices[iVtx1+(iSlicesX+1)];
- }
- }
- }}
- // create slope edges
- #define START_OF_SLOPE_EDGES (iSlicesX*(iSlicesZ+1)+(iSlicesX+1)*iSlicesZ)
- {for( INDEX iz=0; iz<iSlicesZ; iz++)
- {
- {for( INDEX ix=0; ix<iSlicesX; ix++)
- {
- INDEX iVtx1 = iz*(iSlicesX+1)+ix;
- INDEX iEdg = START_OF_SLOPE_EDGES + iz*iSlicesX+ix;
- CObjectEdge &oedg = osec.osc_aoedEdges[iEdg];
- oedg.oed_Vertex0 = &osec.osc_aovxVertices[iVtx1];
- oedg.oed_Vertex1 = &osec.osc_aovxVertices[iVtx1+iSlicesX+1+1];
- }
- }
- }}
- // create border edges
- #define START_OF_BORDER_EDGES (iSlicesX*(iSlicesZ+1)+(iSlicesX+1)*iSlicesZ+iSlicesX*iSlicesZ)
- {
- // 0
- INDEX iEdg = START_OF_BORDER_EDGES + 0;
- CObjectEdge &oedg = osec.osc_aoedEdges[iEdg];
- INDEX iVtx0 = (iSlicesX+1)*iSlicesZ;
- oedg.oed_Vertex0 = &osec.osc_aovxVertices[iVtx0];
- oedg.oed_Vertex1 = &osec.osc_aovxVertices[START_OF_CEILING_VERTICES+0];
- }
- {
- // 1
- INDEX iEdg = START_OF_BORDER_EDGES + 1;
- CObjectEdge &oedg = osec.osc_aoedEdges[iEdg];
- INDEX iVtx0 = (iSlicesX+1)*(iSlicesZ+1)-1;
- oedg.oed_Vertex0 = &osec.osc_aovxVertices[iVtx0];
- oedg.oed_Vertex1 = &osec.osc_aovxVertices[START_OF_CEILING_VERTICES+1];
- }
- {
- // 2
- INDEX iEdg = START_OF_BORDER_EDGES + 2;
- CObjectEdge &oedg = osec.osc_aoedEdges[iEdg];
- INDEX iVtx0 = iSlicesX;
- oedg.oed_Vertex0 = &osec.osc_aovxVertices[iVtx0];
- oedg.oed_Vertex1 = &osec.osc_aovxVertices[START_OF_CEILING_VERTICES+2];
- }
- {
- // 3
- INDEX iEdg = START_OF_BORDER_EDGES + 3;
- CObjectEdge &oedg = osec.osc_aoedEdges[iEdg];
- INDEX iVtx0 = 0;
- oedg.oed_Vertex0 = &osec.osc_aovxVertices[iVtx0];
- oedg.oed_Vertex1 = &osec.osc_aovxVertices[START_OF_CEILING_VERTICES+3];
- }
- // create ceiling edges
- #define START_OF_CEILING_EDGES (START_OF_BORDER_EDGES + 4)
- {
- // 0
- INDEX iEdg = START_OF_CEILING_EDGES + 0;
- CObjectEdge &oedg = osec.osc_aoedEdges[iEdg];
- oedg.oed_Vertex0 = &osec.osc_aovxVertices[START_OF_CEILING_VERTICES];
- oedg.oed_Vertex1 = &osec.osc_aovxVertices[START_OF_CEILING_VERTICES+1];
- }
- {
- // 1
- INDEX iEdg = START_OF_CEILING_EDGES + 1;
- CObjectEdge &oedg = osec.osc_aoedEdges[iEdg];
- oedg.oed_Vertex0 = &osec.osc_aovxVertices[START_OF_CEILING_VERTICES+1];
- oedg.oed_Vertex1 = &osec.osc_aovxVertices[START_OF_CEILING_VERTICES+2];
- }
- {
- // 2
- INDEX iEdg = START_OF_CEILING_EDGES + 2;
- CObjectEdge &oedg = osec.osc_aoedEdges[iEdg];
- oedg.oed_Vertex0 = &osec.osc_aovxVertices[START_OF_CEILING_VERTICES+2];
- oedg.oed_Vertex1 = &osec.osc_aovxVertices[START_OF_CEILING_VERTICES+3];
- }
- {
- // 3
- INDEX iEdg = START_OF_CEILING_EDGES + 3;
- CObjectEdge &oedg = osec.osc_aoedEdges[iEdg];
- oedg.oed_Vertex0 = &osec.osc_aovxVertices[START_OF_CEILING_VERTICES+3];
- oedg.oed_Vertex1 = &osec.osc_aovxVertices[START_OF_CEILING_VERTICES+0];
- }
- // get material
- CObjectMaterial &omat = *_pomMaterial;
- // allocate polygons and their planes
- INDEX ctPolygons = iSlicesX*iSlicesZ*2+4+1;
- osec.osc_aopoPolygons.New(ctPolygons);
- osec.osc_aoplPlanes.New(ctPolygons);
-
- osec.osc_aopoPolygons.Lock();
- osec.osc_aoplPlanes.Lock();
- // create floor polygons and their planes
- for( INDEX iPolygon=0; iPolygon<iSlicesX*iSlicesZ; iPolygon++)
- {
- // obtain edges of one broken checked polygon
- CObjectEdge *poe0, *poe1, *poe2, *poe3, *poe4;
- GetTerrainPolygonEdges(osec, iPolygon, iSlicesX, iSlicesZ, poe0, poe1, poe2, poe3, poe4);
- {
- // create upper polygon
- CObjectPlane &opl = osec.osc_aoplPlanes[iPolygon*2+0];
- opl = DOUBLEplane3D( *poe3->oed_Vertex1, *poe3->oed_Vertex0, *poe0->oed_Vertex0);
- CObjectPolygon &opo = osec.osc_aopoPolygons[iPolygon*2+0];
- opo.opo_Plane = &opl;
- // set polygon edges
- opo.opo_PolygonEdges.New(3);
- opo.opo_PolygonEdges.Lock();
- opo.opo_PolygonEdges[0].ope_Edge = poe0;
- opo.opo_PolygonEdges[0].ope_Backward = TRUE;
- opo.opo_PolygonEdges[1].ope_Edge = poe4;
- opo.opo_PolygonEdges[1].ope_Backward = FALSE;
- opo.opo_PolygonEdges[2].ope_Edge = poe3;
- opo.opo_PolygonEdges[2].ope_Backward = TRUE;
- opo.opo_PolygonEdges.Unlock();
- // set other polygon properties
- opo.opo_Material = &omat;
- opo.opo_ulFlags = BPOF_FULLBRIGHT|BPOF_DETAILPOLYGON;
- opo.opo_colorColor = theApp.m_vfpCurrent.vfp_colPolygonsColor;
- }
- {
- // create lower polygon
- CObjectPlane &opl = osec.osc_aoplPlanes[iPolygon*2+1];
- opl = DOUBLEplane3D( *poe1->oed_Vertex0, *poe1->oed_Vertex1, *poe2->oed_Vertex1);
- CObjectPolygon &opo = osec.osc_aopoPolygons[iPolygon*2+1];
- opo.opo_Plane = &opl;
- // set polygon edges
- opo.opo_PolygonEdges.New(3);
- opo.opo_PolygonEdges.Lock();
- opo.opo_PolygonEdges[0].ope_Edge = poe1;
- opo.opo_PolygonEdges[0].ope_Backward = FALSE;
- opo.opo_PolygonEdges[1].ope_Edge = poe2;
- opo.opo_PolygonEdges[1].ope_Backward = FALSE;
- opo.opo_PolygonEdges[2].ope_Edge = poe4;
- opo.opo_PolygonEdges[2].ope_Backward = TRUE;
- opo.opo_PolygonEdges.Unlock();
- // set other polygon properties
- opo.opo_Material = &omat;
- opo.opo_ulFlags = BPOF_FULLBRIGHT|BPOF_DETAILPOLYGON;
- opo.opo_colorColor = theApp.m_vfpCurrent.vfp_colPolygonsColor;
- }
- }
- // create side polygons and their planes
- #define START_OF_SIDE_POLYGONS (iSlicesX*iSlicesZ*2)
- {
- // side polygon 0
- CObjectPolygon &opo = osec.osc_aopoPolygons[START_OF_SIDE_POLYGONS+0];
- CObjectEdge &oe0 = osec.osc_aoedEdges[ START_OF_BORDER_EDGES+0];
- CObjectEdge &oe1 = osec.osc_aoedEdges[ START_OF_CEILING_EDGES+0];
- CObjectPlane &opl = osec.osc_aoplPlanes[START_OF_SIDE_POLYGONS+0];
- opl = DOUBLEplane3D( *oe0.oed_Vertex0, *oe0.oed_Vertex1, *oe1.oed_Vertex1);
- opo.opo_Plane = &opl;
- opo.opo_PolygonEdges.New(iSlicesX+3);
- opo.opo_PolygonEdges.Lock();
- INDEX iEdg=0;
- for( ; iEdg<iSlicesX; iEdg++)
- {
- INDEX iEdgeIdx = iSlicesX*iSlicesZ+iEdg;
- opo.opo_PolygonEdges[iEdg].ope_Edge = &osec.osc_aoedEdges[ iEdgeIdx];
- opo.opo_PolygonEdges[iEdg].ope_Backward = TRUE;
- }
- opo.opo_PolygonEdges[iEdg+0].ope_Edge = &osec.osc_aoedEdges[ START_OF_BORDER_EDGES+0];
- opo.opo_PolygonEdges[iEdg+0].ope_Backward = FALSE;
- opo.opo_PolygonEdges[iEdg+1].ope_Edge = &osec.osc_aoedEdges[ START_OF_CEILING_EDGES+0];
- opo.opo_PolygonEdges[iEdg+1].ope_Backward = FALSE;
- opo.opo_PolygonEdges[iEdg+2].ope_Edge = &osec.osc_aoedEdges[ START_OF_BORDER_EDGES+1];
- opo.opo_PolygonEdges[iEdg+2].ope_Backward = TRUE;
- opo.opo_Material = &omat;
- opo.opo_ulFlags = ulNonFllorPolygonFlags;
- opo.opo_colorColor = theApp.m_vfpCurrent.vfp_colPolygonsColor;
- opo.opo_PolygonEdges.Unlock();
- }
- {
- // side polygon 1
- CObjectPolygon &opo = osec.osc_aopoPolygons[START_OF_SIDE_POLYGONS+1];
- CObjectEdge &oe0 = osec.osc_aoedEdges[ START_OF_BORDER_EDGES+1];
- CObjectEdge &oe1 = osec.osc_aoedEdges[ START_OF_CEILING_EDGES+1];
- CObjectPlane &opl = osec.osc_aoplPlanes[START_OF_SIDE_POLYGONS+1];
- opl = DOUBLEplane3D( *oe0.oed_Vertex0, *oe0.oed_Vertex1, *oe1.oed_Vertex1);
- opo.opo_Plane = &opl;
- opo.opo_PolygonEdges.New(iSlicesZ+3);
- opo.opo_PolygonEdges.Lock();
- INDEX iEdg=0;
- for( ; iEdg<iSlicesZ; iEdg++)
- {
- opo.opo_PolygonEdges[iEdg].ope_Edge = &osec.osc_aoedEdges[ START_OF_VERTICAL_EDGES+iSlicesX+iEdg*(iSlicesX+1)];
- opo.opo_PolygonEdges[iEdg].ope_Backward = FALSE;
- }
- opo.opo_PolygonEdges[iEdg+0].ope_Edge = &osec.osc_aoedEdges[ START_OF_BORDER_EDGES+1];
- opo.opo_PolygonEdges[iEdg+0].ope_Backward = FALSE;
- opo.opo_PolygonEdges[iEdg+1].ope_Edge = &osec.osc_aoedEdges[ START_OF_CEILING_EDGES+1];
- opo.opo_PolygonEdges[iEdg+1].ope_Backward = FALSE;
- opo.opo_PolygonEdges[iEdg+2].ope_Edge = &osec.osc_aoedEdges[ START_OF_BORDER_EDGES+2];
- opo.opo_PolygonEdges[iEdg+2].ope_Backward = TRUE;
- opo.opo_Material = &omat;
- opo.opo_ulFlags = ulNonFllorPolygonFlags;
- opo.opo_colorColor = theApp.m_vfpCurrent.vfp_colPolygonsColor;
- opo.opo_PolygonEdges.Unlock();
- }
- {
- // side polygon 2
- CObjectPolygon &opo = osec.osc_aopoPolygons[START_OF_SIDE_POLYGONS+2];
- CObjectEdge &oe0 = osec.osc_aoedEdges[ START_OF_BORDER_EDGES+2];
- CObjectEdge &oe1 = osec.osc_aoedEdges[ START_OF_CEILING_EDGES+2];
- CObjectPlane &opl = osec.osc_aoplPlanes[START_OF_SIDE_POLYGONS+2];
- opl = DOUBLEplane3D( *oe0.oed_Vertex0, *oe0.oed_Vertex1, *oe1.oed_Vertex1);
- opo.opo_Plane = &opl;
- opo.opo_PolygonEdges.New(iSlicesX+3);
- opo.opo_PolygonEdges.Lock();
- INDEX iEdg=0;
- for( ; iEdg<iSlicesX; iEdg++)
- {
- opo.opo_PolygonEdges[iEdg].ope_Edge = &osec.osc_aoedEdges[ iEdg];
- opo.opo_PolygonEdges[iEdg].ope_Backward = FALSE;
- }
- opo.opo_PolygonEdges[iEdg+0].ope_Edge = &osec.osc_aoedEdges[ START_OF_BORDER_EDGES+2];
- opo.opo_PolygonEdges[iEdg+0].ope_Backward = FALSE;
- opo.opo_PolygonEdges[iEdg+1].ope_Edge = &osec.osc_aoedEdges[ START_OF_CEILING_EDGES+2];
- opo.opo_PolygonEdges[iEdg+1].ope_Backward = FALSE;
- opo.opo_PolygonEdges[iEdg+2].ope_Edge = &osec.osc_aoedEdges[ START_OF_BORDER_EDGES+3];
- opo.opo_PolygonEdges[iEdg+2].ope_Backward = TRUE;
- opo.opo_Material = &omat;
- opo.opo_ulFlags = ulNonFllorPolygonFlags;
- opo.opo_colorColor = theApp.m_vfpCurrent.vfp_colPolygonsColor;
- opo.opo_PolygonEdges.Unlock();
- }
- {
- // side polygon 3
- CObjectPolygon &opo = osec.osc_aopoPolygons[START_OF_SIDE_POLYGONS+3];
- CObjectEdge &oe0 = osec.osc_aoedEdges[ START_OF_BORDER_EDGES+3];
- CObjectEdge &oe1 = osec.osc_aoedEdges[ START_OF_CEILING_EDGES+3];
- CObjectPlane &opl = osec.osc_aoplPlanes[START_OF_SIDE_POLYGONS+3];
- opl = DOUBLEplane3D( *oe0.oed_Vertex0, *oe0.oed_Vertex1, *oe1.oed_Vertex1);
- opo.opo_Plane = &opl;
- opo.opo_PolygonEdges.New(iSlicesZ+3);
- opo.opo_PolygonEdges.Lock();
- INDEX iEdg=0;
- for( ; iEdg<iSlicesZ; iEdg++)
- {
- opo.opo_PolygonEdges[iEdg].ope_Edge = &osec.osc_aoedEdges[ START_OF_VERTICAL_EDGES+iEdg*(iSlicesX+1)];
- opo.opo_PolygonEdges[iEdg].ope_Backward = TRUE;
- }
- opo.opo_PolygonEdges[iEdg+0].ope_Edge = &osec.osc_aoedEdges[ START_OF_BORDER_EDGES+3];
- opo.opo_PolygonEdges[iEdg+0].ope_Backward = FALSE;
- opo.opo_PolygonEdges[iEdg+1].ope_Edge = &osec.osc_aoedEdges[ START_OF_CEILING_EDGES+3];
- opo.opo_PolygonEdges[iEdg+1].ope_Backward = FALSE;
- opo.opo_PolygonEdges[iEdg+2].ope_Edge = &osec.osc_aoedEdges[ START_OF_BORDER_EDGES+0];
- opo.opo_PolygonEdges[iEdg+2].ope_Backward = TRUE;
- opo.opo_Material = &omat;
- opo.opo_ulFlags = ulNonFllorPolygonFlags;
- opo.opo_colorColor = theApp.m_vfpCurrent.vfp_colPolygonsColor;
- opo.opo_PolygonEdges.Unlock();
- }
- // create ceiling polygon and its plane
- #define CEILING_POLYGON (iSlicesX*iSlicesZ*2+4)
- {
- // ceiling polygon
- CObjectPolygon &opo = osec.osc_aopoPolygons[CEILING_POLYGON];
- CObjectEdge &oe0 = osec.osc_aoedEdges[ START_OF_CEILING_EDGES+0];
- CObjectEdge &oe1 = osec.osc_aoedEdges[ START_OF_CEILING_EDGES+1];
- CObjectPlane &opl = osec.osc_aoplPlanes[CEILING_POLYGON];
- opl = DOUBLEplane3D( *oe1.oed_Vertex1, *oe1.oed_Vertex0, *oe0.oed_Vertex0);
- opo.opo_Plane = &opl;
- opo.opo_PolygonEdges.New(4);
- opo.opo_PolygonEdges.Lock();
- opo.opo_PolygonEdges[0].ope_Edge = &osec.osc_aoedEdges[ START_OF_CEILING_EDGES+0];
- opo.opo_PolygonEdges[0].ope_Backward = TRUE;
- opo.opo_PolygonEdges[1].ope_Edge = &osec.osc_aoedEdges[ START_OF_CEILING_EDGES+1];
- opo.opo_PolygonEdges[1].ope_Backward = TRUE;
- opo.opo_PolygonEdges[2].ope_Edge = &osec.osc_aoedEdges[ START_OF_CEILING_EDGES+2];
- opo.opo_PolygonEdges[2].ope_Backward = TRUE;
- opo.opo_PolygonEdges[3].ope_Edge = &osec.osc_aoedEdges[ START_OF_CEILING_EDGES+3];
- opo.opo_PolygonEdges[3].ope_Backward = TRUE;
- opo.opo_Material = &omat;
- opo.opo_ulFlags = ulNonFllorPolygonFlags;
- opo.opo_colorColor = theApp.m_vfpCurrent.vfp_colPolygonsColor;
- opo.opo_PolygonEdges.Unlock();
- }
- osec.osc_aovxVertices.Unlock();
- osec.osc_aoedEdges.Unlock();
- osec.osc_aoplPlanes.Unlock();
- osec.osc_aopoPolygons.Unlock();
- theApp.m_vfpCurrent.vfp_o3dPrimitive.Optimize();
- }
- void GetTerrainPolygonEdges(CObjectSector &osec, INDEX iPolygon, INDEX iSlicesX, INDEX iSlicesZ,
- CObjectEdge *&poe0, CObjectEdge *&poe1, CObjectEdge *&poe2,
- CObjectEdge *&poe3, CObjectEdge *&poe4)
- {
- INDEX iPolX = iPolygon%iSlicesX;
- INDEX iPolZ = iPolygon/iSlicesX;
-
- INDEX iEdge0 = iPolZ*iSlicesX+iPolX;
- poe0 = &osec.osc_aoedEdges[ iEdge0];
-
- INDEX iEdge1 = START_OF_VERTICAL_EDGES+iPolZ*(iSlicesX+1)+iPolX;
- poe1 = &osec.osc_aoedEdges[ iEdge1];
-
- INDEX iEdge2 = iEdge0+iSlicesX;
- poe2 = &osec.osc_aoedEdges[ iEdge2];
-
- INDEX iEdge3 = iEdge1+1;
- poe3 = &osec.osc_aoedEdges[ iEdge3];
- INDEX iEdge4 = START_OF_SLOPE_EDGES+iPolZ*iSlicesX+iPolX;
- poe4 = &osec.osc_aoedEdges[ iEdge4];
- }
- void CWorldEditorDoc::CreatePrimitive(void)
- {
- // this is patch because deleting of primitive property page can call this
- if( m_iMode != CSG_MODE) return;
- // activ texture must exist
- ASSERT( theApp.m_ptdActiveTexture != NULL);
- InitializeObject3DForPrimitive();
- switch( theApp.m_vfpCurrent.vfp_ptPrimitiveType)
- {
- case PT_CONUS:
- case PT_TORUS:
- {
- // calculate width, height and lenght
- DOUBLE fWidth = theApp.m_vfpCurrent.vfp_fXMax-theApp.m_vfpCurrent.vfp_fXMin;
- DOUBLE fHeight = theApp.m_vfpCurrent.vfp_fYMax-theApp.m_vfpCurrent.vfp_fYMin;
- DOUBLE fLenght = theApp.m_vfpCurrent.vfp_fZMax-theApp.m_vfpCurrent.vfp_fZMin;
- // some values must be valid, so if they are not, coorect them
- if( fWidth < SNAP_FLOAT_GRID) fWidth = SNAP_FLOAT_GRID;
- if( fHeight < SNAP_FLOAT_GRID) fHeight = SNAP_FLOAT_GRID;
- if( fLenght < SNAP_FLOAT_GRID) fLenght = SNAP_FLOAT_GRID;
- // divide width and lenght by two because these values are used as radiuses
- fWidth /= 2.0f;
- fLenght/= 2.0f;
- // get count of vertices that will be used for creating base polygon
- INDEX vtxCt = theApp.m_vfpCurrent.vfp_avVerticesOnBaseOfPrimitive.Count();
- // if currently used number of vertices is not same as one used for last create primitive,
- // or if change occure in width or lenght
- if( (m_bPrimitiveCreatedFirstTime) ||
- (m_ctLastPrimitiveVertices != vtxCt) ||
- (m_fLastPrimitiveWidth != fWidth) ||
- (m_fLastPrimitiveLenght != fLenght) ||
- (m_bLastIfOuter != theApp.m_vfpCurrent.vfp_bOuter) ||
- (m_ttLastTriangularisationType != theApp.m_vfpCurrent.vfp_ttTriangularisationType) )
- {
- // recreate base vertices (discard vertex dragging)
- if( !_bDontRecalculateBase)
- {
- theApp.m_vfpCurrent.CalculatePrimitiveBase();
- }
- _bDontRecalculateBase = FALSE;
- // and remember new values for base, wait with recreating before any
- // change occure or until CSG operaton is applyed
- m_bPrimitiveCreatedFirstTime = FALSE;
- m_ctLastPrimitiveVertices = vtxCt;
- m_fLastPrimitiveWidth = fWidth;
- m_fLastPrimitiveLenght = fLenght;
- m_bLastIfOuter = theApp.m_vfpCurrent.vfp_bOuter;
- m_ttLastTriangularisationType = theApp.m_vfpCurrent.vfp_ttTriangularisationType;
- }
- // create primitive for the first time
- if( theApp.m_vfpCurrent.vfp_ptPrimitiveType == PT_CONUS)
- {
- CreateConusPrimitive();
- }
- else
- {
- CreateTorusPrimitive();
- }
- break;
- }
- case PT_STAIRCASES:
- {
- CreateStaircasesPrimitive();
- break;
- }
- case PT_SPHERE:
- {
- CreateSpherePrimitive();
- break;
- }
- case PT_TERRAIN:
- {
- CreateTerrainPrimitive();
- break;
- }
- default:
- {
- ASSERTALWAYS( "Invalid primitive type found!");
- }
- }
- // update position property page
- m_chSelections.MarkChanged();
- }
- /*
- * refresh primitive page
- */
- void CWorldEditorDoc::RefreshPrimitivePage(void)
- {
- CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
- // if info exists and active page is primitive page
- if( (pMainFrame->m_pInfoFrame != NULL) &&
- (pMainFrame->m_pInfoFrame->m_pInfoSheet->GetActivePage() ==
- &pMainFrame->m_pInfoFrame->m_pInfoSheet->m_PgPrimitive) )
- {
- // refresh primitive page
- pMainFrame->m_pInfoFrame->m_pInfoSheet->m_PgPrimitive.UpdateData( FALSE);
- }
- }
- /*
- * refresh position page
- */
- void CWorldEditorDoc::RefreshCurrentInfoPage(void)
- {
- CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
- // if info exists
- if( pMainFrame->m_pInfoFrame != NULL)
- {
- // if active page is position page
- if( pMainFrame->m_pInfoFrame->m_pInfoSheet->GetActivePage() ==
- &pMainFrame->m_pInfoFrame->m_pInfoSheet->m_PgPosition)
- {
- // refresh position page
- pMainFrame->m_pInfoFrame->m_pInfoSheet->m_PgPosition.UpdateData( FALSE);
- }
- // if active page is texture page
- else if( pMainFrame->m_pInfoFrame->m_pInfoSheet->GetActivePage() ==
- &pMainFrame->m_pInfoFrame->m_pInfoSheet->m_PgTexture)
- {
- // refresh polygon page
- pMainFrame->m_pInfoFrame->m_pInfoSheet->m_PgTexture.UpdateData( FALSE);
- }
- }
- }
- /*
- * snaps parameters for creating primitive to grid
- */
- void CWorldEditorDoc::SnapPrimitiveValuesToGrid(void)
- {
- /*
- SnapFloat( theApp.m_vfpCurrent.vfp_fShearX);
- SnapFloat( theApp.m_vfpCurrent.vfp_fShearZ);
- SnapFloat( theApp.m_vfpCurrent.vfp_fXMin);
- SnapFloat( theApp.m_vfpCurrent.vfp_fXMax);
- SnapFloat( theApp.m_vfpCurrent.vfp_fYMin);
- SnapFloat( theApp.m_vfpCurrent.vfp_fYMax);
- SnapFloat( theApp.m_vfpCurrent.vfp_fZMin);
- SnapFloat( theApp.m_vfpCurrent.vfp_fZMax);
- */
- }
- /*
- * Constructor.
- */
- CUndo::CUndo(void) // throw char *
- {
- static INDEX iUndoFile = 0; // counter for undo files
- static char achUndoFileName[256];
- // create a temporary file name
- sprintf(achUndoFileName, "Temp\\WED_Undo%d.tmp", iUndoFile);
- m_fnmUndoFile = CTString(achUndoFileName);
- // increment the counter of undo files
- iUndoFile++;
- }
- /*
- * Destructor.
- */
- CUndo::~CUndo(void)
- {
- // delete the temporary file
- RemoveFile(m_fnmUndoFile);
- }
- /*
- * Loads state of the world from given undo/redo object
- */
- void CWorldEditorDoc::LoadWorldFromUndoRedoList( CUndo *pUndoRedo)
- {
- // try to
- try
- {
- // load new world from the undo file
- m_woWorld.Load_t(pUndoRedo->m_fnmUndoFile);
- // m_woWorld.ReinitializeEntities();
- // flush stale caches
- _pShell->Execute("FreeUnusedStock();");
- // invalidate document (i.e. all views)
- UpdateAllViews( NULL);
- }
- // report errors
- catch( char *err_str)
- {
- AfxMessageBox( CString(err_str));
- }
- }
- /*
- * Saves current state of the world as tail of give undo/redo list
- */
- void CWorldEditorDoc::SaveWorldIntoUndoRedoList( CListHead &lhList)
- {
- // try to
- try
- {
- // allocate new undo/redo object
- CUndo *pUndoRedo = new CUndo;
- // save the world to the undo file
- m_woWorld.Save_t(pUndoRedo->m_fnmUndoFile);
- // add new undo as tail into undo list
- lhList.AddTail( pUndoRedo->m_lnListNode);
- }
- // report errors
- catch( char *err_str)
- {
- AfxMessageBox( CString(err_str));
- }
- }
- /*
- * Remebers last operation into undo buffer
- */
- void CWorldEditorDoc::RememberUndo(void)
- {
- // if undo remembering is disabled
- if( !theApp.m_bRememberUndo)
- {
- return;
- }
- // delete redo list
- FORDELETELIST(CUndo, m_lnListNode, m_lhRedo, itRedo)
- {
- delete &itRedo.Current();
- }
- // while there are more members in undo buffer than allowed or list isn't empty
- while( (m_lhUndo.Count() >= theApp.m_Preferences.ap_iUndoLevels) &&
- (!m_lhUndo.IsEmpty()) )
- {
- // get first member in undo list
- CUndo *pUndo = LIST_HEAD( m_lhUndo, CUndo, m_lnListNode);
- // remove it
- pUndo->m_lnListNode.Remove();
- // and delete it
- delete pUndo;
- }
-
- // if undo level is 0, don't remember any undo
- if( theApp.m_Preferences.ap_iUndoLevels == 0)
- {
- return;
- }
- // save current state of level into undo list
- SaveWorldIntoUndoRedoList( m_lhUndo);
- }
- /*
- * Undoes last operation
- */
- void CWorldEditorDoc::Undo(void)
- {
- // if undo level is 0, or undo list is empty, don't do any undo
- if( (theApp.m_Preferences.ap_iUndoLevels == 0) ||
- (m_lhUndo.IsEmpty()) )
- {
- return;
- }
- // clear selections
- ClearSelections();
- // get tail member from undo buffer
- CUndo *pUndo = LIST_TAIL( m_lhUndo, CUndo, m_lnListNode);
- // remove it from undo buffer
- pUndo->m_lnListNode.Remove();
- // save current state of level into redo list
- SaveWorldIntoUndoRedoList( m_lhRedo);
- // restore last saved state from undo list
- LoadWorldFromUndoRedoList( pUndo);
- // delete just used undo member
- delete pUndo;
- }
- /*
- * Redoes last operation
- */
- void CWorldEditorDoc::Redo(void)
- {
- // if redo list is empty, don't do any redo
- if( m_lhRedo.IsEmpty() )
- {
- return;
- }
-
- // clear selections
- ClearSelections();
- // get tail member from redo buffer
- CUndo *pRedo = LIST_TAIL( m_lhRedo, CUndo, m_lnListNode);
- // remove it from redo buffer
- pRedo->m_lnListNode.Remove();
-
- // save current state of level into undo list
- SaveWorldIntoUndoRedoList( m_lhUndo);
- // restore last saved state from redo list
- LoadWorldFromUndoRedoList( pRedo);
- // delete just used redo member
- delete pRedo;
- }
- void CWorldEditorDoc::OnEditUndo()
- {
- if( GetEditingMode()==TERRAIN_MODE)
- {
- if( m_iCurrentTerrainUndo>=0)
- {
- ApplyTerrainUndo(&m_dcTerrainUndo[m_iCurrentTerrainUndo]);
- }
- }
- else
- {
- Undo();
- }
- m_chDocument.MarkChanged();
- UpdateAllViews( NULL);
- }
- void CWorldEditorDoc::OnUpdateEditUndo(CCmdUI* pCmdUI)
- {
- if( GetEditingMode()==TERRAIN_MODE)
- {
- pCmdUI->Enable( m_iCurrentTerrainUndo>=0);
- }
- else
- {
- pCmdUI->Enable( !m_lhUndo.IsEmpty());
- }
- }
- void CWorldEditorDoc::OnEditRedo()
- {
- if( GetEditingMode()==TERRAIN_MODE)
- {
- INDEX ctRedos=m_dcTerrainUndo.Count()-1-m_iCurrentTerrainUndo;
- if( ctRedos>0)
- {
- ApplyTerrainRedo(&m_dcTerrainUndo[m_iCurrentTerrainUndo+1]);
- }
- }
- else
- {
- Redo();
- }
- m_chDocument.MarkChanged();
- UpdateAllViews( NULL);
- }
- void CWorldEditorDoc::OnUpdateEditRedo(CCmdUI* pCmdUI)
- {
- if( GetEditingMode()==TERRAIN_MODE)
- {
- INDEX ctRedos=m_dcTerrainUndo.Count()-1-m_iCurrentTerrainUndo;
- pCmdUI->Enable( ctRedos>0);
- }
- else
- {
- pCmdUI->Enable( !m_lhRedo.IsEmpty());
- }
- }
- // paste given texture over polygon selection
- void CWorldEditorDoc::PasteTextureOverSelection_t( CTFileName fnTexName)
- {
- // for each of the selected polygons
- FOREACHINDYNAMICCONTAINER( m_selPolygonSelection, CBrushPolygon, itbpo)
- {
- CTextureData *pTD = (CTextureData *) itbpo->bpo_abptTextures[m_iTexture].bpt_toTexture.GetData();
- if( (pTD == NULL) || (pTD->GetName() != fnTexName) )
- {
- itbpo->bpo_abptTextures[m_iTexture].bpt_toTexture.SetData_t( fnTexName);
- // mark that document has been modified
- SetModifiedFlag( TRUE);
- // mark that selections have been changed
- m_chSelections.MarkChanged();
- }
- }
- // update all views
- UpdateAllViews( NULL);
- }
- FLOAT _fLastTimeDeselectAllUsed = -10000.0f;
- // delete all selected members in current selection mode
- void CWorldEditorDoc::DeselectAll(void)
- {
- // if browse entities mode is on
- if( m_bBrowseEntitiesMode)
- {
- // cancel browse entities mode
- OnBrowseEntitiesMode();
- }
- else
- {
- FLOAT fCurrentTime = _pTimer->GetRealTimeTick();
- if( (fCurrentTime-_fLastTimeDeselectAllUsed)<1.0f)
- {
- ClearSelections();
- _fLastTimeDeselectAllUsed = fCurrentTime;
- return;
- }
- _fLastTimeDeselectAllUsed = fCurrentTime;
- // according to current selection mode clear selected members
- switch( GetEditingMode())
- {
- case POLYGON_MODE:
- {
- m_selPolygonSelection.Clear();
- break;
- };
- case SECTOR_MODE:
- {
- m_selSectorSelection.Clear();
- break;
- };
- case ENTITY_MODE:
- {
- m_selEntitySelection.Clear();
- break;
- };
- case VERTEX_MODE:
- {
- m_selVertexSelection.Clear();
- break;
- };
- case CSG_MODE:
- {
- break;
- };
- case TERRAIN_MODE:
- {
- m_ptrSelectedTerrain=NULL;
- theApp.m_ctTerrainPage.MarkChanged();
- break;
- };
- default:
- {
- FatalError("Unknown editing mode.");
- break;
- };
- }
- }
- // mark that selections have been changed
- m_chSelections.MarkChanged();
- // redraw all viewes
- UpdateAllViews( NULL);
- }
- void CWorldEditorDoc::OnWorldSettings()
- {
- CDlgWorldSettings dlgWorldSettings;
- dlgWorldSettings.SetupBcgSettings( FALSE);
- if( dlgWorldSettings.DoModal() != IDOK) return;
- try
- {
- // !!!! m_woWorld.SetBackgroundTexture_t(CTString(dlgWorldSettings.m_fnBackgroundPicture));
- }
- catch( char *strError)
- {
- AfxMessageBox( CString(strError));
- }
- m_woWorld.SetBackgroundColor( dlgWorldSettings.m_BackgroundColor.GetColor());
- m_woWorld.SetDescription( CTString(CStringA(dlgWorldSettings.m_strMissionDescription)));
- SetModifiedFlag( TRUE);
- UpdateAllViews( NULL);
- }
- /*
- * CSG Add
- */
- void CWorldEditorDoc::OnCsgAdd()
- {
- BOOL bShift = (GetKeyState( VK_SHIFT)&0x8000) != 0;
- if( bShift) PreApplyCSG( CSG_ADD_REVERSE); // reverse priorities
- else PreApplyCSG( CSG_ADD);
- }
- void CWorldEditorDoc::PreApplyCSG(enum CSGType CSGType)
- {
- if( GetEditingMode() != CSG_MODE)
- {
- // search for destination entity
- CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
- CEntity *penTarget = pMainFrame->m_CSGDesitnationCombo.GetSelectedBrushEntity();
- if( (penTarget == NULL) || (penTarget->IsSelected( ENF_SELECTED)) )
- {
- AfxMessageBox( L"Illegal CSG operands (target must not be selected) !");
- return;
- }
- // create temporary world
- CWorld woDummyWorld;
- // create zero placement
- CPlacement3D plZeroPlacement;
- plZeroPlacement.pl_PositionVector = FLOAT3D(0.0f,0.0f,0.0f);
- plZeroPlacement.pl_OrientationAngle = ANGLE3D(0,0,0);
- CDynamicContainer<CEntity> dcenDummy;
- // for all still selected brush entities
- {FOREACHINDYNAMICCONTAINER(m_selEntitySelection, CEntity, iten)
- {
- CEntity::RenderType rt = iten->GetRenderType();
- // if the entity is brush and it is not empty
- if( rt==CEntity::RT_BRUSH || rt==CEntity::RT_FIELDBRUSH)
- {
- // copy entity into dummy world
- woDummyWorld.CopyOneEntity( *iten, plZeroPlacement);
- }
- // deselect entities that are not brushes
- else
- {
- // deselect clicked sector
- dcenDummy.Add( &iten.Current());
- }
- }}
-
- // for entities that should be deselected
- {FOREACHINDYNAMICCONTAINER(dcenDummy, CEntity, iten)
- {
- m_selEntitySelection.Deselect( *iten);
- }}
- dcenDummy.Clear();
-
- // remember undo before doing CSG operations
- RememberUndo();
- // clear all selections except entity
- ClearSelections( ST_ENTITY);
- // delete all brush entities that are still selected
- m_woWorld.DestroyEntities( m_selEntitySelection);
- // set wait cursor
- CWaitCursor StartWaitCursor;
- m_csgtLastUsedCSGOperation = CSG_ADD_ENTITIES;
- m_bPreLastUsedPrimitiveMode = m_bLastUsedPrimitiveMode;
- m_bLastUsedPrimitiveMode = FALSE;
- // for all of the dummy world's entities
- {FOREACHINDYNAMICCONTAINER(woDummyWorld.wo_cenEntities, CEntity, iten)
- {
- // create another dummy world
- CWorld woOneBrush;
- // copy entity from dummy world to world containing only one brush
- CEntity *penOnlyBrush = woOneBrush.CopyOneEntity( *iten, plZeroPlacement);
- // ----------- Do CSG beetween current entity and destination combo's entity
- switch( CSGType)
- {
- case CSG_ADD:
- {
- m_woWorld.CSGAdd(*penTarget, woOneBrush, *penOnlyBrush, plZeroPlacement);
- break;
- }
- case CSG_ADD_REVERSE:
- {
- m_woWorld.CSGAddReverse(*penTarget, woOneBrush, *penOnlyBrush, plZeroPlacement);
- break;
- }
- case CSG_REMOVE:
- {
- m_woWorld.CSGRemove(*penTarget, woOneBrush, *penOnlyBrush, plZeroPlacement);
- break;
- }
- case CSG_SPLIT_SECTORS:
- {
- m_woWorld.SplitSectors(*penTarget, m_selSectorSelection, woOneBrush, *penOnlyBrush, plZeroPlacement);
- break;
- }
- case CSG_SPLIT_POLYGONS:
- {
- m_woWorld.SplitPolygons(*penTarget, m_selPolygonSelection, woOneBrush, *penOnlyBrush, plZeroPlacement);
- break;
- }
- default:
- {
- ASSERTALWAYS("PreAplyCSG() function called with illegal CSG operation.");
- return;
- }
- }
- }}
- // mark that selections have been changed
- SetModifiedFlag(TRUE);
- m_chSelections.MarkChanged();
- m_chDocument.MarkChanged();
- }
- else
- {
- ApplyCSG( CSGType);
- }
- UpdateAllViews( NULL);
- }
- BOOL CWorldEditorDoc::IsEntityCSGEnabled(void)
- {
- if(m_pwoSecondLayer != NULL) return TRUE;
- // if we are in entity mode
- if( GetEditingMode() != CSG_MODE)
- {
- // for all selected entities
- FOREACHINDYNAMICCONTAINER(m_selEntitySelection, CEntity, iten)
- {
- CEntity::RenderType rt = iten->GetRenderType();
- if( rt==CEntity::RT_BRUSH || rt==CEntity::RT_FIELDBRUSH)
- {
- return TRUE;
- }
- }
- }
- return FALSE;
- }
- void CWorldEditorDoc::OnUpdateCsgAdd(CCmdUI* pCmdUI)
- {
- pCmdUI->Enable( IsEntityCSGEnabled());
- }
- /*
- * CSG Remove
- */
- void CWorldEditorDoc::OnCsgRemove()
- {
- PreApplyCSG( CSG_REMOVE);
- }
- void CWorldEditorDoc::OnUpdateCsgRemove(CCmdUI* pCmdUI)
- {
- pCmdUI->Enable( IsEntityCSGEnabled());
- }
- /*
- * CSG Split Sectors.
- */
- void CWorldEditorDoc::OnCsgSplitSectors()
- {
- PreApplyCSG( CSG_SPLIT_SECTORS);
- }
- void CWorldEditorDoc::OnUpdateCsgSplitSectors(CCmdUI* pCmdUI)
- {
- pCmdUI->Enable( IsEntityCSGEnabled());
- }
- /*
- * CSG Join Sectors.
- */
- void CWorldEditorDoc::OnCsgJoinSectors()
- {
- ApplyCSG( CSG_JOIN_SECTORS);
- }
- void CWorldEditorDoc::OnUpdateCsgJoinSectors(CCmdUI* pCmdUI)
- {
- pCmdUI->Enable( m_woWorld.CanJoinSectors( m_selSectorSelection));
- }
- /*
- * CSG Split Polygons.
- */
- void CWorldEditorDoc::OnCsgSplitPolygons()
- {
- PreApplyCSG( CSG_SPLIT_POLYGONS);
- }
- void CWorldEditorDoc::OnUpdateCsgSplitPolygons(CCmdUI* pCmdUI)
- {
- pCmdUI->Enable( IsEntityCSGEnabled() && m_selPolygonSelection.Count() > 0);
- }
- /*
- * CSG Join Polygons.
- */
- void CWorldEditorDoc::OnCsgJoinPolygons()
- {
- BOOL bCtrl = (GetKeyState( VK_CONTROL)&0x8000) != 0;
- if (bCtrl) {
- ApplyCSG(CSG_JOIN_POLYGONS_KEEP_TEXTURES); // keep textures if control pressed
- } else {
- ApplyCSG(CSG_JOIN_POLYGONS);
- }
- }
- void CWorldEditorDoc::OnUpdateCsgJoinPolygons(CCmdUI* pCmdUI)
- {
- // check for polygon mode and count (crashed here right after merging vertices)
- if( (m_iMode == POLYGON_MODE) && (m_selPolygonSelection.Count() != 0) )
- {
- pCmdUI->Enable( m_woWorld.CanJoinPolygons(m_selPolygonSelection));
- }
- else
- {
- pCmdUI->Enable( FALSE);
- }
- }
- void CWorldEditorDoc::OnCsgJoinAllPolygons()
- {
- BOOL bCtrl = (GetKeyState( VK_CONTROL)&0x8000) != 0;
- if (bCtrl) {
- ApplyCSG(CSG_JOIN_ALL_POLYGONS_KEEP_TEXTURES); // keep textures if control pressed
- } else {
- ApplyCSG(CSG_JOIN_ALL_POLYGONS);
- }
- }
- void CWorldEditorDoc::OnUpdateCsgJoinAllPolygons(CCmdUI* pCmdUI)
- {
- pCmdUI->Enable( m_woWorld.CanJoinAllPossiblePolygons(m_selPolygonSelection));
- }
- /*
- * Cancel CSG.
- */
- void CWorldEditorDoc::OnCsgCancel()
- {
- if( m_iMode == CSG_MODE)
- {
- CancelCSG();
- }
- else
- {
- SetEditingMode( VERTEX_MODE);
- }
- }
- void CWorldEditorDoc::OnShowOrientation()
- {
- m_bOrientationIcons = !m_bOrientationIcons;
- theApp.WriteProfileInt(L"World editor", L"Orientation icons", m_bOrientationIcons);
- UpdateAllViews( NULL);
- }
- void CWorldEditorDoc::OnUpdateShowOrientation(CCmdUI* pCmdUI)
- {
- pCmdUI->SetCheck( m_bOrientationIcons);
- }
- void CWorldEditorDoc::OnAutoSnap()
- {
- m_bAutoSnap = !m_bAutoSnap;
- }
- void CWorldEditorDoc::OnUpdateAutoSnap(CCmdUI* pCmdUI)
- {
- pCmdUI->SetCheck( m_bAutoSnap);
- }
- void CWorldEditorDoc::OnCalculateShadows()
- {
- RememberUndo(); // this is before wait cursor, so that we can see if it gets blocked here
- // set wait cursor
- CWaitCursor StartWaitCursor;
- // reset profile
- _pfWorldEditingProfile.Reset();
- m_woWorld.CalculateDirectionalShadows();
- if( GetEditingMode()==TERRAIN_MODE)
- {
- CTerrain *ptTerrain=GetTerrain();
- if(ptTerrain!=NULL) ptTerrain->UpdateShadowMap();
- }
- // create shadows report
- _pfWorldEditingProfile.Report( theApp.m_strCSGAndShadowStatistics);
- theApp.m_strCSGAndShadowStatistics.SaveVar(CTString("Temp\\Profile_Shadows.txt"));
- // mark that document has changed
- SetModifiedFlag(TRUE);
- m_chDocument.MarkChanged();
- // invalidate document (i.e. all views)
- UpdateAllViews( NULL);
- }
- void CWorldEditorDoc::OnHideSelected()
- {
- if( m_iMode == ENTITY_MODE)
- {
- OnHideSelectedEntities();
- }
- else
- {
- OnHideSelectedSectors();
- }
- }
- void CWorldEditorDoc::OnHideUnselected()
- {
- if( m_iMode == ENTITY_MODE)
- {
- OnHideUnselectedEntities();
- }
- if( m_iMode == SECTOR_MODE)
- {
- OnHideUnselectedSectors();
- }
- if( m_iMode == TERRAIN_MODE)
- {
- theApp.m_iTerrainBrushMode=TBM_MAXIMUM;
- theApp.m_ctTerrainPageCanvas.MarkChanged();
- SetStatusLineModeInfoMessage();
- }
- }
- void CWorldEditorDoc::OnShowAll()
- {
- if( m_iMode == ENTITY_MODE)
- {
- OnShowAllEntities();
- }
- if( m_iMode == SECTOR_MODE)
- {
- OnShowAllSectors();
- }
- }
- void CWorldEditorDoc::OnUpdateHideSelected(CCmdUI* pCmdUI)
- {
- // enable button if selection is not empty
- if( m_iMode == ENTITY_MODE)
- {
- pCmdUI->Enable( m_selEntitySelection.Count() != 0);
- }
- else
- {
- pCmdUI->Enable( m_selSectorSelection.Count() != 0);
- }
- }
- void CWorldEditorDoc::OnHideSelectedSectors()
- {
- // hide selected sectors
- m_woWorld.HideSelectedSectors( m_selSectorSelection);
- // update all views
- UpdateAllViews( NULL);
- }
- void CWorldEditorDoc::OnHideUnselectedSectors()
- {
- // hide unselected sectors
- m_woWorld.HideUnselectedSectors();
- // update all views
- UpdateAllViews( NULL);
- }
- void CWorldEditorDoc::OnShowAllSectors()
- {
- // hide unselected sectors
- m_woWorld.ShowAllSectors();
- // update all views
- UpdateAllViews( NULL);
- }
- void CWorldEditorDoc::OnHideSelectedEntities()
- {
- // hide selected entities
- m_woWorld.HideSelectedEntities( m_selEntitySelection);
- // update all views
- UpdateAllViews( NULL);
- }
- void CWorldEditorDoc::OnHideUnselectedEntities()
- {
- // hide unselected entities
- m_woWorld.HideUnselectedEntities();
- // update all views
- UpdateAllViews( NULL);
- }
- void CWorldEditorDoc::OnShowAllEntities()
- {
- // hide unselected entities
- m_woWorld.ShowAllEntities();
- // update all views
- UpdateAllViews( NULL);
- }
- // How box is created from 2 vertices: indices of first or second vertice, one that gives
- // current coordinate for one of box's vertices (we have two source points, T0 and T1.
- // Coordinate for box vertice 0 is B0(xT0, yT0, zT0), vertice 1 is B1(xT1, yT0, zT0) ...)
- static INDEX _aiBoxCreation[8][3] = {
- 0,0,0,
- 1,0,0,
- 1,0,1,
- 0,0,1,
- 0,1,0,
- 1,1,0,
- 1,1,1,
- 0,1,1
- };
- // Array of indices to vertices that need to be corrected if one of box's vertices is moved
- // (if vertice 0 moved, copy its x coordinate to vertices 3,7,4, copy y coordinate to
- // vertices 1,2,3, z to 1,5,4...)
- static INDEX _aiCorrectVertices[8][3*3] = {
- 3,7,4, 1,2,3, 1,5,4,
- 2,5,6, 0,2,3, 0,4,5,
- 1,5,6, 0,1,3, 3,6,7,
- 0,4,7, 0,1,2, 2,6,7,
- 0,3,7, 5,6,7, 0,1,5,
- 1,2,6, 4,6,7, 0,1,4,
- 1,2,5, 4,5,7, 2,3,7,
- 0,3,4, 4,5,6, 2,3,6
- };
- // Selects entity with given index inside volume
- void CWorldEditorDoc::SelectGivenEntity( INDEX iEntityToSelect)
- {
- // clear normal entity selection
- m_selEntitySelection.Clear();
- // if there is any entity in volume container
- if( m_cenEntitiesSelectedByVolume.Count() != 0)
- {
- // clip requested entity
- if( iEntityToSelect >= m_cenEntitiesSelectedByVolume.Count())
- {
- iEntityToSelect = 0;
- }
- m_iSelectedEntityInVolume = iEntityToSelect;
- // lock the selection
- m_cenEntitiesSelectedByVolume.Lock();
- // get requested entity
- CEntity *penEntity = m_cenEntitiesSelectedByVolume.Pointer(m_iSelectedEntityInVolume);
- // unlock the selection
- m_cenEntitiesSelectedByVolume.Unlock();
- // add entity into normal selection
- m_selEntitySelection.Select( *penEntity);
- // center entity
- POSITION pos = GetFirstViewPosition();
- CWorldEditorView *pWedView = (CWorldEditorView *) GetNextView(pos);
- pWedView->OnCenterEntity();
- }
- // mark that selections have been changed
- m_chSelections.MarkChanged();
- // obtain main frame ptr
- CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
- // and refresh property combo manualy calling on idle
- pMainFrame->m_PropertyComboBar.m_PropertyComboBox.OnIdle( 0);
- // update all views
- UpdateAllViews( NULL);
- }
- /*
- * Function puts world's entites occupied by volume box to volume box selection
- */
- void CWorldEditorDoc::SelectEntitiesByVolumeBox(void)
- {
- m_iSelectedEntityInVolume = 0;
- // create volume box (for browsing entities)
- FLOAT3D vMinMax[2];
- vMinMax[0] = m_vCreateBoxVertice0;
- vMinMax[1] = m_vCreateBoxVertice1;
- // create coordinates for box's vertices
- for( INDEX iBoxVertice=0;iBoxVertice<8;iBoxVertice++)
- {
- m_avVolumeBoxVertice[iBoxVertice] = FLOAT3D( vMinMax[_aiBoxCreation[iBoxVertice][0]](1),
- vMinMax[_aiBoxCreation[iBoxVertice][1]](2),
- vMinMax[_aiBoxCreation[iBoxVertice][2]](3) );
- }
- // create bbox from requested volume
- FLOATaabbox3D bboxVolume( m_vCreateBoxVertice0, m_vCreateBoxVertice1);
- // clear entity volume container
- m_cenEntitiesSelectedByVolume.Clear();
- // clear normal entity selection
- m_selEntitySelection.Clear();
- // for all of the world's entities
- FOREACHINDYNAMICCONTAINER(m_woWorld.wo_cenEntities, CEntity, iten)
- {
- CPlacement3D plEntityPlacement = iten->GetPlacement();
- // if entity handle is inside volume box
- if( bboxVolume.HasContactWith( FLOATaabbox3D(plEntityPlacement.pl_PositionVector)) )
- {
- // add entity into volume container
- m_cenEntitiesSelectedByVolume.Add( iten);
- }
- }
- SetStatusLineModeInfoMessage();
- }
- /*
- * Function corects coordinates of vertices that represent box because given vertice is
- * moved and box has invalid geometry
- */
- void CWorldEditorDoc::CorrectBox(INDEX iMovedVtx, FLOAT3D vNewPosition)
- {
- for( INDEX iCoordinate=0;iCoordinate<3; iCoordinate++)
- {
- for( INDEX iVtxToCorrect=0;iVtxToCorrect<3; iVtxToCorrect++)
- {
- // copy coordinate
- m_avVolumeBoxVertice[ _aiCorrectVertices[iMovedVtx][iCoordinate*3+iVtxToCorrect]]
- (iCoordinate+1) = vNewPosition(iCoordinate+1);
- }
- }
- // copy new moved vertice's position
- m_avVolumeBoxVertice[ iMovedVtx] = vNewPosition;
- // set new values for next creation of volume box
- m_vCreateBoxVertice0 = m_avVolumeBoxVertice[ 0];
- m_vCreateBoxVertice1 = m_avVolumeBoxVertice[ 6];
- }
- void CWorldEditorDoc::OnBrowseEntitiesMode()
- {
- m_bBrowseEntitiesMode = !m_bBrowseEntitiesMode;
- // if we should start select by volume (or browse entities) mode
- if( m_bBrowseEntitiesMode)
- {
- SelectEntitiesByVolumeBox();
- }
- // stop select by volume mode
- else
- {
- // write to ini last vertices used for volume box creation
- char strIni[ 128];
- sprintf( strIni, "%f %f %f",
- m_vCreateBoxVertice0(1), m_vCreateBoxVertice0(2), m_vCreateBoxVertice0(3));
- theApp.WriteProfileString( L"World editor", L"Volume box min", CString(strIni));
- sprintf( strIni, "%f %f %f",
- m_vCreateBoxVertice1(1), m_vCreateBoxVertice1(2), m_vCreateBoxVertice1(3));
- theApp.WriteProfileString( L"World editor", L"Volume box max", CString(strIni));
- m_chSelections.MarkChanged();
- }
- // update all views
- UpdateAllViews( NULL);
- }
- void CWorldEditorDoc::OnUpdateBrowseEntitiesMode(CCmdUI* pCmdUI)
- {
- pCmdUI->SetCheck( m_bBrowseEntitiesMode);
- pCmdUI->Enable( GetEditingMode() == ENTITY_MODE);
- }
- void CWorldEditorDoc::OnPreviousSelectedEntity()
- {
- CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
- INDEX iEntityToSelect = (m_iSelectedEntityInVolume+
- m_cenEntitiesSelectedByVolume.Count()-1)%m_cenEntitiesSelectedByVolume.Count();
-
- // clip entity index
- if( iEntityToSelect >= m_cenEntitiesSelectedByVolume.Count())
- {
- iEntityToSelect = 0;
- }
- CTString strMessage;
- strMessage.PrintF("Entity %d/%d", iEntityToSelect, m_cenEntitiesSelectedByVolume.Count());
- pMainFrame->SetStatusBarMessage( strMessage, STATUS_LINE_PANE, 2);
-
- SelectGivenEntity( iEntityToSelect);
- }
- void CWorldEditorDoc::OnNextSelectedEntity()
- {
- CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
- INDEX iEntityToSelect = (m_iSelectedEntityInVolume+1)%m_cenEntitiesSelectedByVolume.Count();
- // clip entity index
- if( iEntityToSelect >= m_cenEntitiesSelectedByVolume.Count() )
- {
- iEntityToSelect = 0;
- }
-
- CTString strMessage;
- strMessage.PrintF("Entity %d/%d", iEntityToSelect, m_cenEntitiesSelectedByVolume.Count());
- pMainFrame->SetStatusBarMessage( strMessage, STATUS_LINE_PANE, 2);
-
- SelectGivenEntity( iEntityToSelect);
- }
- void CWorldEditorDoc::OnUpdatePreviousSelectedEntity(CCmdUI* pCmdUI)
- {
- pCmdUI->Enable( m_cenEntitiesSelectedByVolume.Count()>0);
- }
- void CWorldEditorDoc::OnUpdateNextSelectedEntity(CCmdUI* pCmdUI)
- {
- pCmdUI->Enable( m_cenEntitiesSelectedByVolume.Count()>0);
- }
- void CWorldEditorDoc::OnSelectAllInVolume( void)
- {
- // for each of the entities selected by volume
- FOREACHINDYNAMICCONTAINER( m_cenEntitiesSelectedByVolume, CEntity, iten)
- {
- if( !iten->IsSelected( ENF_SELECTED))
- {
- // add entity into normal selection
- m_selEntitySelection.Select( *iten);
- }
- }
- // clear volume container
- //m_cenEntitiesSelectedByVolume.Clear();
- // go out of browse by volume mode
- if( m_bBrowseEntitiesMode) OnBrowseEntitiesMode();
- // mark that selections have been changed
- m_chSelections.MarkChanged();
- // obtain main frame ptr
- CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
- // and refresh property combo manualy calling on idle
- pMainFrame->m_PropertyComboBar.m_PropertyComboBox.OnIdle( 0);
- // update all views
- UpdateAllViews( NULL);
- }
- void CWorldEditorDoc::OnJoinLayers()
- {
- ApplyCSG( CSG_JOIN_LAYERS);
- }
- void CWorldEditorDoc::OnUpdateSelectByClass(CCmdUI* pCmdUI)
- {
- pCmdUI->Enable( TRUE);
- }
- void CWorldEditorDoc::OnSelectByClass()
- {
- CWorldEditorView *pWorldEditorView = theApp.GetActiveView();
- CDlgBrowseByClass dlgBrowseByClass;
- INDEX ctEntities = m_cenEntitiesSelectedByVolume.Count();
- // auto start in all entities mode if no entities are selected
- dlgBrowseByClass.m_bShowVolume = (ctEntities != 0);
- if( dlgBrowseByClass.DoModal() == IDOK)
- {
- m_chSelections.MarkChanged();
- SetEditingMode( ENTITY_MODE);
- UpdateAllViews( NULL);
- if( (pWorldEditorView != NULL) &&
- (dlgBrowseByClass.m_bCenterSelected) )
- {
- pWorldEditorView->CenterSelected();
- }
- }
- }
- void CWorldEditorDoc::OnSelectByClassImportant()
- {
- CWorldEditorView *pWorldEditorView = theApp.GetActiveView();
- CDlgBrowseByClass dlgBrowseByClass;
- dlgBrowseByClass.m_bShowImportants = TRUE;
- if( dlgBrowseByClass.DoModal() == IDOK)
- {
- m_chSelections.MarkChanged();
- SetEditingMode( ENTITY_MODE);
- UpdateAllViews( NULL);
- if( (pWorldEditorView != NULL) &&
- (dlgBrowseByClass.m_bCenterSelected) )
- {
- pWorldEditorView->CenterSelected();
- }
- }
- }
- void CWorldEditorDoc::OnCrossroadForN()
- {
- if( m_iMode == VERTEX_MODE)
- {
- CDlgSnapVertex dlg;
- dlg.DoModal();
- }
- else
- {
- OnSelectByClassAll();
- }
- }
- void CWorldEditorDoc::OnSelectByClassAll()
- {
- CWorldEditorView *pWorldEditorView = theApp.GetActiveView();
- CDlgBrowseByClass dlgBrowseByClass;
- dlgBrowseByClass.m_bShowVolume = FALSE;
- if( dlgBrowseByClass.DoModal() == IDOK)
- {
- m_chSelections.MarkChanged();
- SetEditingMode( ENTITY_MODE);
- UpdateAllViews( NULL);
- if( (pWorldEditorView != NULL) &&
- (dlgBrowseByClass.m_bCenterSelected) )
- {
- pWorldEditorView->CenterSelected();
- }
- }
- }
- void CWorldEditorDoc::OnTexture1()
- {
- theApp.m_bTexture1 = !theApp.m_bTexture1;
- UpdateAllViews( NULL);
- }
- void CWorldEditorDoc::OnUpdateTexture1(CCmdUI* pCmdUI)
- {
- pCmdUI->SetCheck( theApp.m_bTexture1);
- }
- void CWorldEditorDoc::OnTexture2()
- {
- theApp.m_bTexture2 = !theApp.m_bTexture2;
- UpdateAllViews( NULL);
- }
- void CWorldEditorDoc::OnUpdateTexture2(CCmdUI* pCmdUI)
- {
- pCmdUI->SetCheck( theApp.m_bTexture2);
- }
- void CWorldEditorDoc::OnTexture3()
- {
- theApp.m_bTexture3 = !theApp.m_bTexture3;
- UpdateAllViews( NULL);
- }
- void CWorldEditorDoc::OnUpdateTexture3(CCmdUI* pCmdUI)
- {
- pCmdUI->SetCheck( theApp.m_bTexture3);
- }
- void CWorldEditorDoc::SetActiveTextureLayer(INDEX iLayer)
- {
- if( GetEditingMode()==TERRAIN_MODE)
- {
- CTerrain *ptTerrain=GetTerrain();
- if(ptTerrain==NULL) return;
- if(iLayer>=ptTerrain->tr_atlLayers.Count()) return;
- SelectLayer(iLayer);
- m_chSelections.MarkChanged();
- theApp.m_ctTerrainPageCanvas.MarkChanged();
- }
- else if(iLayer<3)
- {
- m_iTexture = iLayer;
- m_chSelections.MarkChanged();
- UpdateAllViews( NULL);
- }
- }
- void CWorldEditorDoc::OnTextureMode1()
- {
- SetActiveTextureLayer(0);
- }
- void CWorldEditorDoc::OnTextureMode2()
- {
- SetActiveTextureLayer(1);
- }
- void CWorldEditorDoc::OnTextureMode3()
- {
- SetActiveTextureLayer(2);
- }
- void CWorldEditorDoc::OnTextureMode4()
- {
- SetActiveTextureLayer(3);
- }
- void CWorldEditorDoc::OnTextureMode5()
- {
- SetActiveTextureLayer(4);
- }
- void CWorldEditorDoc::OnTextureMode6()
- {
- SetActiveTextureLayer(5);
- }
- void CWorldEditorDoc::OnTextureMode7()
- {
- SetActiveTextureLayer(6);
- }
- void CWorldEditorDoc::OnTextureMode8()
- {
- SetActiveTextureLayer(7);
- }
- void CWorldEditorDoc::OnTextureMode9()
- {
- SetActiveTextureLayer(8);
- }
- void CWorldEditorDoc::OnTextureMode10()
- {
- SetActiveTextureLayer(9);
- }
- void CWorldEditorDoc::OnSaveThumbnail( void)
- {
- // remember current position for thumbnail saving into world
- CWorldEditorView *pViewForThumbnail = theApp.GetActiveView();
- if( pViewForThumbnail == NULL) return;
- CChildFrame *pChild = pViewForThumbnail->GetChildFrame();
- // set new viewer settings
- m_woWorld.wo_plThumbnailFocus = pChild->m_mvViewer.mv_plViewer;
- m_woWorld.wo_fThumbnailTargetDistance = pChild->m_mvViewer.mv_fTargetDistance;
- // save thumbnail
- SaveThumbnail();
- }
- void CWorldEditorDoc::SaveThumbnail()
- {
- CDrawPort *pDrawPort;
- CImageInfo II;
- CTextureData TD;
- CAnimData AD;
- ULONG flags = NONE;
- // if document isn't saved, call save as
- if( GetPathName() == "")
- {
- // if failed
- if( !DoFileSave()) return;
- }
- // try to find perspective view
- POSITION pos = GetFirstViewPosition();
- CWorldEditorView *pViewForThumbnail = theApp.GetActiveView();
- CWorldEditorView *pWedView;
- FOREVER
- {
- pWedView = (CWorldEditorView *) GetNextView(pos);
- if( pWedView == NULL) return;
- if( pWedView->m_ptProjectionType == CSlaveViewer::PT_PERSPECTIVE)
- {
- pViewForThumbnail = pWedView;
- break;
- }
- }
- // if perspective view can't be found, don't do anything
- if( pViewForThumbnail == NULL) return;
- CChildFrame *pChild = pViewForThumbnail->GetChildFrame();
- // create canvas to render picture
- _pGfx->CreateWorkCanvas( 128, 128, &pDrawPort);
- if( pDrawPort != NULL)
- {
- if( pDrawPort->Lock())
- {
- // remember old viewer settings
- CPlacement3D plOrgPlacement = pChild->m_mvViewer.mv_plViewer;
- FLOAT fOldTargetDistance = pChild->m_mvViewer.mv_fTargetDistance;
- // set new viewer settings
- pChild->m_mvViewer.mv_plViewer = m_woWorld.wo_plThumbnailFocus;
- pChild->m_mvViewer.mv_fTargetDistance = m_woWorld.wo_fThumbnailTargetDistance;
- // render vew from thumbnail position
- pViewForThumbnail->RenderView( pDrawPort);
- // restore orgiginal position
- pChild->m_mvViewer.mv_plViewer = plOrgPlacement;
- pChild->m_mvViewer.mv_fTargetDistance = fOldTargetDistance;
- pDrawPort->Unlock();
- }
-
- CTFileName fnDocument = CTString( CStringA(GetPathName()));
- CTFileName fnThumbnail = fnDocument.FileDir() + fnDocument.FileName() + CTString(".tbn");
- pDrawPort->GrabScreen(II);
- // try to
- try {
- // remove application path
- fnThumbnail.RemoveApplicationPath_t();
- // create image info from texture
- TD.Create_t( &II, 128, MAX_MEX_LOG2, FALSE);
- // save the thumbnail
- CTFileStream File;
- File.Create_t( fnThumbnail);
- TD.Write_t( &File);
- File.Close();
- }
- // if failed
- catch (char *strError) {
- // report error
- AfxMessageBox(CString(strError));
- }
- _pGfx->DestroyWorkCanvas( pDrawPort);
- pDrawPort = NULL;
- }
- CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
- // refresh browser (open and close current virtual directory)
- pMainFrame->m_Browser.CloseSelectedDirectory();
- pMainFrame->m_Browser.OpenSelectedDirectory();
- }
- void CWorldEditorDoc::ResetPrimitive()
- {
- if( !m_bPrimitiveMode) return;
- FLOAT fDX = (theApp.m_vfpCurrent.vfp_fXMax+theApp.m_vfpCurrent.vfp_fXMin)/2.0f;
- FLOAT fDY = theApp.m_vfpCurrent.vfp_fYMin;
- FLOAT fDZ = (theApp.m_vfpCurrent.vfp_fZMax+theApp.m_vfpCurrent.vfp_fZMin)/2.0f;
- FLOAT fWidth = theApp.m_vfpCurrent.vfp_fXMax-theApp.m_vfpCurrent.vfp_fXMin;
- FLOAT fHeight = theApp.m_vfpCurrent.vfp_fYMax-theApp.m_vfpCurrent.vfp_fYMin;
- FLOAT fLenght = (theApp.m_vfpCurrent.vfp_fZMax-theApp.m_vfpCurrent.vfp_fZMin);
- FLOAT3D vDelta = FLOAT3D( fDX, fDY, fDZ);
- m_plSecondLayer.pl_PositionVector += vDelta;
- theApp.m_vfpCurrent.vfp_plPrimitive = m_plSecondLayer;
- theApp.m_vfpCurrent.vfp_fXMin = -fWidth/2.0f;
- theApp.m_vfpCurrent.vfp_fXMax = fWidth/2.0f;
- theApp.m_vfpCurrent.vfp_fYMin = 0.0f;
- theApp.m_vfpCurrent.vfp_fYMax = fHeight;
- theApp.m_vfpCurrent.vfp_fZMin = -fLenght/2.0f;
- theApp.m_vfpCurrent.vfp_fZMax = fLenght/2.0f;
-
- RefreshPrimitivePage();
- m_bPrimitiveCreatedFirstTime = TRUE;
- _bDontRecalculateBase = FALSE;
- CreatePrimitive();
- UpdateAllViews( NULL);
- }
- void CWorldEditorDoc::DeletePrimitiveVertex(INDEX iVtxToDelete)
- {
- // get count of vertices on the base
- INDEX vtxCt = theApp.m_vfpCurrent.vfp_avVerticesOnBaseOfPrimitive.Count();
- if( vtxCt < 4) return;
- CStaticArray<DOUBLE3D> avDecreased;
- avDecreased.New(vtxCt-1);
- INDEX iVtxNew = 0;
- for( INDEX iVtxOld = 0; iVtxOld<vtxCt; iVtxOld++)
- {
- if( iVtxOld != iVtxToDelete)
- {
- avDecreased[iVtxNew] = theApp.m_vfpCurrent.vfp_avVerticesOnBaseOfPrimitive[iVtxOld];
- iVtxNew++;
- }
- }
- // copy new array back to primitive
- theApp.m_vfpCurrent.vfp_avVerticesOnBaseOfPrimitive.Clear();
- theApp.m_vfpCurrent.vfp_avVerticesOnBaseOfPrimitive.New(vtxCt-1);
- for( INDEX iVtx=0; iVtx<vtxCt-1; iVtx++)
- {
- theApp.m_vfpCurrent.vfp_avVerticesOnBaseOfPrimitive[iVtx] = avDecreased[iVtx];
- }
- m_ctLastPrimitiveVertices = vtxCt-1;
- RefreshPrimitivePage();
- CreatePrimitive();
- UpdateAllViews( NULL);
- }
- void CWorldEditorDoc::InsertPrimitiveVertex(INDEX iEdge, FLOAT3D vVertexToInsert)
- {
- // get count of vertices on the base
- INDEX vtxCt = theApp.m_vfpCurrent.vfp_avVerticesOnBaseOfPrimitive.Count();
- CStaticArray<DOUBLE3D> avIncreased;
- avIncreased.New(vtxCt+1);
- INDEX iVtxNew = 0;
- for( INDEX iVtxOld = 0; iVtxOld<vtxCt; iVtxOld++)
- {
- avIncreased[iVtxNew] = theApp.m_vfpCurrent.vfp_avVerticesOnBaseOfPrimitive[iVtxOld];
- iVtxNew++;
- if( iVtxOld == iEdge)
- {
- avIncreased[iVtxNew] = FLOATtoDOUBLE(vVertexToInsert);
- avIncreased[iVtxNew](2) = 0.0f;
- iVtxNew++;
- }
- }
- // copy new array back to primitive
- theApp.m_vfpCurrent.vfp_avVerticesOnBaseOfPrimitive.Clear();
- theApp.m_vfpCurrent.vfp_avVerticesOnBaseOfPrimitive.New(vtxCt+1);
- for( INDEX iVtx=0; iVtx<vtxCt+1; iVtx++)
- {
- theApp.m_vfpCurrent.vfp_avVerticesOnBaseOfPrimitive[iVtx] = avIncreased[iVtx];
- }
- m_ctLastPrimitiveVertices = vtxCt+1;
- RefreshPrimitivePage();
- CreatePrimitive();
- UpdateAllViews( NULL);
- }
- void CWorldEditorDoc::OnUpdateLinks()
- {
- CWaitCursor wc;
- m_woWorld.RebuildLinks();
- }
- void CWorldEditorDoc::OnSnapshot()
- {
- RememberUndo();
- }
- void CWorldEditorDoc::OnMirrorAndStretch()
- {
- if (!m_bPrimitiveMode) {
- CDlgMirrorAndStretch dlg;
- // set dialog name
- if (m_pwoSecondLayer != NULL) {
- dlg.m_strName = "Mirror and stretch second layer";
- } else {
- dlg.m_strName = "Mirror and stretch entire world";
- }
- if( dlg.DoModal() == IDOK)
- {
- ApplyMirrorAndStretch( dlg.m_iMirror, dlg.m_fStretch);
- }
- } else {
- ASSERT(FALSE);
- }
- }
- void CWorldEditorDoc::OnFlipLayer()
- {
- if (!m_bPrimitiveMode) {
- ApplyMirrorAndStretch( m_iMirror, 1.0f);
- m_iMirror = (m_iMirror+1)%4;
- ApplyMirrorAndStretch( m_iMirror, 1.0f);
- }
- }
- void CWorldEditorDoc::OnUpdateFlipLayer(CCmdUI* pCmdUI)
- {
- // enable only for second layer
- pCmdUI->Enable( m_pwoSecondLayer != NULL && !m_bPrimitiveMode);
- }
- void CWorldEditorDoc::ApplyMirrorAndStretch(INDEX iMirror, FLOAT fStretch)
- {
- try
- {
- CWorld woDummy;
- if( m_pwoSecondLayer != NULL)
- {
- woDummy.MirrorAndStretch( *m_pwoSecondLayer, fStretch,
- (enum WorldMirrorType)iMirror);
- woDummy.Save_t(CTString("Temp\\MirrorAndStretch.wld"));
- m_pwoSecondLayer->Clear();
- m_pwoSecondLayer->Load_t(CTString("Temp\\MirrorAndStretch.wld"));
- }
- else
- {
- int iRes = AfxMessageBox(L"Are you sure you want to mirror/stretch entire world?", MB_ICONEXCLAMATION|MB_YESNO|MB_DEFBUTTON2);
- if (iRes!=IDYES) {
- return;
- }
- CWaitCursor wcWait;
- RememberUndo();
- ClearSelections();
- woDummy.MirrorAndStretch( m_woWorld, fStretch,
- (enum WorldMirrorType)iMirror);
- woDummy.Save_t(CTString("Temp\\MirrorAndStretch.wld"));
- m_woWorld.Clear();
- m_woWorld.Load_t(CTString("Temp\\MirrorAndStretch.wld"));
- m_woWorld.CalculateNonDirectionalShadows();
- m_chDocument.MarkChanged();
- SetModifiedFlag();
- }
- }
- catch (char *strError)
- {
- AfxMessageBox(CString(strError));
- }
- UpdateAllViews( NULL);
- }
- void CWorldEditorDoc::OnFilterSelection()
- {
- CDlgFilterPolygonSelection dlgFilterPolygonSelection;
- dlgFilterPolygonSelection.DoModal();
- }
- BOOL CWorldEditorDoc::IsCloneUpdatingAllowed(void)
- {
- INDEX ctEntities = m_selEntitySelection.Count();
- // if only one entity is selected
- if( ctEntities == 1)
- {
- // get only selected entity
- m_selEntitySelection.Lock();
- CEntity *penOnlySelected = &m_selEntitySelection[0];
- m_selEntitySelection.Unlock();
- // if entity doesn't have parent
- if( penOnlySelected->GetParent() == NULL)
- {
- // allow clone updating
- return TRUE;
- }
- }
- // disable clone updating
- return FALSE;
- }
- void CWorldEditorDoc::OnUpdateUpdateClones(CCmdUI* pCmdUI)
- {
- pCmdUI->Enable( IsCloneUpdatingAllowed() );
- }
- // delete selected entity with all descendents
- void DeleteEntityWithDescendents( CWorld &woWorld, CEntity *penParent)
- {
- FORDELETELIST( CEntity, en_lnInParent, penParent->en_lhChildren, itenChild)
- {
- DeleteEntityWithDescendents( woWorld, &*itenChild);
- }
- woWorld.DestroyOneEntity( penParent);
- }
- void CWorldEditorDoc::OnUpdateClones()
- {
- // for each case
- if( m_selEntitySelection.Count() == 0)
- {
- return;
- }
-
- // get only selected entity
- m_selEntitySelection.Lock();
- CEntity *penOnlySelected = &m_selEntitySelection[0];
- m_selEntitySelection.Unlock();
- // clear selections before destroying some entities
- ClearSelections();
- // remember placements and delete all clones (entities with same name)
- CTString strName = penOnlySelected->GetName();
- if( strName == "World Base")
- {
- CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
- if( ::MessageBoxA( pMainFrame->m_hWnd, "Are you sure that you want to execute update clones\n"
- "on entity named: \"World Base\"?", "Warning !", MB_YESNO | MB_ICONWARNING | MB_DEFBUTTON1|
- MB_SYSTEMMODAL | MB_TOPMOST) != IDYES)
- {
- return;
- }
- }
- RememberUndo();
- CDynamicContainer<CEntity> apenClones;
- {FOREACHINDYNAMICCONTAINER( m_woWorld.wo_cenEntities, CEntity, iten)
- {
- // if this is clone (by name), it is not original and it is not child of some other entity
- if( (strName == iten->GetName()) && ( &*iten != penOnlySelected) && (iten->GetParent() == NULL) )
- {
- apenClones.Add( &*iten);
- }
- }}
- apenClones.Lock();
- // remember placements of clones
- CStaticArray<CPlacement3D> aplClones;
- INDEX ctEntities = apenClones.Count();
- aplClones.New( ctEntities);
- {for( INDEX iEntity=0; iEntity<ctEntities; iEntity++)
- {
- aplClones[ iEntity] = apenClones[ iEntity].GetPlacement();
- }}
- // delete clones with their descendents
- {for( INDEX iEntity=0; iEntity<ctEntities; iEntity++)
- {
- DeleteEntityWithDescendents( m_woWorld, &apenClones[ iEntity]);
- }}
- // clone entity(ies) for each remembered placement
- {for( INDEX iEntity=0; iEntity<ctEntities; iEntity++)
- {
- m_woWorld.CopyEntityInWorld( *penOnlySelected, aplClones[ iEntity]);
- }}
- apenClones.Unlock();
- m_chSelections.MarkChanged();
- m_chDocument.MarkChanged();
- SetModifiedFlag();
- UpdateAllViews( NULL);
- }
- void CWorldEditorDoc::SetCutMode( CWorldEditorView *pwedView)
- {
- POSITION pos = GetFirstViewPosition();
- CWorldEditorView *pwedTemp;
- FOREVER
- {
- pwedTemp = (CWorldEditorView *) GetNextView(pos);
- if( pwedTemp == NULL) return;
- if( pwedTemp == pwedView)
- {
- pwedTemp->m_bCutMode = TRUE;
- }
- }
- }
- void CreateCuttingWorld( FLOATplane3D &plPolygon, FLOATaabbox3D &box, CObject3D &o3d)
- {
- // ------------------- Create polygon that will be used for cutting
- FLOAT3D v0, v1, v2, v3;
- v0=v1=v2=v3= FLOAT3D( 0.0f, 0.0f, 0.0f);
- // find major axes of the polygon plane
- INDEX iMajorAxis1, iMajorAxis2;
- GetMajorAxesForPlane( plPolygon, iMajorAxis1, iMajorAxis2);
- FLOAT3D vCenter = box.Center();
- FLOAT fSize = box.Size().Length();
- v0(iMajorAxis1) = vCenter(iMajorAxis1)-fSize; v0(iMajorAxis2) = vCenter(iMajorAxis2)+fSize;
- v1(iMajorAxis1) = vCenter(iMajorAxis1)+fSize; v1(iMajorAxis2) = vCenter(iMajorAxis2)+fSize;
- v2(iMajorAxis1) = vCenter(iMajorAxis1)+fSize; v2(iMajorAxis2) = vCenter(iMajorAxis2)-fSize;
- v3(iMajorAxis1) = vCenter(iMajorAxis1)-fSize; v3(iMajorAxis2) = vCenter(iMajorAxis2)-fSize;
- // project coordinates back to plane
- FLOAT3D vp0, vp1, vp2, vp3;
- vp0 = plPolygon.ProjectPoint( v0);
- vp1 = plPolygon.ProjectPoint( v1);
- vp2 = plPolygon.ProjectPoint( v2);
- vp3 = plPolygon.ProjectPoint( v3);
- // add vertices
- CObjectSector *pos = o3d.ob_aoscSectors.New(1);
- pos->osc_aovxVertices.New(4);
- pos->osc_aovxVertices.Lock();
- pos->osc_aovxVertices[0] = FLOATtoDOUBLE(vp0);
- pos->osc_aovxVertices[1] = FLOATtoDOUBLE(vp1);
- pos->osc_aovxVertices[2] = FLOATtoDOUBLE(vp2);
- pos->osc_aovxVertices[3] = FLOATtoDOUBLE(vp3);
- // add edges
- pos->osc_aoedEdges.New(4);
- pos->osc_aoedEdges.Lock();
- pos->osc_aoedEdges[0].oed_Vertex0 = &pos->osc_aovxVertices[0];
- pos->osc_aoedEdges[0].oed_Vertex1 = &pos->osc_aovxVertices[1];
- pos->osc_aoedEdges[1].oed_Vertex0 = &pos->osc_aovxVertices[1];
- pos->osc_aoedEdges[1].oed_Vertex1 = &pos->osc_aovxVertices[2];
- pos->osc_aoedEdges[2].oed_Vertex0 = &pos->osc_aovxVertices[2];
- pos->osc_aoedEdges[2].oed_Vertex1 = &pos->osc_aovxVertices[3];
- pos->osc_aoedEdges[3].oed_Vertex0 = &pos->osc_aovxVertices[3];
- pos->osc_aoedEdges[3].oed_Vertex1 = &pos->osc_aovxVertices[0];
-
- // add plane
- CObjectPlane *popl = pos->osc_aoplPlanes.New(1);
- *popl = FLOATtoDOUBLE(plPolygon);
- // add material
- CObjectMaterial *pom = pos->osc_aomtMaterials.New(1);
- // set must-exist texture
- pom->omt_Name = "Textures\\Editor\\Default.tex";
- // add polygon
- CObjectPolygon *pop = pos->osc_aopoPolygons.New(1);
- pop->opo_Plane = popl;
- pop->opo_Material = pom;
- pop->opo_PolygonEdges.New(4);
- pop->opo_PolygonEdges.Lock();
- pop->opo_PolygonEdges[0].ope_Edge = &pos->osc_aoedEdges[0];
- pop->opo_PolygonEdges[1].ope_Edge = &pos->osc_aoedEdges[1];
- pop->opo_PolygonEdges[2].ope_Edge = &pos->osc_aoedEdges[2];
- pop->opo_PolygonEdges[3].ope_Edge = &pos->osc_aoedEdges[3];
- pop->opo_PolygonEdges.Unlock();
- // unlock locked arrays
- pos->osc_aovxVertices.Unlock();
- pos->osc_aoedEdges.Unlock();
- }
- void CWorldEditorDoc::ApplyCut( void)
- {
- // find the view that defines cut plane
- POSITION posView = GetFirstViewPosition();
- if( m_pCutLineView == NULL)
- {
- ASSERTALWAYS( "Cut line view wasn't set properly!");
- // don't allow calling without cutting view ptr set
- return;
- }
- CWorldEditorView *pwedView;
- FOREVER
- {
- pwedView = (CWorldEditorView *) GetNextView(posView);
- // if we didn't find it in list of views
- if( pwedView == NULL)
- {
- // don't do anything
- return;
- }
- // if we found it
- if( pwedView == m_pCutLineView)
- {
- // stop looping
- break;
- }
- }
- // calculate cutting plane
- FLOAT3D &vcl0 = m_vCutLineStart;
- FLOAT3D &vcl1 = m_vCutLineEnd;
- // get cutting edge vector
- FLOAT3D vCutLine = vcl1-vcl0;
- // cross product with viewer direction vector will give us cutting plane normal
- // so calculate viewer direction vector
- CAnyProjection3D prProjection;
- // create a slave viewer
- CSlaveViewer svViewer(
- m_pCutLineView->GetChildFrame()->m_mvViewer,
- m_pCutLineView->m_ptProjectionType,
- m_plGrid,
- m_pCutLineView->m_pdpDrawPort);
- svViewer.MakeProjection(prProjection);
- prProjection->Prepare();
- // make the ray from viewer point through the dummy point, in current projection
- CPlacement3D plRay;
- prProjection->RayThroughPoint( FLOAT3D(0.0f, 0.0f, 0.0f), plRay);
- // get viewer's direction vector
- FLOAT3D vDirection;
- AnglesToDirectionVector( plRay.pl_OrientationAngle, vDirection);
-
- // make cross product
- FLOAT3D vNormal = vCutLine * vDirection;
-
- // create plane from normal vector and one of cutting edge points
- FLOATplane3D plPolygon(vNormal, vcl0);
- // exit cut mode
- theApp.m_bCutModeOn = FALSE;
- // we need to obtain brush for CSG
- CBrush3D *pbrBrush = NULL;
- // if we are in polygon mode
- if( GetEditingMode() == POLYGON_MODE)
- {
- CBrushPolygon *pbpo = m_selPolygonSelection.GetFirstInSelection();
- if( pbpo == NULL)
- {
- ASSERTALWAYS( "Apply cut called in polygon mode, but none polygon is selected.");
- return;
- }
- pbrBrush = pbpo->bpo_pbscSector->bsc_pbmBrushMip->bm_pbrBrush;
- }
- else if( GetEditingMode() == ENTITY_MODE)
- {
- // do nothing
- }
- else
- {
- // we must be in sector mode
- ASSERT( GetEditingMode() == SECTOR_MODE);
- CBrushSector *pbsc = m_selSectorSelection.GetFirstInSelection();
- if( pbsc == NULL)
- {
- ASSERTALWAYS( "Apply cut called in sector mode, but none sector is selected.");
- return;
- }
- pbrBrush = pbsc->bsc_pbmBrushMip->bm_pbrBrush;
- }
- // brush containing polygon or sector will be our target entity
- CEntity *penTarget = NULL;
- if( pbrBrush != NULL)
- {
- penTarget=pbrBrush->br_penEntity;
- }
- RememberUndo();
- // ------------------- Create cutting world
- // obtain child frame
- CChildFrame *pWedChild = pwedView->GetChildFrame();
- // remember auto mip brushing flag
- BOOL bAutoMipBrushingOn = pWedChild->m_bAutoMipBrushingOn;
- // turn off auto mip brushing
- pWedChild->m_bAutoMipBrushingOn = FALSE;
- // create world cutter
- CWorld woCutter;
- // create zero-placement
- CPlacement3D plOrigin;
- plOrigin.pl_PositionVector = FLOAT3D(0.0f,0.0f,0.0f);
- plOrigin.pl_OrientationAngle = ANGLE3D(0,0,0);
- // create main brush entity
- CEntity *penCutter = NULL;
- try
- {
- penCutter = woCutter.CreateEntity_t( plOrigin, CTFILENAME("Classes\\WorldBase.ecl"));
- }
- catch( char *err_str)
- {
- AfxMessageBox( CString(err_str));
- return;
- }
- // prepare the entity
- penCutter->Initialize();
- if( GetEditingMode() == ENTITY_MODE)
- {
- }
- else
- {
- // ------------------- Create brush mip and sector
- CBrush3D *pbr = penCutter->GetBrush();
- // brush must exist
- if( pbr == NULL)
- {
- ASSERTALWAYS( "Brush not properly initialized!");
- return;
- }
- FLOATaabbox3D box;
- // obtain bounding box of selected polygons/sectors
- if( GetEditingMode() == POLYGON_MODE)
- {
- FOREACHINDYNAMICCONTAINER(m_selPolygonSelection, CBrushPolygon, itbpo)
- {
- box |= itbpo->bpo_boxBoundingBox;
- }
- }
- else if( GetEditingMode() == SECTOR_MODE)
- {
- FOREACHINDYNAMICCONTAINER(m_selSectorSelection, CBrushSector, itbsc)
- {
- box |= itbsc->bsc_boxBoundingBox;
- }
- }
- // create object3d to hold plane-cutter primitive
- CObject3D o3d;
- CreateCuttingWorld( plPolygon, box, o3d);
-
- // convert object 3d to brush
- try
- {
- pbr->FromObject3D_t( o3d);
- pbr->CalculateBoundingBoxes();
- }
- // report errors
- catch( char *err_str)
- {
- AfxMessageBox( CString(err_str));
- }
- // -------- Apply BSP cut operation
- if( GetEditingMode() == POLYGON_MODE)
- {
- // clear all selections except polygon seletion
- ClearSelections( ST_POLYGON);
- // apply "split polygons"
- m_woWorld.SplitPolygons(*penTarget, m_selPolygonSelection, woCutter, *penCutter, plOrigin);
- }
- else
- {
- // clear all selections except sector seletion
- ClearSelections( ST_SECTOR);
- // apply "split sectors"
- m_woWorld.SplitSectors(*penTarget, m_selSectorSelection, woCutter, *penCutter, plOrigin);
- }
- }
- // restore auto mip brushing
- pWedChild->m_bAutoMipBrushingOn = bAutoMipBrushingOn;
- m_chSelections.MarkChanged();
- SetModifiedFlag(TRUE);
- m_chDocument.MarkChanged();
- UpdateAllViews( NULL);
- }
- void CWorldEditorDoc::ReloadWorld(void)
- {
- // clear selections
- ClearSelections();
- m_chDocument.MarkChanged();
- // try to
- try
- {
- // load new world from the undo file
- m_woWorld.Load_t(m_woWorld.wo_fnmFileName);
- // flush stale caches
- _pShell->Execute("FreeUnusedStock();");
- // invalidate document (i.e. all views)
- UpdateAllViews( NULL);
- }
- // report errors
- catch( char *err_str)
- {
- AfxMessageBox( CString(err_str));
- }
- }
- void CWorldEditorDoc::OnCheckEdit(void)
- {
- CTFileName fnmFileName;
- ExpandFilePath(EFP_READ, m_woWorld.wo_fnmFileName, fnmFileName);
- CTString strCommand;
- strCommand.PrintF("p4 edit %s", fnmFileName);
- INDEX iResult = system(strCommand);
- if(iResult != 0) {
- WarningMessage( "Unable to perform open for edit!");
- return;
- }
- ReloadWorld();
- CTString strMessage;
- strMessage.PrintF("Opened for edit: %s", (const char *)m_woWorld.wo_fnmFileName);
- AfxMessageBox( CString(strMessage));
- }
- void CWorldEditorDoc::OnCheckAdd()
- {
- CTFileName fnmFileName;
- ExpandFilePath(EFP_READ, m_woWorld.wo_fnmFileName, fnmFileName);
- CTString strCommand;
- strCommand.PrintF("p4 add %s", fnmFileName);
- INDEX iResult = system(strCommand);
- if(iResult != 0) {
- WarningMessage( "Unable to perform open for add!");
- return;
- }
- ReloadWorld();
- CTString strMessage;
- strMessage.PrintF( "Marked for add: %s", (const char *)m_woWorld.wo_fnmFileName);
- AfxMessageBox( CString(strMessage));
- }
- void CWorldEditorDoc::OnCheckDelete()
- {
- CTFileName fnmFileName;
- ExpandFilePath(EFP_READ, m_woWorld.wo_fnmFileName, fnmFileName);
- CTString strCommand;
- strCommand.PrintF("p4 delete %s", fnmFileName);
- INDEX iResult = system(strCommand);
- if(iResult != 0) {
- WarningMessage( "Unable to perform open for delete!");
- return;
- }
- ReloadWorld();
- CTString strMessage;
- strMessage.PrintF( "Marked for delete: %s", (const char *)m_woWorld.wo_fnmFileName);
- AfxMessageBox( CString(strMessage));
- }
- BOOL CWorldEditorDoc::IsReadOnly(void)
- {
- return IsFileReadOnly(m_woWorld.wo_fnmFileName);
- }
- void CWorldEditorDoc::OnUpdateCheckEdit(CCmdUI* pCmdUI)
- {
- pCmdUI->Enable(TRUE);
- }
- void CWorldEditorDoc::OnUpdateCheckAdd(CCmdUI* pCmdUI)
- {
- pCmdUI->Enable(TRUE);
- }
- void CWorldEditorDoc::OnUpdateCheckDelete(CCmdUI* pCmdUI)
- {
- pCmdUI->Enable(TRUE);
- }
- BOOL CWorldEditorDoc::IsBrushUpdatingAllowed(void)
- {
- // if only one entity is selected
- if( m_selEntitySelection.Count()==1)
- {
- // get only selected entity
- CEntity *pen = m_selEntitySelection.GetFirstInSelection();
- // if it is brush entity
- if (pen->en_RenderType == CEntity::RT_BRUSH && pen->en_pbrBrush!=NULL)
- {
- // allow updating
- return TRUE;
- }
- }
- // disable updating
- return FALSE;
- }
- void CWorldEditorDoc::OnUpdateBrushes()
- {
- POSITION pos = GetFirstViewPosition();
- CWorldEditorView *pWedView = (CWorldEditorView *) GetNextView(pos);
- ASSERT( pWedView != NULL);
- RememberUndo();
- // get only selected entity
- CEntity *pen = m_selEntitySelection.GetFirstInSelection();
- CTString strClone=pen->GetName();
- FOREACHINDYNAMICCONTAINER(m_woWorld.wo_cenEntities, CEntity, iten)
- {
- if(iten!=pen &&
- iten->GetName()==strClone &&
- iten->en_RenderType==CEntity::RT_BRUSH)
- {
- iten->en_pbrBrush->Copy(*pen->en_pbrBrush, 1.0f, FALSE);
- pWedView->DiscardShadows( &*iten);
- }
- }
- UpdateAllViews( NULL);
- }
- void CWorldEditorDoc::OnInsert3dObject()
- {
- theApp.Insert3DObjects(this);
- }
- void CWorldEditorDoc::OnExport3dObject()
- {
- CTFileName fnName = _EngineGUI.FileRequester( "Export polygons as ...",
- "Raw 3D object\0*.raw\0" FILTER_ALL FILTER_END, "Export geometry directory", "Worlds\\");
- if( fnName == "") return;
-
- try
- {
- CTFileStream strmFile;
- strmFile.Create_t( fnName);
- strmFile.PutLine_t("No name");
- // for each of the selected polygons
- FOREACHINDYNAMICCONTAINER( m_selPolygonSelection, CBrushPolygon, itbpo)
- {
- CBrushPolygon &bpo = *itbpo;
- for( INDEX iVtx=0; iVtx<bpo.bpo_aiTriangleElements.Count(); iVtx+=3)
- {
- CBrushVertex &vtx1=*bpo.bpo_apbvxTriangleVertices[bpo.bpo_aiTriangleElements[iVtx+0]];
- CBrushVertex &vtx2=*bpo.bpo_apbvxTriangleVertices[bpo.bpo_aiTriangleElements[iVtx+1]];
- CBrushVertex &vtx3=*bpo.bpo_apbvxTriangleVertices[bpo.bpo_aiTriangleElements[iVtx+2]];
- CTString strTemp;
- strTemp.PrintF("%g %g %g %g %g %g %g %g %g",
- vtx1.bvx_vAbsolute(1), vtx1.bvx_vAbsolute(2), vtx1.bvx_vAbsolute(3),
- vtx2.bvx_vAbsolute(1), vtx2.bvx_vAbsolute(2), vtx2.bvx_vAbsolute(3),
- vtx3.bvx_vAbsolute(1), vtx3.bvx_vAbsolute(2), vtx3.bvx_vAbsolute(3));
- strmFile.PutLine_t( strTemp);
- }
- }
- strmFile.Close();
- }
- catch( char *err_str)
- {
- AfxMessageBox( CString(err_str));
- }
- }
- void CWorldEditorDoc::OnUpdateExport3dObject(CCmdUI* pCmdUI)
- {
- pCmdUI->Enable( m_selPolygonSelection.Count()!=0);
- }
- void CWorldEditorDoc::OnPopupVtxAllign()
- {
- CDlgAllignVertices dlg;
- dlg.DoModal();
- }
- void CWorldEditorDoc::OnPopupVtxFilter()
- {
- CDlgFilterVertexSelection dlg;
- dlg.DoModal();
- }
- void CWorldEditorDoc::OnPopupVtxNumeric()
- {
- CDlgSnapVertex dlg;
- dlg.DoModal();
- }
- void CWorldEditorDoc::OnExportPlacements()
- {
- CStaticStackArray<CTString> astrNeddedSmc;
- try
- {
- CTFileName fnWorld=m_woWorld.wo_fnmFileName;
- // "entity placement and names"
- CTFileName fnExport=fnWorld.FileDir()+fnWorld.FileName()+".epn";
- // open text file
- CTFileStream strmFile;
- strmFile.Create_t( fnExport, CTStream::CM_TEXT);
- // for each entity in world
- FOREACHINDYNAMICCONTAINER(m_woWorld.wo_cenEntities, CEntity, iten)
- {
- CEntity &en=*iten;
- // obtain entity class ptr
- CDLLEntityClass *pdecDLLClass = en.GetClass()->ec_pdecDLLClass;
- // obtain position
- FLOAT3D vPos=en.GetPlacement().pl_PositionVector;
- FLOAT3D vRot=en.GetPlacement().pl_OrientationAngle;
- // dump class name and placement
- CTString strLine;
- CTString strName=en.GetName();
- if(strName=="") {
- strName="Dummy name";
- }
- strLine.PrintF("Class: \"%s\", Name: \"%s\", Position: (%f, %f, %f), Rotation: (%f, %f, %f)",
- pdecDLLClass->dec_strName, strName, vPos(1), vPos(2), vPos(3), vRot(1), vRot(2), vRot(3));
- strmFile.PutLine_t(strLine);
- // if this is model holder 3 class, we should also dump model path
- if(CTString(pdecDLLClass->dec_strName)=="ModelHolder3")
- {
- CTFileName fnmFile=CTString("Unknown");
- FLOAT3D vStretch=FLOAT3D(1.0f,1.0f,1.0f);
- // for all classes in hierarchy of this entity
- for(;pdecDLLClass!=NULL; pdecDLLClass = pdecDLLClass->dec_pdecBase)
- {
- // for all properties
- for(INDEX iProperty=0; iProperty<pdecDLLClass->dec_ctProperties; iProperty++)
- {
- CEntityProperty *pepProperty = &pdecDLLClass->dec_aepProperties[iProperty];
- if( pepProperty->ep_eptType == CEntityProperty::EPT_FILENAME &&
- CTString(pepProperty->ep_strName) == "Model file (.smc)")
- {
- // obtain file name
- fnmFile = ENTITYPROPERTY( &en, pepProperty->ep_slOffset, CTFileName);
- BOOL bExistsInList=FALSE;
- for(INDEX iSmc=0; iSmc<astrNeddedSmc.Count(); iSmc++)
- {
- if(astrNeddedSmc[iSmc]==CTString(fnmFile))
- {
- bExistsInList=TRUE;
- break;
- }
- }
- if(!bExistsInList)
- {
- CTString &strNew=astrNeddedSmc.Push();
- strNew=CTString(fnmFile);
- }
- }
- if( pepProperty->ep_eptType == CEntityProperty::EPT_FLOAT &&
- CTString(pepProperty->ep_strName) == "StretchAll")
- {
- FLOAT fStretchAll = ENTITYPROPERTY( &en, pepProperty->ep_slOffset, FLOAT);
- vStretch(1)*=fStretchAll;
- vStretch(2)*=fStretchAll;
- vStretch(3)*=fStretchAll;
- }
- if( pepProperty->ep_eptType == CEntityProperty::EPT_ANGLE3D &&
- CTString(pepProperty->ep_strName) == "StretchXYZ")
- {
- ANGLE3D vStretchXYZ = ENTITYPROPERTY( &en, pepProperty->ep_slOffset, ANGLE3D);
- vStretch(1)*=vStretchXYZ(1);
- vStretch(2)*=vStretchXYZ(2);
- vStretch(3)*=vStretchXYZ(3);
- }
- }
- }
- CTString strLine;
- strLine.PrintF("Smc: \"%s\" Stretch: (%f, %f, %f)", CTString(fnmFile), vStretch(1), vStretch(2), vStretch(3));
- strmFile.PutLine_t(strLine);
- }
- }
-
- // "entity placement and names"
- CTFileName fnSml=fnWorld.FileDir()+fnWorld.FileName()+".sml";
- // open text file
- CTFileStream strmSmlFile;
- strmSmlFile.Create_t( fnSml, CTStream::CM_TEXT);
- // save needed smc's
- for(INDEX iSmc=0; iSmc<astrNeddedSmc.Count(); iSmc++)
- {
- strmSmlFile.PutLine_t(astrNeddedSmc[iSmc]);
- }
- AfxMessageBox(L"Placements exported!", MB_OK|MB_ICONINFORMATION);
- }
- catch( char *err_str)
- {
- AfxMessageBox( CString(err_str));
- }
- }
- CTFileName CorrectSlashes(const CTFileName &fnmFile)
- {
- char afnmSlash[1024];
- for(INDEX iChar=0; iChar<fnmFile.Length(); iChar++) {
- afnmSlash[iChar] = fnmFile[iChar];
- if(afnmSlash[iChar]=='\\') {
- afnmSlash[iChar] = '/';
- }
- }
- // end the string
- afnmSlash[fnmFile.Length()] = 0;
- return CTString(afnmSlash);
- }
- // Detects detail texture and replaces it with normal map texture
- CTFileName RemapDetailTexturePath(CTFileName &fnmFile)
- {
- if(fnmFile.FindSubstr("/Detail/") >=0) {
- return fnmFile.FileDir() + fnmFile.FileName() + "_NM.tex";
- }
- return fnmFile;
- }
- CTString FixQuotes(const CTString &strOrg)
- {
- char achrFixed[1024];
- INDEX iFixedChar = 0;
- for(INDEX iChar=0; iChar<strOrg.Length(); iChar++) {
- // if we found a quote
- if(strOrg[iChar]=='\"') {
- // replace it with \"
- achrFixed[iFixedChar++] = '\\';
- achrFixed[iFixedChar++] = '\"';
- } else {
- achrFixed[iFixedChar++] = strOrg[iChar];
- }
- }
- // end the string
- achrFixed[iFixedChar] = 0;
- return CTString(achrFixed);
- }
- // Class used to represent polygon during brush to .amf exporting
- class CAmfNGon {
- public:
- CDynamicContainer<CBrushVertex> ang_cbpoVertices;
- public:
- void FromBrushPolygon(CBrushPolygon *pbpo);
- };
- // Class used to represent polygon during brush to .amf exporting
- class CAmfPolygon {
- public:
- CStaticStackArray<CAmfNGon> amfp_aangNgons;
- public:
- void FromBrushPolygon(CBrushPolygon *pbpo);
- };
- // Creates polygon consisting of vertex loop from brush polygon
- void CAmfPolygon::FromBrushPolygon(CBrushPolygon *pbpo)
- {
- // make copy of the index array
- CStaticArray<INDEX> aiTriangles;
- aiTriangles.CopyArray( pbpo->bpo_aiTriangleElements);
- _nextNgon:
- // copy loop into n-gon
- CAmfNGon &aNgon = amfp_aangNgons.Push();
- // find first triangle that is not handled
- INDEX iFirstNGonTriangle = -1;
- {for(INDEX iTri=0; iTri<aiTriangles.Count()/3; iTri++) {
- if(aiTriangles[iTri*3] != -1) {
- iFirstNGonTriangle=iTri;
- break;
- }
- }}
- // triangle must be found
- if(iFirstNGonTriangle==-1) {
- return;
- }
-
- // and add it to the loop and mark them as handled
- aNgon.ang_cbpoVertices.Add( pbpo->bpo_apbvxTriangleVertices[aiTriangles[iFirstNGonTriangle*3+0]]); aiTriangles[iFirstNGonTriangle*3+0] = -1;
- aNgon.ang_cbpoVertices.Add( pbpo->bpo_apbvxTriangleVertices[aiTriangles[iFirstNGonTriangle*3+1]]); aiTriangles[iFirstNGonTriangle*3+1] = -1;
- aNgon.ang_cbpoVertices.Add( pbpo->bpo_apbvxTriangleVertices[aiTriangles[iFirstNGonTriangle*3+2]]); aiTriangles[iFirstNGonTriangle*3+2] = -1;
-
- // re-entry point for expanding loop
- _nextLoopEdge:;
- // for each loop's edge
- for(INDEX iLoopEdge=0; iLoopEdge<aNgon.ang_cbpoVertices.Count(); iLoopEdge++) {
- // get edge vertices
- CBrushVertex *pbvLoop0 = &aNgon.ang_cbpoVertices[iLoopEdge];
- CBrushVertex *pbvLoop1 = &aNgon.ang_cbpoVertices[(iLoopEdge+1)%aNgon.ang_cbpoVertices.Count()];
- // find triangle that shares edge
- for(INDEX iTri=0; iTri<aiTriangles.Count()/3; iTri++) {
- // for each edge in triangle
- for(INDEX iTriEdge=0; iTriEdge<3; iTriEdge++) {
- // fetch edge vertex indices
- INDEX iTriVtx0 = aiTriangles[iTri*3+iTriEdge];
- INDEX iTriVtx1 = aiTriangles[iTri*3+(iTriEdge+1)%3];
- // if triangle is already handled
- if(iTriVtx0==-1 || iTriVtx1==-1) {
- break;
- }
- CBrushVertex *pbvEdg0 = pbpo->bpo_apbvxTriangleVertices[iTriVtx0];
- CBrushVertex *pbvEdg1 = pbpo->bpo_apbvxTriangleVertices[iTriVtx1];
- // if this edge is the same as the loop edge
- if(pbvLoop0==pbvEdg1 && pbvLoop1==pbvEdg0) {
- // find index of vertex to insert (third vertex)
- INDEX iThirdVtxNo;
- if(iTriEdge==0) { iThirdVtxNo=2;}
- else if(iTriEdge==1) { iThirdVtxNo=0;}
- else { iThirdVtxNo=1;}
- INDEX iThirdVertex = aiTriangles[iTri*3+iThirdVtxNo];
- // mark that triangle is integrated into the loop
- aiTriangles[iTri*3+0] = -1;
- aiTriangles[iTri*3+1] = -1;
- aiTriangles[iTri*3+2] = -1;
- CBrushVertex *pbvThird = pbpo->bpo_apbvxTriangleVertices[iThirdVertex];
- aNgon.ang_cbpoVertices.Insert(pbvThird, iLoopEdge+1);
- goto _nextLoopEdge;
- }
- }
- }
- }
- // test if all triangles are cleared
- {for(INDEX iTri=0; iTri<aiTriangles.Count()/3; iTri++) {
- // if not all are cleared
- if(aiTriangles[iTri*3] != -1) {
- // add another ngon
- goto _nextNgon;
- }
- }}
- }
- // Types of exported types
- enum ExportType {
- ET_RENDERING,
- ET_VISIBILITY,
- };
- // Class used to collect surface data for brush to .amf exporting
- class CAmfSurface {
- public:
- CDynamicContainer<CBrushPolygon> sf_cbpoPolygons;
- CAnimData *sf_padAnimData; // surface's texture
- UBYTE sf_ubMaterial; // surface's material
- public:
- CAmfSurface(void) {
- sf_padAnimData = NULL;
- };
-
- // Calculates count of ngons
- INDEX GetNGonCount(void) {
- INDEX ctNgons = 0;
- for(INDEX iPlg=0; iPlg<sf_cbpoPolygons.Count(); iPlg++) {
- CBrushPolygon &bpo = sf_cbpoPolygons[iPlg];
- CAmfPolygon *amfp = (CAmfPolygon *)bpo.bpo_pspoScreenPolygon;
- ctNgons += amfp->amfp_aangNgons.Count();
- }
- return ctNgons;
- };
- // Calculates count of ngon vertices
- INDEX GetNGonVertexCount(void) {
- INDEX ctVertices = 0;
- for(INDEX iPlg=0; iPlg<sf_cbpoPolygons.Count(); iPlg++) {
- CBrushPolygon &bpo = sf_cbpoPolygons[iPlg];
- CAmfPolygon *amfp = (CAmfPolygon *)bpo.bpo_pspoScreenPolygon;
- for(INDEX iNgon=0; iNgon<amfp->amfp_aangNgons.Count(); iNgon++) {
- CAmfNGon &aNgon = amfp->amfp_aangNgons[iNgon];
- ctVertices += aNgon.ang_cbpoVertices.Count();
- }
- }
- return ctVertices;
- };
- };
- // Tests if given polygon is visible
- BOOL IsPolygonVisible(const CBrushPolygon &bpo)
- {
- // if is invisible
- if(bpo.bpo_ulFlags&BPOF_INVISIBLE) {
- return FALSE;
- }
- // if is portal
- if(bpo.bpo_ulFlags&BPOF_PORTAL) {
- // if is translucent portal
- if(bpo.bpo_ulFlags&BPOF_TRANSLUCENT) {
- // it is visible
- return TRUE;
- }
- return FALSE;
- }
- return TRUE;
- }
- // Exports one layer of given type
- void ExportLayer_t(CWorldEditorDoc *pDoc, CEntity &en, ExportType etExportType, CBrushMip *pbmMip, CTFileStream &strmAmf,
- const CString &strLayerName, INDEX iLayerNo, BOOL bFieldBrush, BOOL bCollisionOnlyBrush)
- {
- // sort brush polygons for their textures
- CDynamicContainer<CAmfSurface> cbpoSurfaces;
- // assume that there will not be any portals nor occluders
- CStaticStackArray<INDEX> ciPortals;
- CStaticStackArray<INDEX> ciOccluders;
- CStaticStackArray<INDEX> ciClassifiers;
-
- // for each sector in the brush mip
- INDEX iPlgGlobal=0;
- {for(INDEX iSector=0; iSector<pbmMip->bm_abscSectors.Count(); iSector++) {
- CBrushSector &bs = pbmMip->bm_abscSectors[iSector];
- // for each polygon in the sector
- for(INDEX iPlg=0; iPlg<bs.bsc_abpoPolygons.Count(); iPlg++) {
- CBrushPolygon &bpo = bs.bsc_abpoPolygons[iPlg];
- // if we are exporting collision (e.g. for empty brushes)
- if(etExportType==ET_RENDERING) {
- if(!bFieldBrush && (!IsPolygonVisible(bpo) && !bCollisionOnlyBrush) ) {
- continue;
- }
- CAnimData *pad = bpo.bpo_abptTextures[0].bpt_toTexture.GetData();
- UBYTE ubMaterial = bpo.bpo_bppProperties.bpp_ubSurfaceType;
- BOOL bFound = FALSE;
- for(INDEX iSurf=0; iSurf<cbpoSurfaces.Count(); iSurf++) {
- CAmfSurface &asSurf = cbpoSurfaces[iSurf];
- // if this surface for the texture-surface pair is already defined
- if( (asSurf.sf_padAnimData==pad) && (asSurf.sf_ubMaterial==ubMaterial) ) {
- // add polygon to existing surface
- asSurf.sf_cbpoPolygons.Add(&bpo);
- bFound = TRUE;
- break;
- }
- }
- // if surface with current texture and material is not yet defined
- if(!bFound) {
- CAmfSurface *pSurf = (CAmfSurface *) new(CAmfSurface);
- cbpoSurfaces.Add(pSurf);
- pSurf->sf_cbpoPolygons.Add(&bpo);
- pSurf->sf_padAnimData = pad;
- pSurf->sf_ubMaterial = ubMaterial;
- }
- } else if(etExportType==ET_VISIBILITY) {
- BOOL bClassifier = FALSE;
- BOOL bOccluder = FALSE;
- BOOL bPortal = FALSE;
- // if this polygon is not involved in visibility
- if(bpo.bpo_ulFlags&BPOF_DETAILPOLYGON) {
- bClassifier = TRUE;
- }
- else if(bpo.bpo_ulFlags&BPOF_OCCLUDER) {
- bOccluder = TRUE;
- }
- else if(bpo.bpo_ulFlags&BPOF_PORTAL) {
- bPortal = TRUE;
- }
- // if surface is not yet defined
- if(cbpoSurfaces.Count()==0) {
- // add one
- CAmfSurface *pSurf = (CAmfSurface *) new(CAmfSurface);
- cbpoSurfaces.Add(pSurf);
- }
- CAmfPolygon *amfp = (CAmfPolygon *)bpo.bpo_pspoScreenPolygon;
- for(INDEX iNgon=0; iNgon<amfp->amfp_aangNgons.Count(); iNgon++) {
- if(bClassifier) { ciClassifiers.Push() = iPlgGlobal; }
- if(bOccluder) { ciOccluders.Push() = iPlgGlobal; }
- if(bPortal) { ciPortals.Push() = iPlgGlobal; }
- iPlgGlobal++;
- }
- cbpoSurfaces[0].sf_cbpoPolygons.Add(&bpo);
- }
- }
- }}
- // count total surface polygons and vertices
- INDEX ctTotalPolygons = 0;
- INDEX ctTotalVertices = 0;
- {for(INDEX iSurf=0; iSurf<cbpoSurfaces.Count(); iSurf++) {
- CAmfSurface &amfs = cbpoSurfaces[iSurf];
- ctTotalPolygons+=amfs.GetNGonCount();
- ctTotalVertices+=amfs.GetNGonVertexCount();
- }}
- // if there is no polygons to export
- if(ctTotalPolygons==0) {
- return;
- }
-
- strmAmf.FPrintF_t(" LAYER_NAME \"%s\"\n", strLayerName);
- strmAmf.FPrintF_t(" LAYER_INDEX %d\n", iLayerNo);
- strmAmf.PutLine_t(" {");
- INDEX ctVertexMaps = etExportType==ET_RENDERING ? 4 : 1;
- strmAmf.FPrintF_t(" VERTEX_MAPS %d\n", ctVertexMaps);
- strmAmf.PutLine_t(" {");
- strmAmf.PutLine_t(" VERTEX_MAP \"morph.position\"");
- strmAmf.PutLine_t(" {");
- strmAmf.FPrintF_t(" ELEMENTS %d\n", ctTotalVertices);
- strmAmf.PutLine_t(" {");
- {for(INDEX iSurf=0; iSurf<cbpoSurfaces.Count(); iSurf++) {
- CAmfSurface &asSurf = cbpoSurfaces[iSurf];
- for(INDEX iPlg=0; iPlg<asSurf.sf_cbpoPolygons.Count(); iPlg++) {
- CBrushPolygon &bpo = asSurf.sf_cbpoPolygons[iPlg];
- CAmfPolygon *amfp = (CAmfPolygon *)bpo.bpo_pspoScreenPolygon;
- for(INDEX iNgon=0; iNgon<amfp->amfp_aangNgons.Count(); iNgon++) {
- CAmfNGon &aNgon = amfp->amfp_aangNgons[iNgon];
- for(INDEX iVtx=0; iVtx<aNgon.ang_cbpoVertices.Count(); iVtx++) {
- CBrushVertex &bVtx = aNgon.ang_cbpoVertices[iVtx];
- strmAmf.FPrintF_t(" { %f, %f, %f; }\n", bVtx.bvx_vdPreciseRelative(1), bVtx.bvx_vdPreciseRelative(2), bVtx.bvx_vdPreciseRelative(3));
- }
- }
- }
- }}
- strmAmf.PutLine_t(" }");
- strmAmf.PutLine_t(" }");
- if(etExportType==ET_RENDERING) {
- for(INDEX iTextureLayer=0; iTextureLayer<3; iTextureLayer++) {
- strmAmf.FPrintF_t(" VERTEX_MAP \"texcoord.Texture %d\"", iTextureLayer+1);
- strmAmf.PutLine_t(" {");
- strmAmf.FPrintF_t(" ELEMENTS %d\n", ctTotalVertices);
- strmAmf.PutLine_t(" {");
- {for(INDEX iSurf=0; iSurf<cbpoSurfaces.Count(); iSurf++) {
- CAmfSurface &asSurf = cbpoSurfaces[iSurf];
- for(INDEX iPlg=0; iPlg<asSurf.sf_cbpoPolygons.Count(); iPlg++) {
- CBrushPolygon &bpo = asSurf.sf_cbpoPolygons[iPlg];
- // fetch mapping parameters
- CMappingVectors mvDefault;
- mvDefault.FromPlane_DOUBLE(bpo.bpo_pbplPlane->bpl_pldPreciseRelative);
- // calculate mapping transformation vectors
- CMappingDefinition &md = bpo.bpo_abptTextures[iTextureLayer].bpt_mdMapping;
- // if there is no texture
- MEX mexTexSizeU, mexTexSizeV;
- if(bpo.bpo_abptTextures[iTextureLayer].bpt_toTexture.GetData()==NULL) {
- mexTexSizeU = 1024;
- mexTexSizeV = 1024;
- } else {
- mexTexSizeU = bpo.bpo_abptTextures[iTextureLayer].bpt_toTexture.GetWidth();
- mexTexSizeV = bpo.bpo_abptTextures[iTextureLayer].bpt_toTexture.GetHeight();
- }
- const FLOAT fMulU = 1024.0f /mexTexSizeU; // (no need to do shift-opt, because it won't speed up much!)
- const FLOAT fMulV = 1024.0f /mexTexSizeV;
- CMappingVectors mvTransform;
- md.MakeMappingVectors(mvDefault, mvTransform);
- CAmfPolygon *amfp = (CAmfPolygon *)bpo.bpo_pspoScreenPolygon;
- for(INDEX iNgon=0; iNgon<amfp->amfp_aangNgons.Count(); iNgon++) {
- CAmfNGon &aNgon = amfp->amfp_aangNgons[iNgon];
- for(INDEX iVtx=0; iVtx<aNgon.ang_cbpoVertices.Count(); iVtx++) {
- CBrushVertex &bVtx = aNgon.ang_cbpoVertices[iVtx];
- // calculate mapping coordinates
- FLOAT3D vUV = bVtx.bvx_vRelative-mvTransform.mv_vO;
- FLOAT fU = vUV % mvTransform.mv_vU;
- FLOAT fV = vUV % mvTransform.mv_vV;
- fU *= fMulU;
- fV *= fMulV;
- // fix qnans
- if(!_finite(fU)) { fU=0;}
- if(!_finite(fV)) { fV=0;}
- strmAmf.FPrintF_t(" { %f, %f; }\n", fU, fV);
- }
- }
- }
- }}
- strmAmf.PutLine_t(" }");
- strmAmf.PutLine_t(" }");
- }
- }
- strmAmf.PutLine_t(" }");
- strmAmf.FPrintF_t(" VERTICES %d\n", ctTotalVertices);
- strmAmf.PutLine_t(" {");
- for(INDEX iVtx=0; iVtx<ctTotalVertices; iVtx++) {
- if(etExportType==ET_RENDERING) {
- strmAmf.FPrintF_t(" { 4: 0[%d], 1[%d], 2[%d], 3[%d];}\n", iVtx, iVtx, iVtx, iVtx);
- } else {
- strmAmf.FPrintF_t(" { 1: 0[%d]; }\n", iVtx);
- }
- }
- strmAmf.PutLine_t(" }");
- strmAmf.FPrintF_t(" POLYGONS %d\n", ctTotalPolygons);
- strmAmf.PutLine_t(" {");
- INDEX iPlgVtx = 0;
- {for(INDEX iSurf=0; iSurf<cbpoSurfaces.Count(); iSurf++) {
- CAmfSurface &asSurf = cbpoSurfaces[iSurf];
- for(INDEX iPlg=0; iPlg<asSurf.sf_cbpoPolygons.Count(); iPlg++) {
- CBrushPolygon &bpo = asSurf.sf_cbpoPolygons[iPlg];
- CAmfPolygon *amfp = (CAmfPolygon *)bpo.bpo_pspoScreenPolygon;
- for(INDEX iNgon=0; iNgon<amfp->amfp_aangNgons.Count(); iNgon++) {
- CAmfNGon &aNgon = amfp->amfp_aangNgons[iNgon];
- INDEX ctPlgVertices = aNgon.ang_cbpoVertices.Count();
- if(ctPlgVertices==0) {
- strmAmf.FPrintF_t(" { 3: 0, 0, 0; }\n");
- } else {
- strmAmf.FPrintF_t(" { %d: ", ctPlgVertices);
- for(INDEX iVtx=0; iVtx<ctPlgVertices; iVtx++) {
- if(iVtx==ctPlgVertices-1) {
- strmAmf.FPrintF_t("%d; }\n", iPlgVtx++);
- } else {
- strmAmf.FPrintF_t("%d, ", iPlgVtx++);
- }
- }
- }
- }
- }
- }}
- strmAmf.PutLine_t(" }");
- // for rendering
- if(etExportType==ET_RENDERING) {
- strmAmf.FPrintF_t(" POLYGON_MAPS %d\n", cbpoSurfaces.Count());
- strmAmf.PutLine_t(" {");
- // dump surfaces
- INDEX iPlgGlobal=0;
- {for(INDEX iSurf=0; iSurf<cbpoSurfaces.Count(); iSurf++) {
- CAmfSurface &asSurf = cbpoSurfaces[iSurf];
- CBrushPolygon &bpo = asSurf.sf_cbpoPolygons[0];
- strmAmf.FPrintF_t(" POLYGON_MAP_NAME \"surface.Default_%d_%d\"\n", en.en_ulID, iSurf);
- #if 1
- // dump surface data
- if(bCollisionOnlyBrush) {
- strmAmf.PutLine_t(" POLYGON_MAP_SHADER \"\"");
- } else {
- strmAmf.PutLine_t(" POLYGON_MAP_SHADER \"Bin/Shaders.module|Standard\"");
- }
- strmAmf.PutLine_t(" {");
- // export material info
- CString strMaterial = pDoc->m_woWorld.wo_astSurfaceTypes[asSurf.sf_ubMaterial].st_strName;
- strmAmf.FPrintF_t(" Material \"%s\";\n", strMaterial);
- // export first layer data
- CTFileName strPath;
- strPath = bpo.bpo_abptTextures[0].bpt_toTexture.GetName();
- strPath = CorrectSlashes(strPath);
- strPath = RemapDetailTexturePath(strPath);
- if(bFieldBrush) {
- strmAmf.FPrintF_t(" \"base color\" Color %d;\n", C_GREEN|128);
- strmAmf.FPrintF_t(" \"blend type\" BlendType \"%translucent\";\n");
- strmAmf.FPrintF_t(" \"double sided\" Bool \"TRUE\";\n");
- } else {
- // setup blend type for translucent portals
- if( (bpo.bpo_ulFlags&BPOF_PORTAL) && (bpo.bpo_ulFlags&BPOF_TRANSLUCENT) ) {
- strmAmf.FPrintF_t(" \"blend type\" BlendType \"%translucent\";\n");
- }
- //strPath.SetAbsolutePath();
- //strPath.ReplaceSubstr("\\", "\\\\");
- //strmAmf.FPrintF_t(" \"base texture\" Texture \"%s\";\n", strPath);
- //strmAmf.FPrintF_t(" \"base uvmap\" UVMap \"Texture 1\";\n");
- strmAmf.FPrintF_t(" \"base color\" Color %d;\n", bpo.bpo_abptTextures[0].s.bpt_colColor);
- // export second layer data
- //strPath = bpo.bpo_abptTextures[1].bpt_toTexture.GetName();
- //strPath = CorrectSlashes(strPath);
- //strPath = RemapDetailTexturePath(strPath);
- //strmAmf.FPrintF_t(" \"blend mask\" Texture \"%s\";\n", strPath);
- //strmAmf.FPrintF_t(" \"mask uvmap\" UVMap \"Texture 2\";\n");
- // export third layer data
- //strPath = bpo.bpo_abptTextures[2].bpt_toTexture.GetName();
- //strPath = CorrectSlashes(strPath);
- //strPath = RemapDetailTexturePath(strPath);
- //strmAmf.FPrintF_t(" \"detail normalmap\" Texture \"%s\";\n", strPath);
- //strmAmf.FPrintF_t(" \"detail uvmap\" UVMap \"Texture 3\";\n");
- //strmAmf.FPrintF_t(" \"tangent uvmap\" UVMap \"Texture 3\";\n");
- }
- strmAmf.PutLine_t(" }");
- #else
- strmAmf.PutLine_t(" POLYGON_MAP_SHADER \"Bin/GameSamHD.module|Architecture\"");
- strmAmf.PutLine_t(" {");
- // export material info
- CString strMaterial = pDoc->m_woWorld.wo_astSurfaceTypes[asSurf.sf_ubMaterial].st_strName;
- strmAmf.FPrintF_t(" Material \"%s\";\n", strMaterial);
- // export first layer data
- CTFileName strPath;
- strPath = bpo.bpo_abptTextures[0].bpt_toTexture.GetName();
- strPath = CorrectSlashes(strPath);
- strPath = RemapDetailTexturePath(strPath);
- strmAmf.FPrintF_t(" \"diffuse 1 texture\" Texture \"%s\";\n", strPath);
- strmAmf.FPrintF_t(" \"diffuse 1 uvmap\" UVMap \"Texture 1\";\n");
- // export second layer data
- strPath = bpo.bpo_abptTextures[1].bpt_toTexture.GetName();
- strPath = CorrectSlashes(strPath);
- strPath = RemapDetailTexturePath(strPath);
- strmAmf.FPrintF_t(" \"shade\" Texture \"%s\";\n", strPath);
- strmAmf.FPrintF_t(" \"shade uvmap\" UVMap \"Texture 2\";\n");
- // export third layer data
- strPath = bpo.bpo_abptTextures[2].bpt_toTexture.GetName();
- strPath = CorrectSlashes(strPath);
- strPath = RemapDetailTexturePath(strPath);
- strmAmf.FPrintF_t(" \"normal map 1\" Texture \"%s\";\n", strPath);
- strmAmf.FPrintF_t(" \"normal 1 uvmap\" UVMap \"Texture 3\";\n");
- strmAmf.FPrintF_t(" \"tangent uvmap\" UVMap \"Texture 3\";\n");
- strmAmf.PutLine_t(" }");
- #endif
- strmAmf.PutLine_t(" POLYGON_MAP_SMOOTHING_ANGLE 30");
- INDEX ctSurfacePolygons = asSurf.GetNGonCount();
- strmAmf.FPrintF_t(" POLYGONS_COUNT %d\n", ctSurfacePolygons);
- strmAmf.PutLine_t(" {");
- for(INDEX iPlg=0; iPlg<ctSurfacePolygons; iPlg++) {
- strmAmf.FPrintF_t(" %d;\n", iPlgGlobal++);
- }
- strmAmf.PutLine_t(" }");
- }}
- strmAmf.PutLine_t(" }");
- } else if(etExportType==ET_VISIBILITY) {
- // for visibility
- INDEX ctSectors = pbmMip->bm_abscSectors.Count();
- INDEX iOccluderPolyMaps = ciOccluders.Count()>0 ? 1 : 0;
- INDEX iPortalPolyMaps = ciPortals.Count()>0 ? 1 : 0;
- INDEX iClassifierPolyMaps = ciClassifiers.Count()>0 ? 1 : 0;
- strmAmf.FPrintF_t(" POLYGON_MAPS %d\n", ctSectors+iOccluderPolyMaps+iPortalPolyMaps+iClassifierPolyMaps);
- strmAmf.PutLine_t(" {");
- // dump sectors as separate polygon maps
- {for(INDEX iSector=0; iSector<pbmMip->bm_abscSectors.Count(); iSector++) {
- // count sector polygons
- INDEX ctSectorPolygons = 0;
- CBrushSector *pbs = &pbmMip->bm_abscSectors[iSector];
- {for(INDEX iSurf=0; iSurf<cbpoSurfaces.Count(); iSurf++) {
- CAmfSurface &asSurf = cbpoSurfaces[iSurf];
- for(INDEX iPlg=0; iPlg<asSurf.sf_cbpoPolygons.Count(); iPlg++) {
- CBrushPolygon &bpo = asSurf.sf_cbpoPolygons[iPlg];
- if(bpo.bpo_pbscSector==pbs) {
- CAmfPolygon *amfp = (CAmfPolygon *)bpo.bpo_pspoScreenPolygon;
- INDEX ctNgons = amfp->amfp_aangNgons.Count();
- ctSectorPolygons += ctNgons;
- }
- }
- }}
- strmAmf.FPrintF_t(" POLYGON_MAP_NAME \"sector.Sector_%d\"\n", iSector);
- strmAmf.FPrintF_t(" POLYGONS_COUNT %d\n", ctSectorPolygons);
- strmAmf.PutLine_t(" {");
- // dump polygon indices
- INDEX iPlgGlobal = 0;
- {for(INDEX iSurf=0; iSurf<cbpoSurfaces.Count(); iSurf++) {
- CAmfSurface &asSurf = cbpoSurfaces[iSurf];
- for(INDEX iPlg=0; iPlg<asSurf.sf_cbpoPolygons.Count(); iPlg++) {
- CBrushPolygon &bpo = asSurf.sf_cbpoPolygons[iPlg];
- CAmfPolygon *amfp = (CAmfPolygon *)bpo.bpo_pspoScreenPolygon;
- for(INDEX iNgon=0; iNgon<amfp->amfp_aangNgons.Count(); iNgon++) {
- if(bpo.bpo_pbscSector==pbs) {
- strmAmf.FPrintF_t(" %d;\n", iPlgGlobal);
- }
- iPlgGlobal++;
- }
- }
- }}
- strmAmf.PutLine_t(" }");
- }}
- // dump portals
- if(ciPortals.Count()>0) {
- strmAmf.PutLine_t(" POLYGON_MAP_NAME \"portal.VisPortal\"");
- strmAmf.FPrintF_t(" POLYGONS_COUNT %d\n", ciPortals.Count());
- strmAmf.PutLine_t(" {");
- // dump polygon indices
- {for(INDEX iPlg=0; iPlg<ciPortals.Count(); iPlg++) {
- strmAmf.FPrintF_t(" %d;\n", ciPortals[iPlg]);
- }}
- strmAmf.PutLine_t(" }");
- }
- // dump occluders
- if(ciOccluders.Count()>0) {
- strmAmf.PutLine_t(" POLYGON_MAP_NAME \"portal.VisOccluder\"");
- strmAmf.FPrintF_t(" POLYGONS_COUNT %d\n", ciOccluders.Count());
- strmAmf.PutLine_t(" {");
- // dump polygon indices
- {for(INDEX iPlg=0; iPlg<ciOccluders.Count(); iPlg++) {
- strmAmf.FPrintF_t(" %d;\n", ciOccluders[iPlg]);
- }}
- strmAmf.PutLine_t(" }");
- }
- // dump classifiers
- if(ciClassifiers.Count()>0) {
- strmAmf.PutLine_t(" POLYGON_MAP_NAME \"portal.VisClassifier\"");
- strmAmf.FPrintF_t(" POLYGONS_COUNT %d\n", ciClassifiers.Count());
- strmAmf.PutLine_t(" {");
- // dump polygon indices
- {for(INDEX iPlg=0; iPlg<ciClassifiers.Count(); iPlg++) {
- strmAmf.FPrintF_t(" %d;\n", ciClassifiers[iPlg]);
- }}
- strmAmf.PutLine_t(" }");
- }
- strmAmf.PutLine_t(" }");
- }
- strmAmf.PutLine_t(" }");
- }
- // Tests if entity brushes are valid
- BOOL IsBrushVisible(CEntity &en)
- {
- // fetch first mip
- CBrushMip *pbmMip = en.en_pbrBrush->GetFirstMip();
- if(pbmMip==NULL) {
- return FALSE;
- }
- INDEX ctPolygons = 0;
- for(INDEX iSector=0; iSector<pbmMip->bm_abscSectors.Count(); iSector++) {
- CBrushSector &bs = pbmMip->bm_abscSectors[iSector];
- // for each polygon in the sector
- for(INDEX iPlg=0; iPlg<bs.bsc_abpoPolygons.Count(); iPlg++) {
- CBrushPolygon &bpo = bs.bsc_abpoPolygons[iPlg];
- if(!IsPolygonVisible(bpo)) {
- continue;
- }
- ctPolygons++;
- }
- }
- // if there was no polygons to export
- return ctPolygons>0;
- }
- // Tests if entity brush is empty
- BOOL IsBrushEmpty(CEntity &en)
- {
- // fetch first mip
- CBrushMip *pbmMip = en.en_pbrBrush->GetFirstMip();
- if(pbmMip==NULL) {
- return FALSE;
- }
- INDEX ctPolygons = 0;
- for(INDEX iSector=0; iSector<pbmMip->bm_abscSectors.Count(); iSector++) {
- CBrushSector &bs = pbmMip->bm_abscSectors[iSector];
- if(bs.bsc_abpoPolygons.Count()>0) {
- return FALSE;
- }
- }
- return TRUE;
- }
- // Exports given brush mip into .amf format
- void ExportEntityToAMF_t(CWorldEditorDoc *pDoc, CEntity &en, const CTFileName &fnAmf, BOOL bFieldBrush, BOOL bInvisibleBrush, BOOL bEmptyBrush)
- {
- // fetch first mip
- CBrushMip *pbmMip = en.en_pbrBrush->GetFirstMip();
- // convert all of the brush polygons into ngons
- // for each sector in the brush mip
- {for(INDEX iSector=0; iSector<pbmMip->bm_abscSectors.Count(); iSector++) {
- CBrushSector &bs = pbmMip->bm_abscSectors[iSector];
- // for each polygon in the sector
- for(INDEX iPlg=0; iPlg<bs.bsc_abpoPolygons.Count(); iPlg++) {
- CBrushPolygon &bpo = bs.bsc_abpoPolygons[iPlg];
- // convert it into ngons
- CAmfPolygon *pap = new(CAmfPolygon);
- pap->FromBrushPolygon(&bpo);
- bpo.bpo_pspoScreenPolygon = (CScreenPolygon *) pap;
- }
- }}
- try
- {
- // open .amf file
- CTFileStream strmAmf;
- strmAmf.Create_t( fnAmf, CTStream::CM_TEXT);
- strmAmf.PutLine_t("SE_MESH 1.01");
- strmAmf.PutLine_t("");
- // export visibility for zoning brushes
- INDEX ctLayers = en.en_ulFlags&ENF_ZONING ? 2 : 1;
- if(bEmptyBrush) {
- ctLayers = 0;
- }
- strmAmf.FPrintF_t("LAYERS %d\n", ctLayers);
- strmAmf.PutLine_t("{");
- if(bInvisibleBrush) {
- ExportLayer_t(pDoc, en, ET_RENDERING, pbmMip, strmAmf, "Collision", 0, bFieldBrush, TRUE);
- } else {
- ExportLayer_t(pDoc, en, ET_RENDERING, pbmMip, strmAmf, "Rendering", 0, bFieldBrush, FALSE);
- }
- if(ctLayers>1) {
- ExportLayer_t(pDoc, en, ET_VISIBILITY, pbmMip, strmAmf, "Visibility", 1, bFieldBrush, FALSE);
- }
- strmAmf.PutLine_t("}");
- }
- catch( char *err_str) {
- AfxMessageBox( CString(err_str));
- }
- }
- void CWorldEditorDoc::OnExportEntities()
- {
- CStaticStackArray<CTString> astrNeddedSmc;
- try
- {
- CTFileName fnWorld=m_woWorld.wo_fnmFileName;
- // "entity placement and names"
- CTFileName fnExport=fnWorld.FileDir()+fnWorld.FileName()+".awf";
- // open text file
- CTFileStream strmFile;
- strmFile.Create_t( fnExport, CTStream::CM_TEXT);
- // prepare container of entities to export
- CDynamicContainer<CEntity> dcEntitiesToExport;
- // for each entity in world
- {FOREACHINDYNAMICCONTAINER(m_woWorld.wo_cenEntities, CEntity, iten)
- {
- CEntity &en=*iten;
- dcEntitiesToExport.Add(&en);
- }}
- // write count of entities
- CTString strLine;
- strLine.PrintF("ENTITIES %d {", dcEntitiesToExport.Count());
- strmFile.PutLine_t(strLine);
- // for each entity in world
- FOREACHINDYNAMICCONTAINER(dcEntitiesToExport, CEntity, iten)
- {
- CEntity &en=*iten;
- // obtain entity class ptr
- CDLLEntityClass *pdecDLLClass = en.GetClass()->ec_pdecDLLClass;
- // obtain position
- FLOAT3D vPos=en.GetPlacement().pl_PositionVector;
- FLOAT3D vRot=en.GetPlacement().pl_OrientationAngle;
- // count entity attributes
- INDEX ctEntityAttributes = 0;
- // for all classes in hierarchy of this entity
- CDLLEntityClass *pdecDLLClassCount = pdecDLLClass;
- for(;pdecDLLClassCount!=NULL; pdecDLLClassCount = pdecDLLClassCount->dec_pdecBase) {
- // for all properties
- for(INDEX iProperty=0; iProperty<pdecDLLClassCount->dec_ctProperties; iProperty++) {
- CEntityProperty *pepProperty = &pdecDLLClassCount->dec_aepProperties[iProperty];
- if(pepProperty->ep_strName!=CTString("")) {
- ctEntityAttributes++;
- }
- }
- }
- // if render type is brush
- if( (en.en_RenderType==CEntity::RT_BRUSH || en.en_RenderType==CEntity::RT_FIELDBRUSH) && en.en_pbrBrush!=NULL) {
- // add one more property because we will add one that will hint "InvisibleBrush"
- ctEntityAttributes++;
- }
- // write count of entity attributes (add 5 fixed ones, for class, ID, spawn flags, parent, name, pos, rot)
- strLine.PrintF(" ENTITY_ATTRIBUTES %d {", ctEntityAttributes+7);
- strmFile.PutLine_t(strLine);
- // entity class
- strLine.PrintF(" \"ENTITYCLASS\" = string(\"SS1 %s\");", pdecDLLClass->dec_strName);
- strmFile.PutLine_t(strLine);
- // entity ID
- strLine.PrintF(" \"ID\" = long(%d);", en.en_ulID);
- strmFile.PutLine_t(strLine);
- // entity spawn flags
- strLine.PrintF(" \"SS1_SPAWN_FLAGS\" = long(%d);", en.en_ulSpawnFlags);
- strmFile.PutLine_t(strLine);
- // entity name
- CTString strName=en.GetName();
- if(strName=="") {
- strName="<unnamed>";
- }
- SLONG idParent=-1;
- CEntity *penParent = en.GetParent();
- if(penParent!=NULL) {
- idParent = penParent->en_ulID;
- }
- strLine.PrintF(" \"PARENT\" = long(%d);", idParent);
- strmFile.PutLine_t(strLine);
- strLine.PrintF(" \"NAME\" = string(\"%s\");", strName);
- strmFile.PutLine_t(strLine);
- // position
- strLine.PrintF(" \"POS\" = float3(%f, %f, %f);", vPos(1), vPos(2), vPos(3));
- strmFile.PutLine_t(strLine);
- // rotation
- strLine.PrintF(" \"ROT\" = float3(%f, %f, %f);", vRot(1), vRot(2), vRot(3));
- strmFile.PutLine_t(strLine);
- // for all classes in hierarchy of this entity
- for(;pdecDLLClass!=NULL; pdecDLLClass = pdecDLLClass->dec_pdecBase) {
- // for all properties
- for(INDEX iProperty=0; iProperty<pdecDLLClass->dec_ctProperties; iProperty++) {
- CEntityProperty *pepProperty = &pdecDLLClass->dec_aepProperties[iProperty];
- if(pepProperty->ep_strName==CTString("")) {
- continue;
- }
- // enumerator
- if( pepProperty->ep_eptType == CEntityProperty::EPT_ENUM) {
- INDEX iEnumValue = ENTITYPROPERTY( &en, pepProperty->ep_slOffset, INDEX);
- strLine.PrintF(" \"%s\" = long(%d);", pepProperty->ep_strName, iEnumValue);
- strmFile.PutLine_t(strLine);
- }
- // boolean
- if( pepProperty->ep_eptType == CEntityProperty::EPT_BOOL) {
- INDEX iBooleanValue = ENTITYPROPERTY( &en, pepProperty->ep_slOffset, BOOL);
- strLine.PrintF(" \"%s\" = long(%d);", pepProperty->ep_strName, iBooleanValue);
- strmFile.PutLine_t(strLine);
- }
- // float value
- if( pepProperty->ep_eptType == CEntityProperty::EPT_FLOAT) {
- FLOAT fFloat = ENTITYPROPERTY( &en, pepProperty->ep_slOffset, FLOAT);
- strLine.PrintF(" \"%s\" = float(%f);", pepProperty->ep_strName, fFloat);
- strmFile.PutLine_t(strLine);
- }
- // color
- if( pepProperty->ep_eptType == CEntityProperty::EPT_COLOR) {
- COLOR colValue = ENTITYPROPERTY( &en, pepProperty->ep_slOffset, COLOR);
- strLine.PrintF(" \"%s\" = long(%d);", pepProperty->ep_strName, colValue);
- strmFile.PutLine_t(strLine);
- }
- // string
- if( pepProperty->ep_eptType == CEntityProperty::EPT_STRING) {
- CTString strString = FixQuotes(ENTITYPROPERTY( &en, pepProperty->ep_slOffset, CTString));
- strLine.PrintF(" \"%s\" = string(\"%s\");", pepProperty->ep_strName, strString);
- strmFile.PutLine_t(strLine);
- }
- // range
- if( pepProperty->ep_eptType == CEntityProperty::EPT_RANGE) {
- FLOAT fFloat = ENTITYPROPERTY( &en, pepProperty->ep_slOffset, FLOAT);
- strLine.PrintF(" \"%s\" = float(%f);", pepProperty->ep_strName, fFloat);
- strmFile.PutLine_t(strLine);
- }
- // entity ptr
- if( pepProperty->ep_eptType == CEntityProperty::EPT_ENTITYPTR) {
- // get the pointer
- CEntityPointer &penPointed = ENTITYPROPERTY( &en, pepProperty->ep_slOffset, CEntityPointer);
- SLONG ulID = penPointed==NULL ? -1 : penPointed->en_ulID;
- strLine.PrintF(" \"%s\" = long(%d);", pepProperty->ep_strName, ulID);
- strmFile.PutLine_t(strLine);
- }
- // file name
- if( pepProperty->ep_eptType == CEntityProperty::EPT_FILENAME ||
- pepProperty->ep_eptType == CEntityProperty::EPT_FILENAMENODEP) {
- CTFileName fnmFile = CorrectSlashes(ENTITYPROPERTY( &en, pepProperty->ep_slOffset, CTFileName));
- strLine.PrintF(" \"%s\" = string(\"%s\");", pepProperty->ep_strName, fnmFile);
- strmFile.PutLine_t(strLine);
- }
- // index value
- if( pepProperty->ep_eptType == CEntityProperty::EPT_INDEX) {
- INDEX iValue = ENTITYPROPERTY( &en, pepProperty->ep_slOffset, INDEX);
- strLine.PrintF(" \"%s\" = long(%d);", pepProperty->ep_strName, iValue);
- strmFile.PutLine_t(strLine);
- }
- // animation value
- if( pepProperty->ep_eptType == CEntityProperty::EPT_ANIMATION) {
- INDEX iValue = ENTITYPROPERTY( &en, pepProperty->ep_slOffset, INDEX);
- strLine.PrintF(" \"%s\" = long(%d);", pepProperty->ep_strName, iValue);
- strmFile.PutLine_t(strLine);
- }
- // illumination type
- if( pepProperty->ep_eptType == CEntityProperty::EPT_ILLUMINATIONTYPE) {
- INDEX iValue = ENTITYPROPERTY( &en, pepProperty->ep_slOffset, INDEX);
- strLine.PrintF(" \"%s\" = long(%d);", pepProperty->ep_strName, iValue);
- strmFile.PutLine_t(strLine);
- }
- // angle
- if( pepProperty->ep_eptType == CEntityProperty::EPT_ANGLE) {
- INDEX iValue = ENTITYPROPERTY( &en, pepProperty->ep_slOffset, INDEX);
- strLine.PrintF(" \"%s\" = long(%d);", pepProperty->ep_strName, iValue);
- strmFile.PutLine_t(strLine);
- }
- // float 3D
- if( pepProperty->ep_eptType == CEntityProperty::EPT_FLOAT3D) {
- FLOAT3D vValue = ENTITYPROPERTY( &en, pepProperty->ep_slOffset, FLOAT3D);
- strLine.PrintF(" \"%s\" = float3(%f, %f, %f);", pepProperty->ep_strName, vValue(1), vValue(2), vValue(3));
- strmFile.PutLine_t(strLine);
- }
- // angle 3D
- if( pepProperty->ep_eptType == CEntityProperty::EPT_ANGLE3D) {
- ANGLE3D vAngle3D = ENTITYPROPERTY( &en, pepProperty->ep_slOffset, ANGLE3D);
- strLine.PrintF(" \"%s\" = float3(%f, %f, %f);", pepProperty->ep_strName, vAngle3D(1), vAngle3D(2), vAngle3D(3));
- strmFile.PutLine_t(strLine);
- }
- // string trans
- if( pepProperty->ep_eptType == CEntityProperty::EPT_STRINGTRANS) {
- CTString strString = FixQuotes(ENTITYPROPERTY( &en, pepProperty->ep_slOffset, CTString));
- strLine.PrintF(" \"%s\" = string(\"%s\");", pepProperty->ep_strName, strString);
- strmFile.PutLine_t(strLine);
- }
- // flags
- if( pepProperty->ep_eptType == CEntityProperty::EPT_FLAGS) {
- ULONG ulValue = ENTITYPROPERTY( &en, pepProperty->ep_slOffset, ULONG);
- strLine.PrintF(" \"%s\" = long(%d);", pepProperty->ep_strName, ulValue);
- strmFile.PutLine_t(strLine);
- }
- // EPT_FLOATAABBOX3D - bounding box
- if( pepProperty->ep_eptType == CEntityProperty::EPT_FLOATAABBOX3D) {
- // get value for bounding box
- FLOATaabbox3D bboxOld = ENTITYPROPERTY( &en, pepProperty->ep_slOffset, FLOATaabbox3D);
- FLOAT3D vMin = bboxOld.Min();
- FLOAT3D vMax = bboxOld.Max();
- strLine.PrintF(" \"%s\" = box(%f, %f, %f),(%f, %f, %f);", pepProperty->ep_strName,
- vMin(1), vMin(2), vMin(3), vMax(1), vMax(2), vMax(3));
- strmFile.PutLine_t(strLine);
- }
- }
- }
- // if render type is brush
- if( (en.en_RenderType==CEntity::RT_BRUSH || en.en_RenderType==CEntity::RT_FIELDBRUSH) && en.en_pbrBrush!=NULL) {
- // add one "fake" property that will hint "invisible brush" status
- BOOL bInvisibleBrush = !IsBrushVisible(en);
- BOOL bEmptyBrush = IsBrushEmpty(en);
- strLine.PrintF(" \"Hint: Invisible brush\" = long(%d);", bInvisibleBrush);
- strmFile.PutLine_t(strLine);
- // ".amf" file name
- CTString strEntityID;
- strEntityID.PrintF("%d", en.en_ulID);
- CTFileName fnAmf;
- fnAmf.PrintF("%s_%s.amf", fnWorld.FileDir()+fnWorld.FileName(), strEntityID);
- BOOL bFieldBrush = en.en_RenderType==CEntity::RT_FIELDBRUSH;
- ExportEntityToAMF_t(this, en, fnAmf, bFieldBrush, bInvisibleBrush, bEmptyBrush);
- }
- // close entity attributes section
- strLine.PrintF(" }");
- strmFile.PutLine_t(strLine);
- }
- // close entity section
- strLine.PrintF("}");
- strmFile.PutLine_t(strLine);
-
- // "entity placement and names"
- CTFileName fnSml=fnWorld.FileDir()+fnWorld.FileName()+".sml";
- // open text file
- CTFileStream strmSmlFile;
- strmSmlFile.Create_t( fnSml, CTStream::CM_TEXT);
- // save needed smc's
- for(INDEX iSmc=0; iSmc<astrNeddedSmc.Count(); iSmc++)
- {
- strmSmlFile.PutLine_t(astrNeddedSmc[iSmc]);
- }
- AfxMessageBox(L"Entities exported!", MB_OK|MB_ICONINFORMATION);
- }
- catch( char *err_str)
- {
- AfxMessageBox( CString(err_str));
- }
- }
|