gameedit.cpp 222 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835
  1. ////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright 2016 RWS Inc, All Rights Reserved
  4. //
  5. // This program is free software; you can redistribute it and/or modify
  6. // it under the terms of version 2 of the GNU General Public License as published by
  7. // the Free Software Foundation
  8. //
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License along
  15. // with this program; if not, write to the Free Software Foundation, Inc.,
  16. // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  17. //
  18. // GameEdit.cpp
  19. // Project: Nostril (aka Postal)
  20. //
  21. // This module impliments the game editor.
  22. //
  23. // History:
  24. // 12/18/96 MJR Started.
  25. //
  26. // 01/14/97 BRH Added CDoofus and CTkachuk keys to the editor
  27. //
  28. // 01/17/97 BRH Added CRocketMan key to the editor
  29. //
  30. // 01/21/97 JMI Converted from rspGetKey() and rspGetMouseEvent() to
  31. // RInputEvent API (rspGetNextInputEvent() ).
  32. //
  33. // 01/21/97 JMI Added Realm Bar GUI and Object Picker GUI.
  34. // Now open and save realm invoke file system dialogs
  35. // to browse.
  36. //
  37. // 01/22/97 JMI Now requests that you save before doing anything that
  38. // might be detremental(sp!) to the current level (e.g., New,
  39. // Close, etc.).
  40. //
  41. // 01/22/97 JMI PlayRealm() now saves and loads the current level in
  42. // TEMP_FILE_NAME.
  43. //
  44. // 01/22/97 JMI The object picker list box now only adds items that are
  45. // user creatable in the editor (as indicated by
  46. // CThing::ms_aClassInfo[ID].bEditorCreatable.
  47. //
  48. // 01/22/97 MJR Added use of realm's time object. Also, it now uses a
  49. // separate realm object in the play loop so as to avoid any
  50. // possible interference between it and the editor's realm.
  51. //
  52. // 01/23/97 JMI Fixed 'assing' comment because we definitely wouldn't
  53. // want the word 'assing' appearing in our code anywhere.
  54. // Who's the assinine jack ass for a dumb ass that wrote
  55. // 'assing' in the first place anyway?! What an asswipe.
  56. // Now you are only asked if you want to save before an op
  57. // that destroys the current realm if that realm contains
  58. // anything.
  59. // Now hots for individual GUIs are called independently in
  60. // the editor.
  61. //
  62. // 01/23/97 JMI Now when you click an item in the list box, the item is
  63. // created, the EditNew() is called, and then the item can
  64. // be moved to the drop spot.
  65. //
  66. // 01/23/97 JMI Now shows the system cursor when not placing an object.
  67. //
  68. // 01/24/97 JMI Can now adjust display size with Numpad + and -. Always
  69. // restores display size when exiting editor to the original
  70. // size (when entered editor).
  71. // External effects: g_pimScreenBuf.
  72. //
  73. // 01/24/97 JMI Now PlayRealm() also supports the adjustment of the display
  74. // area. Also, cursor no longer does height cursor's drag
  75. // logic unless in drop dude mode.
  76. //
  77. // 01/25/97 JMI Added scrollbars to edit mode.
  78. //
  79. // 01/26/97 JMI Forgot to update scrollbars in PlayRealm().
  80. //
  81. // 01/26/97 JMI Added selection. This required creating a root RHot for
  82. // the Hood and a child RHot for each of the other CThings.
  83. //
  84. // 01/27/97 JMI Now you can double click an existing item to move it,
  85. // hit enter while it is selected to modify it, or hit
  86. // delete while it is selected to delete it.
  87. //
  88. // 01/27/97 JMI Now if you delete the item with the selection and then try
  89. // to move it, it doesn't crash. A technological breakthrough
  90. // enabled this by collapsing ms_p*Move into ms_p*Sel and
  91. // adding an ms_sMoving flag.
  92. //
  93. // 01/28/97 JMI Now you can toggle layers on and off using the layers list-
  94. // box.
  95. //
  96. // 01/29/97 JMI Quickly changed UI...will update cleaner later...just need
  97. // to get this to Bill so he can do cool Buoy stuff.
  98. //
  99. // 01/29/97 BRH Added ability to link Bouys. It draws the link between
  100. // two bouy's that you are attempting to link. Also added
  101. // a CNavigationNet pointer to the editor to keep track
  102. // of the currently selected NavNet to which new Bouys
  103. // are added. Will need to add a GUI item to let the user
  104. // select the 'current' NavNet when you have more than one.
  105. // Also still need to add the function to display the lines
  106. // between all bouys once the network is linked together.
  107. //
  108. // 01/30/97 JMI Now when you open/load or new a realm, the size affected
  109. // stuff is updated via a call to SizeUpdate().
  110. //
  111. // 01/30/97 BRH Added key 'B' as a toggle for showing the bouy lines.
  112. // Added a set of bouy lines to the editor which can be
  113. // added to when a new line is drawn or completely set
  114. // up with all bouy lines by calling UpdateNetLines.
  115. // Now I need the CThing unique ID numbers so that when
  116. // bouys are reloaded, they will know what CNavigationNet
  117. // to relink themselves to.
  118. //
  119. // 01/30/97 JMI Now the editor assigns a realm unique ID to every item it
  120. // creates.
  121. //
  122. // 01/31/97 JMI If CreateNewThing() failed to create a new CBuoy b/c there
  123. // was no current NavNet, it returned success. Now it returns
  124. // failure.
  125. //
  126. // 02/02/97 JMI If a CThing derived class has an EditHotSpot() defined, the
  127. // editor will be able to smoothly drag the thing. If it does
  128. // not have this function, the cursor will jump when a drag
  129. // is started.
  130. // Also, made cursor aware of the height on the attribute map.
  131. // Also, made the distinction between an editor hotbox event
  132. // and another event.
  133. //
  134. // 02/03/97 JMI Moved all input in editor loop into DoInput() and all output
  135. // in editor loop to DoOutput(). This makes it a little easier
  136. // to figure out what's going on, but DoInput() is still rather
  137. // large (mainly due to the two switch statements).
  138. //
  139. // 02/03/97 JMI Can track a particular CThing during PlayRealm(). To track
  140. // a CThing, hold down shift and then click the thing. There
  141. // should be a beep signifying the item was set as the tracked
  142. // thing. Hit 'T' in PlayRealm() mode to toggle tracking mode
  143. // vs. scrollbar mode.
  144. //
  145. // 02/03/97 JMI Now loads GUIs and cursor images via
  146. // FullPath(GAME_PATH_VD, "...") and uses temp path
  147. // FullPath(GAME_PATH_HD, "...") for realms in PlayRealm().
  148. // In PlayRealm(), the grip is now reset when switching from
  149. // scrollbar to track target mode.
  150. //
  151. // 02/04/97 JMI Changed LoadDib() call to Load() (which now supports
  152. // loading of DIBs).
  153. //
  154. // 02/04/97 JMI SizeUpdate() was directly accessing members of CHood. Now
  155. // calls CHood.GetWidth(),GetHeight() instead.
  156. //
  157. // 02/04/97 JMI You can now change the game's priority level via the keys
  158. // '1', '2', & '3' where '1' is the highest priority and
  159. // '3' is lowest.
  160. //
  161. // 02/05/97 BRH NewRealm now automatically creates a NavNet for the realm
  162. // right after it creates a Hood. Many objects depend on the
  163. // NavNet object being in place before they are added so
  164. // the editor now creates one by default.
  165. //
  166. // 02/05/97 JMI The toggle of layers is now stimulated by the actual list-
  167. // box item, rather than the "Toggle Button" which I will
  168. // remove from the LAYERS.GUI after checking this in.
  169. //
  170. // 02/06/97 BRH Checked for CBouy and CNavigationNet when deleting things
  171. // in the editor. You may not delete the last remaining
  172. // NavNet. If you delete a Bouy, it will unlink the bouy from
  173. // its network first and update the lines if necessary. If
  174. // you delete a NavNet, it will delete all of its bouys.
  175. //
  176. // 02/07/97 JMI Added use of new CGameEditThing.
  177. //
  178. // 02/12/97 JMI Added pause feature in PlayRealm(). Also, added keys for
  179. // speeding up, slowing down, and normalizing game time, but
  180. // have not implemented that yet b/c it requires a change to
  181. // CTime.
  182. //
  183. // 02/12/97 JMI Temp fix until GetMaxHeight() returns *4 value (or the *4
  184. // an app thing?). Also, fixed bug where I was getting the
  185. // height via the cursor's screen pos (not the cursor's world
  186. // pos).
  187. //
  188. // 02/13/97 JMI Now the editor sets the Camera's Hood. This fixed the prob
  189. // the grip was having finding the realm limits and allows us
  190. // to utilize the newest scene which gets its alpha stuff from
  191. // the hood passed to it by the camera. The camera's connect-
  192. // ed to the realm bone, ... .
  193. //
  194. // 02/13/97 JMI In the previous update, the camera's hood was being set
  195. // after the load realm, but too late. Now it's set earlier.
  196. // Since before, it was never set, it was never a problem b/c
  197. // the camera's hood was NULL.
  198. //
  199. // 02/13/97 JMI On the second entrance to GameEdit(), ms_pcameraCur was
  200. // already pointing at an old deleted camera.
  201. // Also, I guess the camera and realm were not being delete'd
  202. // in GameEdit().
  203. //
  204. // 02/14/97 JMI SizeUpdate() now makes sure the camera's hood is up to
  205. // date.
  206. // 02/17/97 JMI Now checks rspGetQuitStatus().
  207. //
  208. // 02/19/97 JMI PlayRealm() now checks for camera tracking object
  209. // iteratively.
  210. //
  211. // 02/20/97 JMI Now uses input interface for user input.
  212. //
  213. // 02/21/97 JMI Now makes sure scrollbars don't have focus in PlayRealm().
  214. // Also, makes all CDudes X-Rayable.
  215. //
  216. // 02/22/97 JMI Now SetDisplayArea() only changes the display device
  217. // settings if g_GameSettings.m_sUseCurrentDeviceDimensions
  218. // is FALSE.
  219. //
  220. // 02/22/97 JMI Now sets working dir to levels dir when entering editor.
  221. //
  222. // 02/24/97 JMI CloseRealm() now purges g_resmgrGame.
  223. //
  224. // 02/25/97 JMI CloseRealm() now also purges prealm->m_resmgr.
  225. // Also, CloseRealm() now clears ms_pcameraCur's hood ptr
  226. // and calls SizeUpdate().
  227. //
  228. // 02/25/97 JMI Resized viewable area and repositioned GUIs into non-
  229. // viewable areas.
  230. // Also, added SetCameraArea() function which will resize the
  231. // device mode and the display area such that the camera area
  232. // will be the specified size.
  233. //
  234. // 02/28/97 JMI Added satellite cameras. No current way to resize them
  235. // though. That kinda sux. But they're there.
  236. //
  237. // 03/03/97 JMI Now cameras work in PlayRealm() mode.
  238. // Also, now, on entry to GameEdit(), stores device settings
  239. // and uses them in restoring the display area on exit.
  240. // Previously, only the display area was restored with the
  241. // device mode as returned by rspSuggestVideoMode().
  242. //
  243. // 03/05/97 JMI Dude now commits suicide when user exits PlayRealm().
  244. // CreateNewThing() now uses CThing::ConstructWithID() to
  245. // create new things.
  246. //
  247. // 03/06/97 JMI PlayRealm() now sends a suicide message to the local dude
  248. // instead of setting his state.
  249. //
  250. // 03/06/97 BRH Added NetLog() function for debugging NavNet links. Prints
  251. // out a text file of connected bouys.
  252. //
  253. // 03/09/97 JMI Added GUIs bar for showing/hiding GUIs, NavNets listbox,
  254. // and Map GUI.
  255. // Also, CloseRealm() now clears ms_pgething.
  256. //
  257. // 03/10/97 JMI Now using correct rspBlitT scale version so map actually
  258. // gets blit (but transparent for color 0 (which it should
  259. // not contain)).
  260. //
  261. // 03/10/97 JMI Now you can click on the map to move the main camera to the
  262. // clicked area.
  263. //
  264. // 03/10/97 BRH Added a route table printout to NetLog function to verify
  265. // that the routing tables are correct.
  266. //
  267. // 03/13/97 BRH Made a change to the route table printout.
  268. //
  269. // 03/13/97 JMI Now calls CDude::DrawStatus() for the local dude.
  270. //
  271. // 03/17/97 JMI Now scrolls the view if a dragged item is on or beyond an
  272. // edge.
  273. // Also, now cancels current drag in CloseRealm() and before
  274. // calling PlayRealm().
  275. //
  276. // 03/19/97 JMI Added flag indicating the view should not be scrolled while
  277. // dragging/moving a CThing. This is utilized when a CThing
  278. // is first created from the CThing pick list so it doesn't
  279. // cause immediate scrolling. It is re-enabled as soon as the
  280. // thing is dragged into the view, destroyed, or placed.
  281. // Also, now the view will start scrolling within
  282. // DRAG_SCROLL_BUFFER pixels of any view edge.
  283. //
  284. // 03/19/97 JMI Switched to the new input event hotbox callback for thing
  285. // hotboxes.
  286. //
  287. // 03/19/97 BRH Made sure network line draw is turned off when the current
  288. // realm is closed so that lines don't show up on the next
  289. // realm and it doesn't crash when you quit the editor with
  290. // lines turned on.
  291. //
  292. // 03/24/97 JMI PlayRealm() now passes a ptr to the realm to GetLocalInput.
  293. //
  294. // 03/25/97 JMI Changed CURSOR_BASE_IMAGE_FILE, CURSOR_TIP_IMAGE_FILE, and
  295. // PICK_OBJECT_FILE to 8.3 compliant names.
  296. //
  297. // 03/27/97 JMI ThingHotCall now makes sure the event it processes has not
  298. // yet been used. Also, you may no longer drag the hood.
  299. //
  300. // 03/28/97 JMI Now the scrollbar tray and button clicks will advance more
  301. // than just a few pixels.
  302. // Now, if there is no current camera focus, it is set to the
  303. // first CDude created.
  304. //
  305. // 03/28/97 JMI Fixed exit button. Also my last change made change had
  306. // caused the Hood hotbox to parent itself which caused hosed
  307. // behavior. Fixed.
  308. //
  309. // 03/28/97 JMI Now resets directory back to original when done.
  310. //
  311. // 04/03/97 JMI Main dude's status is now displayed below the view (instead
  312. // of on it).
  313. //
  314. // 04/04/97 JMI ms_sbVert and ms_sbHorz are now smooth scrollers.
  315. //
  316. // 04/10/97 BRH Updated this to work with the new multi layer attribute
  317. // maps using the helper functions.
  318. //
  319. // 04/11/97 JMI Changed GetLocalInput() to take the RInputEvent.
  320. //
  321. // 04/16/97 BRH Added an #ifdef REALM_NONSTL for testing the new
  322. // non-stl lists for the CThings in the realm. References
  323. // to either method are available by changing the
  324. // REALM_NONSTRL macro in realm.h
  325. //
  326. // 04/17/97 BRH Fixed a bug in the new list code where it wasn't
  327. // advancing the list pointer at the end of the loop, cauing
  328. // an infinite loop.
  329. //
  330. // 04/17/97 BRH Changed call to Startup and Shutdown in realm, changed
  331. // calls in this file from 1 parameter to 0 parameters.
  332. //
  333. // 04/21/97 JMI Menu is now activated by escape key.
  334. //
  335. // 04/21/97 BRH Bouys are now linked by right clicking on the bouy, or
  336. // on the Mac, hold down open-apple & click to connect
  337. // bouy lines. Double click on a bouy now brings up
  338. // its EditModify dialog box.
  339. //
  340. // 04/22/97 JMI No longer uses chdir() to get the open dialog into the
  341. // correct directory. Now we simply default ms_szFileName
  342. // to the path of the dir we want to save under.
  343. //
  344. // 04/22/97 JMI Removed #include <direct.h>.
  345. //
  346. // 04/29/97 JMI Added key motivated new item placement.
  347. //
  348. // 05/01/97 JMI Added ability to create regions to be associated with
  349. // pylons. These regions are saved with the .RLM with the
  350. // same name except the .RLM is changed to .RGN.
  351. // To edit a pylon's region, double right click it, use left
  352. // and right mouse buttons to paint, Num pad + and - to
  353. // control brush size, and Escape to end trigger region paint
  354. // mode.
  355. // Also, added focus next and prev.
  356. // Also, made enlarge/reduce screen during PlayRealm() update
  357. // the CDude's status area.
  358. //
  359. // 05/02/97 JMI Now, while editing a pylon's trigger region, it is drawn
  360. // with a game sprite so we can have alpha so you can see
  361. // what you're drawing on.
  362. //
  363. // 05/02/97 JMI Changed number of pylons trigger regions to 256 b/c I didn't
  364. // want to bother adding 1 in all the special locations.
  365. //
  366. // 05/04/97 BRH Removed #ifdef sections referring to STL lists.
  367. //
  368. // 05/09/97 JMI Assigned pylon instance IDs into ms_argns[].u16InstanceId
  369. // so the multigrid for pylon triggers can contain a mapping
  370. // from pylon ID to instance ID.
  371. //
  372. // 05/12/97 JRD Added the creation of the Trigger Attribute map into the
  373. // save realm process.
  374. //
  375. // 05/15/97 JMI Added a common SaveRealm(char*) that does all the stuff
  376. // necessary to save the realm and triggers so that the
  377. // PlayRealm() gets everything done that would happen normally.
  378. //
  379. // 05/23/97 BRH Added support for NavNets in the editor's list box.
  380. // Added code for button callbacks to switch the current
  381. // Nav Net, and to remove them from the list when they are
  382. // deleted.
  383. //
  384. // 05/25/97 JMI Holding down CONTROL, ALT, and/or SHIFT provides different
  385. // variations on the amount pylon regions are moved by arrow
  386. // keys.
  387. //
  388. // 05/26/97 JMI If you hold down CONTROL while hitting DEL, the editor will
  389. // delete all objects of the type of the currently selected
  390. // objects.
  391. //
  392. // 05/29/97 JMI Removed references to m_pRealm->m_pAttribMap which no longer
  393. // exists.
  394. //
  395. // 06/07/97 JMI Now, in PlayRealm(), if no dude exists, we attempt to use
  396. // CWarp::WarpInAnywhere() to create one. This will fail, if
  397. // there are no warps in the specified realm.
  398. // Changed message for CTRL-DEL group deletes as per
  399. // humiliation.
  400. // Added realm status info to PlayRealm().
  401. //
  402. // 06/09/97 JMI Now generates a unique temp filename for PlayRealm() that
  403. // is generated at least in part by the current OS.
  404. //
  405. // 06/11/97 MJR If mouse is enabled (via InputSettings) then the mouse
  406. // cursor is now hidden and then restored while playing
  407. // the realm.
  408. //
  409. // 06/12/97 JMI Commented out use of rspSetDoSystemMode() in PlayRealm().
  410. //
  411. // 06/16/97 JMI Now passes destination buffer in StartMenu() call.
  412. //
  413. // 06/16/97 JMI Added copy/paste.
  414. //
  415. // 06/16/97 JMI PlayRealm() now calls the realm's hood's SetPalette().
  416. // It also clears the key status array.
  417. //
  418. // 06/17/97 JMI Converted all occurrences of rand() to GetRand() and
  419. // srand() to SeedRand().
  420. //
  421. // 06/26/97 JMI Now enables RMix's autopump feature during the PlayRealm()
  422. // and disables it before exiting.
  423. //
  424. // 06/26/97 JMI DrawCursor() now uses the realm's Map3Dto2D().
  425. //
  426. // 06/26/97 JMI Now editor's cursor is fully 3D and there are two functions
  427. // for mapping between screen & realm coords
  428. // (MapScreen2Realm() and Maprealm2Screen() ).
  429. //
  430. // 06/30/97 JMI Converted to use new m_pLayers member of CScene (was using
  431. // m_layers).
  432. //
  433. // MJR Replaced SAFE_GUI_REF with new GuiItem.h-defined macro.
  434. //
  435. // JMI Now all bouy lines are mapped through Maprealm2Screen()
  436. // before being drawn.
  437. //
  438. // 07/03/97 JMI Converted calls to rspOpen/SaveBox() to new parm
  439. // conventions.
  440. //
  441. // 07/05/97 JMI Now you can clear the current camera focus thing by
  442. // SHIFT-Left-clicking on the hood.
  443. //
  444. // 07/05/97 MJR Changed to RSP_BLACK_INDEX instead of 0.
  445. //
  446. // 07/07/97 JMI Added extremely CHEEZY thing that checks for an active
  447. // input settings menu and, if so, calls EditInputSettings().
  448. //
  449. // 07/07/97 JMI Now SetCameraArea() sets the display area based on user
  450. // settings from g_GameSettings. Also, SetDisplayArea()
  451. // always updates these settings when the user changes the
  452. // display area.
  453. //
  454. // 07/07/97 BRH Added processing for the properties button on the Realm
  455. // bar which calls the realm's EditModify function to put
  456. // up its properties dialog box for the realm.
  457. //
  458. // MJR Added regular plus and minus in addition to numpad versions
  459. // for changing display size.
  460. //
  461. // 07/10/97 JMI Now you cannot select an item in the 'PickObj' list when
  462. // you are dragging an item.
  463. //
  464. // 07/14/97 JMI Now there is a place to put exceptions to what can be
  465. // copied (via Copy/Paste). Currently, you cannot copy
  466. // Bouys, Pylons, NavNets, and Hoods.
  467. //
  468. // 07/15/97 JMI Now you can display the attributes with a green mist over
  469. // the hood by checking boxes in 'View Attributes'. You can
  470. // also use NUMPAD_MULTIPLY and NUMPAD_DIVIDE to vary the
  471. // opacity of this mist.
  472. //
  473. // 07/16/97 JMI Can now take snap shots from editor. Also, F3 does auto
  474. // X ray.
  475. //
  476. // 07/18/97 JMI Now updates the sound location with the camera target.
  477. //
  478. // 07/18/97 JMI Got rid of bogus immitation PlaySample functions.
  479. // Now there is one PlaySample() function. Also, you now
  480. // MUST specify a category and you don't have to specify a
  481. // SoundInstance ptr to specify a volume.
  482. //
  483. // 07/19/97 JMI Now calls InitLocalInput() in PlayRealm() just prior to
  484. // starting.
  485. //
  486. // 07/20/97 JMI Now uses back/foreground callbacks to suspend/resume the
  487. // realm (PlayRealm() only), adjust CPU hoggage, and make
  488. // sure the cursor is visible when in the background.
  489. //
  490. // 07/20/97 JMI DelThing() was dereferencing the ptr to the object to be
  491. // deleted after it was cleared by the special cases that
  492. // don't allow deletion. Fixed.
  493. //
  494. // 07/20/97 MJR Added conditional compile to disable save & play.
  495. // Added use of RFile callback during load to call Update().
  496. //
  497. // 07/20/97 JMI Fixed syntax error produced when we added the above
  498. // conditional compile option.
  499. //
  500. // 07/21/97 JMI PlayRealm() now sets the input mode to live via
  501. // SetInputMode().
  502. //
  503. // 07/22/97 JMI Now shows the info for the currently selected thing.
  504. //
  505. // 07/22/97 JMI Now PlayRealm() displays the "display info" (FPS, etc.).
  506. //
  507. // 07/23/97 JMI Changed EDIT_KEY_TRACKING_TOGGLE to CONTROL T (was T).
  508. //
  509. // 07/25/97 BRH Fixed problem of last bouy link causing the editor
  510. // to crash when the highlight was left active. Also fixed
  511. // bug that crashed the editor if you hit space bar before
  512. // loading a hood.
  513. //
  514. // 07/25/97 MJR Made separate function to get temp file names and added
  515. // mac-specific version of that code.
  516. // Also added message box if there's an error playing the
  517. // realm.
  518. //
  519. // 07/27/97 JMI Now maps pylon trigger regions' initial positions from 3D
  520. // to 2D viewing plane.
  521. // Also, added '=' as another option for enlarging the display
  522. // since most games don't actually require you to hit SHIFT to
  523. // get the actual '+'.
  524. // Also, converted movement keys for pylon trigger regions to
  525. // use the key status array (instead of
  526. // rspGetNextInputEvent() ).
  527. // Also, CTRL, ALT, and SHIFT speed ups for movement now speed
  528. // up draw block sizing.
  529. //
  530. // 07/30/97 BRH Changed the toggle bouy key to turn off the bouys in
  531. // addition to the bouy lines.
  532. //
  533. // 07/31/97 JMI Now allows you to turn off clipping to the realm edges
  534. // via the '?' key so you can scroll off the world looking
  535. // for lost souls or whatever.
  536. // Also, added realm statistics activated by 'I' key in both
  537. // edit and play modes.
  538. //
  539. // 07/31/97 BRH Made the hots on the bouys inactive when they are hidden.
  540. //
  541. // 07/31/97 JMI Now shows the cursor, if hidden, in ShowRealmStatistics()
  542. // and restores its show level when done. Also, clears inputs
  543. // before returning.
  544. // Also, PlayRealm() Suspend()s the realm before calling
  545. // ShowRealmStatistics() and Resume()s it afterward.
  546. //
  547. // 07/31/97 JMI Changed EDIT_KEY_REALM_STATISTICS to F11 (was 'I') so it
  548. // wouldn't interfere with typing cheats.
  549. //
  550. // 08/01/97 JMI Changed %.2f sprintf format specifiers to %g. It's not as
  551. // pretty but it's more compact. The problem if the %f is it
  552. // will put hundreds of 0's after the decimal point if it
  553. // needs to display a very small number.
  554. //
  555. // 08/02/97 JMI Now makes sure the CBouys' show/hidden status is in synch
  556. // with the ms_bDrawNetwork flag (the flag defaults to false
  557. // and the bouys default to shown).
  558. // Also, now does not actiavte bouys' hots when loading a
  559. // level while ms_bDrawNetwork is false.
  560. // Also, if a new bouy is created while ms_bDrawNetwork is
  561. // false, its hot is initially inactive.
  562. //
  563. // 08/05/97 BRH Defaulted the bouy network to ON.
  564. //
  565. // 08/06/97 JMI Changed instances of InitLocalInput() to ClearLocalInput().
  566. //
  567. // 08/07/97 JMI Now PlayRealm() and GameEdit() set the appropriate realm
  568. // flags so things can know what we're doing.
  569. //
  570. // 08/08/97 MJR Moved background/foreground callbacks to game.cpp.
  571. //
  572. // 08/08/97 BRH Fixed display of NavNet names in the listbox after loading,
  573. // also clears them on CloseRealm.
  574. //
  575. // 08/09/97 JMI Now shows wait cursor during CRealm::Load() calls.
  576. //
  577. // 08/09/97 JMI Added some pretty UNdeluxe, ugly, not-too-useful load/save
  578. // progress feedback.
  579. //
  580. // 08/10/97 JMI Now allows ALT-ENTER to function as EditModify() as well as
  581. // the original ENTER.
  582. //
  583. // 08/10/97 JMI Removed unreferenced local var u32ColorIndex.
  584. //
  585. // 08/12/97 JMI No longer sets the realm's progress callback.
  586. // Also, now passes input events to GetLocalInput() which
  587. // GetLocalInput() now uses for finding cheat key combos.
  588. //
  589. // 08/13/97 JMI No longer attempts to show the attribute map when there
  590. // is no hood.
  591. //
  592. // 08/14/97 JMI Now you can select a thing from the realm stats list to
  593. // be selected by the editor in 'edit mode' (not edit play
  594. // mode which could be done later using IDs) which would be
  595. // cool.
  596. //
  597. // 08/16/97 BRH Added the feature that deletes all but the pylons, bouys,
  598. // soundthings and sound relays on a level so that it is
  599. // easy to strip a level down to a template. Also fixed a
  600. // problem with left over bouy lines if you had a level
  601. // showing bouys and then started a new level, the lines
  602. // would still be showing on that new level. Now it deletes
  603. // the bouy lines when a new level is started.
  604. //
  605. // 08/17/97 JMI Now unlocks the composite buffer before a video mode change
  606. // and relocks it again after a video mode change. This
  607. // occurred in two spots.
  608. //
  609. // JMI Now hides the mouse cursor while the menu is up.
  610. //
  611. // JMI Now ignores all input when in a menu.
  612. //
  613. // JMI Also, disables postal organ option from within the editor.
  614. //
  615. // 08/21/97 JMI PlayRealm() now sets the difficulty to the global settings
  616. // difficulty.
  617. //
  618. // 08/21/97 JMI Changed call to Update() to UpdateSystem() and occurrences
  619. // of rspUpdateDisplay() to UpdateDisplay().
  620. //
  621. // 08/22/97 JMI Changed occurrences of UpdateDisplay() back to
  622. // rspUpdateDisplay(). Now that we are using the lock
  623. // functions correctly, we don't need them.
  624. // Also, removed rspLockBuffer() and rspUnlockBuffer() that
  625. // were used to encapsulate the entire app in a lock.
  626. // Incorporated correct usage of rspLock/UnlockBuffer().
  627. //
  628. // 08/23/97 JMI Now does not save the .rgns when in PlayRealm().
  629. //
  630. // 08/25/97 JMI Made the dude show up with the user selected texture.
  631. //
  632. // 08/27/97 JMI Changed file counter messages to be very short (no file
  633. // name) and be in the upper left corner.
  634. //
  635. // 08/27/97 JMI Now sets the editor GUIs font back to the editor's pref
  636. // after ending a menu b/c the menu uses the global RGuiItem
  637. // RPrint too.
  638. //
  639. // 08/27/97 JMI Set video mode was being called while the composite buffer
  640. // was locked which, perhaps, should not be allowed. Fixed.
  641. //
  642. // 08/30/97 JMI Now, if a warp is selected when Play is chosen, PlayRealm()
  643. // will use that warp. Also, tried to make a generic
  644. // mechanism for PlayRealm() to utilize the current selection
  645. // in choosing among multiple things.
  646. //
  647. // 09/04/97 JMI If the quit status was non zero, it wasn't calling
  648. // CloseRealm() before exiting.
  649. //
  650. // 09/12/97 MJR Now the entire file doesn't compile when the editor is
  651. // disabled.
  652. //
  653. // 10/15/97 JMI Now LoadRealm() converts the system path returned from
  654. // rspOpenBox() to a RSPiX path before passing it to
  655. // CRealm::Load() which then converts it back to system. Even
  656. // though it was working without this change on the PC, it did
  657. // not work on the Mac.
  658. //
  659. // 10/15/97 JMI Applied above change to PlayRealm() as well.
  660. //
  661. // 12/02/97 JMI Now uses gsi.sAlwaysSetHWMode on Win32 platforms to avoid
  662. // flicker when changing display area without changing video
  663. // hardware settings.
  664. //
  665. // 10/03/99 JMI Fixed pasto in RealmOpProgress() where buffer was unlocked
  666. // twice rather than being locked and unlocked.
  667. //
  668. ////////////////////////////////////////////////////////////////////////////////
  669. //
  670. // Features to be added:
  671. //
  672. // Add ability for cursor to track the attribute map height. Maybe just a key
  673. // you hit and it adjust the cursor height to whatever the attribute map says
  674. // at the current cursor position.
  675. //
  676. // Add ability to move screen using cursor keys in play mode. Use key to
  677. // toggle between that and the ability to track the currently tagged target.
  678. // When you aren't using keys to move screen, they can be used by the main
  679. // dude. Need to create a mechanism by which main dude gets keyboard and mouse
  680. // input indirectly.
  681. //
  682. // Add a way to tag any object in the game so the camera will follow it.
  683. // This might actually require a fundamental CThing change, because there
  684. // would need to be a standardized method of getting an object's position.
  685. // CDude's would need to have such a feature, but I don't know if it's worth
  686. // generalizing this to all CThings.
  687. //
  688. // Modify EditNew() and EditModify(), or add an EditRect(), so that we can
  689. // get a rect that will be used as the basis for the object's hotbox. Maybe
  690. // EditRect() would be better because it could double as a way for us to track
  691. // an object! In fact, it HAS to be a separate function because when we load
  692. // a realm, we need to go through all the objects that were loaded and adding
  693. // new hotboxes to them, since the hotbox info doesn't get saved. A separate
  694. // function makes this easy.
  695. //
  696. // Once we have a separate EditRect() function, we'd be very tempted not to
  697. // use RHot anymore, because all we need is a simple list of rects that we
  698. // scan through for collisions. The main advantage would be that I could
  699. // impliment a simple method of re-ordering the priorities, which helps when
  700. // you've got multiple objects in the same area. RHot could be made to do
  701. // this, but it seems like it would be clumsy.
  702. //
  703. // Add psuedo-xray mode to scene so we can see objects when they go behind
  704. // buildings.
  705. //
  706. ////////////////////////////////////////////////////////////////////////////////
  707. #include "RSPiX.h"
  708. #include <ctype.h>
  709. #include <set>
  710. // This is used to get rid of all trace of the editor code when it's disabled
  711. #if !defined(EDITOR_DISABLED)
  712. #include "game.h"
  713. #include "update.h"
  714. #include "realm.h"
  715. #include "camera.h"
  716. #include "localize.h"
  717. #include "hood.h"
  718. #include "bouy.h"
  719. #include "navnet.h"
  720. #include "grip.h"
  721. #include "menus.h"
  722. #include "SampleMaster.h"
  723. #include "gameedit.h"
  724. #include "input.h"
  725. #include "pylon.h"
  726. #include "TriggerRgn.h"
  727. #include "TriggerRegions.h"
  728. #include "trigger.h"
  729. #include "dude.h"
  730. #include "warp.h"
  731. #include "InputSettingsDlg.h"
  732. #include "play.h"
  733. #include "score.h"
  734. #include "CompileOptions.h"
  735. ////////////////////////////////////////////////////////////////////////////////
  736. // Macros/types/etc.
  737. ////////////////////////////////////////////////////////////////////////////////
  738. #define EDIT_KEY_LOADREALM 'L'
  739. #define EDIT_KEY_OPENREALM 'O'
  740. #define EDIT_KEY_SAVEREALM 'S'
  741. #define EDIT_KEY_NEWREALM 'N'
  742. #define EDIT_KEY_TOGGLEBOUY 'B'
  743. #define EDIT_KEY_PICKOBJECT1 '1'
  744. #define EDIT_KEY_PICKOBJECT2 '2'
  745. #define EDIT_KEY_PICKOBJECT3 '3'
  746. #define EDIT_KEY_PICKOBJECT4 '4'
  747. #define EDIT_KEY_PICKOBJECT5 '5'
  748. #define EDIT_KEY_PICKOBJECT6 '6'
  749. #define EDIT_KEY_EXIT 27
  750. #define EDIT_KEY_MENU 27
  751. #define EDIT_KEY_CANCEL 27
  752. #define EDIT_KEY_PLAY 'P'
  753. #define EDIT_KEY_SCROLL_L RSP_GK_LEFT
  754. #define EDIT_KEY_SCROLL_R RSP_GK_RIGHT
  755. #define EDIT_KEY_SCROLL_U RSP_GK_UP
  756. #define EDIT_KEY_SCROLL_D RSP_GK_DOWN
  757. #define EDIT_KEY_ENDPLAY 27
  758. #define EDIT_KEY_PAUSE RSP_GK_PAUSE
  759. #define EDIT_KEY_SPEED_UP RSP_GK_NUMPAD_ASTERISK
  760. #define EDIT_KEY_SPEED_DOWN RSP_GK_NUMPAD_DIVIDE
  761. #define EDIT_KEY_SPEED_NORMAL RSP_GK_NUMPAD_DECIMAL
  762. #define EDIT_KEY_MODIFY1 '\r'
  763. #define EDIT_KEY_MODIFY2 ('\r' | RSP_GKF_ALT)
  764. #define EDIT_KEY_DELETE RSP_GK_DELETE
  765. #define EDIT_KEY_DELETE_GROUP (RSP_GK_DELETE | RSP_GKF_CONTROL)
  766. #define EDIT_KEY_DELETE_MOST (RSP_GKF_CONTROL | 'D')
  767. #define EDIT_KEY_ENLARGE_DISPLAY1 RSP_GK_NUMPAD_PLUS
  768. #define EDIT_KEY_ENLARGE_DISPLAY2 '+'
  769. #define EDIT_KEY_ENLARGE_DISPLAY3 '='
  770. #define EDIT_KEY_REDUCE_DISPLAY1 RSP_GK_NUMPAD_MINUS
  771. #define EDIT_KEY_REDUCE_DISPLAY2 '-'
  772. #define EDIT_KEY_INCREASE_OPACITY RSP_GK_NUMPAD_ASTERISK
  773. #define EDIT_KEY_DECREASE_OPACITY RSP_GK_NUMPAD_DIVIDE
  774. #define EDIT_KEY_CAMERA_TRACKING (RSP_GKF_CONTROL | 'T')
  775. #define EDIT_KEY_SENDTOBACK RSP_SK_CONTROL
  776. #define EDIT_KEY_SETCAMERATRACK RSP_SK_SHIFT
  777. #define EDIT_KEY_NEWITEM ' '
  778. #define EDIT_KEY_NEXTITEM '\t'
  779. #define EDIT_KEY_PREVITEM (RSP_GKF_SHIFT | '\t')
  780. #define EDIT_KEY_COPY (RSP_GKF_CONTROL | 'C')
  781. #define EDIT_KEY_CUT (RSP_GKF_CONTROL | 'X')
  782. #define EDIT_KEY_PASTE (RSP_GKF_CONTROL | 'V')
  783. #define EDIT_KEY_DOS_COPY (RSP_GKF_CONTROL | RSP_GK_INSERT)
  784. #define EDIT_KEY_DOS_CUT (RSP_GKF_SHIFT | RSP_GK_DELETE)
  785. #define EDIT_KEY_DOS_PASTE (RSP_GKF_SHIFT | RSP_GK_INSERT)
  786. #define EDIT_KEY_TOGGLE_DISP_INFO RSP_GK_F4
  787. #define EDIT_KEY_SHOW_MISSION RSP_GK_F5
  788. #define EDIT_KEY_OVERSHOOT_EDGES1 (RSP_GKF_SHIFT | '?')
  789. #define EDIT_KEY_OVERSHOOT_EDGES2 ('?')
  790. #define EDIT_KEY_REALM_STATISTICS (RSP_GK_F11)
  791. // Note that this uses RSP_SK_* macros for use the rspGetKeyStatusArray() key interface.
  792. #define KEY_XRAY_ALL RSP_SK_F3
  793. #define KEY_SNAP_PICTURE RSP_SK_ENTER
  794. #define KEY_ABORT_REALM_OPERATION RSP_SK_ESCAPE
  795. #define EDIT_SCROLL_AMOUNT 16
  796. #define CURSOR_BASE_IMAGE_FILE "res/editor/CursBase.bmp"
  797. #define CURSOR_BASE_HOTX 7
  798. #define CURSOR_BASE_HOTY 7
  799. #define CURSOR_TIP_IMAGE_FILE "res/editor/CursTip.bmp"
  800. #define CURSOR_TIP_HOTX 7
  801. #define CURSOR_TIP_HOTY 7
  802. #define DRAG_MIN_X 1
  803. #define DRAG_MIN_Y 1
  804. #define DRAG_MIN_TIME 500
  805. #define CURSOR_NOTHING 0
  806. #define CURSOR_LEFT_BUTTON_UP 1
  807. #define CURSOR_LEFT_DOUBLE_CLICK 2
  808. #define CURSOR_LEFT_DRAG_BEGIN 3
  809. #define CURSOR_LEFT_DRAG_END 4
  810. #define CURSOR_RIGHT_BUTTON_UP 5
  811. #define CURSOR_RIGHT_DOUBLE_CLICK 6
  812. #define CURSOR_RIGHT_DRAG_BEGIN 7
  813. #define CURSOR_RIGHT_DRAG_END 8
  814. #define REALM_BAR_FILE "res/editor/RealmBar.gui"
  815. #define PICK_OBJECT_FILE "res/editor/PickObj.gui"
  816. #define LAYERS_GUI_FILE "res/editor/Layers.gui"
  817. #define CAMERAS_GUI_FILE "res/editor/Cameras.gui"
  818. #define SHOWATTRIBS_GUI_FILE "res/editor/Attribs.gui"
  819. #define INFO_GUI_FILE "res/editor/Info.gui"
  820. #define VIEW_GUI_FILE "res/editor/camera.gui"
  821. #define REALM_STATISTICS_GUI_FILE "res/editor/stats.gui"
  822. #define GUIS_FONT_HEIGHT 15
  823. #define REALM_BAR_X 0
  824. #define REALM_BAR_Y (g_pimScreenBuf->m_sHeight - DISPLAY_BOTTOM_BORDER)
  825. #define PICKOBJ_LIST_X (g_pimScreenBuf->m_sWidth - DISPLAY_RIGHT_BORDER)
  826. #define PICKOBJ_LIST_Y 0
  827. #define LAYERS_LIST_X (g_pimScreenBuf->m_sWidth - DISPLAY_RIGHT_BORDER)
  828. #define LAYERS_LIST_Y (ms_pguiPickObj->m_sY + ms_pguiPickObj->m_im.m_sHeight)
  829. #define CAMERAS_LIST_X (LAYERS_LIST_X)
  830. #define CAMERAS_LIST_Y (ms_pguiLayers->m_sY + ms_pguiLayers->m_im.m_sHeight)
  831. #define GUIS_BAR_X 0
  832. #define GUIS_BAR_Y (ms_pguiRealmBar->m_sY + ms_pguiRealmBar->m_im.m_sHeight)
  833. #define MAP_X MAX(ms_pguiRealmBar->m_sX + ms_pguiRealmBar->m_im.m_sWidth, \
  834. ms_pguiGUIs->m_sX + ms_pguiGUIs->m_im.m_sWidth)
  835. #define MAP_Y (g_pimScreenBuf->m_sHeight - DISPLAY_BOTTOM_BORDER)
  836. #define NAVNETS_X (g_pimScreenBuf->m_sWidth - DISPLAY_RIGHT_BORDER)
  837. #define NAVNETS_Y (ms_pguiCameras->m_sY + ms_pguiCameras->m_im.m_sHeight)
  838. #define SHOWATTRIBS_X 0
  839. #define SHOWATTRIBS_Y (ms_pguiGUIs->m_sY + ms_pguiGUIs->m_im.m_sHeight)
  840. #define INFO_X (ms_pguiShowAttribs->m_sX + ms_pguiShowAttribs->m_im.m_sWidth)
  841. #define INFO_Y SHOWATTRIBS_Y
  842. #define SCROLL_BAR_THICKNESS 15
  843. // IDs:
  844. #define GUI_ID_NEW_REALM 1
  845. #define GUI_ID_OPEN_REALM 2
  846. #define GUI_ID_SAVE_REALM 3
  847. #define GUI_ID_CLOSE_REALM 4
  848. #define GUI_ID_PLAY_REALM 5
  849. #define GUI_ID_SAVE_REALM_AS 6
  850. #define GUI_ID_TOGGLE_LAYER 7
  851. #define GUI_ID_EXIT 8
  852. #define GUI_ID_PROPERTIES 23
  853. #define GUI_ID_NEW_CAMERA 9
  854. #define GUI_ID_CLOSE_CAMERA 10
  855. #define GUI_ID_CAMERA_LIST 11
  856. #define GUI_ID_NAVNET_LIST 11
  857. #define GUI_ID_REALM_VISIBLE 12
  858. #define GUI_ID_LAYERS_VISIBLE 13
  859. #define GUI_ID_THINGS_VISIBLE 14
  860. #define GUI_ID_CAMERAS_VISIBLE 15
  861. #define GUI_ID_NAVNETS_VISIBLE 16
  862. #define GUI_ID_MAP_VISIBLE 17
  863. #define GUI_ID_MAP_REFRESH 18
  864. #define GUI_ID_NEW_THING 19
  865. #define GUI_ID_COPY 20
  866. #define GUI_ID_CUT 21
  867. #define GUI_ID_PASTE 22
  868. #define GUI_ID_PICK_LIST 3
  869. #define GUI_ID_LAYER_LIST 3
  870. #define GUI_ID_MAP_ZONE 1
  871. #define GUI_ID_ATTRIB_LAYERS 100
  872. #define GUI_ID_ATTRIB_HEIGHT 101
  873. #define GUI_ID_ATTRIB_NOWALK 102
  874. #define GUI_ID_ATTRIB_LIGHT 103
  875. #define GUI_ID_INFO_X_POS 100
  876. #define GUI_ID_INFO_Y_POS 101
  877. #define GUI_ID_INFO_Z_POS 102
  878. #define GUI_ID_REALM_STATISTICS 1000
  879. // The ID of the item to be selected by default.
  880. #define DEFAULT_THING_ID CThing::CDudeID
  881. // Each item added to the Pick Object listbox will have an GUI ID of this plus
  882. // their class ID (e.g., CDude's list item would be LIST_ITEM_GUI_ID_BASE + CDudeId).
  883. // Don't define any editor GUI items with GUI IDs above this.
  884. #define LIST_ITEM_GUI_ID_BASE 0x70000000
  885. // Determines the number of elements in the passed array at compile time.
  886. #define NUM_ELEMENTS(a) (sizeof(a) / sizeof(a[0]) )
  887. // Amount to inc or dec display area when adjusted.
  888. // Indicate here as inc (i.e., positive).
  889. #define DISPLAY_SIZE_DELTA_X 20
  890. #define DISPLAY_SIZE_DELTA_Y 20
  891. // Amount of bottom border.
  892. #define DISPLAY_BOTTOM_BORDER 200
  893. #define DISPLAY_RIGHT_BORDER 100
  894. // Initial camera viewable area.
  895. #define INITIAL_CAMERA_X 640
  896. #define INITIAL_CAMERA_Y 400
  897. // Front most priority for a hotbox.
  898. #define FRONTMOST_HOT_PRIORITY -32767
  899. // The colors used for the selection rectangle surrounding the currently
  900. // selected CThing.
  901. #define SELECTION_COLOR1 RSP_BLACK_INDEX
  902. #define SELECTION_COLOR2 RSP_WHITE_INDEX
  903. #define SELECTION_THICKNESS 1
  904. #define GUIS_GUI_FILE "res/editor/GUIs.gui"
  905. #define MAP_GUI_FILE "res/editor/Map.gui"
  906. #define NAVNETS_GUI_FILE "res/editor/NavNets.gui"
  907. #define DISP_INFO_FONT_H 15
  908. #define DUDE_STATUS_RECT_X 10
  909. #define DUDE_STATUS_RECT_Y (REALM_STATUS_RECT_Y + REALM_STATUS_RECT_H + 3)
  910. #define DUDE_STATUS_RECT_W (ms_pcameraCur->m_sViewW - DUDE_STATUS_RECT_X)
  911. #define DUDE_STATUS_RECT_H (g_GameSettings.m_sDisplayInfo ? (INFO_STATUS_RECT_Y - DUDE_STATUS_RECT_Y) : (g_pimScreenBuf->m_sHeight - DUDE_STATUS_RECT_Y) )// (g_pimScreenBuf->m_sHeight - DUDE_STATUS_RECT_Y)
  912. #define REALM_STATUS_RECT_X 10
  913. #define REALM_STATUS_RECT_Y (ms_pcameraCur->m_sFilmViewY + ms_pcameraCur->m_sViewH + 3)
  914. #define REALM_STATUS_RECT_W (ms_pcameraCur->m_sViewW - REALM_STATUS_RECT_X)
  915. #define REALM_STATUS_RECT_H (40)
  916. #define INFO_STATUS_RECT_X 10
  917. #define INFO_STATUS_RECT_Y (g_pimScreenBuf->m_sHeight - INFO_STATUS_RECT_H)
  918. #define INFO_STATUS_RECT_W (g_pimScreenBuf->m_sWidth - INFO_STATUS_RECT_X)
  919. #define INFO_STATUS_RECT_H (DISP_INFO_FONT_H + 1)
  920. // This value is mutliplied by the amount the cursor is off the edge of the view
  921. // and the result is used to scroll the view.
  922. #define EDGE_MOVEMENT_MULTIPLIER 1
  923. // This value indicates the number of pixels around the edge of the view that
  924. // imply scrolling while dragging or moving an object.
  925. #define DRAG_SCROLL_BUFFER 10
  926. // Amount the scroll bar buttons will scroll.
  927. #define SCROLL_BTN_INCDEC 10
  928. // Directory to get *.RLM files from.
  929. #define INITIAL_REALM_DIR "res/Levels/."
  930. // Defines the alpha level used when blitting the trigger region currently being
  931. // editted.
  932. #define DEF_TRIGGER_RGN_ALPHA_LEVEL 80
  933. // The alpha level used when showing the attributes.
  934. #define DEF_ATTRIBUTES_ALPHA_LEVEL 80
  935. #define TRIGGER_RGN_DRAW_INDEX 250
  936. #define SHOW_ATTRIBS_DRAW_INDEX 250
  937. // Initial size for paste buffer.
  938. #define PASTE_BUFFER_INITIAL_SIZE 1024
  939. // Amount paste buffer grows as it gets larger.
  940. #define PASTE_BUFFER_GROW_SIZE 1024
  941. #define MAX_ALPHA_LEVEL 255
  942. #define MIN_ALPHA_LEVEL 15
  943. #define INCDEC_ALPHA_LEVEL 10
  944. #define MY_RFILE_CALLBACK_INTERVAL 100
  945. #define PROGRESS_CALLBACK_INTERVAL 100
  946. #define PROGRESS_X (ms_pcameraCur->m_sFilmViewX + 10)
  947. #define PROGRESS_Y (ms_pcameraCur->m_sFilmViewY + 30)
  948. #define PROGRESS_W (ms_pcameraCur->m_sViewW - PROGRESS_X - 10)
  949. #define PROGRESS_H 10
  950. #define PROGRESS_COLOR_INDEX 252
  951. #define PROGRESS_OUTLINE_COLOR_INDEX 249
  952. // The font for the editor GUIs.
  953. #define EDITOR_GUI_FONT g_fontBig
  954. ////////////////////////////////////////////////////////////////////////////////
  955. // Typedefs/structures
  956. ////////////////////////////////////////////////////////////////////////////////
  957. typedef struct TAG_Line
  958. {
  959. short sX0;
  960. short sY0;
  961. short sX1;
  962. short sY1;
  963. bool operator < (const TAG_Line& rhs) const
  964. {
  965. if (this->sX0 > rhs.sX0)
  966. return false;
  967. if (this->sX0 < rhs.sX0)
  968. return true;
  969. // sX0 is equal at this point
  970. if (this->sY0 > rhs.sY0)
  971. return false;
  972. if (this->sY0 < rhs.sY0)
  973. return true;
  974. // sX0 & sY0 are equal at this point
  975. if (this->sX1 > rhs.sX1)
  976. return false;
  977. if (this->sX1 < rhs.sX1)
  978. return true;
  979. // sX0 & sY0 & sX1 are equal at this point
  980. if (this->sY1 > rhs.sY1)
  981. return false;
  982. if (this->sY1 < rhs.sY1)
  983. return true;
  984. // Else the whole thing is equal
  985. return false;
  986. }
  987. bool operator == (const TAG_Line& rhs) const
  988. {
  989. return (this->sX0 == rhs.sX0 &&
  990. this->sY0 == rhs.sY0 &&
  991. this->sX1 == rhs.sX1 &&
  992. this->sY1 == rhs.sY1);
  993. }
  994. } LINKLINE;
  995. #if _MSC_VER >= 1020 || __MWERKS__ >= 0x1100
  996. #if __MWERKS >= 0x1100
  997. ITERATOR_TRAITS(const LINKLINE);
  998. #endif
  999. typedef set <LINKLINE, less<LINKLINE>, allocator<LINKLINE> > lineset;
  1000. #else
  1001. typedef set <LINKLINE, less<LINKLINE> > lineset;
  1002. #endif
  1003. // Container for a GUI and Camera pair.
  1004. typedef struct
  1005. {
  1006. RGuiItem* pgui;
  1007. RScrollBar* psbVert;
  1008. RScrollBar* psbHorz;
  1009. CCamera cam;
  1010. short sViewW;
  1011. short sViewH;
  1012. } View;
  1013. ////////////////////////////////////////////////////////////////////////////////
  1014. // Variables/data
  1015. ////////////////////////////////////////////////////////////////////////////////
  1016. RImage* m_pimCursorBase;
  1017. RImage* m_pimCursorTip;
  1018. CBouy* m_pBouyLink0;
  1019. CBouy* m_pBouyLink1;
  1020. lineset m_NetLines;
  1021. static bool ms_bDrawNetwork = true;
  1022. // ID of item most recently pressed or 0, if none.
  1023. static long ms_lPressedId = 0;
  1024. // Realm filename. Assuming only one Realm loaded at once.
  1025. static char ms_szFileName[RSP_MAX_PATH] = "";
  1026. static short ms_sMoving = FALSE; // TRUE, if moving/placing a thing (ms_pthingSel).
  1027. static CThing* ms_pthingSel = NULL; // CThing* to thing currently selected.
  1028. static RHot* ms_photSel = NULL; // RHot* to hotbox associated with selected thing.
  1029. // Initial width and height of display so we can
  1030. // restore video mode when done editting.
  1031. static short ms_sInitialDisplayWidth = 0;
  1032. static short ms_sInitialDisplayHeight = 0;
  1033. static short ms_sInitialDeviceDepth = 0;
  1034. static short ms_sInitialDeviceWidth = 0;
  1035. static short ms_sInitialDeviceHeight = 0;
  1036. // The current camera.
  1037. // Scrollbars' callback update camera pointed to by this.
  1038. static CCamera* ms_pcameraCur = NULL;
  1039. // Global GUIs (used in both editing and edit play modes).
  1040. static RScrollBar ms_sbVert;
  1041. static RScrollBar ms_sbHorz;
  1042. // This points to the CHood's hotbox which is the root of all other CThing
  1043. // hotboxes.
  1044. static RHot* ms_photHood = NULL;
  1045. // This is the hotbox priority of the farthest item from the user.
  1046. // Start out as close to front as possible.
  1047. static short ms_sBackPriority = FRONTMOST_HOT_PRIORITY;
  1048. // Made this global (was static in GetCursor()) for temp.
  1049. static short ms_sDragState = 0;
  1050. // Root level GUIs to load from *.gui files.
  1051. static RGuiItem* ms_pguiRealmBar = NULL;
  1052. static RGuiItem* ms_pguiPickObj = NULL;
  1053. static RGuiItem* ms_pguiLayers = NULL;
  1054. static RGuiItem* ms_pguiCameras = NULL;
  1055. static RGuiItem* ms_pguiGUIs = NULL;
  1056. static RGuiItem* ms_pguiMap = NULL;
  1057. static RGuiItem* ms_pguiNavNets = NULL;
  1058. static RGuiItem* ms_pguiShowAttribs = NULL;
  1059. static RGuiItem* ms_pguiInfo = NULL;
  1060. // Child GUIs that need to be frequently accessed.
  1061. static RListBox* ms_plbLayers = NULL;
  1062. static RGuiItem* ms_pguiMapZone = NULL;
  1063. static RGuiItem* ms_pguiInfoXPos = NULL;
  1064. static RGuiItem* ms_pguiInfoYPos = NULL;
  1065. static RGuiItem* ms_pguiInfoZPos = NULL;
  1066. // The current ratio being used for the map.
  1067. static double ms_dMapRatio = 0.0;
  1068. // The current CGameEditThing.
  1069. static CGameEditThing* ms_pgething = NULL;
  1070. // List of cameras and their GUI.
  1071. static RList<View> ms_listViews;
  1072. // If true, scrolling via drag/move of CThing is allowed.
  1073. static bool ms_bDragScroll = true;
  1074. // Trigger regions for pylons.
  1075. static TriggerRgn ms_argns[256];
  1076. // Current pylon being editted.
  1077. static CPylon* ms_pylonEdit = NULL; // NULL for none.
  1078. // Current block size for drawing.
  1079. static short ms_sDrawBlockSize = 5;
  1080. // Sprite used to draw pylon trigger region in the editor.
  1081. static CSprite2 ms_spriteTriggerRgn;
  1082. // Copy/Paste buffer.
  1083. static RFile ms_filePaste;
  1084. // File count used for items in the paste buffer (always decremented so we
  1085. // can guarantee that statics are saved).
  1086. static short ms_sFileCount = -1;
  1087. // Type of item to paste.
  1088. static CThing::ClassIDType ms_idPaste;
  1089. // Sprite used to draw attributes.
  1090. static CSprite2 ms_spriteAttributes;
  1091. // Attribute masks to draw.
  1092. static U16 ms_u16TerrainMask;
  1093. static U16 ms_u16LayerMask;
  1094. // Used by RFile callback function
  1095. static long ms_lRFileCallbackTime;
  1096. static long ms_lFileBytesSoFar;
  1097. static char ms_szFileOpDescriptionFrmt[512];
  1098. static RPrint ms_printFile;
  1099. static short ms_sFileOpTextX;
  1100. static short ms_sFileOpTextY;
  1101. static short ms_sFileOpTextW;
  1102. static short ms_sFileOpTextH;
  1103. // Amount to scroll off edge of realm.
  1104. static long ms_lEdgeOvershoot = 1000;
  1105. ////////////////////////////////////////////////////////////////////////////////
  1106. // Function prototypes
  1107. ////////////////////////////////////////////////////////////////////////////////
  1108. // Do ALL editor input.
  1109. static bool DoInput( // Returns true when done.
  1110. CRealm* prealm, // Ptr to current realm.
  1111. CCamera* pcamera, // Ptr to current camera.
  1112. short* psCursorX, // Out: Cursor X position.
  1113. short* psCursorY, // Out: Cursor Y position.
  1114. short* psCursorZ); // Out: Cursor Z position.
  1115. // Do ALL editor output.
  1116. static void DoOutput( // Returns nothing.
  1117. CRealm* prealm, // Ptr to current realm.
  1118. CCamera* pcamera, // Ptr to current camera.
  1119. short sCursorX, // Cursor X position.
  1120. short sCursorY, // Cursor Y position.
  1121. short sCursorZ); // Cursor Z position.
  1122. static void GetCursor( // Returns nothing.
  1123. RInputEvent* pie, // In: Input event.
  1124. // Out: pie->sUsed = TRUE, if used.
  1125. short* psX, // Out: X coord of event.
  1126. short* psY, // Out: Y coord of event.
  1127. short* psZ, // Out: Z coord of event.
  1128. short* psEvent); // Out: Event type.
  1129. static short InitCursor(
  1130. void);
  1131. static void KillCursor(
  1132. void);
  1133. static void DrawCursor(
  1134. short sCursorX, // In: Cursor hotspot x coord
  1135. short sCursorY, // In: Cursor hotspot y coord
  1136. short sCursorZ, // In: Cursor hotspot z coord
  1137. RImage* pimDst, // In: Image to draw to
  1138. CRealm* prealm, // In: Realm.
  1139. CCamera* pcamera); // In: Camera on prealm.
  1140. static short NewRealm(
  1141. CRealm* prealm);
  1142. static short CloseRealm(
  1143. CRealm* prealm);
  1144. static short LoadRealm(
  1145. CRealm* prealm);
  1146. static short SaveRealm( // Returns 0 on success.
  1147. CRealm* prealm, // In: Realm to save.
  1148. char* pszRealmName, // In: Filename to save as.
  1149. bool bSaveTriggerRegions); // In: Save the trigger regions too.
  1150. static short SaveRealm(
  1151. CRealm* prealm);
  1152. static short SaveRealmAs(
  1153. CRealm* prealm);
  1154. static void PlayRealm( // Returns nothing.
  1155. CRealm* prealm, // In: Realm to play.
  1156. CThing* pthingSel); // In: Currently selected CThing which can
  1157. // be used to give PlayRealm() a hint on which
  1158. // of several things the user wants to use.
  1159. // For example, a selected warp is the used
  1160. // as the warp in point.
  1161. // Create a new CThing derived object of type id in prealm at the specified
  1162. // position.
  1163. static short CreateNewThing( // Returns 0 on success.
  1164. CRealm* prealm, // In: Realm to add new CThing to.
  1165. CThing::ClassIDType id, // ID of new CThing type to create.
  1166. short sPosX, // Position for new CThing.
  1167. short sPosY, // Position for new CThing.
  1168. short sPosZ, // Position for new CThing.
  1169. CThing** ppthing, // Out: Pointer to new thing.
  1170. RHot** pphot, // Out: Pointer to new hotbox for thing.
  1171. RFile* pfile = NULL); // In: Optional file to load from (instead of EditNew()).
  1172. // Move a thing to the specified location and update its RHot with an
  1173. // EditRect() call.
  1174. static void MoveThing( // Returns nothing.
  1175. CThing* pthing, // Thing to move.
  1176. RHot* phot, // Thing's hotbox.
  1177. short sPosX, // New position.
  1178. short sPosY, // New position.
  1179. short sPosZ); // New position.
  1180. // Enlarges the display area.
  1181. static void OnEnlargeDisplay(
  1182. CCamera* pcamera, // Camera to update.
  1183. CRealm* prealm); // Realm to update.
  1184. // Reduces the display area.
  1185. static void OnReduceDisplay(
  1186. CCamera* pcamera, // Camera to update.
  1187. CRealm* prealm); // Realm to update.
  1188. // Set display mode such that display area is as
  1189. // specified.
  1190. static short SetDisplayArea( // Returns 0 on success.
  1191. short sDisplayD, // New depth of display.
  1192. short sDisplayW, // New width of display area.
  1193. short sDisplayH); // New height of display area.
  1194. // Set display mode and display area such that camera view
  1195. // is specified size.
  1196. static short SetCameraArea(void); // Returns 0 on success.
  1197. // Adjust the display area by the specified deltas.
  1198. static short AdjustDisplaySize( // Returns 0 on success.
  1199. short sAdjustX, // Amount to increase width of display area.
  1200. // Can be negative to decrease.
  1201. short sAdjustY, // Amount to increase height of display area.
  1202. // Can be negative to decrease.
  1203. CCamera* pcamera, // Camera to update.
  1204. CRealm* prealm); // Realm to update.
  1205. // Update screen size sensitive objects.
  1206. static short SizeUpdate( // Returns 0 on success.
  1207. CCamera* pcamera, // Camera to update.
  1208. CRealm* prealm); // Realm to update.
  1209. // Resets all RHots including and descended from ms_photHood
  1210. // to FRONTMOST_HOT_PRIORITY.
  1211. static void ResetHotPriorities(void); // Returns nothing.
  1212. // Callback from GUIs. This will set ms_lPressedId to pgui->m_lId.
  1213. static void GuiPressedCall( // Returns nothing.
  1214. RGuiItem* pgui); // GUI item pressed.
  1215. // Callback from pressed list items.
  1216. static void ListItemPressedCall( // Returns nothing.
  1217. RGuiItem* pgui); // GUI item pressed.
  1218. // Callback from scrollbars indicating change in thumb position.
  1219. static void ScrollPosUpdate( // Returns nothing.
  1220. RScrollBar* psb); // ScrollBar that was updated.
  1221. // Callback from RHot when an event occurs within it.
  1222. static void ThingHotCall( // Returns nothing.
  1223. RHot* phot, // Ptr to RHot that generated event.
  1224. RInputEvent* pie); // In: Most recent user input event.
  1225. // Out: Depends on callbacks. Generally,
  1226. // pie->sUsed = TRUE, if used.
  1227. // Draws the rubber band type line while creating bouy links.
  1228. static void DrawBouyLink( // Returns nothing.
  1229. CRealm* prealm, // In: Realm.
  1230. CCamera* pcamera); // In: View of prealm.
  1231. // AddLine - add the newly drawn line to the set of lines.
  1232. static void AddNewLine(short sX0, short sY0, short sX1, short sY1);
  1233. // Writes out a log of connected bouys. This is for debugging only
  1234. static void NetLog(CNavigationNet* pNavNet);
  1235. // UpdateNetLines - build the full list of link lines from the
  1236. // navigation net. This function can be used after the bouys have
  1237. // been loaded for a realm before the first time the DrawNetwork is
  1238. // called. There may also be a key to refresh the lines. This will
  1239. // also be called when switching the 'current' network
  1240. static void UpdateNetLines(CNavigationNet* pNavNet);
  1241. // Draw network - draw the lines
  1242. static void DrawNetwork( // Returns nothing.
  1243. CRealm* prealm, // In: Realm.
  1244. CCamera* pcamera); // In: View of prealm.
  1245. // Get the Editor Thing from the specified realm.
  1246. static CGameEditThing* GetEditorThing( // Returns ptr to editor thing for
  1247. // specified realm or NULL.
  1248. CRealm* prealm); // Realm to get editor thing from.
  1249. // Creates a view and adds it to the list of views.
  1250. static short AddView( // Returns 0 on success.
  1251. CRealm* prealm); // In: Realm in which to setup camera.
  1252. // Kills a view and removes it from the list of views.
  1253. static void RemoveView( // Returns nothing.
  1254. View* pview); // In: View to remove or NULL to remove currently
  1255. // selected view.
  1256. // Removes all current views.
  1257. static void RemoveViews(void);
  1258. // Creates a new View and adds it to the list of Views.
  1259. static short CreateView( // Returns 0 on success.
  1260. View** ppview, // Out: New view, if not NULL.
  1261. CRealm* prealm); // In: Realm in which to setup camera.
  1262. // Destroys a View and removes it from the list of Views.
  1263. static void KillView( // Returns nothing.
  1264. View* pview); // View to kill.
  1265. // Draw specified view.
  1266. static void DrawView( // Returns nothing.
  1267. View* pview, // View to draw.
  1268. CRealm* prealm); // Realm to draw.
  1269. // Draw all views.
  1270. static void DrawViews( // Returns nothing.
  1271. CRealm* prealm); // Realm to draw.
  1272. // Clear the specified GUI's area.
  1273. static void ClearGUI( // Returns nothing.
  1274. RGuiItem* pgui); // In: GUI's whose area we should clean.
  1275. // Clear all views.
  1276. static void ClearViews(void); // Returns nothing.
  1277. // Do focus hotbox logic and such for GUIs.
  1278. static void DoView( // Returns nothing.
  1279. View* pview, // View to do.
  1280. RInputEvent* pie); // Input event to process.
  1281. // Do all views.
  1282. static void DoViews( // Returns nothing.
  1283. RInputEvent* pie); // Input event to process.
  1284. // Draw the map.
  1285. static void RefreshMap( // Returns nothing.
  1286. CRealm* prealm); // Realm to map.
  1287. // Cancel any thing drag.
  1288. static void CancelDrag(CRealm* prealm);// Returns nothing.
  1289. // Place any thing being dragged.
  1290. static void DragDrop( // Returns nothing.
  1291. short sDropX, // In: Drop x position.
  1292. short sDropY, // In: Drop y position.
  1293. short sDropZ); // In: Drop z position.
  1294. // Move focus to next item in realm's thing list.
  1295. static void NextItem( // Returns nothing.
  1296. CRealm* prealm); // In: The realm we want the next thing in.
  1297. // Move focus to previous item in realm's thing list.
  1298. static void PrevItem( // Returns nothing.
  1299. CRealm* prealm); // In: The realm we want the next thing in.
  1300. // Load the trigger regions for the specified realm.
  1301. static short LoadTriggerRegions( // Returns 0 on success.
  1302. char* pszRealmName); // In: Name of the REALM (*.RLM) file.
  1303. // The .ext is stripped and .rgn is appended.
  1304. // Save the trigger regions for the specified realm.
  1305. static short SaveTriggerRegions( // Returns 0 on success.
  1306. char* pszRealmName, // In: Name of the REALM (*.RLM) file.
  1307. CRealm* prealm); // The .ext is stripped and .rgn is appended.
  1308. // Create the trigger attribute layer for the realm
  1309. static short CreateTriggerRegions( // Returns 0 on success.
  1310. CRealm* prealm ); // In: Access of Realm Info
  1311. // Change or clear the current pylon being edited.
  1312. static void EditPylonTriggerRegion( // Returns nothing.
  1313. CThing* pthingPylon); // In: Pylon whose trigger area we want to
  1314. // Set the selection to the specified CThing.
  1315. static CThing* SetSel( // Returns CThing that previously was selected.
  1316. CThing* pthingSel, // In: CThing to be selected.
  1317. RHot* photSel); // In: Hotbox of CThing to be selected.
  1318. // Delete the specified item.
  1319. static void DelThing( // Returns nothing.
  1320. CThing* pthingDel, // In: CThing to be deleted.
  1321. RHot* photDel, // In: Hotbox of CThing to be deleted.
  1322. CRealm* prealm); // In: Current realm
  1323. // Delete all the items in the currently selected class.
  1324. static void DelClass( // Returns nothing.
  1325. CThing* pthingDel, // In: CThing to be deleted.
  1326. CRealm* prealm); // In: Current realm
  1327. // Delete all but the basic items from the realm in order to make template levels
  1328. static void DelMost( // Return nothing
  1329. CRealm* prealm); // In: Current realm
  1330. // Copy a thing to the paste buffer.
  1331. static short CopyItem( // Returns 0 on success.
  1332. CThing* pthingCopy); // In: CThing to copy.
  1333. // Copy a thing to the paste buffer.
  1334. static short PasteItem( // Returns 0 on success.
  1335. CRealm* prealm, // In: The realm to paste into.
  1336. short sX, // In: Location for new thing.
  1337. short sY, // In: Location for new thing.
  1338. short sZ); // In: Location for new thing.
  1339. // Map a screen coordinate to a realm coordinate.
  1340. // Note that this function's *psRealmY output is always
  1341. // the height specified by the realm's attribute map
  1342. // at the resulting *psRealmX, *psRealmZ.
  1343. static void MapScreen2Realm( // Returns nothing.
  1344. CRealm* prealm, // In: Realm.
  1345. CCamera* pcamera, // In: View of prealm.
  1346. short sScreenX, // In: Screen x coord.
  1347. short sScreenY, // In: Screen y coord.
  1348. short* psRealmX, // Out: Realm x coord.
  1349. short* psRealmY, // Out: Realm y coord (always via realm's height map).
  1350. short* psRealmZ); // Out: Realm z coord.
  1351. // Map a realm coordinate to a screen coordinate.
  1352. static void Maprealm2Screen( // Returns nothing.
  1353. CRealm* prealm, // In: Realm.
  1354. CCamera* pcamera, // In: View of prealm.
  1355. short sRealmX, // In: Realm x coord.
  1356. short sRealmY, // In: Realm y coord.
  1357. short sRealmZ, // In: Realm z coord.
  1358. short* psScreenX, // Out: Screen x coord.
  1359. short* psScreenY); // Out: Screen y coord.
  1360. // Blit attribute areas lit by the specified mask into the specified image.
  1361. static void AttribBlit( // Returns nothing.
  1362. RMultiGrid* pmg, // In: Multigrid of attributes.
  1363. U16 u16Mask, // In: Mask of important attributes.
  1364. RImage* pimDst, // In: Destination image.
  1365. short sSrcX, // In: Where in Multigrid to start.
  1366. short sSrcY, // In: Where in Multigrid to start.
  1367. short sW, // In: How much of multigrid to use.
  1368. short sH); // In: How much of multigrid to use.
  1369. // Callback for attrib mask multibtns.
  1370. static void AttribMaskBtnPressed( // Returns nothing.
  1371. RGuiItem* pgui_pmb); // In: Ptr to the pressed GUI (which is a multibtn).
  1372. // Resizes the attribute sprite, if allocated.
  1373. static short SizeShowAttribsSprite(void); // Returns 0 on success.
  1374. // Convert a .RLM filename to a .RGN one.
  1375. static void RlmNameToRgnName( // Returns nothing.
  1376. char* pszRealmName, // In: .RLM name.
  1377. char* pszRgnName); // Out: .RGN name.
  1378. // Our RFile callback
  1379. static void MyRFileCallback(long lBytes);
  1380. // Update selection info in the info GUI.
  1381. static void UpdateSelectionInfo( // Returns nothing.
  1382. bool bTitle = false); // In: true to update the title info as well.
  1383. static short TmpFileName( // Returns 0 if successfull, non-zero otherwise
  1384. char* pszFileName, // Out: Temp file name returned here
  1385. short sMaxSize); // In: Maximum size of file name
  1386. // Show statistics for the specified realm.
  1387. static short ShowRealmStatistics( // Returns 0 on success.
  1388. CRealm* prealm, // In: Realm to get stats on.
  1389. CThing** ppthing); // Out: Selected thing, if not NULL.
  1390. // Init load/save counter. You should call KillFileCounter() after
  1391. // done with the file access.
  1392. static void InitFileCounter( // Returns nothing.
  1393. char* pszDescriptionFrmt); // In: sprintf format for description of
  1394. // operation.
  1395. // Kill load/save counter. Can be called multiple times w/o corresponding
  1396. // Init().
  1397. static void KillFileCounter(void); // Returns nothing.
  1398. // Callback from realm during time intensive operations.
  1399. static bool RealmOpProgress( // Returns true to continue; false to
  1400. // abort operation.
  1401. short sLastItemProcessed, // In: Number of items processed so far.
  1402. short sTotalItemsToProcess); // In: Total items to process.
  1403. ////////////////////////////////////////////////////////////////////////////////
  1404. //
  1405. // Set some basic stuff for specified item.
  1406. //
  1407. ////////////////////////////////////////////////////////////////////////////////
  1408. inline void SetPressedCall( // Returns nothing.
  1409. RGuiItem* pguiRoot, // Root item.
  1410. long lId) // ID of GUI item to set.
  1411. {
  1412. ASSERT(pguiRoot != NULL);
  1413. RGuiItem* pgui = pguiRoot->GetItemFromId(lId);
  1414. if (pgui != NULL)
  1415. {
  1416. // Set callback.
  1417. pgui->m_bcUser = GuiPressedCall;
  1418. }
  1419. else
  1420. {
  1421. TRACE("SetPressedCall(): ID %ld missing.\n", lId);
  1422. }
  1423. }
  1424. ////////////////////////////////////////////////////////////////////////////////
  1425. //
  1426. // Set the user values of the specified GUI.
  1427. //
  1428. ////////////////////////////////////////////////////////////////////////////////
  1429. inline void SetMBValsAndCallback( // Returns nothing.
  1430. RGuiItem* pguiRoot, // In: Root item.
  1431. long lId, // In: ID of child to set user vals on.
  1432. U32 u32UserInstance, // In: Value for m_ulUserInstance.
  1433. U32 u32UserData, // In: Value for m_ulUserData.
  1434. short sState) // In: Initial MultiBtn state.
  1435. {
  1436. RMultiBtn* pmb = (RMultiBtn*)pguiRoot->GetItemFromId(lId);
  1437. if (pmb)
  1438. {
  1439. pmb->m_ulUserInstance = u32UserInstance;
  1440. pmb->m_ulUserData = u32UserData;
  1441. pmb->m_bcUser = AttribMaskBtnPressed;
  1442. pmb->m_sState = sState;
  1443. // Reflect new state.
  1444. pmb->Compose();
  1445. }
  1446. }
  1447. ////////////////////////////////////////////////////////////////////////////////
  1448. //
  1449. // Run the game editor
  1450. //
  1451. ////////////////////////////////////////////////////////////////////////////////
  1452. extern void GameEdit(
  1453. void)
  1454. {
  1455. // Clear any members that need to be intialized on each entrance.
  1456. ms_pcameraCur = NULL;
  1457. ms_pthingSel = NULL;
  1458. ms_photSel = NULL;
  1459. ms_plbLayers = NULL;
  1460. ms_pgething = NULL;
  1461. ms_photHood = NULL;
  1462. // Disable 'Organ' on 'Audio Options' menu.
  1463. menuAudioOptions.ami[1].sEnabled = FALSE;
  1464. // Set alpha level to default.
  1465. ms_spriteTriggerRgn.m_sAlphaLevel = DEF_TRIGGER_RGN_ALPHA_LEVEL;
  1466. ms_spriteAttributes.m_sAlphaLevel = DEF_ATTRIBUTES_ALPHA_LEVEL;
  1467. // Set attrib masks to not display any attributes.
  1468. ms_u16TerrainMask = 0;
  1469. ms_u16LayerMask = 0;
  1470. // Set filename such that initially open and save dialogs start in
  1471. // *.RLM dir.
  1472. strcpy(ms_szFileName, FullPathVD(INITIAL_REALM_DIR));
  1473. // Clear mouse and keyboard events
  1474. rspClearAllInputEvents();
  1475. // Remember initial display settings.
  1476. rspGetVideoMode(
  1477. &ms_sInitialDeviceDepth,
  1478. &ms_sInitialDeviceWidth,
  1479. &ms_sInitialDeviceHeight,
  1480. NULL,
  1481. &ms_sInitialDisplayWidth,
  1482. &ms_sInitialDisplayHeight);
  1483. // Clear screen
  1484. rspLockBuffer();
  1485. rspRect(RSP_BLACK_INDEX, g_pimScreenBuf, 0, 0, g_pimScreenBuf->m_sWidth, g_pimScreenBuf->m_sHeight);
  1486. rspUnlockBuffer();
  1487. rspUpdateDisplay();
  1488. // Display message if necessary
  1489. #ifdef DISABLE_EDITOR_SAVE_AND_PLAY
  1490. rspMsgBox(
  1491. RSP_MB_ICN_INFO | RSP_MB_BUT_OK,
  1492. "Postal Editor",
  1493. "This is the same game editor we used to create the entire game. "
  1494. "The only things that aren't working in it are the \"Save\" and "
  1495. "\"Play\" functions. We had to disable these for various reasons, "
  1496. "not the least of which is that it would have taken up more space. "
  1497. "But please, check it out and let us know what you think!");
  1498. #endif
  1499. // Clear rubber band links for bouys
  1500. m_pBouyLink0 = m_pBouyLink1 = NULL;
  1501. // Init cursor stuff
  1502. if (InitCursor() == 0)
  1503. {
  1504. //////////////////////////////////////////////////////////////////////
  1505. // Create realm.
  1506. //////////////////////////////////////////////////////////////////////
  1507. // Create a realm. At some point we will probably extend the editor to
  1508. // be able to handle multiple realms at once. For now it just has one.
  1509. CRealm* prealm = new CRealm;
  1510. ASSERT(prealm != 0);
  1511. // This realm will only be used for editting, so it make it known.
  1512. prealm->m_flags.bEditing = true;
  1513. // Setup progress callback right away.
  1514. // prealm->m_fnProgress = RealmOpProgress;
  1515. // Reset realm time here and never do anything to it while in the editor.
  1516. // This way, game objects will be able to access the time, but will never
  1517. // see any change, which seems like a good thing.
  1518. prealm->m_time.Reset();
  1519. //////////////////////////////////////////////////////////////////////
  1520. // Setup camera.
  1521. //////////////////////////////////////////////////////////////////////
  1522. CCamera* pcamera = new CCamera;
  1523. ASSERT(pcamera != NULL);
  1524. pcamera->SetScene(&(prealm->m_scene));
  1525. // Update display size sensitive objects.
  1526. SizeUpdate(pcamera, prealm);
  1527. pcamera->SetFilm(g_pimScreenBuf, 0, 0);
  1528. ms_pcameraCur = pcamera;
  1529. /////////////////////////////////////////////////////////////////////////
  1530. // Set up GUIs.
  1531. /////////////////////////////////////////////////////////////////////////
  1532. // Make sure there's a font in the default RPrint for GUIs.
  1533. // Also, sets the size the GUIs will use when printing text.
  1534. RGuiItem::ms_print.SetFont(GUIS_FONT_HEIGHT, &EDITOR_GUI_FONT);
  1535. // Load GUIs.
  1536. ms_pguiRealmBar = RGuiItem::LoadInstantiate(FullPath(GAME_PATH_VD, REALM_BAR_FILE) );
  1537. ms_pguiPickObj = RGuiItem::LoadInstantiate(FullPath(GAME_PATH_VD, PICK_OBJECT_FILE) );
  1538. ms_pguiLayers = RGuiItem::LoadInstantiate(FullPath(GAME_PATH_VD, LAYERS_GUI_FILE) );
  1539. ms_pguiCameras = RGuiItem::LoadInstantiate(FullPath(GAME_PATH_VD, CAMERAS_GUI_FILE) );
  1540. ms_pguiGUIs = RGuiItem::LoadInstantiate(FullPath(GAME_PATH_VD, GUIS_GUI_FILE) );
  1541. ms_pguiMap = RGuiItem::LoadInstantiate(FullPath(GAME_PATH_VD, MAP_GUI_FILE) );
  1542. ms_pguiNavNets = RGuiItem::LoadInstantiate(FullPath(GAME_PATH_VD, NAVNETS_GUI_FILE) );
  1543. ms_pguiShowAttribs = RGuiItem::LoadInstantiate(FullPath(GAME_PATH_VD, SHOWATTRIBS_GUI_FILE) );
  1544. ms_pguiInfo = RGuiItem::LoadInstantiate(FullPath(GAME_PATH_VD, INFO_GUI_FILE) );
  1545. // Make sure we got all our GUIs . . .
  1546. if ( ms_pguiRealmBar != NULL
  1547. && ms_pguiPickObj != NULL
  1548. && ms_pguiLayers != NULL
  1549. && ms_pguiCameras != NULL
  1550. && ms_pguiGUIs != NULL
  1551. && ms_pguiMap != NULL
  1552. && ms_pguiNavNets != NULL
  1553. && ms_pguiShowAttribs
  1554. && ms_pguiInfo)
  1555. {
  1556. // Set items that are to notify us.
  1557. SetPressedCall(ms_pguiRealmBar, GUI_ID_NEW_REALM);
  1558. SetPressedCall(ms_pguiRealmBar, GUI_ID_OPEN_REALM);
  1559. SetPressedCall(ms_pguiRealmBar, GUI_ID_SAVE_REALM);
  1560. SetPressedCall(ms_pguiRealmBar, GUI_ID_CLOSE_REALM);
  1561. SetPressedCall(ms_pguiRealmBar, GUI_ID_PLAY_REALM);
  1562. SetPressedCall(ms_pguiRealmBar, GUI_ID_SAVE_REALM_AS);
  1563. SetPressedCall(ms_pguiRealmBar, GUI_ID_EXIT);
  1564. SetPressedCall(ms_pguiRealmBar, GUI_ID_PROPERTIES);
  1565. // Show the Realm Bar.
  1566. ms_pguiRealmBar->SetVisible(ms_pguiRealmBar->m_sVisible);
  1567. // Get object picker list box.
  1568. RListBox* plbPicker = (RListBox*)ms_pguiPickObj->GetItemFromId(GUI_ID_PICK_LIST);
  1569. ASSERT(plbPicker != NULL);
  1570. ASSERT(plbPicker->m_type == RGuiItem::ListBox);
  1571. // Add available objects to listbox.
  1572. CThing::ClassIDType idCur;
  1573. RGuiItem* pguiItem;
  1574. for (idCur = 1; idCur < CThing::TotalIDs; idCur++)
  1575. {
  1576. // If item is editor creatable . . .
  1577. if (CThing::ms_aClassInfo[idCur].bEditorCreatable == true)
  1578. {
  1579. // Add string for each item to listbox.
  1580. pguiItem = plbPicker->AddString((char*)CThing::ms_aClassInfo[idCur].pszClassName);
  1581. if (pguiItem != NULL)
  1582. {
  1583. pguiItem->m_lId = LIST_ITEM_GUI_ID_BASE + idCur;
  1584. pguiItem->m_ulUserData = (ULONG)idCur;
  1585. // Set the callback on pressed.
  1586. pguiItem->m_bcUser = ListItemPressedCall;
  1587. }
  1588. }
  1589. }
  1590. // Format list items.
  1591. plbPicker->AdjustContents();
  1592. // Select the DEFAULT_THING_ID.
  1593. RGuiItem* pguiDefThing = ms_pguiPickObj->GetItemFromId(DEFAULT_THING_ID + LIST_ITEM_GUI_ID_BASE);
  1594. if (pguiDefThing != NULL)
  1595. {
  1596. plbPicker->SetSel(pguiDefThing);
  1597. // Ensure that the default item is visible. Not scrolled off somewhere.
  1598. plbPicker->EnsureVisible(pguiDefThing);
  1599. }
  1600. // Activate pick object box.
  1601. ms_pguiPickObj->SetVisible(ms_pguiPickObj->m_sVisible);
  1602. // Get layer tweaker list box.
  1603. ms_plbLayers = (RListBox*)ms_pguiLayers->GetItemFromId(GUI_ID_LAYER_LIST);
  1604. ASSERT(ms_plbLayers != NULL);
  1605. ASSERT(ms_plbLayers->m_type == RGuiItem::ListBox);
  1606. // Add available layers to listbox.
  1607. short sLayer;
  1608. for (sLayer = CRealm::LayerBg; sLayer < CRealm::TotalLayers; sLayer++)
  1609. {
  1610. // Add string for each item to listbox.
  1611. pguiItem = ms_plbLayers->AddString(CRealm::ms_apszLayerNames[sLayer]);
  1612. if (pguiItem != NULL)
  1613. {
  1614. // Remember which layer it's associated with.
  1615. pguiItem->m_ulUserData = (ULONG)sLayer;
  1616. // We'll need to know when these are pressed.
  1617. pguiItem->m_bcUser = ListItemPressedCall;
  1618. pguiItem->m_lId = GUI_ID_TOGGLE_LAYER;
  1619. // These are push buttons.
  1620. ASSERT(pguiItem->m_type == RGuiItem::PushBtn);
  1621. ((RPushBtn*)pguiItem)->m_state
  1622. = (prealm->m_scene.m_pLayers[sLayer].m_bHidden == false) ? RPushBtn::On : RPushBtn::Off;
  1623. // Realize state.
  1624. pguiItem->Compose();
  1625. }
  1626. }
  1627. // Format list items.
  1628. ms_plbLayers->AdjustContents();
  1629. ms_pguiLayers->SetVisible(ms_pguiLayers->m_sVisible);
  1630. // Set callbacks.
  1631. SetPressedCall(ms_pguiCameras, GUI_ID_NEW_CAMERA);
  1632. SetPressedCall(ms_pguiCameras, GUI_ID_CLOSE_CAMERA);
  1633. ms_pguiCameras->SetVisible(ms_pguiCameras->m_sVisible);
  1634. // --------- GUIs bar --------
  1635. // Set items that are to notify us.
  1636. SetPressedCall(ms_pguiGUIs, GUI_ID_REALM_VISIBLE);
  1637. SetPressedCall(ms_pguiGUIs, GUI_ID_LAYERS_VISIBLE);
  1638. SetPressedCall(ms_pguiGUIs, GUI_ID_THINGS_VISIBLE);
  1639. SetPressedCall(ms_pguiGUIs, GUI_ID_CAMERAS_VISIBLE);
  1640. SetPressedCall(ms_pguiGUIs, GUI_ID_NAVNETS_VISIBLE);
  1641. SetPressedCall(ms_pguiGUIs, GUI_ID_MAP_VISIBLE);
  1642. // Set items' states.
  1643. ms_pguiGUIs->SetVisible(TRUE);
  1644. // ---------- NavNets list --------
  1645. ms_pguiNavNets->SetVisible(ms_pguiNavNets->m_sVisible);
  1646. // ---------- Show Attribs --------
  1647. SetMBValsAndCallback(ms_pguiShowAttribs, GUI_ID_ATTRIB_LAYERS, (U32)(&ms_u16LayerMask), REALM_ATTR_LAYER_MASK, 1);
  1648. SetMBValsAndCallback(ms_pguiShowAttribs, GUI_ID_ATTRIB_HEIGHT, (U32)(&ms_u16TerrainMask), REALM_ATTR_HEIGHT_MASK, 1);
  1649. SetMBValsAndCallback(ms_pguiShowAttribs, GUI_ID_ATTRIB_NOWALK, (U32)(&ms_u16TerrainMask), REALM_ATTR_NOT_WALKABLE, 1);
  1650. SetMBValsAndCallback(ms_pguiShowAttribs, GUI_ID_ATTRIB_LIGHT, (U32)(&ms_u16TerrainMask), REALM_ATTR_LIGHT_BIT, 1);
  1651. ms_pguiShowAttribs->SetVisible(TRUE);
  1652. // ---------- Info ----------------
  1653. ms_pguiInfoXPos = ms_pguiInfo->GetItemFromId(GUI_ID_INFO_X_POS);
  1654. ms_pguiInfoYPos = ms_pguiInfo->GetItemFromId(GUI_ID_INFO_Y_POS);
  1655. ms_pguiInfoZPos = ms_pguiInfo->GetItemFromId(GUI_ID_INFO_Z_POS);
  1656. ms_pguiInfo->SetVisible(TRUE);
  1657. // ---------- Map -----------------
  1658. SetPressedCall(ms_pguiMap, GUI_ID_MAP_REFRESH);
  1659. ms_pguiMapZone = ms_pguiMap->GetItemFromId(GUI_ID_MAP_ZONE);
  1660. ms_pguiMap->SetVisible(ms_pguiMap->m_sVisible);
  1661. // Copy colors and such to scrollbars.
  1662. ms_pguiPickObj->CopyParms(&ms_sbVert);
  1663. ms_pguiPickObj->CopyParms(&ms_sbHorz);
  1664. ms_sbHorz.m_oOrientation = RScrollBar::Horizontal;
  1665. ms_sbVert.SetVisible(TRUE);
  1666. ms_sbHorz.SetVisible(TRUE);
  1667. ms_sbVert.m_upcUser = ScrollPosUpdate;
  1668. ms_sbHorz.m_upcUser = ScrollPosUpdate;
  1669. // Smooth scrolling.
  1670. ms_sbVert.m_scrollage = RScrollBar::Smooth;
  1671. ms_sbHorz.m_scrollage = RScrollBar::Smooth;
  1672. // Set display size based on the user's settings.
  1673. SetCameraArea();
  1674. // Update size sensitive objects (including scrollbars).
  1675. SizeUpdate(pcamera, prealm);
  1676. //////////////////////////////////////////////////////////////////////
  1677. // Prepare user input.
  1678. //////////////////////////////////////////////////////////////////////
  1679. // Clear mouse and keyboard events
  1680. rspClearAllInputEvents();
  1681. // Make sure the system cursor is visible.
  1682. // Store show level so we can restore it.
  1683. short sCursorShowLevel = rspGetMouseCursorShowLevel();
  1684. rspSetMouseCursorShowLevel(1);
  1685. // User must load an existing realm or start a new one to go any further
  1686. bool bGoEdit = false;
  1687. bool bExit = false;
  1688. // Set currently select thing to default value
  1689. CThing::ClassIDType idCurrent = DEFAULT_THING_ID;
  1690. // Clear mouse and keyboard events
  1691. rspClearAllInputEvents();
  1692. //////////////////////////////////////////////////////////////////////
  1693. // Editor's main loop.
  1694. //////////////////////////////////////////////////////////////////////
  1695. bExit = false;
  1696. short sCursorX, sCursorY, sCursorZ;
  1697. while (!bExit)
  1698. {
  1699. ///////////////////////////////////////////////////////////////////
  1700. // System update.
  1701. ///////////////////////////////////////////////////////////////////
  1702. UpdateSystem();
  1703. ///////////////////////////////////////////////////////////////////
  1704. // Input.
  1705. ///////////////////////////////////////////////////////////////////
  1706. bExit = DoInput(prealm, pcamera, &sCursorX, &sCursorY, &sCursorZ);
  1707. ///////////////////////////////////////////////////////////////////
  1708. // Output.
  1709. ///////////////////////////////////////////////////////////////////
  1710. DoOutput(prealm, pcamera, sCursorX, sCursorY, sCursorZ);
  1711. }
  1712. // Done with the views.
  1713. RemoveViews();
  1714. // Restore cursor show level.
  1715. rspSetMouseCursorShowLevel(sCursorShowLevel);
  1716. // Done with GUIs.
  1717. delete ms_pguiRealmBar;
  1718. ms_pguiRealmBar = NULL;
  1719. delete ms_pguiPickObj;
  1720. ms_pguiPickObj = NULL;
  1721. delete ms_pguiLayers;
  1722. ms_pguiLayers = NULL;
  1723. delete ms_pguiCameras;
  1724. ms_pguiCameras = NULL;
  1725. delete ms_pguiGUIs;
  1726. ms_pguiGUIs = NULL;
  1727. delete ms_pguiMap;
  1728. ms_pguiMap = NULL;
  1729. delete ms_pguiNavNets;
  1730. ms_pguiNavNets = NULL;
  1731. delete ms_pguiShowAttribs;
  1732. ms_pguiShowAttribs = NULL;
  1733. delete ms_pguiInfo;
  1734. ms_pguiInfo = NULL;
  1735. }
  1736. else
  1737. {
  1738. rspMsgBox(
  1739. RSP_MB_ICN_STOP | RSP_MB_BUT_OK,
  1740. g_pszCriticalErrorTitle,
  1741. g_pszAssetsMissingError);
  1742. }
  1743. // Done with the realm.
  1744. delete prealm;
  1745. prealm = NULL;
  1746. // Done with the camera.
  1747. delete pcamera;
  1748. pcamera = NULL;
  1749. ms_pcameraCur = NULL;
  1750. // Kill cursor stuff
  1751. KillCursor();
  1752. }
  1753. // If there is an image, delete it.
  1754. delete ms_spriteAttributes.m_pImage;
  1755. ms_spriteAttributes.m_pImage = NULL;
  1756. // If paste buffer open . . .
  1757. if (ms_filePaste.IsOpen() != FALSE)
  1758. {
  1759. ms_filePaste.Close();
  1760. }
  1761. // Restore display mode.
  1762. rspSetVideoMode(
  1763. ms_sInitialDeviceDepth,
  1764. ms_sInitialDeviceWidth,
  1765. ms_sInitialDeviceHeight,
  1766. ms_sInitialDisplayWidth,
  1767. ms_sInitialDisplayHeight);
  1768. // Give Jeff a chance to update his cool wrapper.
  1769. // I'm not sure if this is necessary, but let's be safe.
  1770. rspNameBuffers(&g_pimScreenBuf);
  1771. // Clear mouse and keyboard events
  1772. rspClearAllInputEvents();
  1773. // Clear screen
  1774. rspLockBuffer();
  1775. rspRect(RSP_BLACK_INDEX, g_pimScreenBuf, 0, 0, g_pimScreenBuf->m_sWidth, g_pimScreenBuf->m_sHeight);
  1776. rspUnlockBuffer();
  1777. rspUpdateDisplay();
  1778. // Re-enable 'Organ' on 'Audio Options' menu.
  1779. menuAudioOptions.ami[1].sEnabled = TRUE;
  1780. }
  1781. ////////////////////////////////////////////////////////////////////////////////
  1782. //
  1783. // Do ALL editor input.
  1784. //
  1785. ////////////////////////////////////////////////////////////////////////////////
  1786. static bool DoInput( // Returns true when done.
  1787. CRealm* prealm, // Ptr to current realm.
  1788. CCamera* pcamera, // Ptr to current camera.
  1789. short* psCursorX, // Out: Cursor X position.
  1790. short* psCursorY, // Out: Cursor Y position.
  1791. short* psCursorZ) // Out: Cursor Z position.
  1792. {
  1793. bool bExit = false;
  1794. short sCursorX;
  1795. short sCursorY;
  1796. short sCursorZ;
  1797. short sCursorEvent;
  1798. RInputEvent ie;
  1799. // Get next input event.
  1800. ie.type = RInputEvent::None;
  1801. rspGetNextInputEvent(&ie);
  1802. Menu* pmenu = GetCurrentMenu();
  1803. // If there is a menu . . .
  1804. if (pmenu != NULL)
  1805. {
  1806. // This is CHEEZY AS HELL but the normal menu callback calls
  1807. // game.cpp which sets its action flag telling it to call this
  1808. // function. Not sure how to do it here. Will we need to call
  1809. // game.cpp, play.cpp, and gameedit.cpp whenever this menu is
  1810. // activated?
  1811. if (pmenu == &menuJoystick || pmenu == &menuMouse || pmenu == &menuKeyboard)
  1812. {
  1813. // Do the input settings.
  1814. EditInputSettings();
  1815. }
  1816. // Menu on top (even of cursor).
  1817. DoMenuInput(&ie, 0);
  1818. // If there is no longer a menu . . .
  1819. if (GetCurrentMenu() == NULL)
  1820. {
  1821. // Show the mouse.
  1822. rspShowMouseCursor();
  1823. // Fade in and restore colors.
  1824. PalTranOff();
  1825. }
  1826. }
  1827. else
  1828. {
  1829. // If editting a pylon trigger region . . .
  1830. if (ms_pylonEdit != NULL)
  1831. {
  1832. static short sButtons = 0;
  1833. // Get cursor position and event
  1834. GetCursor(&ie, &sCursorX, &sCursorY, &sCursorZ, &sCursorEvent);
  1835. UCHAR ucId = ms_pylonEdit->m_ucID;
  1836. static U8* pau8KeyStatus = rspGetKeyStatusArray();
  1837. // Move unit for arrow key movement of region.
  1838. // Note: Combinations of SHIFT, CONTROL, and ALT
  1839. // provide super fast movement.
  1840. short sMoveUnit = 1;
  1841. if (pau8KeyStatus[RSP_SK_SHIFT] & 1)
  1842. sMoveUnit *= 2;
  1843. if (pau8KeyStatus[RSP_SK_CONTROL] & 1)
  1844. sMoveUnit *= 3;
  1845. if (pau8KeyStatus[RSP_SK_ALT] & 1)
  1846. sMoveUnit *= 4;
  1847. if (pau8KeyStatus[RSP_SK_LEFT] & 1)
  1848. {
  1849. ms_argns[ucId].sX -= sMoveUnit;
  1850. ms_spriteTriggerRgn.m_sX2 -= sMoveUnit;
  1851. // Update sprite in scene.
  1852. prealm->m_scene.UpdateSprite(&ms_spriteTriggerRgn);
  1853. }
  1854. else if (pau8KeyStatus[RSP_SK_RIGHT] & 1)
  1855. {
  1856. ms_argns[ucId].sX += sMoveUnit;
  1857. ms_spriteTriggerRgn.m_sX2 += sMoveUnit;
  1858. // Update sprite in scene.
  1859. prealm->m_scene.UpdateSprite(&ms_spriteTriggerRgn);
  1860. }
  1861. else if (pau8KeyStatus[RSP_SK_UP] & 1)
  1862. {
  1863. ms_argns[ucId].sY -= sMoveUnit;
  1864. ms_spriteTriggerRgn.m_sY2 -= sMoveUnit;
  1865. // Update sprite in scene.
  1866. prealm->m_scene.UpdateSprite(&ms_spriteTriggerRgn);
  1867. }
  1868. else if (pau8KeyStatus[RSP_SK_DOWN] & 1)
  1869. {
  1870. ms_argns[ucId].sY += sMoveUnit;
  1871. ms_spriteTriggerRgn.m_sY2 += sMoveUnit;
  1872. // Update sprite in scene.
  1873. prealm->m_scene.UpdateSprite(&ms_spriteTriggerRgn);
  1874. }
  1875. // If unused event . . .
  1876. if (ie.sUsed == FALSE)
  1877. {
  1878. if (ie.type == RInputEvent::Mouse)
  1879. {
  1880. sButtons = ie.sButtons;
  1881. }
  1882. else
  1883. {
  1884. if (ie.type == RInputEvent::Key)
  1885. {
  1886. switch (ie.lKey & 0x0000FFFF)
  1887. {
  1888. case 27:
  1889. EditPylonTriggerRegion(NULL);
  1890. break;
  1891. case EDIT_KEY_ENLARGE_DISPLAY1:
  1892. case EDIT_KEY_ENLARGE_DISPLAY2:
  1893. case EDIT_KEY_ENLARGE_DISPLAY3:
  1894. if (ms_sDrawBlockSize + sMoveUnit > ms_sDrawBlockSize)
  1895. {
  1896. ms_sDrawBlockSize += sMoveUnit;
  1897. }
  1898. break;
  1899. case EDIT_KEY_REDUCE_DISPLAY1:
  1900. case EDIT_KEY_REDUCE_DISPLAY2:
  1901. ms_sDrawBlockSize -= sMoveUnit;
  1902. if (ms_sDrawBlockSize < 2)
  1903. {
  1904. ms_sDrawBlockSize = 2;
  1905. }
  1906. break;
  1907. case EDIT_KEY_DECREASE_OPACITY:
  1908. ms_spriteTriggerRgn.m_sAlphaLevel -= INCDEC_ALPHA_LEVEL;
  1909. if (ms_spriteTriggerRgn.m_sAlphaLevel < MIN_ALPHA_LEVEL)
  1910. {
  1911. ms_spriteTriggerRgn.m_sAlphaLevel = MIN_ALPHA_LEVEL;
  1912. }
  1913. break;
  1914. case EDIT_KEY_INCREASE_OPACITY:
  1915. ms_spriteTriggerRgn.m_sAlphaLevel += INCDEC_ALPHA_LEVEL;
  1916. if (ms_spriteTriggerRgn.m_sAlphaLevel > MAX_ALPHA_LEVEL)
  1917. {
  1918. ms_spriteTriggerRgn.m_sAlphaLevel = MAX_ALPHA_LEVEL;
  1919. }
  1920. break;
  1921. }
  1922. }
  1923. }
  1924. }
  1925. switch (sButtons)
  1926. {
  1927. case 1:
  1928. rspRect(
  1929. TRIGGER_RGN_DRAW_INDEX, // *** FUDGE ***.
  1930. ms_argns[ucId].pimRgn,
  1931. pcamera->m_sScene2FilmX + sCursorX - ms_argns[ucId].sX - ms_sDrawBlockSize / 2,
  1932. pcamera->m_sScene2FilmY + sCursorZ - ms_argns[ucId].sY - ms_sDrawBlockSize / 2,
  1933. ms_sDrawBlockSize,
  1934. ms_sDrawBlockSize);
  1935. break;
  1936. case 2:
  1937. rspRect(
  1938. 0,
  1939. ms_argns[ucId].pimRgn,
  1940. pcamera->m_sScene2FilmX + sCursorX - ms_argns[ucId].sX - ms_sDrawBlockSize / 2,
  1941. pcamera->m_sScene2FilmY + sCursorZ - ms_argns[ucId].sY - ms_sDrawBlockSize / 2,
  1942. ms_sDrawBlockSize,
  1943. ms_sDrawBlockSize);
  1944. break;
  1945. }
  1946. }
  1947. else
  1948. {
  1949. // If unused key event . . .
  1950. if (ie.type == RInputEvent::Key && ie.sUsed == FALSE)
  1951. {
  1952. // Force alpha keys to upper keys
  1953. if (isalpha(ie.lKey & 0xffff))
  1954. ie.lKey = (ie.lKey & 0xffff0000) | toupper(ie.lKey & 0xffff);
  1955. // In case we're gonna scroll, set amount based on CTRL key status
  1956. short sScrollX = EDIT_SCROLL_AMOUNT;
  1957. short sScrollY = EDIT_SCROLL_AMOUNT;
  1958. if (ie.lKey & RSP_GKF_CONTROL)
  1959. {
  1960. sScrollX = pcamera->m_sViewW;
  1961. sScrollY = pcamera->m_sViewH;
  1962. }
  1963. // Check for special editor keys
  1964. switch (ie.lKey)
  1965. {
  1966. case EDIT_KEY_LOADREALM:
  1967. case EDIT_KEY_OPENREALM:
  1968. ms_lPressedId = GUI_ID_OPEN_REALM;
  1969. // Used the key.
  1970. ie.sUsed = TRUE;
  1971. break;
  1972. case EDIT_KEY_SAVEREALM:
  1973. ms_lPressedId = GUI_ID_SAVE_REALM_AS;
  1974. // Used the key.
  1975. ie.sUsed = TRUE;
  1976. break;
  1977. case EDIT_KEY_NEWREALM:
  1978. ms_lPressedId = GUI_ID_NEW_REALM;
  1979. // Used the key.
  1980. ie.sUsed = TRUE;
  1981. break;
  1982. case EDIT_KEY_TOGGLEBOUY:
  1983. // Toggle the draw bouy flag
  1984. ms_bDrawNetwork = !ms_bDrawNetwork;
  1985. if (ms_bDrawNetwork)
  1986. {
  1987. CThing* pThing;
  1988. CListNode<CThing>* pNext = prealm->m_aclassHeads[CThing::CBouyID].m_pnNext;
  1989. while (pNext->m_powner != NULL)
  1990. {
  1991. pThing = pNext->m_powner;
  1992. if (pThing)
  1993. if (pThing->m_phot)
  1994. pThing->m_phot->SetActive(TRUE);
  1995. pNext = pNext->m_pnNext;
  1996. }
  1997. UpdateNetLines(prealm->GetCurrentNavNet());
  1998. CBouy::Show();
  1999. }
  2000. else
  2001. {
  2002. CThing* pThing;
  2003. CListNode<CThing>* pNext = prealm->m_aclassHeads[CThing::CBouyID].m_pnNext;
  2004. while (pNext->m_powner != NULL)
  2005. {
  2006. pThing = pNext->m_powner;
  2007. if (pThing)
  2008. if (pThing->m_phot)
  2009. pThing->m_phot->SetActive(FALSE);
  2010. pNext = pNext->m_pnNext;
  2011. }
  2012. CBouy::Hide();
  2013. }
  2014. // Used the key
  2015. ie.sUsed = TRUE;
  2016. break;
  2017. case EDIT_KEY_PLAY:
  2018. ms_lPressedId = GUI_ID_PLAY_REALM;
  2019. // Used the key.
  2020. ie.sUsed = TRUE;
  2021. break;
  2022. case EDIT_KEY_MENU: // EDIT_KEY_CANCEL
  2023. // If moving . . .
  2024. if (ms_sMoving != FALSE)
  2025. {
  2026. CancelDrag(prealm);
  2027. }
  2028. else
  2029. {
  2030. #if 1
  2031. // If menu is not running . . .
  2032. if (GetCurrentMenu() == NULL)
  2033. {
  2034. // Fade out and preserve colors.
  2035. PalTranOn();
  2036. if (StartMenu(&menuEditor, &g_resmgrShell, g_pimScreenBuf) == 0)
  2037. {
  2038. // Hide the mouse.
  2039. rspHideMouseCursor();
  2040. }
  2041. }
  2042. #else
  2043. ms_lPressedId = GUI_ID_EXIT;
  2044. #endif
  2045. }
  2046. // Used the key.
  2047. ie.sUsed = TRUE;
  2048. break;
  2049. case EDIT_KEY_SCROLL_L:
  2050. // Scroll left
  2051. ms_sbHorz.SetPos(pcamera->m_sSceneViewX - sScrollX);
  2052. // Used the key.
  2053. ie.sUsed = TRUE;
  2054. break;
  2055. case EDIT_KEY_SCROLL_R:
  2056. // Scroll right
  2057. ms_sbHorz.SetPos(pcamera->m_sSceneViewX + sScrollX);
  2058. // Used the key.
  2059. ie.sUsed = TRUE;
  2060. break;
  2061. case EDIT_KEY_SCROLL_U:
  2062. // Scroll up
  2063. ms_sbVert.SetPos(pcamera->m_sSceneViewY - sScrollY);
  2064. // Used the key.
  2065. ie.sUsed = TRUE;
  2066. break;
  2067. case EDIT_KEY_SCROLL_D:
  2068. // Scroll down
  2069. ms_sbVert.SetPos(pcamera->m_sSceneViewY + sScrollY);
  2070. // Used the key.
  2071. ie.sUsed = TRUE;
  2072. break;
  2073. case EDIT_KEY_ENLARGE_DISPLAY1:
  2074. case EDIT_KEY_ENLARGE_DISPLAY2:
  2075. case EDIT_KEY_ENLARGE_DISPLAY3:
  2076. OnEnlargeDisplay(pcamera, prealm);
  2077. break;
  2078. case EDIT_KEY_REDUCE_DISPLAY1:
  2079. case EDIT_KEY_REDUCE_DISPLAY2:
  2080. OnReduceDisplay(pcamera, prealm);
  2081. break;
  2082. case EDIT_KEY_MODIFY1:
  2083. case EDIT_KEY_MODIFY2:
  2084. // Verify there is a selection . . .
  2085. if (ms_pthingSel != NULL)
  2086. {
  2087. ASSERT(ms_photSel != NULL);
  2088. // Modify.
  2089. ms_pthingSel->EditModify();
  2090. // Size may have changed.
  2091. RRect rc;
  2092. ms_pthingSel->EditRect(&rc);
  2093. // Update hot.
  2094. ms_photSel->m_sX = rc.sX;
  2095. ms_photSel->m_sY = rc.sY;
  2096. ms_photSel->m_sW = rc.sW;
  2097. ms_photSel->m_sH = rc.sH;
  2098. }
  2099. break;
  2100. case EDIT_KEY_NEWITEM:
  2101. ms_lPressedId = GUI_ID_NEW_THING;
  2102. break;
  2103. case EDIT_KEY_NEXTITEM:
  2104. NextItem(prealm);
  2105. break;
  2106. case EDIT_KEY_PREVITEM:
  2107. PrevItem(prealm);
  2108. break;
  2109. case EDIT_KEY_DELETE_GROUP:
  2110. DelClass(ms_pthingSel, prealm);
  2111. break;
  2112. case EDIT_KEY_DELETE_MOST:
  2113. DelMost(prealm);
  2114. break;
  2115. case EDIT_KEY_DELETE:
  2116. // Delete item.
  2117. DelThing(ms_pthingSel, ms_photSel, prealm);
  2118. break;
  2119. case EDIT_KEY_DOS_COPY:
  2120. case EDIT_KEY_COPY:
  2121. ms_lPressedId = GUI_ID_COPY;
  2122. break;
  2123. case EDIT_KEY_DOS_CUT:
  2124. case EDIT_KEY_CUT:
  2125. ms_lPressedId = GUI_ID_CUT;
  2126. break;
  2127. case EDIT_KEY_DOS_PASTE:
  2128. case EDIT_KEY_PASTE:
  2129. ms_lPressedId = GUI_ID_PASTE;
  2130. break;
  2131. case EDIT_KEY_DECREASE_OPACITY:
  2132. if (ms_spriteAttributes.m_pImage)
  2133. {
  2134. ms_spriteAttributes.m_sAlphaLevel -= INCDEC_ALPHA_LEVEL;
  2135. if (ms_spriteAttributes.m_sAlphaLevel < MIN_ALPHA_LEVEL)
  2136. {
  2137. ms_spriteAttributes.m_sAlphaLevel = MIN_ALPHA_LEVEL;
  2138. }
  2139. }
  2140. break;
  2141. case EDIT_KEY_INCREASE_OPACITY:
  2142. if (ms_spriteAttributes.m_pImage)
  2143. {
  2144. ms_spriteAttributes.m_sAlphaLevel += INCDEC_ALPHA_LEVEL;
  2145. if (ms_spriteAttributes.m_sAlphaLevel > MAX_ALPHA_LEVEL)
  2146. {
  2147. ms_spriteAttributes.m_sAlphaLevel = MAX_ALPHA_LEVEL;
  2148. }
  2149. }
  2150. break;
  2151. case EDIT_KEY_OVERSHOOT_EDGES1:
  2152. case EDIT_KEY_OVERSHOOT_EDGES2:
  2153. if (pcamera->m_bClip == true)
  2154. {
  2155. pcamera->m_bClip = false;
  2156. // Update visual components.
  2157. SizeUpdate(pcamera, prealm);
  2158. }
  2159. else
  2160. {
  2161. pcamera->m_bClip = true;
  2162. // Update visual components.
  2163. SizeUpdate(pcamera, prealm);
  2164. }
  2165. break;
  2166. case EDIT_KEY_REALM_STATISTICS:
  2167. {
  2168. CThing* pthing;
  2169. ShowRealmStatistics(prealm, &pthing);
  2170. if (pthing)
  2171. {
  2172. SetSel(pthing, NULL);
  2173. }
  2174. break;
  2175. }
  2176. default:
  2177. break;
  2178. }
  2179. }
  2180. // Pass events to hotboxes before sucked up by edit cursor.
  2181. ms_pguiGUIs->m_hot.Do(&ie);
  2182. ms_pguiRealmBar->m_hot.Do(&ie);
  2183. //If there is a hood . . .
  2184. if (prealm->m_asClassNumThings[CThing::CHoodID] > 0)
  2185. {
  2186. // Do extra views.
  2187. DoViews(&ie);
  2188. // Do other GUIs.
  2189. ms_pguiPickObj->m_hot.Do(&ie);
  2190. ms_pguiLayers->m_hot.Do(&ie);
  2191. ms_pguiNavNets->m_hot.Do(&ie);
  2192. ms_pguiMap->m_hot.Do(&ie);
  2193. ms_pguiShowAttribs->m_hot.Do(&ie);
  2194. ms_pguiInfo->m_hot.Do(&ie);
  2195. }
  2196. ms_sbVert.m_hot.Do(&ie);
  2197. ms_sbHorz.m_hot.Do(&ie);
  2198. // If there's a hood hotbox and no item being dragged . . .
  2199. if (ms_photHood != NULL && ms_sMoving == FALSE)
  2200. {
  2201. // Pass the event to the Thing hotboxes in Realm coords.
  2202. RInputEvent ieRealm = ie;
  2203. ieRealm.sPosX += pcamera->m_sScene2FilmX;
  2204. ieRealm.sPosY += pcamera->m_sScene2FilmY;
  2205. ms_photHood->Do(&ieRealm);
  2206. // If used by editor hotbox . . .
  2207. if (ie.sUsed != ieRealm.sUsed)
  2208. {
  2209. // Note that it was used by editor hotbox.
  2210. ie.lUser = 1;
  2211. }
  2212. }
  2213. else
  2214. {
  2215. // If not yet used . . .
  2216. if (ie.sUsed == FALSE)
  2217. {
  2218. // Make it an editor event.
  2219. ie.lUser = 1;
  2220. }
  2221. }
  2222. // Get cursor position and event
  2223. GetCursor(&ie, &sCursorX, &sCursorY, &sCursorZ, &sCursorEvent);
  2224. // If there is a realm . . .
  2225. if (prealm != NULL)
  2226. {
  2227. // Map the cursor position to a realm coordinate.
  2228. MapScreen2Realm(prealm, pcamera, sCursorX, sCursorZ, &sCursorX, &sCursorY, &sCursorZ);
  2229. }
  2230. switch(sCursorEvent)
  2231. {
  2232. case CURSOR_LEFT_BUTTON_UP:
  2233. break;
  2234. case CURSOR_RIGHT_BUTTON_UP:
  2235. break;
  2236. case CURSOR_LEFT_DOUBLE_CLICK:
  2237. break;
  2238. case CURSOR_RIGHT_DOUBLE_CLICK:
  2239. break;
  2240. case CURSOR_LEFT_DRAG_BEGIN:
  2241. // If there is a selection . . .
  2242. if (ms_pthingSel != NULL)
  2243. {
  2244. // Let's not drag the hood . . .
  2245. if (ms_pthingSel->GetClassID() != CThing::CHoodID)
  2246. {
  2247. // Move mode.
  2248. ms_sMoving = TRUE;
  2249. // Make sure this is valid.
  2250. ASSERT(ms_photSel != NULL);
  2251. // Get hotspot for item in 2D.
  2252. short sOffsetX;
  2253. short sOffsetY;
  2254. ms_pthingSel->EditHotSpot(&sOffsetX, &sOffsetY);
  2255. // Reposition cursor to hotspot.
  2256. rspSetMouse(
  2257. (ms_photSel->m_sX - pcamera->m_sScene2FilmX) + sOffsetX,
  2258. (ms_photSel->m_sY - pcamera->m_sScene2FilmY) + sOffsetY);
  2259. // If cursor shown . . .
  2260. if (rspGetMouseCursorShowLevel() > 0)
  2261. {
  2262. // Hide it.
  2263. rspHideMouseCursor();
  2264. }
  2265. }
  2266. }
  2267. break;
  2268. case CURSOR_LEFT_DRAG_END:
  2269. DragDrop(
  2270. sCursorX, // x
  2271. sCursorY, // y
  2272. sCursorZ); // z
  2273. break;
  2274. case CURSOR_NOTHING:
  2275. // If there is an item being moved . . .
  2276. if (ms_sMoving != FALSE)
  2277. {
  2278. ASSERT(ms_pthingSel != NULL);
  2279. ASSERT(ms_photSel != NULL);
  2280. MoveThing(
  2281. ms_pthingSel,
  2282. ms_photSel,
  2283. sCursorX, // x
  2284. sCursorY, // y
  2285. sCursorZ); // z
  2286. bool bInsideNonScroll = true;
  2287. CNavigationNet* pNavNet = prealm->GetCurrentNavNet();
  2288. if (pNavNet)
  2289. UpdateNetLines(pNavNet);
  2290. short sScreenX;
  2291. short sScreenY;
  2292. Maprealm2Screen(
  2293. prealm,
  2294. pcamera,
  2295. sCursorX,
  2296. 0,
  2297. sCursorZ,
  2298. &sScreenX,
  2299. &sScreenY);
  2300. // If on or beyond any edge of the view . . .
  2301. if (sScreenX < DRAG_SCROLL_BUFFER)
  2302. {
  2303. if (ms_bDragScroll == true)
  2304. {
  2305. ms_sbHorz.SetPos(ms_sbHorz.GetPos() + (sScreenX - DRAG_SCROLL_BUFFER) * EDGE_MOVEMENT_MULTIPLIER);
  2306. }
  2307. // Note that the cursor is not in the non-scroll area.
  2308. bInsideNonScroll = false;
  2309. }
  2310. else if (sScreenX > pcamera->m_sViewW - DRAG_SCROLL_BUFFER)
  2311. {
  2312. if (ms_bDragScroll == true)
  2313. {
  2314. ms_sbHorz.SetPos(ms_sbHorz.GetPos() + (sScreenX - (pcamera->m_sViewW - DRAG_SCROLL_BUFFER)) * EDGE_MOVEMENT_MULTIPLIER);
  2315. }
  2316. // Note that the cursor is not in the non-scroll area.
  2317. bInsideNonScroll = false;
  2318. }
  2319. if (sScreenY < DRAG_SCROLL_BUFFER)
  2320. {
  2321. if (ms_bDragScroll == true)
  2322. {
  2323. ms_sbVert.SetPos(ms_sbVert.GetPos() + (sScreenY - DRAG_SCROLL_BUFFER) * EDGE_MOVEMENT_MULTIPLIER);
  2324. }
  2325. // Note that the cursor is not in the non-scroll area.
  2326. bInsideNonScroll = false;
  2327. }
  2328. else if (sScreenY > pcamera->m_sViewH - DRAG_SCROLL_BUFFER)
  2329. {
  2330. if (ms_bDragScroll == true)
  2331. {
  2332. ms_sbVert.SetPos(ms_sbVert.GetPos() + (sScreenY - (pcamera->m_sViewH - DRAG_SCROLL_BUFFER)) * EDGE_MOVEMENT_MULTIPLIER);
  2333. }
  2334. // Note that the cursor is not in the non-scroll area.
  2335. bInsideNonScroll = false;
  2336. }
  2337. // If inside the non-scroll area . . .
  2338. if (bInsideNonScroll == true)
  2339. {
  2340. // Enable scrolling.
  2341. ms_bDragScroll = true;
  2342. }
  2343. }
  2344. break;
  2345. default:
  2346. break;
  2347. }
  2348. // Do GUI input focus stuff.
  2349. RGuiItem::DoFocus(&ie);
  2350. // Switch on ID of item clicked.
  2351. switch (ms_lPressedId)
  2352. {
  2353. case 0: // Nothin'.
  2354. break;
  2355. case GUI_ID_NEW_REALM:
  2356. // Create new realm
  2357. NewRealm(prealm);
  2358. // Setup camera.
  2359. pcamera->SetHood(prealm->m_phood);
  2360. m_pBouyLink0 = NULL;
  2361. m_pBouyLink1 = NULL;
  2362. break;
  2363. case GUI_ID_OPEN_REALM:
  2364. // Load realm
  2365. LoadRealm(prealm);
  2366. m_pBouyLink0 = NULL;
  2367. m_pBouyLink1 = NULL;
  2368. break;
  2369. case GUI_ID_SAVE_REALM:
  2370. // Save realm
  2371. SaveRealm(prealm);
  2372. break;
  2373. case GUI_ID_SAVE_REALM_AS:
  2374. // Save realm
  2375. SaveRealmAs(prealm);
  2376. break;
  2377. case GUI_ID_PLAY_REALM:
  2378. if (prealm->m_phood != NULL)
  2379. {
  2380. CancelDrag(prealm);
  2381. // Simulate playing the realm
  2382. PlayRealm(prealm, ms_pthingSel);
  2383. // Restore global camera.
  2384. ms_pcameraCur = pcamera;
  2385. // Display size may have changed.
  2386. SizeUpdate(pcamera, prealm);
  2387. }
  2388. else
  2389. {
  2390. // ***LOCALIZE***.
  2391. rspMsgBox(
  2392. RSP_MB_ICN_INFO | RSP_MB_BUT_OK,
  2393. "Play a Realm",
  2394. "There is no hood. Cannot play.");
  2395. }
  2396. break;
  2397. case GUI_ID_CLOSE_REALM:
  2398. // Clear the ream.
  2399. CloseRealm(prealm);
  2400. m_pBouyLink0 = NULL;
  2401. m_pBouyLink1 = NULL;
  2402. break;
  2403. case GUI_ID_EXIT:
  2404. // If we can close the realm . . .
  2405. if (CloseRealm(prealm) == 0)
  2406. {
  2407. // Exit the editor
  2408. bExit = true;
  2409. m_pBouyLink0 = NULL;
  2410. m_pBouyLink1 = NULL;
  2411. }
  2412. break;
  2413. case GUI_ID_PROPERTIES:
  2414. // Call the realm's edit modify dialog function
  2415. prealm->EditModify();
  2416. break;
  2417. case GUI_ID_TOGGLE_LAYER:
  2418. {
  2419. // Get currently selected list item.
  2420. RGuiItem* pguiSel = ms_plbLayers->GetSel();
  2421. if (pguiSel != NULL)
  2422. {
  2423. // Get layer to toggle.
  2424. CRealm::Layer layer = (CRealm::Layer)pguiSel->m_ulUserData;
  2425. // Should be push btn.
  2426. ASSERT(pguiSel->m_type == RGuiItem::PushBtn);
  2427. // Toggle.
  2428. prealm->m_scene.m_pLayers[layer].m_bHidden
  2429. = (((RPushBtn*)pguiSel)->m_state == RPushBtn::On) ? false : true;
  2430. }
  2431. break;
  2432. }
  2433. case GUI_ID_NEW_CAMERA:
  2434. {
  2435. AddView(prealm);
  2436. break;
  2437. }
  2438. case GUI_ID_CLOSE_CAMERA:
  2439. {
  2440. RemoveView(NULL);
  2441. break;
  2442. }
  2443. case GUI_ID_REALM_VISIBLE:
  2444. ms_pguiRealmBar->SetVisible(!ms_pguiRealmBar->m_sVisible);
  2445. break;
  2446. case GUI_ID_LAYERS_VISIBLE:
  2447. ms_pguiLayers->SetVisible(!ms_pguiLayers->m_sVisible);
  2448. break;
  2449. case GUI_ID_THINGS_VISIBLE:
  2450. ms_pguiPickObj->SetVisible(!ms_pguiPickObj->m_sVisible);
  2451. break;
  2452. case GUI_ID_CAMERAS_VISIBLE:
  2453. ms_pguiCameras->SetVisible(!ms_pguiCameras->m_sVisible);
  2454. break;
  2455. case GUI_ID_NAVNETS_VISIBLE:
  2456. ms_pguiNavNets->SetVisible(!ms_pguiNavNets->m_sVisible);
  2457. break;
  2458. case GUI_ID_MAP_VISIBLE:
  2459. ms_pguiMap->SetVisible(!ms_pguiMap->m_sVisible);
  2460. break;
  2461. case GUI_ID_MAP_REFRESH:
  2462. RefreshMap(prealm);
  2463. break;
  2464. case GUI_ID_COPY:
  2465. // Copy the selection to the paste buffer.
  2466. CopyItem(ms_pthingSel);
  2467. break;
  2468. case GUI_ID_CUT:
  2469. // Copy the selection to the paste buffer.
  2470. CopyItem(ms_pthingSel);
  2471. // Delete the selection.
  2472. DelThing(ms_pthingSel, ms_photSel, prealm);
  2473. break;
  2474. case GUI_ID_PASTE:
  2475. // Paste from the paste buffer.
  2476. PasteItem(
  2477. prealm, // In: The realm to paste into.
  2478. sCursorX, // x
  2479. sCursorY, // y
  2480. sCursorZ); // z
  2481. break;
  2482. case GUI_ID_NEW_THING:
  2483. {
  2484. // Drop anything currently being dragged.
  2485. DragDrop(
  2486. sCursorX, // x
  2487. sCursorY, // y
  2488. sCursorZ); // z
  2489. // Get object picker list box.
  2490. RListBox* plbPicker = (RListBox*)ms_pguiPickObj->GetItemFromId(GUI_ID_PICK_LIST);
  2491. if (plbPicker != NULL)
  2492. {
  2493. RGuiItem* pguiSel = plbPicker->GetSel();
  2494. // If there is a selection . . .
  2495. if (pguiSel != NULL)
  2496. {
  2497. // Get ID of list item representing thing to create.
  2498. ms_lPressedId = pguiSel->m_lId;
  2499. }
  2500. else
  2501. {
  2502. break;
  2503. }
  2504. }
  2505. else
  2506. {
  2507. break;
  2508. }
  2509. }
  2510. ////// INTENTIONAL FALL THROUGH TO DEFAULT CASE //////
  2511. default:
  2512. // If the range of CThings . . .
  2513. if ( ms_lPressedId >= LIST_ITEM_GUI_ID_BASE
  2514. && ms_lPressedId < LIST_ITEM_GUI_ID_BASE + CThing::TotalIDs
  2515. && ms_sMoving == FALSE)
  2516. {
  2517. CThing* pthingNew;
  2518. RHot* photNew;
  2519. if (CreateNewThing( // CThing* to new thing.
  2520. prealm, // Realm to create in.
  2521. ms_lPressedId - LIST_ITEM_GUI_ID_BASE, // ID to create.
  2522. sCursorX, // x
  2523. sCursorY, // y
  2524. sCursorZ, // z
  2525. &pthingNew, // New thing.
  2526. &photNew) == 0) // New hotbox for thing.
  2527. {
  2528. // Select the new item.
  2529. SetSel(pthingNew, photNew);
  2530. // Start moving/placing object.
  2531. ms_sMoving = TRUE;
  2532. // Disable drag view scrolling.
  2533. ms_bDragScroll = false;
  2534. // Enter drag. Cheesy...Just need to get this to Bill and
  2535. // Then I'll clean up.
  2536. ms_sDragState = 4;
  2537. if (rspGetMouseCursorShowLevel() > 0)
  2538. {
  2539. rspHideMouseCursor();
  2540. }
  2541. }
  2542. }
  2543. break;
  2544. }
  2545. // If the mapped is pressed . . .
  2546. if (ms_pguiMapZone != NULL)
  2547. {
  2548. if (ms_pguiMapZone->m_sPressed != FALSE)
  2549. {
  2550. // Determine position.
  2551. short sPosX, sPosY;
  2552. rspGetMouse(&sPosX, &sPosY, NULL);
  2553. ms_pguiMapZone->TopPosToClient(&sPosX, &sPosY);
  2554. // Map position into map coords scroll to it.
  2555. ms_sbVert.SetPos(sPosY / ms_dMapRatio - pcamera->m_sViewH / 2);
  2556. ms_sbHorz.SetPos(sPosX / ms_dMapRatio - pcamera->m_sViewW / 2);
  2557. }
  2558. }
  2559. }
  2560. // Clear ID.
  2561. ms_lPressedId = 0;
  2562. }
  2563. // If quitting . . .
  2564. if (rspGetQuitStatus() != FALSE)
  2565. {
  2566. bExit = true;
  2567. // Make sure to close the realm...kind've a hack doing it here.
  2568. CloseRealm(prealm);
  2569. }
  2570. // Return cursor position values.
  2571. *psCursorX = sCursorX;
  2572. *psCursorY = sCursorY;
  2573. *psCursorZ = sCursorZ;
  2574. return bExit;
  2575. }
  2576. ////////////////////////////////////////////////////////////////////////////////
  2577. //
  2578. // Do ALL editor output.
  2579. //
  2580. ////////////////////////////////////////////////////////////////////////////////
  2581. static void DoOutput( // Returns nothing.
  2582. CRealm* prealm, // Ptr to current realm.
  2583. CCamera* pcamera, // Ptr to current camera.
  2584. short sCursorX, // Cursor X position.
  2585. short sCursorY, // Cursor Y position.
  2586. short sCursorZ) // Cursor Z position.
  2587. {
  2588. // If not in menu . . .
  2589. if (GetCurrentMenu() == NULL)
  2590. {
  2591. // Lock the composite buffer for much access.
  2592. rspLockBuffer();
  2593. // Update and render realm (in edit mode)
  2594. prealm->EditUpdate();
  2595. prealm->EditRender();
  2596. // Need hood for this . . .
  2597. if (prealm->m_asClassNumThings[CThing::CHoodID] > 0)
  2598. {
  2599. // If showing any attributes . . .
  2600. if (ms_spriteAttributes.m_pImage)
  2601. {
  2602. // Clear the image.
  2603. rspRect(
  2604. 0,
  2605. ms_spriteAttributes.m_pImage,
  2606. 0, 0,
  2607. ms_spriteAttributes.m_pImage->m_sWidth,
  2608. ms_spriteAttributes.m_pImage->m_sHeight);
  2609. prealm->m_scene.UpdateSprite(&ms_spriteAttributes);
  2610. }
  2611. else
  2612. {
  2613. // Get outta there.
  2614. prealm->m_scene.RemoveSprite(&ms_spriteAttributes);
  2615. }
  2616. // If showing any terrain attributes . . .
  2617. if (ms_u16TerrainMask)
  2618. {
  2619. AttribBlit( // Returns nothing.
  2620. prealm->m_pTerrainMap, // In: Multigrid of attributes.
  2621. ms_u16TerrainMask, // In: Mask of important attributes.
  2622. ms_spriteAttributes.m_pImage, // In: Destination image.
  2623. pcamera->m_sScene2FilmX, // In: Where in Multigrid to start.
  2624. pcamera->m_sScene2FilmY, // In: Where in Multigrid to start.
  2625. pcamera->m_sViewW, // In: How much of multigrid to use.
  2626. pcamera->m_sViewH); // In: How much of multigrid to use.
  2627. }
  2628. // If showing any layer attributes . . .
  2629. if (ms_u16LayerMask)
  2630. {
  2631. AttribBlit( // Returns nothing.
  2632. prealm->m_pLayerMap, // In: Multigrid of attributes.
  2633. ms_u16LayerMask, // In: Mask of important attributes.
  2634. ms_spriteAttributes.m_pImage, // In: Destination image.
  2635. pcamera->m_sScene2FilmX, // In: Where in Multigrid to start.
  2636. pcamera->m_sScene2FilmY, // In: Where in Multigrid to start.
  2637. pcamera->m_sViewW, // In: How much of multigrid to use.
  2638. pcamera->m_sViewH); // In: How much of multigrid to use.
  2639. }
  2640. }
  2641. // If avoiding clipping . . .
  2642. if (pcamera->m_bClip == false)
  2643. {
  2644. // Keep it clean.
  2645. pcamera->SnapWithLensCoverOn();
  2646. }
  2647. // Snap a picture.
  2648. pcamera->Snap();
  2649. // Draw the bouy connection line
  2650. DrawBouyLink(prealm, pcamera);
  2651. DrawNetwork(prealm, pcamera);
  2652. // If there's a selected item . . .
  2653. if (ms_pthingSel != NULL)
  2654. {
  2655. static RRect rc;
  2656. static short sColorSwap = 0;
  2657. sColorSwap = (sColorSwap + 1) % 2;
  2658. ms_pthingSel->EditRect(&rc);
  2659. rspRect(
  2660. SELECTION_THICKNESS,
  2661. (sColorSwap == 0) ? SELECTION_COLOR1 : SELECTION_COLOR2,
  2662. g_pimScreenBuf,
  2663. rc.sX - pcamera->m_sScene2FilmX - 1,
  2664. rc.sY - pcamera->m_sScene2FilmY - 1,
  2665. rc.sW + 2,
  2666. rc.sH + 2);
  2667. rspRect(
  2668. SELECTION_THICKNESS,
  2669. (sColorSwap == 1) ? SELECTION_COLOR1 : SELECTION_COLOR2,
  2670. g_pimScreenBuf,
  2671. rc.sX - pcamera->m_sScene2FilmX - SELECTION_THICKNESS - 1,
  2672. rc.sY - pcamera->m_sScene2FilmY - SELECTION_THICKNESS - 1,
  2673. rc.sW + SELECTION_THICKNESS * 2 + 2,
  2674. rc.sH + SELECTION_THICKNESS * 2 + 2);
  2675. }
  2676. // If there's no current hood . . .
  2677. if (prealm->m_phood == NULL)
  2678. {
  2679. // Erase entire screen.
  2680. rspRect(
  2681. RSP_BLACK_INDEX,
  2682. g_pimScreenBuf,
  2683. 0, 0,
  2684. g_pimScreenBuf->m_sWidth,
  2685. g_pimScreenBuf->m_sHeight);
  2686. }
  2687. else
  2688. {
  2689. // Erase non-view area of screen.
  2690. rspRect(
  2691. RSP_BLACK_INDEX,
  2692. g_pimScreenBuf,
  2693. g_pimScreenBuf->m_sWidth - DISPLAY_RIGHT_BORDER,
  2694. 0,
  2695. DISPLAY_RIGHT_BORDER,
  2696. g_pimScreenBuf->m_sHeight);
  2697. rspRect(
  2698. RSP_BLACK_INDEX,
  2699. g_pimScreenBuf,
  2700. 0,
  2701. g_pimScreenBuf->m_sHeight - DISPLAY_BOTTOM_BORDER,
  2702. g_pimScreenBuf->m_sWidth,
  2703. DISPLAY_BOTTOM_BORDER);
  2704. }
  2705. // Update GUIs to composite buffer.
  2706. ms_sbVert.Draw(g_pimScreenBuf);
  2707. ms_sbHorz.Draw(g_pimScreenBuf);
  2708. //If there is a hood . . .
  2709. if (prealm->m_asClassNumThings[CThing::CHoodID] > 0)
  2710. {
  2711. ms_pguiLayers->Draw(g_pimScreenBuf);
  2712. ms_pguiPickObj->Draw(g_pimScreenBuf);
  2713. ms_pguiInfo->Draw(g_pimScreenBuf);
  2714. ms_pguiShowAttribs->Draw(g_pimScreenBuf);
  2715. ms_pguiMap->Draw(g_pimScreenBuf);
  2716. ms_pguiNavNets->Draw(g_pimScreenBuf);
  2717. // Draw extra views.
  2718. DrawViews(prealm);
  2719. }
  2720. ms_pguiRealmBar->Draw(g_pimScreenBuf);
  2721. ms_pguiGUIs->Draw(g_pimScreenBuf);
  2722. // If editting a pylon . . .
  2723. if (ms_pylonEdit != NULL)
  2724. {
  2725. UCHAR ucId = ms_pylonEdit->m_ucID;
  2726. ASSERT(ms_argns[ucId].pimRgn != NULL);
  2727. // Draw trigger region.
  2728. #if 0 // Now done with a sprite.
  2729. rspBlitT(
  2730. 0, // Src transparent color or index.
  2731. ms_argns[ucId].pimRgn, // Src.
  2732. g_pimScreenBuf, // Dst.
  2733. 0, // Src.
  2734. 0, // Src.
  2735. ms_argns[ucId].sX - pcamera->m_sScene2FilmX, // Dst.
  2736. ms_argns[ucId].sY - pcamera->m_sScene2FilmY, // Dst.
  2737. ms_argns[ucId].pimRgn->m_sWidth, // Both.
  2738. ms_argns[ucId].pimRgn->m_sHeight, // Both.
  2739. NULL, // Dst.
  2740. NULL // Src.
  2741. );
  2742. #endif
  2743. // Draw border bounding max bounding rect for region.
  2744. rspRect(
  2745. 1,
  2746. 246 + (GetRand() % 10), // *** HOKEY(sp?) ***
  2747. g_pimScreenBuf,
  2748. ms_argns[ucId].sX - pcamera->m_sScene2FilmX - 1,
  2749. ms_argns[ucId].sY - pcamera->m_sScene2FilmY - 1,
  2750. ms_argns[ucId].pimRgn->m_sWidth + 2,
  2751. ms_argns[ucId].pimRgn->m_sHeight + 2
  2752. );
  2753. // Draw cursor.
  2754. rspRect(
  2755. 1,
  2756. 246 + (GetRand() % 10), // *** HOKEY(sp?) ***
  2757. g_pimScreenBuf,
  2758. sCursorX - ms_sDrawBlockSize / 2,
  2759. sCursorZ - ms_sDrawBlockSize / 2,
  2760. ms_sDrawBlockSize,
  2761. ms_sDrawBlockSize
  2762. );
  2763. }
  2764. // If placing/moving . . .
  2765. if (ms_sMoving != FALSE)
  2766. {
  2767. // Draw cursor at current mouse position
  2768. DrawCursor(sCursorX, sCursorY, sCursorZ, g_pimScreenBuf, prealm, pcamera);
  2769. }
  2770. // Whew. Unlock buffer now that we're done.
  2771. rspUnlockBuffer();
  2772. }
  2773. else
  2774. {
  2775. // Menu.
  2776. DoMenuOutput(g_pimScreenBuf);
  2777. }
  2778. // Update screen
  2779. rspUpdateDisplay();
  2780. }
  2781. ////////////////////////////////////////////////////////////////////////////////
  2782. //
  2783. // Get cursor position and event
  2784. // Ignores events that have already been used.
  2785. //
  2786. ////////////////////////////////////////////////////////////////////////////////
  2787. static void GetCursor( // Returns nothing.
  2788. RInputEvent* pie, // In: Input event.
  2789. // Out: pie->sUsed = TRUE, if used.
  2790. short* psX, // Out: X coord of event.
  2791. short* psY, // Out: Y coord of event.
  2792. short* psZ, // Out: Z coord of event.
  2793. short* psEvent) // Out: Event type.
  2794. {
  2795. // Init mouse drag stuff
  2796. static short sDragX;
  2797. static short sDragY;
  2798. static long lDragTime;
  2799. // Init mouse pressed stuff.
  2800. static short sPressed = FALSE;
  2801. // Init cursor stuff
  2802. static short sCursorY = 0;
  2803. static short sOrigCursorY;
  2804. // Default to no event
  2805. *psEvent = CURSOR_NOTHING;
  2806. ASSERT(pie != NULL);
  2807. short sMouseX = pie->sPosX;
  2808. short sMouseY = pie->sPosY;
  2809. short sButtonEvent = pie->sEvent;
  2810. // If mouse event . . .
  2811. if (pie->type == RInputEvent::Mouse)
  2812. {
  2813. // Evaluate button stuff
  2814. switch (sButtonEvent)
  2815. {
  2816. case RSP_MB0_PRESSED:
  2817. // If occurred in one of our hots . . .
  2818. if (pie->lUser == 1)
  2819. {
  2820. // Note pressed.
  2821. sPressed = TRUE;
  2822. if (ms_sDragState == 0)
  2823. {
  2824. ms_sDragState = 1;
  2825. sDragX = sMouseX;
  2826. sDragY = sMouseY;
  2827. // Might as well use the actual time the event occurred, no?
  2828. lDragTime = pie->lTime;
  2829. // We used the event.
  2830. pie->sUsed = TRUE;
  2831. }
  2832. }
  2833. break;
  2834. case RSP_MB0_RELEASED:
  2835. // If we didn't get the down, we should not process this event.
  2836. if (sPressed != FALSE)
  2837. {
  2838. // If button is released after drag mode was already started, then
  2839. // it acts to end drag mode. Otherwise, we kill any chance of drag
  2840. // mode and use the button for whatever else it might be needed for.
  2841. if (ms_sDragState >= 2)
  2842. {
  2843. if (ms_sDragState == 3)
  2844. {
  2845. // Set mouse position back to where it was where when the drag
  2846. // started. The idea is to hide the drag so the cursor doesn't "jump".
  2847. sMouseX = sDragX;
  2848. sMouseY = sDragY;
  2849. rspSetMouse(sMouseX, sMouseY);
  2850. // We used the event.
  2851. pie->sUsed = TRUE;
  2852. }
  2853. else
  2854. {
  2855. // Return drag event
  2856. *psEvent = CURSOR_LEFT_DRAG_END;
  2857. // We used the event.
  2858. pie->sUsed = TRUE;
  2859. }
  2860. }
  2861. else
  2862. {
  2863. // If not yet used . . .
  2864. if (pie->sUsed == FALSE)
  2865. {
  2866. // Return button event
  2867. *psEvent = CURSOR_LEFT_BUTTON_UP;
  2868. // We used the event.
  2869. pie->sUsed = TRUE;
  2870. }
  2871. }
  2872. // Clera pressed state.
  2873. sPressed = FALSE;
  2874. // Clear drag state
  2875. ms_sDragState = 0;
  2876. }
  2877. break;
  2878. case RSP_MB0_DOUBLECLICK:
  2879. // A double-click SHOULD end drag mode, except that it's possible
  2880. // we assumed it was a drag, and started doing a drag, but now the
  2881. // system sees a second click and decides it was a double-click
  2882. // instead. So I decided that if we're already in "full" drag
  2883. // mode, we ignore the double-click. Otherwise, it ends drag mode.
  2884. if (ms_sDragState < 2)
  2885. {
  2886. ms_sDragState = 0;
  2887. *psEvent = CURSOR_LEFT_DOUBLE_CLICK;
  2888. }
  2889. // We used the event.
  2890. pie->sUsed = TRUE;
  2891. break;
  2892. case RSP_MB1_DOUBLECLICK:
  2893. // If occurred in one of our hots . . .
  2894. if (pie->lUser == 1)
  2895. {
  2896. *psEvent = CURSOR_RIGHT_DOUBLE_CLICK;
  2897. // We used the event.
  2898. pie->sUsed = TRUE;
  2899. }
  2900. break;
  2901. default:
  2902. break;
  2903. }
  2904. }
  2905. else
  2906. {
  2907. // If there was no mouse event, just get the current mouse position
  2908. rspGetMouse(&sMouseX, &sMouseY, NULL);
  2909. }
  2910. // If we're in "maybe" drag mode, check if we should go to "full" drag mode
  2911. if (ms_sDragState == 1)
  2912. {
  2913. // Full drag mode is entered if a minimum amount of time has elapsed or
  2914. // if a minimum movement of the mouse has occurred. This is assuming
  2915. // that the mouse button is still down from when it first went down.
  2916. if (((rspGetMilliseconds() - lDragTime) >= DRAG_MIN_TIME) ||
  2917. (ABS(sMouseX - sDragX) >= DRAG_MIN_X) ||
  2918. (ABS(sMouseY - sDragY) >= DRAG_MIN_Y))
  2919. ms_sDragState = 2;
  2920. }
  2921. // If we reach full drag mode, then we still need to determine whether to
  2922. // pass this drag event back to the caller or use it ourselves as a way to
  2923. // change the cursor's Y-coord (height). I'm not sure how to do it, but
  2924. // it will probably mean checking for collisions with objects at this
  2925. // level. If we are over an object, we would return the drag event. If
  2926. // not, we would use the drag ourselves.
  2927. if (ms_sDragState == 2)
  2928. {
  2929. // For now, it's hardwired to never assume the drag is used to modify the cursor
  2930. if (0)
  2931. {
  2932. // Save info we need when adjusting cursor's y coord
  2933. sOrigCursorY = sCursorY;
  2934. ms_sDragState = 3; // Stretchy cursor mode.
  2935. }
  2936. else
  2937. {
  2938. // Return drag event
  2939. *psEvent = CURSOR_LEFT_DRAG_BEGIN;
  2940. ms_sDragState = 4; // Drag mode.
  2941. }
  2942. }
  2943. // This is the special drag state that means we're adjusting the cursor's y coord
  2944. if (ms_sDragState == 3)
  2945. {
  2946. sCursorY = sOrigCursorY + (sDragY - sMouseY);
  2947. *psX = sDragX; // Keep cursor position where it was at start of drag!
  2948. *psY = sCursorY;
  2949. *psZ = sDragY; // Keep cursor position where it was at start of drag!
  2950. }
  2951. else
  2952. {
  2953. // Move cursor to latest mouse position
  2954. *psX = sMouseX;
  2955. *psY = sCursorY;
  2956. *psZ = sMouseY;
  2957. }
  2958. }
  2959. ////////////////////////////////////////////////////////////////////////////////
  2960. //
  2961. // Init cursor
  2962. //
  2963. ////////////////////////////////////////////////////////////////////////////////
  2964. static short InitCursor(
  2965. void)
  2966. {
  2967. short sResult = 0;
  2968. m_pimCursorBase = new RImage;
  2969. ASSERT(m_pimCursorBase != NULL);
  2970. if (m_pimCursorBase->Load(FullPath(GAME_PATH_VD, CURSOR_BASE_IMAGE_FILE) ) != 0)
  2971. {
  2972. sResult = -1;
  2973. TRACE("LoadCursor(): Couldn't load cursor file: %s\n",
  2974. FullPath(GAME_PATH_VD, CURSOR_BASE_IMAGE_FILE));
  2975. goto Exit;
  2976. }
  2977. if (m_pimCursorBase->Convert(RImage::FSPR8) != RImage::FSPR8)
  2978. {
  2979. sResult = -1;
  2980. TRACE("LoadCursor(): Couldn't convert cursor base to FSPR8!\n");
  2981. goto Exit;
  2982. }
  2983. m_pimCursorTip = new RImage;
  2984. ASSERT(m_pimCursorTip != NULL);
  2985. if (m_pimCursorTip->Load(FullPath(GAME_PATH_VD, CURSOR_TIP_IMAGE_FILE) ) != 0)
  2986. {
  2987. sResult = -1;
  2988. TRACE("LoadCursor(): Couldn't load cursor file: %s\n",
  2989. FullPath(GAME_PATH_VD, CURSOR_TIP_IMAGE_FILE) );
  2990. goto Exit;
  2991. }
  2992. if (m_pimCursorTip->Convert(RImage::FSPR8) != RImage::FSPR8)
  2993. {
  2994. sResult = -1;
  2995. TRACE("LoadCursor(): Couldn't convert cursor tip to FSPR8!\n");
  2996. goto Exit;
  2997. }
  2998. Exit:
  2999. return sResult;
  3000. }
  3001. ////////////////////////////////////////////////////////////////////////////////
  3002. //
  3003. // Kill cursor
  3004. //
  3005. ////////////////////////////////////////////////////////////////////////////////
  3006. static void KillCursor(
  3007. void)
  3008. {
  3009. // Delete cursors (delete doesn't mind if pointer is already 0)
  3010. delete m_pimCursorBase;
  3011. m_pimCursorBase = 0;
  3012. delete m_pimCursorTip;
  3013. m_pimCursorTip = 0;
  3014. }
  3015. ////////////////////////////////////////////////////////////////////////////////
  3016. //
  3017. // Draw edit cursor at specified location on specified image
  3018. //
  3019. ////////////////////////////////////////////////////////////////////////////////
  3020. static void DrawCursor(
  3021. short sCursorX, // In: Cursor hotspot x coord
  3022. short sCursorY, // In: Cursor hotspot y coord
  3023. short sCursorZ, // In: Cursor hotspot z coord
  3024. RImage* pimDst, // In: Image to draw to
  3025. CRealm* prealm, // In: Realm.
  3026. CCamera* pcamera) // In: Camera on prealm.
  3027. {
  3028. // Convert to 2D.
  3029. short sBaseX2;
  3030. short sBaseY2;
  3031. Maprealm2Screen(prealm, pcamera, sCursorX, 0, sCursorZ, &sBaseX2, &sBaseY2);
  3032. short sTipX2;
  3033. short sTipY2;
  3034. Maprealm2Screen(prealm, pcamera, sCursorX, sCursorY, sCursorZ, &sTipX2, &sTipY2);
  3035. // Draw the base (I think this is the hotspot).
  3036. rspBlit(
  3037. m_pimCursorBase,
  3038. pimDst,
  3039. sBaseX2 - CURSOR_BASE_HOTX,
  3040. sBaseY2 - CURSOR_BASE_HOTY);
  3041. // Draw the top offset from the base by y coord (needs to be negated here!)
  3042. rspBlit(
  3043. m_pimCursorTip,
  3044. pimDst,
  3045. sTipX2 - CURSOR_TIP_HOTX,
  3046. sTipY2 - CURSOR_TIP_HOTY);
  3047. // If height is not 0 . . .
  3048. if (sCursorY != 0)
  3049. {
  3050. // Draw a line connecting the base and the tip.
  3051. #if 0
  3052. short sMin = MIN(sCursorZ, (short)(sCursorZ - sCursorY));
  3053. short sMax = MAX(sCursorZ, (short)(sCursorZ - sCursorY));
  3054. for (short y = sMin; y <= sMax; y++)
  3055. rspPlot((UCHAR)255, pimDst, sCursorX, y);
  3056. #else
  3057. rspLine(
  3058. (UCHAR)255,
  3059. pimDst,
  3060. sBaseX2,
  3061. sBaseY2,
  3062. sTipX2,
  3063. sTipY2);
  3064. #endif
  3065. }
  3066. }
  3067. ////////////////////////////////////////////////////////////////////////////////
  3068. //
  3069. // Create new realm
  3070. //
  3071. ////////////////////////////////////////////////////////////////////////////////
  3072. static short NewRealm(
  3073. CRealm* prealm)
  3074. {
  3075. short sResult = 0;
  3076. // Close realm in case it contains anything
  3077. sResult = CloseRealm(prealm);
  3078. if (sResult == 0)
  3079. {
  3080. // Set the bouy lines to default to on
  3081. ms_bDrawNetwork = true;
  3082. // Clear the network lines from the previous level (if any)
  3083. UpdateNetLines(NULL);
  3084. // Set disk path for this realm.
  3085. prealm->m_resmgr.SetBasePath(g_GameSettings.m_szNoSakDir);
  3086. CThing* pthing;
  3087. short sResult = CreateNewThing(prealm, CThing::CHoodID, 0, 0, 0, &pthing, &ms_photHood);
  3088. // Create hood object because we can't really do anything without it
  3089. if (sResult == 0)
  3090. {
  3091. RHot* photdummy;
  3092. sResult = CreateNewThing(prealm, CThing::CGameEditThingID, 0, 0, 0, &pthing, &photdummy);
  3093. // Create editor object . . .
  3094. if (sResult == 0)
  3095. {
  3096. // Store ptr to GameEdit thing.
  3097. ms_pgething = (CGameEditThing*)pthing;
  3098. ms_pgething->m_plbNavNetList = (RListBox*) ms_pguiNavNets->GetItemFromId(GUI_ID_NAVNET_LIST);
  3099. sResult = CreateNewThing(prealm, CThing::CNavigationNetID, 150, 0, 50, &pthing, &ms_photSel);
  3100. if (sResult == 0)
  3101. {
  3102. // Success.
  3103. // Update size affected stuff.
  3104. SizeUpdate(ms_pcameraCur, prealm);
  3105. // Set the palette.
  3106. prealm->m_phood->SetPalette();
  3107. // Freshen the map.
  3108. RefreshMap(prealm);
  3109. sResult = CreateNewThing(prealm, CThing::CTriggerID, 0, 0, 0, &pthing, &photdummy);
  3110. if (sResult == 0)
  3111. {
  3112. prealm -> m_pTriggerMap = ((CTrigger*)pthing)->m_pmgi;
  3113. }
  3114. }
  3115. else
  3116. {
  3117. TRACE("GameEdit:NewRealm - Failed to create default NavNet.\n");
  3118. TRACE(" other objects depending on one may not work correctly.\n");
  3119. }
  3120. }
  3121. }
  3122. }
  3123. return sResult;
  3124. }
  3125. ////////////////////////////////////////////////////////////////////////////////
  3126. //
  3127. // Close realm.
  3128. //
  3129. ////////////////////////////////////////////////////////////////////////////////
  3130. static short CloseRealm(
  3131. CRealm* prealm)
  3132. {
  3133. short sResult = 0;
  3134. // Cancel drag, if one is in progress.
  3135. CancelDrag(prealm);
  3136. // Cancle network line draw if it is on
  3137. if (ms_bDrawNetwork)
  3138. ms_bDrawNetwork = false;
  3139. // Clear the Navigation Net list box in the editor
  3140. if (ms_pgething && ms_pgething->m_plbNavNetList)
  3141. ms_pgething->m_plbNavNetList->RemoveAll();
  3142. // If the realm has anything worth saving . . .
  3143. if (prealm->m_sNumThings > 0)
  3144. {
  3145. // Check for save . . .
  3146. switch (rspMsgBox(
  3147. RSP_MB_ICN_QUERY | RSP_MB_BUT_YESNOCANCEL,
  3148. g_pszAppName,
  3149. g_pszSaveFileQuery) )
  3150. {
  3151. case RSP_MB_RET_YES:
  3152. sResult = SaveRealm(prealm);
  3153. break;
  3154. case RSP_MB_RET_NO:
  3155. break;
  3156. case RSP_MB_RET_CANCEL:
  3157. // User abort.
  3158. sResult = 1;
  3159. break;
  3160. }
  3161. }
  3162. // If successful so far . . .
  3163. if (sResult == 0)
  3164. {
  3165. if (ms_pcameraCur != NULL)
  3166. {
  3167. // Clear hood ptr.
  3168. ms_pcameraCur->SetHood(NULL);
  3169. }
  3170. // Clear realm in case it contains anything
  3171. prealm->Clear();
  3172. // This's gone now.
  3173. ms_pgething = NULL;
  3174. // If there are any . . .
  3175. if (ms_photHood != NULL)
  3176. {
  3177. // Destroy all child hotboxes.
  3178. RHot* phot = ms_photHood->m_listChildren.GetHead();
  3179. while (phot != NULL)
  3180. {
  3181. delete phot;
  3182. phot = ms_photHood->m_listChildren.GetNext();
  3183. }
  3184. // Destroy root/hood hotbox.
  3185. delete ms_photHood;
  3186. ms_photHood = NULL;
  3187. }
  3188. // Clean up trigger regions.
  3189. short i;
  3190. for (i = 0; i < NUM_ELEMENTS(ms_argns); i++)
  3191. {
  3192. ms_argns[i].Destroy();
  3193. }
  3194. // Better clear these.
  3195. ms_sMoving = FALSE;
  3196. SetSel(NULL, NULL);
  3197. // Set filename such that initially open and save dialogs start in
  3198. // *.RLM dir.
  3199. strcpy(ms_szFileName, FullPathVD(INITIAL_REALM_DIR));
  3200. // Update size dependent stuff.
  3201. SizeUpdate(ms_pcameraCur, prealm);
  3202. // Purge resource managers.
  3203. g_resmgrGame.Purge();
  3204. prealm->m_resmgr.Purge();
  3205. }
  3206. return sResult;
  3207. }
  3208. ////////////////////////////////////////////////////////////////////////////////
  3209. //
  3210. // Load realm.
  3211. //
  3212. ////////////////////////////////////////////////////////////////////////////////
  3213. static short LoadRealm(
  3214. CRealm* prealm)
  3215. {
  3216. short sResult = 0;
  3217. // Close current realm.
  3218. sResult = CloseRealm(prealm);
  3219. if (sResult == 0)
  3220. {
  3221. // Attempt to get filename . . .
  3222. // ***LOCALIZE***
  3223. sResult = rspOpenBox(
  3224. "Load Realm",
  3225. ms_szFileName,
  3226. ms_szFileName,
  3227. sizeof(ms_szFileName),
  3228. ".rlm");
  3229. if (sResult == 0)
  3230. {
  3231. // Attach file counter callback to RFile and setup necessary components.
  3232. InitFileCounter("Loading -- %ld bytes so far.");
  3233. // Convert to RSPiX format b/c CRealm::Load() now likes it that way.
  3234. char szRealmName[sizeof(ms_szFileName)];
  3235. strcpy(szRealmName, rspPathFromSystem(ms_szFileName) );
  3236. // Load realm in edit mode
  3237. sResult = prealm->Load(szRealmName, true);
  3238. // Clean and detach file counter.
  3239. KillFileCounter();
  3240. // If load was successful . . .
  3241. if (sResult == 0)
  3242. {
  3243. // Get the editor thing.
  3244. ms_pgething = GetEditorThing(prealm);
  3245. // Start the realm.
  3246. prealm->Startup();
  3247. if (prealm->m_phood)
  3248. {
  3249. // Set hood's palette.
  3250. prealm->m_phood->SetPalette();
  3251. }
  3252. // Store ptr to GameEdit thing.
  3253. CListNode<CThing>* pEditorList = prealm->m_aclassHeads[CThing::CGameEditThingID].m_pnNext;
  3254. CGameEditThing* peditor = (CGameEditThing*) pEditorList->m_powner;
  3255. if (peditor)
  3256. {
  3257. peditor->m_plbNavNetList = (RListBox*) ms_pguiNavNets->GetItemFromId(GUI_ID_NAVNET_LIST);
  3258. }
  3259. ///////////////////////////////////////////////////////////////////
  3260. // Create Hot for every CThing.
  3261. ///////////////////////////////////////////////////////////////////
  3262. // Get the hood . . .
  3263. if (prealm->m_asClassNumThings[CThing::CHoodID] > 0)
  3264. {
  3265. RRect rc;
  3266. // Get first and only Hood iterator.
  3267. CHood* phood = (CHood*) prealm->m_aclassHeads[CThing::CHoodID].m_pnNext->m_powner;
  3268. // Get rectangle.
  3269. phood->EditRect(&rc);
  3270. // Create and setup RHot for hood.
  3271. phood->m_phot = ms_photHood = new RHot(
  3272. rc.sX, // Position.
  3273. rc.sY, // Position.
  3274. rc.sW, // Dimensions.
  3275. rc.sH, // Dimensions.
  3276. ThingHotCall, // Callback.
  3277. TRUE, // TRUE, if active.
  3278. (U32)phood, // User value (CThing*).
  3279. FRONTMOST_HOT_PRIORITY); // New items towards front.
  3280. // If successful . . .
  3281. if (ms_photHood != NULL)
  3282. {
  3283. // Setup hotboxes for all objects.
  3284. CListNode<CThing>* pList;
  3285. CThing* pthing;
  3286. short sActivateHot;
  3287. pList = prealm->m_everythingHead.m_pnNext;
  3288. while (pList->m_powner != NULL && sResult == 0)
  3289. {
  3290. pthing = pList->m_powner;
  3291. // Already got one for Hood. If not the Hood . . .
  3292. if (pthing->GetClassID() != CThing::CHoodID)
  3293. {
  3294. sActivateHot = TRUE;
  3295. // Some types may need to hook in here.
  3296. switch (pthing->GetClassID() )
  3297. {
  3298. case CThing::CBouyID:
  3299. // If bouy lines are hidden . . .
  3300. if (ms_bDrawNetwork == false)
  3301. {
  3302. // Don't activate new bouy hots.
  3303. sActivateHot = FALSE;
  3304. }
  3305. break;
  3306. case CThing::CNavigationNetID:
  3307. ((CNavigationNet*) pthing)->EditPostLoad();
  3308. break;
  3309. }
  3310. // Get rectangle.
  3311. pthing->EditRect(&rc);
  3312. // Create and setup RHot.
  3313. pthing->m_phot = new RHot(
  3314. rc.sX, // Position.
  3315. rc.sY, // Position.
  3316. rc.sW, // Dimensions.
  3317. rc.sH, // Dimensions.
  3318. ThingHotCall, // Callback.
  3319. sActivateHot, // TRUE, if initially active.
  3320. (U32)pthing, // User value (CThing*).
  3321. FRONTMOST_HOT_PRIORITY); // New items towards front.
  3322. // If successful . . .
  3323. if (pthing->m_phot != NULL)
  3324. {
  3325. // Make child of Hood's hotbox.
  3326. pthing->m_phot->SetParent(ms_photHood);
  3327. }
  3328. else
  3329. {
  3330. TRACE("LoadRealm(): Unable to allocate hotbox for thing.\n");
  3331. sResult = 1;
  3332. }
  3333. }
  3334. // Go to next item
  3335. pList = pList->m_pnNext;
  3336. }
  3337. }
  3338. else
  3339. {
  3340. TRACE("LoadRealm(): Unable to allocate hotbox for Hood.\n");
  3341. sResult = 1;
  3342. }
  3343. }
  3344. else
  3345. {
  3346. TRACE("LoadRealm(): Realm has no hood.\n");
  3347. sResult = 1;
  3348. }
  3349. // If any errors occurred . . .
  3350. if (sResult != 0)
  3351. {
  3352. // Clean up any partial stuff.
  3353. CloseRealm(prealm);
  3354. // Report.
  3355. rspMsgBox(
  3356. RSP_MB_ICN_STOP | RSP_MB_BUT_OK,
  3357. g_pszCriticalErrorTitle,
  3358. g_pszGeneralError);
  3359. }
  3360. else
  3361. {
  3362. // Make sure our loaded settings are unaffected.
  3363. short sViewPosX = 0;
  3364. short sViewPosY = 0;
  3365. if (ms_pgething != NULL)
  3366. {
  3367. sViewPosX = ms_pgething->m_sViewPosX;
  3368. sViewPosY = ms_pgething->m_sViewPosY;
  3369. }
  3370. // Set camera's hood.
  3371. ms_pcameraCur->SetHood(prealm->m_phood);
  3372. // Update size affected stuff.
  3373. SizeUpdate(ms_pcameraCur, prealm);
  3374. // If there is an editor thing . . .
  3375. if (ms_pgething != NULL)
  3376. {
  3377. // Update view position.
  3378. ms_sbVert.SetPos(sViewPosY);
  3379. ms_sbHorz.SetPos(sViewPosX);
  3380. }
  3381. // Freshen the map.
  3382. RefreshMap(prealm);
  3383. // Load the regions for the pylons.
  3384. if (LoadTriggerRegions(ms_szFileName) < 0)
  3385. {
  3386. rspMsgBox( // ****LOCALIZE****
  3387. RSP_MB_ICN_INFO | RSP_MB_BUT_OK,
  3388. "LoadRealm()",
  3389. "Pylon editor regions failed to load.");
  3390. }
  3391. // Make sure the bouys' show/hidden state reflects this flag's status.
  3392. if (ms_bDrawNetwork == true)
  3393. {
  3394. CBouy::Show();
  3395. }
  3396. else
  3397. {
  3398. CBouy::Hide();
  3399. }
  3400. }
  3401. }
  3402. else
  3403. {
  3404. rspMsgBox(
  3405. RSP_MB_ICN_STOP | RSP_MB_BUT_OK,
  3406. g_pszCriticalErrorTitle,
  3407. g_pszGeneralError);
  3408. }
  3409. }
  3410. }
  3411. return sResult;
  3412. }
  3413. ////////////////////////////////////////////////////////////////////////////////
  3414. //
  3415. // Save realm as . . .
  3416. //
  3417. ////////////////////////////////////////////////////////////////////////////////
  3418. static short SaveRealmAs(
  3419. CRealm* prealm)
  3420. {
  3421. short sResult = 0;
  3422. #ifdef DISABLE_EDITOR_SAVE_AND_PLAY
  3423. rspMsgBox(
  3424. RSP_MB_ICN_INFO | RSP_MB_BUT_OK,
  3425. "Postal Editor",
  3426. "Sorry, but the save feature is disabled.");
  3427. sResult = -1;
  3428. #else
  3429. // Attempt to get filename . . .
  3430. // ***LOCALIZE***
  3431. if (rspSaveBox(
  3432. "Save Realm",
  3433. ms_szFileName,
  3434. ms_szFileName,
  3435. sizeof(ms_szFileName),
  3436. ".rlm") == 0)
  3437. {
  3438. ASSERT(ms_szFileName[0] != '\0');
  3439. // Save realm.
  3440. // Note that SaveRealm() can call SaveRealmAs(), but should not in this
  3441. // case (since we have a filename now).
  3442. sResult = SaveRealm(prealm);
  3443. }
  3444. else
  3445. {
  3446. // Cancelled.
  3447. sResult = 1;
  3448. }
  3449. #endif
  3450. return sResult;
  3451. }
  3452. ////////////////////////////////////////////////////////////////////////////////
  3453. //
  3454. // Save realm
  3455. //
  3456. ////////////////////////////////////////////////////////////////////////////////
  3457. static short SaveRealm(
  3458. CRealm* prealm)
  3459. {
  3460. short sResult = 0;
  3461. // If filename . . .
  3462. if (strcmp(ms_szFileName, FullPathVD(INITIAL_REALM_DIR)) != 0)
  3463. {
  3464. // Save realm with trigger regions.
  3465. sResult = SaveRealm(prealm, ms_szFileName, true);
  3466. }
  3467. else
  3468. {
  3469. // Get filename before save.
  3470. // Note that SaveRealmAs() calls this SaveRealm().
  3471. sResult = SaveRealmAs(prealm);
  3472. }
  3473. return sResult;
  3474. }
  3475. ////////////////////////////////////////////////////////////////////////////////
  3476. //
  3477. // Save realm with specified name.
  3478. //
  3479. ////////////////////////////////////////////////////////////////////////////////
  3480. static short SaveRealm( // Returns 0 on success.
  3481. CRealm* prealm, // In: Realm to save.
  3482. char* pszRealmName, // In: Filename to save as.
  3483. bool bSaveTriggerRegions) // In: Save the trigger regions too.
  3484. {
  3485. short sResult = 0;
  3486. #ifdef DISABLE_EDITOR_SAVE_AND_PLAY
  3487. rspMsgBox(
  3488. RSP_MB_ICN_INFO | RSP_MB_BUT_OK,
  3489. "Postal Editor",
  3490. "Sorry, but the save feature is disabled.");
  3491. sResult = -1;
  3492. #else
  3493. // Convert the Trigger Regions into an attribute map:
  3494. CreateTriggerRegions(prealm);
  3495. // Attach file counter callback to RFile and setup necessary components.
  3496. InitFileCounter("Saving -- %ld bytes so far.");
  3497. // Save realm
  3498. sResult = prealm->Save(pszRealmName);
  3499. // Clean and detach file counter.
  3500. KillFileCounter();
  3501. // If successful . . .
  3502. if (sResult == 0)
  3503. {
  3504. // If we are to save the trigger regions . . .
  3505. if (bSaveTriggerRegions == true)
  3506. {
  3507. // Save the regions for the pylons.
  3508. if (SaveTriggerRegions(pszRealmName, prealm) < 0)
  3509. {
  3510. rspMsgBox( // ****LOCALIZE****
  3511. RSP_MB_ICN_INFO | RSP_MB_BUT_OK,
  3512. "SaveRealm()",
  3513. "Pylon editor regions failed to save.");
  3514. sResult = -1;
  3515. }
  3516. }
  3517. }
  3518. else
  3519. {
  3520. rspMsgBox(
  3521. RSP_MB_ICN_STOP | RSP_MB_BUT_OK,
  3522. g_pszCriticalErrorTitle,
  3523. g_pszGeneralError);
  3524. }
  3525. #endif
  3526. return sResult;
  3527. }
  3528. ////////////////////////////////////////////////////////////////////////////////
  3529. //
  3530. // Editor's simulated play loop
  3531. //
  3532. ////////////////////////////////////////////////////////////////////////////////
  3533. static void PlayRealm(
  3534. CRealm* pEditRealm, // In: Realm to play.
  3535. CThing* pthingSel) // In: Currently selected CThing which can
  3536. // be used to give PlayRealm() a hint on which
  3537. // of several things the user wants to use.
  3538. // For example, a selected warp is the used
  3539. // as the warp in point.
  3540. {
  3541. #ifdef DISABLE_EDITOR_SAVE_AND_PLAY
  3542. rspMsgBox(
  3543. RSP_MB_ICN_INFO | RSP_MB_BUT_OK,
  3544. "Postal Editor",
  3545. "Sorry, but the play feature is disabled.");
  3546. #else
  3547. // This is not returned by the function, but used internally
  3548. short sResult = 0;
  3549. // Enable RMix's autopump.
  3550. RMix::SetAutoPump(TRUE);
  3551. rspClearAllInputEvents();
  3552. // If mouse is being used, hide mouse cursor
  3553. if (g_InputSettings.m_sUseMouse)
  3554. rspHideMouseCursor();
  3555. // Create a temporary filename
  3556. char szFileName[RSP_MAX_PATH];
  3557. if (TmpFileName(szFileName, sizeof(szFileName)) == 0)
  3558. {
  3559. // Attach file counter callback to RFile and setup necessary components.
  3560. InitFileCounter("Saving -- %ld bytes so far.");
  3561. // Save realm being edited without the trigger regions.
  3562. sResult = SaveRealm(pEditRealm, szFileName, false);
  3563. // Clean and detach file counter.
  3564. KillFileCounter();
  3565. // If successful . . .
  3566. if (sResult == 0)
  3567. {
  3568. // Create a new realm so we don't accidentally rely on any side-effects
  3569. // that may result from using the editor's realm.
  3570. CRealm* prealm = new CRealm;
  3571. ASSERT(prealm != NULL);
  3572. // Setup progress callback right away.
  3573. // prealm->m_fnProgress = RealmOpProgress;
  3574. // Clear realm (just in case)
  3575. prealm->Clear();
  3576. // Note that we are playing from the editor. Might be useful.
  3577. prealm->m_flags.bEditPlay = true;
  3578. prealm->m_flags.sDifficulty = g_GameSettings.m_sDifficulty;
  3579. // Reset time here so that objects can use it when they are loaded
  3580. prealm->m_time.Reset();
  3581. // No memorex here.
  3582. SetInputMode(INPUT_MODE_LIVE);
  3583. // Attach file counter callback to RFile and setup necessary components.
  3584. InitFileCounter("Loading -- %ld bytes so far.");
  3585. // Convert to RSPiX format b/c CRealm::Load() now likes it that way.
  3586. char szRealmName[sizeof(szFileName)];
  3587. strcpy(szRealmName, rspPathFromSystem(szFileName) );
  3588. // Load realm (false indicates NOT edit mode)
  3589. sResult = prealm->Load(szRealmName, false);
  3590. // Clean and detach file counter.
  3591. KillFileCounter();
  3592. // If successful . . .
  3593. if (sResult == 0)
  3594. {
  3595. // Set up the score module - initialize the font etc.
  3596. ScoreInit();
  3597. // Set the multiplayer scores to zero
  3598. ScoreReset();
  3599. // Reset the display timer
  3600. ScoreResetDisplay();
  3601. // Set score mode.
  3602. ScoreSetMode(CScoreboard::SinglePlayer);
  3603. // Startup the realm
  3604. if (prealm->Startup() == 0)
  3605. {
  3606. U16 idSpecificWarp = CIdBank::IdNil;
  3607. //////////// Special behaviors based on the current selection ////////////
  3608. // Note that pthingSel does not exist in prealm (it is in pEditRealm).
  3609. // There is, however, a clone of it with the same ID in prealm. These
  3610. // special behaviors should, therefore, get the thing's ID here and use
  3611. // it to get the ID of the specificied thing in the playing realm.
  3612. // If there is a selection . . .
  3613. if (pthingSel)
  3614. {
  3615. switch (pthingSel->GetClassID() )
  3616. {
  3617. case CThing::CWarpID:
  3618. // Get user's preferred warp.
  3619. idSpecificWarp = pthingSel->GetInstanceID();
  3620. break;
  3621. }
  3622. }
  3623. //////////////////////////////////////////////////////////////////////////
  3624. rspLockBuffer();
  3625. // Erase screen.
  3626. rspRect(
  3627. RSP_BLACK_INDEX,
  3628. g_pimScreenBuf,
  3629. 0,
  3630. 0,
  3631. g_pimScreenBuf->m_sWidth,
  3632. g_pimScreenBuf->m_sHeight);
  3633. rspUnlockBuffer();
  3634. // Could do rspUpdateDisplay() here to guarantee no palette flash
  3635. // but that should not happen anyways b/c the current palette
  3636. // (from the realm's hood loaded in the editor) should be this
  3637. // realm's hood's palette.
  3638. // Set hood palette.
  3639. prealm->m_phood->SetPalette();
  3640. // Clear local input.
  3641. ClearLocalInput();
  3642. // We'll need access to the key status array.
  3643. U8* pau8KeyStatus = rspGetKeyStatusArray();
  3644. // Setup camera
  3645. CCamera* pcamera = new CCamera;
  3646. ASSERT(pcamera != NULL);
  3647. pcamera->SetScene(&(prealm->m_scene));
  3648. // Update display size sensitive objects.
  3649. SizeUpdate(pcamera, prealm);
  3650. pcamera->SetFilm(g_pimScreenBuf, 0, 0);
  3651. pcamera->SetHood(prealm->m_phood);
  3652. ms_pcameraCur = pcamera;
  3653. ScrollPosUpdate(&ms_sbVert);
  3654. ScrollPosUpdate(&ms_sbHorz);
  3655. // Set grip to control camera
  3656. CGrip grip;
  3657. grip.SetParms(100, 1, 1, 8, 8, 1, 1, true);
  3658. grip.SetCamera(pcamera);
  3659. grip.ResetTarget(0, 0, 30);
  3660. // Default to tracking the track ID.
  3661. bool bTracking = true;
  3662. // Get thing to track . . .
  3663. CThing* pthingTrack = NULL;
  3664. U16 u16IdTrack = CIdBank::IdNil;
  3665. if (ms_pgething != NULL)
  3666. {
  3667. u16IdTrack = ms_pgething->m_u16CameraTrackId;
  3668. }
  3669. // Make sure no Scrollbars have focus.
  3670. RGuiItem::SetFocus(NULL);
  3671. CListNode<CThing>* pNext = prealm->m_aclassHeads[CThing::CDudeID].m_pnNext;
  3672. U16 u16IdDude = CIdBank::IdNil;
  3673. while (pNext->m_powner != NULL)
  3674. {
  3675. CDude* pdude = (CDude*) pNext->m_powner;
  3676. // if this is the local dude...
  3677. if (pdude->m_sDudeNum == 0)
  3678. {
  3679. // Store 'im
  3680. u16IdDude = pdude->GetInstanceID();
  3681. // Make him X-Rayable.
  3682. pdude->m_sprite.m_sInFlags |= CSprite::InXrayee;
  3683. }
  3684. pNext = pNext->m_pnNext;
  3685. }
  3686. // If no dude yet . . .
  3687. if (u16IdDude == CIdBank::IdNil)
  3688. {
  3689. // Create one using warps (if any):
  3690. CDude* pdude = NULL;
  3691. CWarp* pwarp = NULL;
  3692. // If there's a specific warp desired . . .
  3693. if (prealm->m_idbank.GetThingByID( (CThing**)&pwarp, idSpecificWarp) == 0)
  3694. {
  3695. // Use the specific warp to create the dude . . .
  3696. if (pwarp->WarpIn( // Returns 0 on success.
  3697. &pdude, // In: CDude to 'warp in', *ppdude = NULL to create one.
  3698. // Out: Newly created CDude, if no CDude passed in.
  3699. CWarp::None) == 0) // In: Options for 'warp in'.
  3700. {
  3701. // Success.
  3702. }
  3703. else
  3704. {
  3705. TRACE("PlayRealm(): Failed to use user specified warp.\n");
  3706. }
  3707. }
  3708. // If no dude yet . . .
  3709. if (pdude == NULL)
  3710. {
  3711. // Warp one in anywhere . . .
  3712. if (CWarp::WarpInAnywhere( // Returns 0 on success.
  3713. prealm, // In: Realm in which to choose CWarp.
  3714. &pdude, // In: CDude to 'warp in', *ppdude = NULL to create one.
  3715. // Out: Newly created CDude, if no CDude passed in.
  3716. CWarp::None) == 0) // In: Options for 'warp in'.
  3717. {
  3718. // Success.
  3719. }
  3720. }
  3721. // If a dude was created . . .
  3722. if (pdude)
  3723. {
  3724. // Store 'im
  3725. u16IdDude = pdude->GetInstanceID();
  3726. // Make him X-Rayable.
  3727. pdude->m_sprite.m_sInFlags |= CSprite::InXrayee;
  3728. // If nothing to track yet . . .
  3729. if (u16IdTrack == CIdBank::IdNil)
  3730. {
  3731. // Use the local dude.
  3732. u16IdTrack = u16IdDude;
  3733. }
  3734. }
  3735. }
  3736. CDude* pdudeLocal = NULL;
  3737. if (prealm->m_idbank.GetThingByID((CThing**)&pdudeLocal, u16IdDude) == 0)
  3738. {
  3739. pdudeLocal->m_sTextureIndex = MAX((short)0, MIN((short)(CDude::MaxTextures - 1), g_GameSettings.m_sPlayerColorIndex));
  3740. // Don't use later.
  3741. pdudeLocal = NULL;
  3742. }
  3743. RInputEvent ie;
  3744. // Setup rectangular area for dude's status.
  3745. RRect rcDudeStatus(
  3746. DUDE_STATUS_RECT_X,
  3747. DUDE_STATUS_RECT_Y,
  3748. DUDE_STATUS_RECT_W,
  3749. DUDE_STATUS_RECT_H);
  3750. // Setup rectangular area for realm's status.
  3751. RRect rcRealmStatus(
  3752. REALM_STATUS_RECT_X,
  3753. REALM_STATUS_RECT_Y,
  3754. REALM_STATUS_RECT_W,
  3755. REALM_STATUS_RECT_H);
  3756. // Setup rectangular area for display info.
  3757. RRect rcInfoStatus(
  3758. INFO_STATUS_RECT_X,
  3759. INFO_STATUS_RECT_Y,
  3760. INFO_STATUS_RECT_W,
  3761. INFO_STATUS_RECT_H);
  3762. long lLastDispTime = 0;
  3763. long lFramesTime = 0;
  3764. long lUpdateDisplayTime = 0;
  3765. long lNumFrames = 0;
  3766. RPrint printDisp;
  3767. printDisp.SetFont(DISP_INFO_FONT_H, &g_fontBig);
  3768. printDisp.SetColor(250, 0, 0);
  3769. printDisp.SetDestination(g_pimScreenBuf);
  3770. char szFileDescriptor[512];
  3771. Play_GetApplicationDescriptor(szFileDescriptor, sizeof(szFileDescriptor) );
  3772. // Reset time again so that the first time update doesn't show (much) elapsed time
  3773. prealm->m_time.Reset();
  3774. bool bDone = false;
  3775. bool bExitRequest = false;
  3776. bool bSuspended = false;
  3777. // Do the loop
  3778. while (bDone == false)
  3779. {
  3780. // Update the realm's game time
  3781. prealm->m_time.Update();
  3782. // System update
  3783. UpdateSystem();
  3784. ie.type = RInputEvent::None;
  3785. rspGetNextInputEvent(&ie);
  3786. if (ie.type == RInputEvent::Key)
  3787. {
  3788. // Force alpha keys to upper keys
  3789. if (isalpha(ie.lKey & 0xffff))
  3790. ie.lKey = (ie.lKey & 0xffff0000) | toupper(ie.lKey & 0xffff);
  3791. switch (ie.lKey)
  3792. {
  3793. case EDIT_KEY_PAUSE:
  3794. if (bSuspended == false)
  3795. {
  3796. prealm->Suspend();
  3797. }
  3798. else
  3799. {
  3800. prealm->Resume();
  3801. }
  3802. bSuspended = !bSuspended;
  3803. break;
  3804. #if 0
  3805. case EDIT_KEY_SPEED_UP:
  3806. break;
  3807. case EDIT_KEY_SPEED_DOWN:
  3808. break;
  3809. case EDIT_KEY_SPEED_NORMAL:
  3810. break;
  3811. #endif
  3812. case EDIT_KEY_ENDPLAY:
  3813. // If first request . . .
  3814. if (bExitRequest == false)
  3815. {
  3816. bExitRequest = true;
  3817. }
  3818. else
  3819. {
  3820. bDone = true;
  3821. }
  3822. break;
  3823. case EDIT_KEY_ENLARGE_DISPLAY1:
  3824. case EDIT_KEY_ENLARGE_DISPLAY2:
  3825. case EDIT_KEY_ENLARGE_DISPLAY3:
  3826. OnEnlargeDisplay(pcamera, prealm);
  3827. // Update status areas. That is, repaginate now.
  3828. rcDudeStatus.sX = DUDE_STATUS_RECT_X;
  3829. rcDudeStatus.sY = DUDE_STATUS_RECT_Y;
  3830. rcDudeStatus.sW = DUDE_STATUS_RECT_W;
  3831. rcDudeStatus.sH = DUDE_STATUS_RECT_H;
  3832. rcRealmStatus.sX = REALM_STATUS_RECT_X;
  3833. rcRealmStatus.sY = REALM_STATUS_RECT_Y;
  3834. rcRealmStatus.sW = REALM_STATUS_RECT_W;
  3835. rcRealmStatus.sH = REALM_STATUS_RECT_H;
  3836. rcInfoStatus.sX = INFO_STATUS_RECT_X;
  3837. rcInfoStatus.sY = INFO_STATUS_RECT_Y;
  3838. rcInfoStatus.sW = INFO_STATUS_RECT_W;
  3839. rcInfoStatus.sH = INFO_STATUS_RECT_H;
  3840. break;
  3841. case EDIT_KEY_REDUCE_DISPLAY1:
  3842. case EDIT_KEY_REDUCE_DISPLAY2:
  3843. OnReduceDisplay(pcamera, prealm);
  3844. // Update status areas. That is, repaginate now.
  3845. rcDudeStatus.sX = DUDE_STATUS_RECT_X;
  3846. rcDudeStatus.sY = DUDE_STATUS_RECT_Y;
  3847. rcDudeStatus.sW = DUDE_STATUS_RECT_W;
  3848. rcDudeStatus.sH = DUDE_STATUS_RECT_H;
  3849. rcRealmStatus.sX = REALM_STATUS_RECT_X;
  3850. rcRealmStatus.sY = REALM_STATUS_RECT_Y;
  3851. rcRealmStatus.sW = REALM_STATUS_RECT_W;
  3852. rcRealmStatus.sH = REALM_STATUS_RECT_H;
  3853. rcInfoStatus.sX = INFO_STATUS_RECT_X;
  3854. rcInfoStatus.sY = INFO_STATUS_RECT_Y;
  3855. rcInfoStatus.sW = INFO_STATUS_RECT_W;
  3856. rcInfoStatus.sH = INFO_STATUS_RECT_H;
  3857. break;
  3858. case EDIT_KEY_CAMERA_TRACKING:
  3859. bTracking = !bTracking;
  3860. // If we are now using grip . . .
  3861. if (bTracking == true)
  3862. {
  3863. // Erase scrollbars.
  3864. rspRect(
  3865. RSP_BLACK_INDEX,
  3866. g_pimScreenBuf,
  3867. ms_sbVert.m_sX,
  3868. ms_sbVert.m_sY,
  3869. ms_sbVert.m_im.m_sWidth,
  3870. ms_sbVert.m_im.m_sHeight);
  3871. rspRect(
  3872. RSP_BLACK_INDEX,
  3873. g_pimScreenBuf,
  3874. ms_sbHorz.m_sX,
  3875. ms_sbHorz.m_sY,
  3876. ms_sbHorz.m_im.m_sWidth,
  3877. ms_sbHorz.m_im.m_sHeight);
  3878. // Reset the grip, if necessary.
  3879. if (pthingTrack != NULL && bTracking == true)
  3880. {
  3881. RRect rc;
  3882. pthingTrack->EditRect(&rc);
  3883. short sHotX, sHotY;
  3884. pthingTrack->EditHotSpot(&sHotX, &sHotY);
  3885. grip.ResetTarget(rc.sX + sHotX, rc.sY + sHotY, rc.sH / 2);
  3886. // Make sure no Scrollbars have focus.
  3887. RGuiItem::SetFocus(NULL);
  3888. }
  3889. }
  3890. else // We are now using scrollbars.
  3891. {
  3892. // Update scroll pos via camera pos.
  3893. ms_sbVert.SetPos(ms_pcameraCur->m_sSceneViewY);
  3894. ms_sbHorz.SetPos(ms_pcameraCur->m_sSceneViewX);
  3895. }
  3896. break;
  3897. // Change priority level.
  3898. case '1':
  3899. case '2':
  3900. case '3':
  3901. // rspSetDoSystemMode(ie.lKey - '1');
  3902. break;
  3903. case EDIT_KEY_TOGGLE_DISP_INFO:
  3904. // Toggle display info flag.
  3905. if (g_GameSettings.m_sDisplayInfo == FALSE)
  3906. {
  3907. g_GameSettings.m_sDisplayInfo = TRUE;
  3908. }
  3909. else
  3910. {
  3911. g_GameSettings.m_sDisplayInfo = FALSE;
  3912. }
  3913. // Repaginate now.
  3914. rcDudeStatus.sH = DUDE_STATUS_RECT_H;
  3915. break;
  3916. case EDIT_KEY_SHOW_MISSION:
  3917. // Show the mission goal line again for about 5 seconds.
  3918. ScoreDisplayStatus(prealm);
  3919. break;
  3920. case EDIT_KEY_REALM_STATISTICS:
  3921. prealm->Suspend();
  3922. ShowRealmStatistics(prealm, NULL);
  3923. prealm->Resume();
  3924. break;
  3925. }
  3926. }
  3927. // If xray all pressed . . .
  3928. if (pau8KeyStatus[KEY_XRAY_ALL] & 1)
  3929. {
  3930. prealm->m_scene.SetXRayAll(TRUE);
  3931. }
  3932. else
  3933. {
  3934. prealm->m_scene.SetXRayAll(FALSE);
  3935. }
  3936. // Lock the composite buffer for access.
  3937. rspLockBuffer();
  3938. // Process input for extra camera GUIs.
  3939. DoViews(&ie);
  3940. // Only do scrollbars if not tracking . . .
  3941. if (bTracking == false)
  3942. {
  3943. // Update hots.
  3944. ms_sbVert.m_hot.Do(&ie);
  3945. ms_sbHorz.m_hot.Do(&ie);
  3946. }
  3947. // Do GUI input focus stuff.
  3948. RGuiItem::DoFocus(&ie);
  3949. // Get local player input and
  3950. // Set controls for the one-and-only CDude
  3951. // Allow cheats.
  3952. SetInput(0, GetLocalInput(prealm, &ie));
  3953. // If exit requested . . .
  3954. if (bExitRequest == true)
  3955. {
  3956. CDude* pdudeLocal;
  3957. // If there's a local dude . . .
  3958. if (prealm->m_idbank.GetThingByID((CThing**)&pdudeLocal, u16IdDude) == 0)
  3959. {
  3960. // If dead . . .
  3961. if (pdudeLocal->m_state == CCharacter::State_Dead)
  3962. {
  3963. // Okay, done.
  3964. bDone = true;
  3965. }
  3966. else
  3967. {
  3968. // Commit suicide.
  3969. GameMessage msg;
  3970. msg.msg_Generic.eType = typeSuicide;
  3971. msg.msg_Generic.sPriority = 0;
  3972. pdudeLocal->SendThingMessage(&msg, pdudeLocal);
  3973. }
  3974. }
  3975. else
  3976. {
  3977. bDone = true;
  3978. }
  3979. }
  3980. // Update and render realm
  3981. prealm->Update();
  3982. prealm->Render();
  3983. if (u16IdTrack != CIdBank::IdNil)
  3984. {
  3985. if (prealm->m_idbank.GetThingByID(&pthingTrack, u16IdTrack) != 0)
  3986. {
  3987. u16IdTrack = CIdBank::IdNil;
  3988. }
  3989. }
  3990. // Update grip/camera
  3991. if (pthingTrack != NULL)
  3992. {
  3993. RRect rc;
  3994. pthingTrack->EditRect(&rc);
  3995. short sHotX, sHotY;
  3996. pthingTrack->EditHotSpot(&sHotX, &sHotY);
  3997. sHotX += rc.sX;
  3998. sHotY += rc.sY;
  3999. short sRealmX, sRealmY, sRealmZ;
  4000. // Convert to realm.
  4001. MapScreen2Realm(
  4002. prealm, // In: Realm.
  4003. pcamera, // In: View of prealm.
  4004. sHotX - pcamera->m_sScene2FilmX, // In: Screen x coord.
  4005. sHotY - pcamera->m_sScene2FilmY, // In: Screen y coord.
  4006. &sRealmX, // Out: Realm x coord.
  4007. &sRealmY, // Out: Realm y coord (always via realm's height map).
  4008. &sRealmZ); // Out: Realm z coord.
  4009. // Set the location of our ear.
  4010. SetSoundLocation(sRealmX, sRealmY, sRealmZ);
  4011. if (bTracking == true)
  4012. {
  4013. grip.TrackTarget(sHotX, sHotY, rc.sH / 2);
  4014. }
  4015. }
  4016. // If quitting . . .
  4017. if (rspGetQuitStatus() != FALSE)
  4018. {
  4019. bDone = true;
  4020. }
  4021. // Snap picture of scene
  4022. pcamera->Snap();
  4023. // If there is a local dude . . .
  4024. CDude* pdudeLocal = NULL;
  4025. // If there's a local dude, get him.
  4026. prealm->m_idbank.GetThingByID((CThing**)&pdudeLocal, u16IdDude);
  4027. // Only do scrollbars if not tracking . . .
  4028. if (bTracking == false)
  4029. {
  4030. // Update GUIs to composite buffer.
  4031. ms_sbVert.Draw(g_pimScreenBuf);
  4032. ms_sbHorz.Draw(g_pimScreenBuf);
  4033. }
  4034. // Draw extra cameras.
  4035. DrawViews(prealm);
  4036. // Done with the composite buffer (except to update it to
  4037. // the screen).
  4038. rspUnlockBuffer();
  4039. // Until the editor is merged into the new play, just do it this way. The only "loss" is that
  4040. // we don't get the various status stuff being displayed while in the editor.
  4041. #if 0
  4042. Play_UpdateDisplays( // Returns nothing.
  4043. prealm, // In: Realm.
  4044. pcamera, // In: Camera.
  4045. pdudeLocal, // In: Local dude.
  4046. &rcDudeStatus, // In: Rect for dude status display.
  4047. &rcRealmStatus, // In: Rect for realm status display.
  4048. &rcInfoStatus, // In: Rect for info status display.
  4049. &printDisp, // In: Print to output display info.
  4050. szFileDescriptor, // In: Date/Time stamp of exe.
  4051. &lLastDispTime, // In/Out: Last time display info was output.
  4052. &lFramesTime, // In/Out: Total time of all frames since last display info output.
  4053. &lUpdateDisplayTime, // In/Out: Total time of all rspUpdateDisplay()s since last display info output.
  4054. &lNumFrames, // In/Out: Number of frames since last display info output.
  4055. 0, // In: Current input sequence number.
  4056. 0, // In: Current frame number.
  4057. NULL, // In: pointer to net client to get player names for Score
  4058. TRUE); // In: Update entire display.
  4059. #else
  4060. rspUpdateDisplay();
  4061. #endif
  4062. // Lock buffer for clearage.
  4063. rspLockBuffer();
  4064. // Clear extra cameras.
  4065. ClearViews();
  4066. rspUnlockBuffer();
  4067. // If snap key is pressed . . .
  4068. if (pau8KeyStatus[KEY_SNAP_PICTURE])
  4069. {
  4070. // Take the snap shot.
  4071. Play_SnapPicture();
  4072. // Clear key status.
  4073. pau8KeyStatus[KEY_SNAP_PICTURE] = 0;
  4074. }
  4075. }
  4076. // Shutdown realm
  4077. prealm->Shutdown();
  4078. // Done with the camera.
  4079. delete pcamera;
  4080. pcamera = NULL;
  4081. ms_pcameraCur = NULL;
  4082. }
  4083. else
  4084. {
  4085. TRACE("EditPlay(): Error starting-up temporary realm!\n");
  4086. sResult = -1;
  4087. }
  4088. }
  4089. else
  4090. {
  4091. TRACE("EditPlay(): Error loading temporary realm!\n");
  4092. }
  4093. // Delete the realm
  4094. delete prealm;
  4095. // Delete temporary file
  4096. remove(szFileName);
  4097. }
  4098. else
  4099. {
  4100. TRACE("EditPlay(): Error saving temporary realm!\n");
  4101. }
  4102. }
  4103. else
  4104. {
  4105. TRACE("PlayRealm(): Error getting temporary file name!\n");
  4106. sResult = -1;
  4107. }
  4108. // If mouse is being used, restore mouse cursor
  4109. if (g_InputSettings.m_sUseMouse)
  4110. rspShowMouseCursor();
  4111. rspClearAllInputEvents();
  4112. // Disable autopump.
  4113. RMix::SetAutoPump(FALSE);
  4114. // If something went wrong, let the user know
  4115. if (sResult)
  4116. {
  4117. rspMsgBox(
  4118. RSP_MB_ICN_STOP | RSP_MB_BUT_OK,
  4119. "Postal Editor",
  4120. "An error has occurred that prevents this realm from being played.");
  4121. }
  4122. #endif // DISABLE_EDITOR_SAVE_AND_PLAY
  4123. }
  4124. ////////////////////////////////////////////////////////////////////////////////
  4125. //
  4126. // Create a new CThing derived object of type id in prealm at the specified
  4127. // position.
  4128. //
  4129. ////////////////////////////////////////////////////////////////////////////////
  4130. static short CreateNewThing( // Returns 0 on success.
  4131. CRealm* prealm, // In: Realm to add new CThing to.
  4132. CThing::ClassIDType id, // ID of new CThing type to create.
  4133. short sPosX, // Position for new CThing.
  4134. short sPosY, // Position for new CThing.
  4135. short sPosZ, // Position for new CThing.
  4136. CThing** ppthing, // Out: Pointer to new thing.
  4137. RHot** pphot, // Out: Pointer to new hotbox for thing.
  4138. RFile* pfile/* = NULL*/) // In: Optional file to load from (instead of EditNew()).
  4139. {
  4140. short sError = 0;
  4141. // Don't allow more than one CHood . . .
  4142. if ((id == CThing::CHoodID) && (prealm->m_asClassNumThings[CThing::CHoodID] > 0))
  4143. {
  4144. // ***LOCALIZE***
  4145. rspMsgBox(
  4146. RSP_MB_ICN_STOP | RSP_MB_BUT_OK,
  4147. "Editor: ",
  4148. "Can't have multiple CHood's!");
  4149. //STRACE("Editor: Can't have multiple CHood's!\n");
  4150. sError = 1;
  4151. }
  4152. else
  4153. {
  4154. if (prealm->m_asClassNumThings[CThing::CHoodID] > 0 || id == CThing::CHoodID)
  4155. {
  4156. if (!(id == CThing::CBouyID && prealm->GetCurrentNavNet() == NULL))
  4157. {
  4158. // Create new object of currently selected type
  4159. if (CThing::ConstructWithID(id, prealm, ppthing) == 0)
  4160. {
  4161. // Successfully allocated object.
  4162. // If loading from file specified . . .
  4163. if (pfile != NULL)
  4164. {
  4165. // Remember its ID.
  4166. U16 idInstance = (*ppthing)->GetInstanceID();
  4167. // Release its ID.
  4168. (*ppthing)->SetInstanceID(CIdBank::IdNil);
  4169. // Load object . . .
  4170. if ((*ppthing)->Load(pfile, true, ms_sFileCount--, CRealm::FileVersion) == 0)
  4171. {
  4172. // Loaded.
  4173. // Reset ID.
  4174. (*ppthing)->SetInstanceID(idInstance);
  4175. // Reserve ID.
  4176. prealm->m_idbank.Take(*ppthing, idInstance);
  4177. // Startup.
  4178. (*ppthing)->Startup();
  4179. // Move.
  4180. (*ppthing)->EditMove(sPosX, sPosY, sPosZ);
  4181. }
  4182. else
  4183. {
  4184. TRACE("CreateNewThing(): Load() failed for object.\n");
  4185. sError = 4;
  4186. }
  4187. }
  4188. else
  4189. {
  4190. // Edit new object (required to get object up and running)
  4191. if ((*ppthing)->EditNew(sPosX, sPosY, sPosZ) == 0)
  4192. {
  4193. // Newed.
  4194. }
  4195. else
  4196. {
  4197. TRACE("CreateNewThing(): EditNew() failed for object.\n");
  4198. sError = 4;
  4199. }
  4200. }
  4201. // If successful so far . . .
  4202. if (sError == 0)
  4203. {
  4204. short sActivateHot = TRUE;
  4205. // Some types may need to hook in here.
  4206. switch ( (*ppthing)->GetClassID() )
  4207. {
  4208. case CThing::CBouyID:
  4209. // If bouy lines are hidden . . .
  4210. if (ms_bDrawNetwork == false)
  4211. {
  4212. // Don't activate new bouy hots.
  4213. sActivateHot = FALSE;
  4214. }
  4215. break;
  4216. }
  4217. // Get pos and dimensions for hot.
  4218. RRect rc;
  4219. (*ppthing)->EditRect(&rc);
  4220. // Allocate a RHot for the item . . .
  4221. (*ppthing)->m_phot = *pphot = new RHot(
  4222. rc.sX, // Position.
  4223. rc.sY, // Position.
  4224. rc.sW, // Dimensions.
  4225. rc.sH, // Dimensions.
  4226. ThingHotCall, // Callback.
  4227. sActivateHot, // TRUE, if initially active.
  4228. (U32)*ppthing, // User value (CThing*).
  4229. FRONTMOST_HOT_PRIORITY); // New items towards front.
  4230. if (*pphot != NULL)
  4231. {
  4232. // If this is not THE HOOD . . .
  4233. if (id != CThing::CHoodID)
  4234. {
  4235. (*pphot)->SetParent(ms_photHood);
  4236. }
  4237. // Special things.
  4238. switch (id)
  4239. {
  4240. case CThing::CDudeID:
  4241. // If there is an editor thing . . .
  4242. if (ms_pgething != NULL)
  4243. {
  4244. // If no camera focus yet . . .
  4245. if (ms_pgething->m_u16CameraTrackId == CIdBank::IdNil)
  4246. {
  4247. // Track this dude.
  4248. ms_pgething->m_u16CameraTrackId = (*ppthing)->GetInstanceID();
  4249. }
  4250. }
  4251. CDude* pdude = (CDude*)(*ppthing);
  4252. // If this is the local dude . . .
  4253. if (pdude->m_sDudeNum == 0)
  4254. {
  4255. // Set him to the user selected color.
  4256. pdude->m_sTextureIndex = MAX((short)0, MIN((short)(CDude::MaxTextures - 1), g_GameSettings.m_sPlayerColorIndex));
  4257. }
  4258. break;
  4259. }
  4260. // If an error occurred after allocation . . .
  4261. if (sError != 0)
  4262. {
  4263. // On error, destroy object
  4264. delete *pphot;
  4265. *pphot = NULL;
  4266. }
  4267. }
  4268. else
  4269. {
  4270. TRACE("CreateNewThing(): Failed to allocate new RHot.\n");
  4271. sError = 3;
  4272. }
  4273. }
  4274. // If an error occurred after allocation . . .
  4275. if (sError != 0)
  4276. {
  4277. // On error, destroy object
  4278. delete *ppthing;
  4279. *ppthing = NULL;
  4280. }
  4281. }
  4282. }
  4283. else
  4284. {
  4285. TRACE("CreateNewThing(): Cannot create a buoy when there's no current NavNet.\n");
  4286. // ***LOCALIZE***
  4287. rspMsgBox(
  4288. RSP_MB_ICN_STOP | RSP_MB_BUT_OK,
  4289. "No current NavNet",
  4290. "Cannot create new Buoy when there is no current NavNet.");
  4291. sError = 6;
  4292. }
  4293. }
  4294. else
  4295. {
  4296. sError = 7;
  4297. }
  4298. }
  4299. return sError;
  4300. }
  4301. ////////////////////////////////////////////////////////////////////////////////
  4302. //
  4303. // Move a thing to the specified location and update its RHot with an
  4304. // EditRect() call.
  4305. //
  4306. ////////////////////////////////////////////////////////////////////////////////
  4307. static void MoveThing( // Returns nothing.
  4308. CThing* pthing, // Thing to move.
  4309. RHot* phot, // Thing's hotbox.
  4310. short sPosX, // New position.
  4311. short sPosY, // New position.
  4312. short sPosZ) // New position.
  4313. {
  4314. ASSERT(pthing != NULL);
  4315. ASSERT(phot != NULL);
  4316. // Move to 3D position.
  4317. pthing->EditMove(
  4318. sPosX,
  4319. sPosY,
  4320. sPosZ);
  4321. // Get 2D position.
  4322. RRect rc;
  4323. pthing->EditRect(
  4324. &rc);
  4325. // Copy to hot.
  4326. phot->m_sX = rc.sX;
  4327. phot->m_sY = rc.sY;
  4328. phot->m_sW = rc.sW;
  4329. phot->m_sH = rc.sH;
  4330. // Update info GUI.
  4331. UpdateSelectionInfo(false);
  4332. }
  4333. ////////////////////////////////////////////////////////////////////////////////
  4334. //
  4335. // Enlarges the display area.
  4336. //
  4337. ////////////////////////////////////////////////////////////////////////////////
  4338. static void OnEnlargeDisplay(
  4339. CCamera* pcamera, // Camera to update.
  4340. CRealm* prealm) // Realm to update.
  4341. {
  4342. AdjustDisplaySize(DISPLAY_SIZE_DELTA_X, DISPLAY_SIZE_DELTA_Y, pcamera, prealm);
  4343. }
  4344. ////////////////////////////////////////////////////////////////////////////////
  4345. //
  4346. // Reduces the display area.
  4347. //
  4348. ////////////////////////////////////////////////////////////////////////////////
  4349. static void OnReduceDisplay(
  4350. CCamera* pcamera, // Camera to update.
  4351. CRealm* prealm) // Realm to update.
  4352. {
  4353. AdjustDisplaySize(-DISPLAY_SIZE_DELTA_X, -DISPLAY_SIZE_DELTA_Y, pcamera, prealm);
  4354. }
  4355. ////////////////////////////////////////////////////////////////////////////////
  4356. //
  4357. // Set display mode such that display area is as
  4358. // specified.
  4359. //
  4360. ////////////////////////////////////////////////////////////////////////////////
  4361. static short SetDisplayArea( // Returns 0 on success.
  4362. short sDeviceD, // New depth of display.
  4363. short sDisplayW, // New width of display area.
  4364. short sDisplayH) // New height of display area.
  4365. {
  4366. short sError = 0;
  4367. short sDeviceW, sDeviceH;
  4368. short sDeviceScaling = FALSE;
  4369. // Get device size/mode for this display size.
  4370. sError = rspSuggestVideoMode(
  4371. sDeviceD,
  4372. sDisplayW,
  4373. sDisplayH,
  4374. 1,
  4375. sDeviceScaling,
  4376. &sDeviceW,
  4377. &sDeviceH,
  4378. &sDeviceScaling);
  4379. // If we are not supposed to change the device dimensions . . .
  4380. if (g_GameSettings.m_sUseCurrentDeviceDimensions != FALSE)
  4381. {
  4382. // Get current device settings.
  4383. rspGetVideoMode(
  4384. &sDeviceD,
  4385. &sDeviceW,
  4386. &sDeviceH);
  4387. // Limit display area.
  4388. sDisplayW = MIN(sDeviceW, sDisplayW);
  4389. sDisplayH = MIN(sDeviceH, sDisplayH);
  4390. }
  4391. // If successful so far . . .
  4392. if (sError == 0)
  4393. {
  4394. // Set the adjusted mode . . .
  4395. sError = rspSetVideoMode(
  4396. sDeviceD,
  4397. sDeviceW,
  4398. sDeviceH,
  4399. sDisplayW,
  4400. sDisplayH,
  4401. 1,
  4402. sDeviceScaling);
  4403. // Give Jeff a chance to update his cool wrapper.
  4404. // I'm not sure if this is necessary, but let's be safe.
  4405. rspNameBuffers(&g_pimScreenBuf);
  4406. if (sError == 0)
  4407. {
  4408. }
  4409. else
  4410. {
  4411. TRACE("SetDisplayArea(): rspSetVideoMode() failed.\n");
  4412. }
  4413. }
  4414. else
  4415. {
  4416. TRACE("SetDisplayArea(): rspSuggestVideoMode() failed.\n");
  4417. }
  4418. // Store latest values (in success or failure).
  4419. g_GameSettings.m_sEditorViewWidth = g_pimScreenBuf->m_sWidth;
  4420. g_GameSettings.m_sEditorViewHeight = g_pimScreenBuf->m_sHeight;
  4421. return sError;
  4422. }
  4423. ////////////////////////////////////////////////////////////////////////////////
  4424. //
  4425. // Set display mode and display area such that camera view
  4426. // is specified size.
  4427. //
  4428. ////////////////////////////////////////////////////////////////////////////////
  4429. static short SetCameraArea(void) // Returns 0 on success.
  4430. {
  4431. short sDepth = 8; // Safety.
  4432. rspGetVideoMode(&sDepth);
  4433. // Determine display area for this camera size.
  4434. short sDisplayW = g_GameSettings.m_sEditorViewWidth;//sCameraW + DISPLAY_RIGHT_BORDER;
  4435. short sDisplayH = g_GameSettings.m_sEditorViewHeight;//sCameraH + DISPLAY_BOTTOM_BORDER;
  4436. // Set the display area/mode.
  4437. return SetDisplayArea(sDepth, sDisplayW, sDisplayH);
  4438. }
  4439. ////////////////////////////////////////////////////////////////////////////////
  4440. //
  4441. // Adjust the display area by the specified deltas.
  4442. //
  4443. ////////////////////////////////////////////////////////////////////////////////
  4444. static short AdjustDisplaySize( // Returns 0 on success.
  4445. short sAdjustX, // Amount to increase width of display area.
  4446. // Can be negative to decrease.
  4447. short sAdjustY, // Amount to increase height of display area.
  4448. // Can be negative to decrease.
  4449. CCamera* pcamera, // Camera to update.
  4450. CRealm* prealm) // Realm to update.
  4451. {
  4452. short sError = 0;
  4453. short sDisplayW = 640; // Safety.
  4454. short sDisplayH = 480; // Safety.
  4455. short sDeviceD = 8; // Safety.
  4456. // Get current settings.
  4457. rspGetVideoMode(
  4458. &sDeviceD,
  4459. NULL,
  4460. NULL,
  4461. NULL,
  4462. &sDisplayW,
  4463. &sDisplayH);
  4464. // New area.
  4465. if (SetDisplayArea(
  4466. sDeviceD,
  4467. sDisplayW + sAdjustX,
  4468. sDisplayH + sAdjustY) == 0)
  4469. {
  4470. SizeUpdate(pcamera, prealm);
  4471. }
  4472. else
  4473. {
  4474. sError = 1;
  4475. }
  4476. return sError;
  4477. }
  4478. ////////////////////////////////////////////////////////////////////////////////
  4479. //
  4480. // Update screen size sensitive objects.
  4481. //
  4482. ////////////////////////////////////////////////////////////////////////////////
  4483. static short SizeUpdate( // Returns 0 on success.
  4484. CCamera* pcamera, // Camera to update.
  4485. CRealm* prealm) // Realm to update.
  4486. {
  4487. short sRes = 0; // Assume success.
  4488. short sDisplayW = 640; // Safety.
  4489. short sDisplayH = 480; // Safety.
  4490. short sDisplayD = 8; // Safety.
  4491. // Get current settings.
  4492. rspGetVideoMode(
  4493. &sDisplayD,
  4494. NULL,
  4495. NULL,
  4496. NULL,
  4497. &sDisplayW,
  4498. &sDisplayH);
  4499. short sViewW = sDisplayW - DISPLAY_RIGHT_BORDER - SCROLL_BAR_THICKNESS;
  4500. short sViewH = sDisplayH - DISPLAY_BOTTOM_BORDER - SCROLL_BAR_THICKNESS;
  4501. // Get the hood . . .
  4502. CHood* phood = NULL;
  4503. if (prealm->m_asClassNumThings[CThing::CHoodID] > 0)
  4504. phood = (CHood*) prealm->m_aclassHeads[CThing::CHoodID].GetNext();
  4505. else
  4506. {
  4507. TRACE("SizeUpdate(): No hood.\n");
  4508. sRes = -1;
  4509. }
  4510. // Give Jeff a chance to update his cool wrapper.
  4511. // I'm not sure if this is necessary, but let's be safe.
  4512. rspNameBuffers(&g_pimScreenBuf);
  4513. // If there's a camera to update . . .
  4514. if (pcamera != NULL)
  4515. {
  4516. pcamera->SetHood(phood);
  4517. // Adjust camera by same amount.
  4518. pcamera->SetView(
  4519. pcamera->m_sSceneViewX,
  4520. pcamera->m_sSceneViewY,
  4521. sViewW,
  4522. sViewH);
  4523. pcamera->SetFilm(g_pimScreenBuf, 0, 0);
  4524. }
  4525. // Put GUIs somewhere out of the way.
  4526. if (ms_pguiRealmBar != NULL)
  4527. {
  4528. ms_pguiRealmBar->Move(REALM_BAR_X, REALM_BAR_Y);
  4529. }
  4530. if (ms_pguiPickObj != NULL)
  4531. {
  4532. ms_pguiPickObj->Move(PICKOBJ_LIST_X, PICKOBJ_LIST_Y);
  4533. }
  4534. if (ms_pguiLayers != NULL)
  4535. {
  4536. ms_pguiLayers->Move(LAYERS_LIST_X, LAYERS_LIST_Y);
  4537. }
  4538. if (ms_pguiCameras != NULL)
  4539. {
  4540. ms_pguiCameras->Move(CAMERAS_LIST_X, CAMERAS_LIST_Y);
  4541. }
  4542. if (ms_pguiGUIs != NULL)
  4543. {
  4544. ms_pguiGUIs->Move(GUIS_BAR_X, GUIS_BAR_Y);
  4545. }
  4546. if (ms_pguiNavNets != NULL)
  4547. {
  4548. ms_pguiNavNets->Move(NAVNETS_X, NAVNETS_Y);
  4549. }
  4550. if (ms_pguiMap != NULL)
  4551. {
  4552. ms_pguiMap->Move(MAP_X, MAP_Y);
  4553. }
  4554. if (ms_pguiShowAttribs)
  4555. {
  4556. ms_pguiShowAttribs->Move(SHOWATTRIBS_X, SHOWATTRIBS_Y);
  4557. }
  4558. if (ms_pguiInfo)
  4559. {
  4560. ms_pguiInfo->Move(INFO_X, INFO_Y);
  4561. }
  4562. long lEdgeOvershoot;
  4563. // If not clipping to realm . . .
  4564. if (pcamera->m_bClip == false)
  4565. {
  4566. lEdgeOvershoot = ms_lEdgeOvershoot;
  4567. }
  4568. else
  4569. {
  4570. lEdgeOvershoot = 0;
  4571. }
  4572. // (Re)Create scrollbars at appropriate sizes . . .
  4573. if (ms_sbVert.Create(
  4574. sViewW,
  4575. 0,
  4576. SCROLL_BAR_THICKNESS,
  4577. sViewH + SCROLL_BAR_THICKNESS,
  4578. sDisplayD) == 0)
  4579. {
  4580. // Set scroll range.
  4581. if (phood != NULL)
  4582. {
  4583. ms_sbVert.SetRange(-lEdgeOvershoot, phood->GetHeight() - sViewH + lEdgeOvershoot);
  4584. }
  4585. else
  4586. {
  4587. ms_sbVert.SetRange(0, 0);
  4588. }
  4589. ms_sbVert.m_lTrayIncDec = sViewH - SCROLL_BTN_INCDEC;
  4590. ms_sbVert.m_lButtonIncDec = SCROLL_BTN_INCDEC;
  4591. ms_sbVert.m_lPosPerSecond = sViewH * 2;
  4592. }
  4593. else
  4594. {
  4595. TRACE("SizeUpdate(): ms_sbVert.Create() failed.\n");
  4596. sRes = -3;
  4597. }
  4598. if (ms_sbHorz.Create(
  4599. 0,
  4600. sViewH,
  4601. sViewW,
  4602. SCROLL_BAR_THICKNESS,
  4603. sDisplayD) == 0)
  4604. {
  4605. // Set scroll range.
  4606. if (phood != NULL)
  4607. {
  4608. ms_sbHorz.SetRange(-lEdgeOvershoot, phood->GetWidth() - sViewW + lEdgeOvershoot);
  4609. }
  4610. else
  4611. {
  4612. ms_sbHorz.SetRange(0, 0);
  4613. }
  4614. ms_sbHorz.m_lTrayIncDec = sViewW - SCROLL_BTN_INCDEC;
  4615. ms_sbHorz.m_lButtonIncDec = SCROLL_BTN_INCDEC;
  4616. ms_sbHorz.m_lPosPerSecond = sViewW * 2;
  4617. }
  4618. else
  4619. {
  4620. TRACE("SizeUpdate(): ms_sbHorz.Create() failed.\n");
  4621. sRes = -3;
  4622. }
  4623. // Re-Create attribute displayer sprite.
  4624. SizeShowAttribsSprite();
  4625. return sRes;
  4626. }
  4627. ////////////////////////////////////////////////////////////////////////////////
  4628. //
  4629. // Get the Editor Thing from the specified realm.
  4630. //
  4631. ////////////////////////////////////////////////////////////////////////////////
  4632. static CGameEditThing* GetEditorThing( // Returns ptr to editor thing for
  4633. // specified realm or NULL.
  4634. CRealm* prealm) // Realm to get editor thing from.
  4635. {
  4636. CGameEditThing* pgething = NULL;
  4637. if (prealm->m_asClassNumThings[CThing::CGameEditThingID] > 0)
  4638. {
  4639. pgething = (CGameEditThing*) prealm->m_aclassHeads[CThing::CGameEditThingID].GetNext();
  4640. }
  4641. else
  4642. {
  4643. TRACE("GetEditorThing(): No editor thing.\n");
  4644. }
  4645. return pgething;
  4646. }
  4647. ////////////////////////////////////////////////////////////////////////////////
  4648. //
  4649. // Callback from GUIs. This will set ms_lPressedId to pgui->m_lId.
  4650. //
  4651. ////////////////////////////////////////////////////////////////////////////////
  4652. static void GuiPressedCall( // Returns nothing.
  4653. RGuiItem* pgui) // GUI item pressed.
  4654. {
  4655. // Set ID of item pressed.
  4656. ms_lPressedId = pgui->m_lId;
  4657. }
  4658. ////////////////////////////////////////////////////////////////////////////////
  4659. //
  4660. // Callback from pressed list items.
  4661. //
  4662. ////////////////////////////////////////////////////////////////////////////////
  4663. static void ListItemPressedCall( // Returns nothing.
  4664. RGuiItem* pgui) // GUI item pressed.
  4665. {
  4666. // If not dragging . . .
  4667. if (ms_sMoving == FALSE)
  4668. {
  4669. // Default logic.
  4670. GuiPressedCall(pgui);
  4671. // Select item.
  4672. RListBox* plb = (RListBox*)pgui->m_ulUserInstance;
  4673. if (plb != NULL)
  4674. {
  4675. // Set new item as selection.
  4676. plb->SetSel(pgui);
  4677. }
  4678. else
  4679. {
  4680. TRACE("ListItemPressedCall(): ListItem has no parent? That would be wrong.\n");
  4681. }
  4682. }
  4683. }
  4684. ////////////////////////////////////////////////////////////////////////////////
  4685. //
  4686. // Callback from Nav Net listbox
  4687. //
  4688. ////////////////////////////////////////////////////////////////////////////////
  4689. void NavNetListPressedCall( // Returns nothing
  4690. RGuiItem* pgui) // GUI item pressed
  4691. {
  4692. // Default logic
  4693. // GuiPressedCall(pgui);
  4694. // Select item
  4695. RGuiItem* pitem = (RGuiItem*) pgui->GetParent();
  4696. RListBox* plb = (RListBox*) pitem->GetParent();
  4697. if (plb != NULL)
  4698. {
  4699. // Set selection
  4700. plb->SetSel(pgui);
  4701. // Set as default Nav Net
  4702. ((CNavigationNet*) pgui->m_ulUserInstance)->SetAsDefault();
  4703. // Make the net lines redraw
  4704. UpdateNetLines((CNavigationNet*) pgui->m_ulUserInstance);
  4705. }
  4706. else
  4707. {
  4708. TRACE("NavNetListPressedCall(): List Item has no parent?\n");
  4709. }
  4710. }
  4711. ////////////////////////////////////////////////////////////////////////////////
  4712. //
  4713. // Callback from scrollbars indicating change in thumb position.
  4714. //
  4715. ////////////////////////////////////////////////////////////////////////////////
  4716. static void ScrollPosUpdate( // Returns nothing.
  4717. RScrollBar* psb) // ScrollBar that was updated.
  4718. {
  4719. // Switch on orientation. Say....
  4720. switch (psb->m_oOrientation)
  4721. {
  4722. case RScrollBar::Vertical:
  4723. // If there's a camera . . .
  4724. if (ms_pcameraCur != NULL)
  4725. {
  4726. ms_pcameraCur->m_sSceneViewY = psb->GetPos();
  4727. ms_pcameraCur->Update();
  4728. }
  4729. // If there is an editor object . . .
  4730. if (ms_pgething != NULL)
  4731. {
  4732. ms_pgething->m_sViewPosY = psb->GetPos();
  4733. }
  4734. break;
  4735. case RScrollBar::Horizontal:
  4736. // If there's a camera . . .
  4737. if (ms_pcameraCur != NULL)
  4738. {
  4739. ms_pcameraCur->m_sSceneViewX = psb->GetPos();
  4740. ms_pcameraCur->Update();
  4741. }
  4742. // If there is an editor object . . .
  4743. if (ms_pgething != NULL)
  4744. {
  4745. ms_pgething->m_sViewPosX = psb->GetPos();
  4746. }
  4747. break;
  4748. }
  4749. }
  4750. ////////////////////////////////////////////////////////////////////////////////
  4751. //
  4752. // Callback from RHot when an event occurs within it.
  4753. //
  4754. ////////////////////////////////////////////////////////////////////////////////
  4755. static void ThingHotCall( // Returns nothing.
  4756. RHot* phot, // Ptr to RHot that generated event.
  4757. RInputEvent* pie) // In: Most recent user input event.
  4758. // Out: Depends on callbacks. Generally,
  4759. // pie->sUsed = TRUE, if used.
  4760. {
  4761. CThing* pthing = (CThing*)phot->m_ulUser;
  4762. ASSERT(pthing != NULL);
  4763. // If not used . . .
  4764. if (pie->sUsed == FALSE)
  4765. {
  4766. // Switch on event.
  4767. switch (pie->sEvent)
  4768. {
  4769. case RSP_MB0_PRESSED:
  4770. {
  4771. SetSel(pthing, phot);
  4772. // Note that we used the event.
  4773. pie->sUsed = TRUE;
  4774. pie->lUser = 1;
  4775. break;
  4776. }
  4777. case RSP_MB0_RELEASED:
  4778. {
  4779. SetSel(pthing, phot);
  4780. // If EDIT_KEY_SENDTOBACK held down . . .
  4781. UCHAR aucKeys[128];
  4782. rspScanKeys(aucKeys);
  4783. if (aucKeys[EDIT_KEY_SENDTOBACK] != 0)
  4784. {
  4785. // Send this hot to back.
  4786. phot->SetPriority(++ms_sBackPriority);
  4787. // If we hit the back . . .
  4788. if (ms_sBackPriority == RHOT_NO_PRIORITY)
  4789. {
  4790. ResetHotPriorities();
  4791. }
  4792. // Unselect.
  4793. SetSel(NULL, NULL);
  4794. }
  4795. // If EDIT_KEY_SETCAMERATRACK held down . . .
  4796. else if (aucKeys[EDIT_KEY_SETCAMERATRACK] != 0)
  4797. {
  4798. // If there is an editor thing . . .
  4799. if (ms_pgething != NULL)
  4800. {
  4801. // If this thing is not the hood . . .
  4802. if (pthing->GetClassID() != CThing::CHoodID)
  4803. {
  4804. // Get ID of item to track.
  4805. ms_pgething->m_u16CameraTrackId = pthing->GetInstanceID();
  4806. }
  4807. else
  4808. {
  4809. // Clear camera track ID.
  4810. ms_pgething->m_u16CameraTrackId = CIdBank::IdNil;
  4811. }
  4812. // User feedback.
  4813. PlaySample(g_smidGeneralBeep, SampleMaster::UserFeedBack);
  4814. }
  4815. else
  4816. {
  4817. TRACE("ThingHotCall(): No Editor CThing.\n");
  4818. }
  4819. }
  4820. // Note that we used the event.
  4821. pie->sUsed = TRUE;
  4822. pie->lUser = 1;
  4823. break;
  4824. }
  4825. // This works on the Mac too because we faked a right mouse button
  4826. // earlier in DoInput.
  4827. // System_Key+Mouse_Button on the mac == PC right mouse button
  4828. case RSP_MB1_PRESSED:
  4829. {
  4830. SetSel(pthing, phot);
  4831. // Size may have changed.
  4832. RRect rc;
  4833. ms_pthingSel->EditRect(&rc);
  4834. // Update hot.
  4835. ms_photSel->m_sX = rc.sX;
  4836. ms_photSel->m_sY = rc.sY;
  4837. ms_photSel->m_sW = rc.sW;
  4838. ms_photSel->m_sH = rc.sH;
  4839. // See if a bouy was double clicked on
  4840. if (ms_pthingSel->GetClassID() == CThing::CBouyID)
  4841. {
  4842. // If no bouys have been clicked on yet, set the
  4843. // starting bouy link and start drawing the line
  4844. if ((m_pBouyLink0 == NULL && m_pBouyLink1 == NULL) ||
  4845. (m_pBouyLink0 != NULL && m_pBouyLink1 != NULL))
  4846. {
  4847. m_pBouyLink0 = (CBouy*) ms_pthingSel;
  4848. m_pBouyLink1 = NULL;
  4849. }
  4850. // This is the ending bouy
  4851. else if (m_pBouyLink0 != NULL && m_pBouyLink1 == NULL)
  4852. {
  4853. m_pBouyLink1 = (CBouy*) ms_pthingSel;
  4854. m_pBouyLink0->AddLink(m_pBouyLink1);
  4855. m_pBouyLink1->AddLink(m_pBouyLink0);
  4856. AddNewLine(m_pBouyLink0->GetX(),
  4857. m_pBouyLink0->GetZ(),
  4858. m_pBouyLink1->GetX(),
  4859. m_pBouyLink1->GetZ());
  4860. }
  4861. }
  4862. // If they double clicked on something other than a bouy
  4863. // while they were drawing a bouy link line, then abort
  4864. // the link draw.
  4865. else if (m_pBouyLink0 != NULL && m_pBouyLink1 == NULL)
  4866. {
  4867. m_pBouyLink0 = m_pBouyLink1 = NULL;
  4868. }
  4869. // Note that we used the event.
  4870. pie->sUsed = TRUE;
  4871. pie->lUser = 1;
  4872. break;
  4873. }
  4874. case RSP_MB0_DOUBLECLICK:
  4875. {
  4876. SetSel(pthing, phot);
  4877. // Modify.
  4878. ms_pthingSel->EditModify();
  4879. // Size may have changed.
  4880. RRect rc;
  4881. ms_pthingSel->EditRect(&rc);
  4882. // Update hot.
  4883. ms_photSel->m_sX = rc.sX;
  4884. ms_photSel->m_sY = rc.sY;
  4885. ms_photSel->m_sW = rc.sW;
  4886. ms_photSel->m_sH = rc.sH;
  4887. // Note that we used the event.
  4888. pie->sUsed = TRUE;
  4889. pie->lUser = 1;
  4890. break;
  4891. }
  4892. case RSP_MB1_DOUBLECLICK:
  4893. {
  4894. SetSel(pthing, phot);
  4895. // If this is a pylon . . .
  4896. if (ms_pthingSel->GetClassID() == CThing::CPylonID)
  4897. {
  4898. // Enter pylon trigger region edit mode.
  4899. EditPylonTriggerRegion(ms_pthingSel);
  4900. // Note that we used the event.
  4901. pie->sUsed = TRUE;
  4902. pie->lUser = 1;
  4903. }
  4904. break;
  4905. }
  4906. }
  4907. }
  4908. }
  4909. ////////////////////////////////////////////////////////////////////////////////
  4910. //
  4911. // Draw the link between the first bouy selected and the mouse cursor
  4912. //
  4913. ////////////////////////////////////////////////////////////////////////////////
  4914. static void DrawBouyLink( // Returns nothing.
  4915. CRealm* prealm, // In: Realm.
  4916. CCamera* pcamera) // In: View of prealm.
  4917. {
  4918. short sMouseX;
  4919. short sMouseY;
  4920. short sButtons;
  4921. if (ms_bDrawNetwork && m_pBouyLink0 != NULL && m_pBouyLink1 != NULL &&
  4922. m_pBouyLink0->Visible() && m_pBouyLink1->Visible())
  4923. {
  4924. // These lines show the paths the characters would take so
  4925. // they should be only on the X/Z plane and, therefore, Y
  4926. // is ignored.
  4927. short sBouyLink0X, sBouyLink0Y;
  4928. Maprealm2Screen(
  4929. prealm,
  4930. pcamera,
  4931. m_pBouyLink0->GetX(),
  4932. 0,
  4933. m_pBouyLink0->GetZ(),
  4934. &sBouyLink0X,
  4935. &sBouyLink0Y);
  4936. short sBouyLink1X, sBouyLink1Y;
  4937. Maprealm2Screen(
  4938. prealm,
  4939. pcamera,
  4940. m_pBouyLink1->GetX(),
  4941. 0,
  4942. m_pBouyLink1->GetZ(),
  4943. &sBouyLink1X,
  4944. &sBouyLink1Y);
  4945. rspLine(249, g_pimScreenBuf,
  4946. sBouyLink0X,
  4947. sBouyLink0Y,
  4948. sBouyLink1X,
  4949. sBouyLink1Y);
  4950. }
  4951. else if (m_pBouyLink0 != NULL && m_pBouyLink1 == NULL)
  4952. {
  4953. // These lines show the paths the characters would take so
  4954. // they should be only on the X/Z plane and, therefore, Y
  4955. // is ignored.
  4956. short sBouyLink0X, sBouyLink0Y;
  4957. Maprealm2Screen(
  4958. prealm,
  4959. pcamera,
  4960. m_pBouyLink0->GetX(),
  4961. 0,
  4962. m_pBouyLink0->GetZ(),
  4963. &sBouyLink0X,
  4964. &sBouyLink0Y);
  4965. rspGetMouse(&sMouseX, &sMouseY, &sButtons);
  4966. rspLine(249, g_pimScreenBuf,
  4967. sBouyLink0X,
  4968. sBouyLink0Y,
  4969. sMouseX, sMouseY);
  4970. }
  4971. }
  4972. ////////////////////////////////////////////////////////////////////////////////
  4973. //
  4974. // Resets all RHots including and descended from ms_photHood
  4975. // to FRONTMOST_HOT_PRIORITY.
  4976. //
  4977. ////////////////////////////////////////////////////////////////////////////////
  4978. static void ResetHotPriorities(void) // Returns nothing.
  4979. {
  4980. if (ms_photHood != NULL)
  4981. {
  4982. // Set Hood's priority.
  4983. ms_photHood->SetPriority(FRONTMOST_HOT_PRIORITY);
  4984. // Do children.
  4985. RHot* phot = ms_photHood->m_listChildren.GetHead();
  4986. while (phot != NULL)
  4987. {
  4988. phot->SetPriority(FRONTMOST_HOT_PRIORITY);
  4989. phot = ms_photHood->m_listChildren.GetNext();
  4990. }
  4991. // Reset backmost priority.
  4992. ms_sBackPriority = FRONTMOST_HOT_PRIORITY;
  4993. }
  4994. }
  4995. ////////////////////////////////////////////////////////////////////////////////
  4996. // AddNewLine
  4997. ////////////////////////////////////////////////////////////////////////////////
  4998. static void AddNewLine(short sX0, short sY0, short sX1, short sY1)
  4999. {
  5000. LINKLINE newLine;
  5001. // Sort the lines by smaller x. If the X is the same then sort
  5002. // by Y. By presorting the lines before adding them, a line with
  5003. // endpoints (x,y) (a,b) and a line (a,b) (x,y) will only be added to
  5004. // the set once as the line (a,b) (x,y) which saves memory and
  5005. // speeds the drawing.
  5006. if (sX0 == sX1)
  5007. {
  5008. if (sY0 < sY1)
  5009. {
  5010. newLine.sX0 = sX0;
  5011. newLine.sY0 = sY0;
  5012. newLine.sX1 = sX1;
  5013. newLine.sY1 = sY1;
  5014. }
  5015. else
  5016. {
  5017. newLine.sX0 = sX1;
  5018. newLine.sY0 = sY1;
  5019. newLine.sX1 = sX0;
  5020. newLine.sY1 = sY0;
  5021. }
  5022. }
  5023. else
  5024. {
  5025. if (sX0 < sX1)
  5026. {
  5027. newLine.sX0 = sX0;
  5028. newLine.sY0 = sY0;
  5029. newLine.sX1 = sX1;
  5030. newLine.sY1 = sY1;
  5031. }
  5032. else
  5033. {
  5034. newLine.sX0 = sX1;
  5035. newLine.sY0 = sY1;
  5036. newLine.sX1 = sX0;
  5037. newLine.sY1 = sY0;
  5038. }
  5039. }
  5040. // Add the line to the set of lines
  5041. m_NetLines.insert(newLine);
  5042. }
  5043. ////////////////////////////////////////////////////////////////////////////////
  5044. // Write a NavNet log file to display the connections.- for debugging purposes
  5045. ////////////////////////////////////////////////////////////////////////////////
  5046. static void NetLog(CNavigationNet* pNavNet)
  5047. {
  5048. /*
  5049. ofstream txtout;
  5050. ofstream routeout;
  5051. CNavigationNet::nodeMap::iterator ibouy;
  5052. CBouy::linkset::iterator ilink;
  5053. UCHAR i;
  5054. UCHAR ucHops;
  5055. txtout.open("c:\\temp\\navnet.txt");
  5056. routeout.open("c:\\temp\\navroute.txt");
  5057. if (txtout.is_open() && routeout.is_open())
  5058. {
  5059. txtout << ";\n";
  5060. txtout << "; NavNet connections file" << endl;
  5061. txtout << ";" << endl;
  5062. txtout << "; Node: Directly connected nodes\n";
  5063. txtout << ";------------------------------------------------------------------\n";
  5064. routeout << ";Bouy Routing Tables" << endl;
  5065. routeout << ";" << endl;
  5066. routeout << ";-----------------------------------------------------------------\n";
  5067. if (pNavNet)
  5068. {
  5069. for (ibouy = pNavNet->m_NodeMap.begin();
  5070. ibouy != pNavNet->m_NodeMap.end(); ibouy++)
  5071. {
  5072. txtout << (USHORT) ((*ibouy).second->m_ucID) << " : ";
  5073. for (ilink = (*ibouy).second->m_apsDirectLinks.begin();
  5074. ilink != (*ibouy).second->m_apsDirectLinks.end(); ilink++)
  5075. {
  5076. txtout << (USHORT) (*ilink)->m_ucID << ", ";
  5077. }
  5078. txtout << endl;
  5079. // Show routing table for reachable links
  5080. routeout << "bouy " << (USHORT) ((*ibouy).second->m_ucID) << endl;
  5081. for (i = 1; i < pNavNet->GetNumNodes(); i++)
  5082. {
  5083. ucHops = (*ibouy).second->NextRouteNode(i);
  5084. if (ucHops < 255)
  5085. {
  5086. routeout << " vialink[" << (USHORT) i << "] = " << (USHORT) ucHops << endl;
  5087. }
  5088. }
  5089. }
  5090. }
  5091. txtout.close();
  5092. routeout.close();
  5093. }
  5094. else
  5095. {
  5096. TRACE("NetLog: Error opening log file for output\n");
  5097. }
  5098. */
  5099. }
  5100. ////////////////////////////////////////////////////////////////////////////////
  5101. // UpdateNetLines
  5102. ////////////////////////////////////////////////////////////////////////////////
  5103. static void UpdateNetLines(CNavigationNet* pNavNet)
  5104. {
  5105. CNavigationNet::nodeMap::iterator ibouy;
  5106. CBouy* pLinkedBouy = NULL;
  5107. if (pNavNet)
  5108. {
  5109. m_NetLines.erase(m_NetLines.begin(), m_NetLines.end());
  5110. for (ibouy = pNavNet->m_NodeMap.begin();
  5111. ibouy != pNavNet->m_NodeMap.end(); ibouy++)
  5112. {
  5113. pLinkedBouy = (*ibouy).second->m_aplDirectLinks.GetHead();
  5114. while (pLinkedBouy)
  5115. {
  5116. AddNewLine((*ibouy).second->GetX(),
  5117. (*ibouy).second->GetZ(),
  5118. pLinkedBouy->GetX(),
  5119. pLinkedBouy->GetZ());
  5120. pLinkedBouy = (*ibouy).second->m_aplDirectLinks.GetNext();
  5121. }
  5122. }
  5123. }
  5124. else
  5125. {
  5126. m_NetLines.erase(m_NetLines.begin(), m_NetLines.end());
  5127. }
  5128. /*
  5129. CNavigationNet::nodeMap::iterator ibouy;
  5130. CBouy::linkset::iterator ilink;
  5131. if (pNavNet)
  5132. {
  5133. m_NetLines.erase(m_NetLines.begin(), m_NetLines.end());
  5134. for (ibouy = pNavNet->m_NodeMap.begin();
  5135. ibouy != pNavNet->m_NodeMap.end(); ibouy++)
  5136. {
  5137. for (ilink = (*ibouy).second->m_apsDirectLinks.begin();
  5138. ilink != (*ibouy).second->m_apsDirectLinks.end(); ilink++)
  5139. {
  5140. AddNewLine((*ibouy).second->GetX(),
  5141. (*ibouy).second->GetZ(),
  5142. (*ilink)->GetX(),
  5143. (*ilink)->GetZ());
  5144. }
  5145. }
  5146. }
  5147. */
  5148. // NetLog(pNavNet);
  5149. }
  5150. ////////////////////////////////////////////////////////////////////////////////
  5151. // DrawNetwork
  5152. ////////////////////////////////////////////////////////////////////////////////
  5153. static void DrawNetwork( // Returns nothing.
  5154. CRealm* prealm, // In: Realm.
  5155. CCamera* pcamera) // In: View of prealm.
  5156. {
  5157. lineset::iterator i;
  5158. if (ms_bDrawNetwork)
  5159. {
  5160. for (i = m_NetLines.begin(); i != m_NetLines.end(); i++)
  5161. {
  5162. // These lines show the paths the characters would take so
  5163. // they should be only on the X/Z plane and, therefore, Y
  5164. // is ignored.
  5165. short sBouyLink0X, sBouyLink0Y;
  5166. Maprealm2Screen(
  5167. prealm,
  5168. pcamera,
  5169. (*i).sX0,
  5170. 0,
  5171. (*i).sY0,
  5172. &sBouyLink0X,
  5173. &sBouyLink0Y);
  5174. short sBouyLink1X, sBouyLink1Y;
  5175. Maprealm2Screen(
  5176. prealm,
  5177. pcamera,
  5178. (*i).sX1,
  5179. 0,
  5180. (*i).sY1,
  5181. &sBouyLink1X,
  5182. &sBouyLink1Y);
  5183. rspLine(250, g_pimScreenBuf,
  5184. sBouyLink0X,
  5185. sBouyLink0Y,
  5186. sBouyLink1X,
  5187. sBouyLink1Y);
  5188. }
  5189. }
  5190. }
  5191. ////////////////////////////////////////////////////////////////////////////////
  5192. // Creates a view and adds it to the list of views.
  5193. ////////////////////////////////////////////////////////////////////////////////
  5194. static short AddView( // Returns 0 on success.
  5195. CRealm* prealm) // In: Realm in which to setup camera.
  5196. {
  5197. static short sNum = 0;
  5198. short sRes = 0; // Assume success.
  5199. RListBox* plb = (RListBox*)ms_pguiCameras->GetItemFromId(GUI_ID_CAMERA_LIST);
  5200. if (plb != NULL)
  5201. {
  5202. View* pview;
  5203. if (CreateView(&pview, prealm) == 0)
  5204. {
  5205. char szTitle[256];
  5206. sprintf(szTitle, "Camera %d", ++sNum);
  5207. RGuiItem* pgui = plb->AddString(szTitle);
  5208. pgui->m_lId = (long)pview;
  5209. plb->AdjustContents();
  5210. pview->pgui->SetText("%s", szTitle);
  5211. pview->pgui->Compose();
  5212. }
  5213. else
  5214. {
  5215. sRes = -2;
  5216. }
  5217. }
  5218. else
  5219. {
  5220. sRes = -1;
  5221. }
  5222. return sRes;
  5223. }
  5224. ////////////////////////////////////////////////////////////////////////////////
  5225. // Kills a view and removes it from the list of views.
  5226. ////////////////////////////////////////////////////////////////////////////////
  5227. static void RemoveView( // Returns nothing.
  5228. View* pview) // In: View to remove or NULL to remove currently
  5229. // selected view.
  5230. {
  5231. RListBox* plb = (RListBox*)ms_pguiCameras->GetItemFromId(GUI_ID_CAMERA_LIST);
  5232. if (plb != NULL)
  5233. {
  5234. RGuiItem* pguiRemove;
  5235. if (pview != NULL)
  5236. {
  5237. pguiRemove = plb->GetItemFromId((long)pview);
  5238. }
  5239. else
  5240. {
  5241. pguiRemove = plb->GetSel();
  5242. }
  5243. if (pguiRemove != NULL)
  5244. {
  5245. KillView((View*)(pguiRemove->m_lId));
  5246. plb->RemoveItem(pguiRemove);
  5247. plb->AdjustContents();
  5248. }
  5249. }
  5250. }
  5251. ////////////////////////////////////////////////////////////////////////////////
  5252. // Removes all current views.
  5253. ////////////////////////////////////////////////////////////////////////////////
  5254. static void RemoveViews(void)
  5255. {
  5256. View* pview = ms_listViews.GetHead();
  5257. while (pview != NULL)
  5258. {
  5259. RemoveView(pview);
  5260. pview = ms_listViews.GetNext();
  5261. }
  5262. }
  5263. ////////////////////////////////////////////////////////////////////////////////
  5264. // Creates a new View and adds it to the list of Views.
  5265. ////////////////////////////////////////////////////////////////////////////////
  5266. static short CreateView( // Returns 0 on success.
  5267. View** ppview, // Out: New view, if not NULL.
  5268. CRealm* prealm) // In: Realm in which to setup camera.
  5269. {
  5270. short sRes = 0; // Assume success.
  5271. if (ppview != NULL)
  5272. {
  5273. *ppview = NULL; // Safety.
  5274. }
  5275. // Create view . . .
  5276. View* pview = new View;
  5277. if (pview != NULL)
  5278. {
  5279. // Create and load GUI . . .
  5280. pview->pgui = RGuiItem::LoadInstantiate(FullPath(GAME_PATH_VD, VIEW_GUI_FILE) );
  5281. if (pview->pgui != NULL)
  5282. {
  5283. pview->pgui->GetClient(NULL, NULL, &(pview->sViewW), &(pview->sViewH) );
  5284. // Get the scrollbars.
  5285. pview->psbVert = (RScrollBar*)pview->pgui->GetItemFromId(3);
  5286. pview->psbHorz = (RScrollBar*)pview->pgui->GetItemFromId(4);
  5287. // Adjust dimensions to make scrollbars visible.
  5288. if (pview->psbVert != NULL)
  5289. {
  5290. pview->sViewW -= pview->psbVert->m_im.m_sWidth;
  5291. }
  5292. if (pview->psbHorz != NULL)
  5293. {
  5294. pview->sViewH -= pview->psbHorz->m_im.m_sHeight;
  5295. }
  5296. // Set scrollbar range based on view size and realm size.
  5297. if (pview->psbVert != NULL)
  5298. {
  5299. pview->psbVert->SetRange(0, prealm->m_phood->GetHeight() - pview->sViewH);
  5300. }
  5301. if (pview->psbHorz != NULL)
  5302. {
  5303. pview->psbHorz->SetRange(0, prealm->m_phood->GetWidth() - pview->sViewW);
  5304. }
  5305. // Add to list . . .
  5306. if (ms_listViews.Add(pview) == 0)
  5307. {
  5308. // Activate.
  5309. pview->pgui->SetVisible(TRUE);
  5310. // Succcess.
  5311. if (ppview != NULL)
  5312. {
  5313. *ppview = pview;
  5314. }
  5315. }
  5316. else
  5317. {
  5318. TRACE("CreateView(): Failed to add view to list.\n");
  5319. sRes = -3;
  5320. }
  5321. // If an error occurred after allocating GUI . . .
  5322. if (sRes != 0)
  5323. {
  5324. delete pview->pgui;
  5325. }
  5326. }
  5327. else
  5328. {
  5329. TRACE("CreateView(): Failed to load %s.\n", VIEW_GUI_FILE);
  5330. sRes = -2;
  5331. }
  5332. // If an error occurred after allocating View . . .
  5333. if (sRes != 0)
  5334. {
  5335. delete pview;
  5336. }
  5337. }
  5338. else
  5339. {
  5340. TRACE("CreateView(): Failed to allocate new View.\n");
  5341. sRes = -1;
  5342. }
  5343. return sRes;
  5344. }
  5345. ////////////////////////////////////////////////////////////////////////////////
  5346. // Destroys a View and removes it from the list of Views.
  5347. ////////////////////////////////////////////////////////////////////////////////
  5348. static void KillView( // Returns nothing.
  5349. View* pview) // View to kill.
  5350. {
  5351. // Remove from list.
  5352. ms_listViews.Remove(pview);
  5353. // Delete.
  5354. delete pview;
  5355. }
  5356. ////////////////////////////////////////////////////////////////////////////////
  5357. // Draw specified view.
  5358. ////////////////////////////////////////////////////////////////////////////////
  5359. static void DrawView( // Returns nothing.
  5360. View* pview, // View to draw.
  5361. CRealm* prealm) // Realm to draw.
  5362. {
  5363. // Get client.
  5364. short sClientPosX, sClientPosY;
  5365. pview->pgui->GetClient(&sClientPosX, &sClientPosY, NULL, NULL);
  5366. // Add in GUI's position.
  5367. sClientPosX += pview->pgui->m_sX;
  5368. sClientPosY += pview->pgui->m_sY;
  5369. // Use scrollbars for position.
  5370. short sViewX = 0; // Safety.
  5371. short sViewY = 0; // Safety.
  5372. if (pview->psbVert != NULL)
  5373. {
  5374. sViewY = pview->psbVert->GetPos();
  5375. }
  5376. if (pview->psbHorz != NULL)
  5377. {
  5378. sViewX = pview->psbHorz->GetPos();
  5379. }
  5380. // Draw GUI.
  5381. pview->pgui->Draw(g_pimScreenBuf);
  5382. // Draw scene.
  5383. pview->cam.Snap(
  5384. pview->sViewW, // In: View's width
  5385. pview->sViewH, // In: View's height
  5386. &(prealm->m_scene), // In: Scene to take picture of
  5387. prealm->m_phood, // In: Da hood.
  5388. sViewX, // In: View's upper left x (in scene coords)
  5389. sViewY, // In: View's upper left y (in scene coords)
  5390. g_pimScreenBuf, // In: Film (where the picture ends up)
  5391. sClientPosX, // In: View's upper left x (in film coords)
  5392. sClientPosY // In: View's upper left y (in film coords)
  5393. );
  5394. }
  5395. ////////////////////////////////////////////////////////////////////////////////
  5396. // Draw all views.
  5397. ////////////////////////////////////////////////////////////////////////////////
  5398. static void DrawViews( // Returns nothing.
  5399. CRealm* prealm) // Realm to draw.
  5400. {
  5401. View* pview = ms_listViews.GetHead();
  5402. while (pview != NULL)
  5403. {
  5404. DrawView(pview, prealm);
  5405. pview = ms_listViews.GetNext();
  5406. }
  5407. ms_pguiCameras->Draw(g_pimScreenBuf);
  5408. }
  5409. ////////////////////////////////////////////////////////////////////////////////
  5410. // Clear specified view.
  5411. ////////////////////////////////////////////////////////////////////////////////
  5412. static void ClearGUI( // Returns nothing.
  5413. RGuiItem* pgui) // In: GUI's whose area we should clean.
  5414. {
  5415. rspRect(
  5416. RSP_BLACK_INDEX,
  5417. g_pimScreenBuf,
  5418. pgui->m_sX,
  5419. pgui->m_sY,
  5420. pgui->m_im.m_sWidth,
  5421. pgui->m_im.m_sHeight);
  5422. }
  5423. ////////////////////////////////////////////////////////////////////////////////
  5424. // Clear all views.
  5425. ////////////////////////////////////////////////////////////////////////////////
  5426. static void ClearViews(void) // Returns nothing.
  5427. {
  5428. View* pview = ms_listViews.GetHead();
  5429. while (pview != NULL)
  5430. {
  5431. ClearGUI(pview->pgui);
  5432. pview = ms_listViews.GetNext();
  5433. }
  5434. ClearGUI(ms_pguiCameras);
  5435. }
  5436. ////////////////////////////////////////////////////////////////////////////////
  5437. // Do focus hotbox logic and such for GUIs.
  5438. ////////////////////////////////////////////////////////////////////////////////
  5439. static void DoView( // Returns nothing.
  5440. View* pview, // View to do.
  5441. RInputEvent* pie) // Input event to process.
  5442. {
  5443. pview->pgui->m_hot.Do(pie);
  5444. }
  5445. ////////////////////////////////////////////////////////////////////////////////
  5446. // Do all views.
  5447. ////////////////////////////////////////////////////////////////////////////////
  5448. static void DoViews(
  5449. RInputEvent* pie) // Input event to process.
  5450. {
  5451. ms_pguiCameras->m_hot.Do(pie);
  5452. View* pview = ms_listViews.GetTail();
  5453. while (pview != NULL)
  5454. {
  5455. DoView(pview, pie);
  5456. pview = ms_listViews.GetPrev();
  5457. }
  5458. }
  5459. ////////////////////////////////////////////////////////////////////////////////
  5460. // Draw the map.
  5461. ////////////////////////////////////////////////////////////////////////////////
  5462. static void RefreshMap( // Returns nothing.
  5463. CRealm* prealm) // Realm to map.
  5464. {
  5465. ASSERT(ms_pguiMap != NULL);
  5466. // Get area to draw in.
  5467. if (ms_pguiMapZone != NULL)
  5468. {
  5469. // Clear.
  5470. ms_pguiMapZone->Compose();
  5471. short sClientX, sClientY, sClientW, sClientH;
  5472. ms_pguiMapZone->GetClient(&sClientX, &sClientY, &sClientW, &sClientH);
  5473. // Allocate temp camera and film . . .
  5474. CCamera camera;
  5475. RImage imFilm;
  5476. short sViewW = prealm->m_phood->m_pimBackground->m_sWidth;
  5477. short sViewH = prealm->m_phood->m_pimBackground->m_sHeight;
  5478. if (imFilm.CreateImage(
  5479. sViewW,
  5480. sViewH,
  5481. RImage::BMP8) == 0)
  5482. {
  5483. // Take a shot.
  5484. camera.Snap(
  5485. sViewW, // In: View's width
  5486. sViewH, // In: View's height
  5487. &(prealm->m_scene), // In: Scene to take picture of
  5488. prealm->m_phood, // In: Hood for this scene.
  5489. 0, // In: View's upper left x (in scene coords)
  5490. 0, // In: View's upper left y (in scene coords)
  5491. &imFilm, // In: Film (where the picture ends up)
  5492. 0, // In: View's upper left x (in film coords)
  5493. 0); // In: View's upper left y (in film coords)
  5494. // Stretch it as necessary to the map view.
  5495. double dRatioX = (double)sClientW / (double)sViewW;
  5496. double dRatioY = (double)sClientH / (double)sViewH;
  5497. ms_dMapRatio = MIN(dRatioX, dRatioY);
  5498. RRect rcClip(sClientX, sClientY, sClientW, sClientH);
  5499. rspBlitT(
  5500. &imFilm, // Src.
  5501. &(ms_pguiMapZone->m_im), // Dst.
  5502. sClientX, // Dst x.
  5503. sClientY, // Dst y.
  5504. ms_dMapRatio, // Scale x.
  5505. ms_dMapRatio, // Scale y.
  5506. &rcClip); // Dst clip.
  5507. }
  5508. else
  5509. {
  5510. TRACE("RefreshMap(): Failed to allocate image at size of the realm.\n");
  5511. }
  5512. }
  5513. }
  5514. ////////////////////////////////////////////////////////////////////////////////
  5515. // Cancel any thing drag.
  5516. ////////////////////////////////////////////////////////////////////////////////
  5517. static void CancelDrag(CRealm* prealm) // Returns nothing.
  5518. {
  5519. // If there is an item being moved . . .
  5520. if (ms_sMoving != FALSE)
  5521. {
  5522. DelThing(ms_pthingSel, ms_photSel, prealm);
  5523. ms_sMoving = FALSE;
  5524. rspShowMouseCursor();
  5525. }
  5526. }
  5527. ////////////////////////////////////////////////////////////////////////////////
  5528. // Place any thing being dragged.
  5529. ////////////////////////////////////////////////////////////////////////////////
  5530. static void DragDrop( // Returns nothing.
  5531. short sDropX, // In: Drop x position.
  5532. short sDropY, // In: Drop y position.
  5533. short sDropZ) // In: Drop z position.
  5534. {
  5535. // If there is an item being moved . . .
  5536. if (ms_sMoving != FALSE)
  5537. {
  5538. ASSERT(ms_pthingSel != NULL);
  5539. ASSERT(ms_photSel != NULL);
  5540. // Final position.
  5541. MoveThing(
  5542. ms_pthingSel,
  5543. ms_photSel,
  5544. sDropX,
  5545. sDropY,
  5546. sDropZ);
  5547. SetSel(NULL, NULL);
  5548. ms_sMoving = FALSE;
  5549. rspShowMouseCursor();
  5550. }
  5551. }
  5552. ////////////////////////////////////////////////////////////////////////////////
  5553. // Called by the menu callback when it wants to tell the editor to continue
  5554. // editting (end the menu).
  5555. ////////////////////////////////////////////////////////////////////////////////
  5556. extern void Edit_Menu_Continue(void)
  5557. {
  5558. StopMenu();
  5559. // Restore our favorite font...size is no matter.
  5560. RGuiItem::ms_print.SetFont(15, &EDITOR_GUI_FONT);
  5561. }
  5562. ////////////////////////////////////////////////////////////////////////////////
  5563. // Called by the menu callback when it wants to tell the editor to quit the
  5564. // editor.
  5565. ////////////////////////////////////////////////////////////////////////////////
  5566. extern void Edit_Menu_ExitEditor(void)
  5567. {
  5568. ms_lPressedId = GUI_ID_EXIT;
  5569. StopMenu();
  5570. // Restore our favorite font...size is no matter.
  5571. RGuiItem::ms_print.SetFont(15, &EDITOR_GUI_FONT);
  5572. }
  5573. ////////////////////////////////////////////////////////////////////////////////
  5574. // Convert a .RLM filename to a .RGN one.
  5575. ////////////////////////////////////////////////////////////////////////////////
  5576. static void RlmNameToRgnName( // Returns nothing.
  5577. char* pszRealmName, // In: .RLM name.
  5578. char* pszRgnName) // Out: .RGN name.
  5579. {
  5580. short sIndex = strlen(pszRealmName);
  5581. while (sIndex-- >= 0)
  5582. {
  5583. if (pszRealmName[sIndex] == '\\')
  5584. {
  5585. sIndex = strlen(pszRealmName);
  5586. break;
  5587. }
  5588. if (pszRealmName[sIndex] == '.')
  5589. {
  5590. break;
  5591. }
  5592. }
  5593. if (sIndex < 0)
  5594. {
  5595. sIndex = strlen(pszRealmName);
  5596. }
  5597. strncpy(pszRgnName, pszRealmName, sIndex);
  5598. pszRgnName[sIndex] = '\0';
  5599. strcat(pszRgnName, ".rgn");
  5600. }
  5601. ////////////////////////////////////////////////////////////////////////////////
  5602. // Move focus to next item in realm's thing list.
  5603. ////////////////////////////////////////////////////////////////////////////////
  5604. static void NextItem( // Returns nothing.
  5605. CRealm* prealm) // In: The realm we want the next thing in.
  5606. {
  5607. if (ms_pthingSel != NULL)
  5608. {
  5609. // This may make ms_pthingSel NULL.
  5610. SetSel(ms_pthingSel->m_everything.GetNext(), NULL);
  5611. }
  5612. if (ms_pthingSel == NULL)
  5613. {
  5614. SetSel(prealm->m_everythingHead.GetNext(), NULL);
  5615. }
  5616. }
  5617. ////////////////////////////////////////////////////////////////////////////////
  5618. // Move focus to previous item in realm's thing list.
  5619. ////////////////////////////////////////////////////////////////////////////////
  5620. static void PrevItem( // Returns nothing.
  5621. CRealm* prealm) // In: The realm we want the next thing in.
  5622. {
  5623. if (ms_pthingSel != NULL)
  5624. {
  5625. // This may make ms_pthingSel NULL.
  5626. SetSel(ms_pthingSel->m_everything.GetPrev(), NULL);
  5627. }
  5628. if (ms_pthingSel == NULL)
  5629. {
  5630. SetSel(prealm->m_everythingTail.GetPrev(), NULL);
  5631. }
  5632. }
  5633. ////////////////////////////////////////////////////////////////////////////////
  5634. // Load the trigger regions for the specified realm.
  5635. ////////////////////////////////////////////////////////////////////////////////
  5636. static short LoadTriggerRegions( // Returns 0 on success.
  5637. char* pszRealmName) // In: Name of the REALM (*.RLM) file.
  5638. // The .ext is stripped and .rgn is appended.
  5639. {
  5640. short sRes = 0; // Assume success.
  5641. // Change filename to .RGN name.
  5642. char szRgnName[RSP_MAX_PATH];
  5643. RlmNameToRgnName(pszRealmName, szRgnName);
  5644. RFile file;
  5645. if (file.Open(szRgnName, "rb", RFile::LittleEndian) == 0)
  5646. {
  5647. short i;
  5648. for (i = 0; i < NUM_ELEMENTS(ms_argns) && sRes == 0; i++)
  5649. {
  5650. sRes = ms_argns[i].Load(&file);
  5651. }
  5652. file.Close();
  5653. }
  5654. else
  5655. {
  5656. TRACE("LoadTriggerRegions(): WARNING: \"%s\" could not be opened.\n", szRgnName);
  5657. sRes = 1;
  5658. }
  5659. return sRes;
  5660. }
  5661. ////////////////////////////////////////////////////////////////////////////////
  5662. // Save the trigger regions for the specified realm.
  5663. ////////////////////////////////////////////////////////////////////////////////
  5664. static short SaveTriggerRegions( // Returns 0 on success.
  5665. char* pszRealmName, // In: Name of the REALM (*.RLM) file.
  5666. CRealm* prealm // In: Access of Realm Info
  5667. ) // The .ext is stripped and .rgn is appended.
  5668. {
  5669. short sRes = 0; // Assume success.
  5670. // Change filename to .RGN name.
  5671. char szRgnName[RSP_MAX_PATH];
  5672. RlmNameToRgnName(pszRealmName, szRgnName);
  5673. RFile file;
  5674. if (file.Open(szRgnName, "wb", RFile::LittleEndian) == 0)
  5675. {
  5676. short i;
  5677. for (i = 0; i < NUM_ELEMENTS(ms_argns) && sRes == 0; i++)
  5678. {
  5679. sRes = ms_argns[i].Save(&file);
  5680. }
  5681. file.Close();
  5682. }
  5683. else
  5684. {
  5685. TRACE("SaveTriggerRegions(): Could not open \"%s\" for write.\n", szRgnName);
  5686. sRes = -1;
  5687. }
  5688. return sRes;
  5689. }
  5690. ////////////////////////////////////////////////////////////////////////////////
  5691. // Create an attribute map for the trigger regions for the specified realm.
  5692. // (And attaches it to the Realm for saving...)
  5693. // The current technique is that the CREALM must ALWAYS have a cTrigger in it,
  5694. // which in itself contains the pointer m_pmgi.
  5695. ////////////////////////////////////////////////////////////////////////////////
  5696. static short CreateTriggerRegions( // Returns 0 on success.
  5697. CRealm* prealm // In: Access of Realm Info
  5698. )
  5699. {
  5700. short sRes = 0; // Assume success.
  5701. if (prealm->m_pTriggerMapHolder == NULL)
  5702. {
  5703. short sResult;
  5704. TRACE("CreateTriggerRegions(): No default CThing to hold triggers!\n");
  5705. TRACE("CreateTriggerRegions(): Adding one for your convenience!\n");
  5706. CThing* pThing = NULL;
  5707. RHot* photdummy;
  5708. sResult = CreateNewThing(prealm, CThing::CTriggerID, 0, 0, 0, &pThing, &photdummy);
  5709. if (sResult == 0)
  5710. {
  5711. prealm -> m_pTriggerMap = ((CTrigger*)pThing)->m_pmgi;
  5712. }
  5713. else
  5714. {
  5715. TRACE("CreateTriggerRegions(): I really, REALLY tried, but there won't be trigger info\n");
  5716. return -1;
  5717. }
  5718. }
  5719. // REMOVE THE OLD TRIGGER MAP!
  5720. if (prealm->m_pTriggerMap) delete prealm->m_pTriggerMap;
  5721. prealm->m_pTriggerMap = NULL;
  5722. ////////////////////////////////////////////////////////////////////////////////
  5723. // Create, Compress, and Save the trigger attribute map for the specified realm.
  5724. ////////////////////////////////////////////////////////////////////////////////
  5725. RMultiGridIndirect* pTriggers = NULL;
  5726. // Let's try going with a maximum of EIGHT overlapping regions for now.
  5727. // And we'll try 32 x 32 tiles for now. Assume tries largest to smallest.
  5728. pTriggers = CreateRegionMap(prealm->m_phood->GetWidth(),
  5729. prealm->m_phood->GetHeight(),8, 32,32);
  5730. if (!pTriggers)
  5731. {
  5732. TRACE("CreateTriggerRegions(): Could not create region attributes!\n");
  5733. sRes = -1;
  5734. }
  5735. else
  5736. {
  5737. if (StrafeAddRegion(pTriggers,ms_argns))
  5738. {
  5739. TRACE("CreateTriggerRegions(): Problem adding attributes!\n");
  5740. sRes = -1;
  5741. delete pTriggers;
  5742. }
  5743. else
  5744. {
  5745. // Create a seondary palette table index
  5746. for (short i = 0;i < 256; i++)
  5747. {
  5748. prealm->m_asPylonUIDs[i] = 0;
  5749. prealm->m_pTriggerMapHolder->m_ausPylonUIDs[i] = 0;
  5750. if (ms_argns[i].pimRgn)
  5751. {
  5752. prealm->m_asPylonUIDs[i] = ms_argns[i].u16InstanceId;
  5753. // Set into the CThing, thich for now is what REALLY counts!
  5754. prealm->m_pTriggerMapHolder->m_ausPylonUIDs[i] = ms_argns[i].u16InstanceId;
  5755. }
  5756. }
  5757. // again, need interactive logic!
  5758. if (CompressMap(pTriggers,16,16) != SUCCESS)
  5759. {
  5760. TRACE("CreateTriggerRegions(): Problem compressing attributes!\n");
  5761. sRes = -1;
  5762. delete pTriggers;
  5763. }
  5764. else
  5765. {
  5766. // Instead os saving it, make it part of the realm:
  5767. // Then, when the realm is saved, so will it be
  5768. // FINALLY, INSTALL IT INTO THE REALM
  5769. // Add it using the official member:
  5770. prealm->m_pTriggerMapHolder->AddData(pTriggers);
  5771. }
  5772. }
  5773. }
  5774. return sRes;
  5775. }
  5776. ////////////////////////////////////////////////////////////////////////////////
  5777. // Change or clear the current pylon being edited.
  5778. ////////////////////////////////////////////////////////////////////////////////
  5779. static void EditPylonTriggerRegion( // Returns nothing.
  5780. CThing* pthingPylon) // In: Pylon whose trigger area we want to
  5781. {
  5782. // If there's a current pylon being edited . . .
  5783. if (ms_pylonEdit != NULL)
  5784. {
  5785. // Remove sprite from scene.
  5786. ms_pylonEdit->m_pRealm->m_scene.RemoveSprite(&ms_spriteTriggerRgn);
  5787. ms_spriteTriggerRgn.m_pImage = NULL;
  5788. // Put it into storage mode.
  5789. ms_argns[ms_pylonEdit->m_ucID].SetMode(TriggerRgn::Storage);
  5790. // Clear.
  5791. ms_pylonEdit = NULL;
  5792. // Show mouse.
  5793. rspShowMouseCursor();
  5794. }
  5795. // If there's a new pylon . . .
  5796. if (pthingPylon != NULL)
  5797. {
  5798. ASSERT(pthingPylon->GetClassID() == CThing::CPylonID);
  5799. CPylon* pylon = (CPylon*)pthingPylon;
  5800. // If the region did not previously exist . . .
  5801. if (ms_argns[pylon->m_ucID].pimRgn == NULL)
  5802. {
  5803. // Set location by mapping 3D pylon position to viewing surface
  5804. // position.
  5805. pthingPylon->m_pRealm->Map3Dto2D(
  5806. pylon->GetX(),
  5807. 0,
  5808. pylon->GetZ(),
  5809. &(ms_argns[pylon->m_ucID].sX),
  5810. &(ms_argns[pylon->m_ucID].sY) );
  5811. ms_argns[pylon->m_ucID].sX -= TriggerRgn::MaxRgnWidth / 2;
  5812. ms_argns[pylon->m_ucID].sY -= TriggerRgn::MaxRgnHeight / 2;
  5813. ms_argns[pylon->m_ucID].u16InstanceId = pylon->GetInstanceID();
  5814. }
  5815. // Attempt to put it into edit mode . . .
  5816. if (ms_argns[pylon->m_ucID].SetMode(TriggerRgn::Edit) == 0)
  5817. {
  5818. ms_spriteTriggerRgn.m_pImage = ms_argns[pylon->m_ucID].pimRgn;
  5819. ms_spriteTriggerRgn.m_sLayer = CRealm::LayerSprite16;
  5820. ms_spriteTriggerRgn.m_sPriority = 32767; // Always on top.
  5821. ms_spriteTriggerRgn.m_sX2 = ms_argns[pylon->m_ucID].sX;
  5822. ms_spriteTriggerRgn.m_sY2 = ms_argns[pylon->m_ucID].sY;
  5823. // Add sprite to scene.
  5824. pylon->m_pRealm->m_scene.UpdateSprite(&ms_spriteTriggerRgn);
  5825. // Success. Remember.
  5826. ms_pylonEdit = pylon;
  5827. // Hide mouse.
  5828. rspHideMouseCursor();
  5829. }
  5830. }
  5831. }
  5832. ////////////////////////////////////////////////////////////////////////////////
  5833. // Set the selection to the specified CThing.
  5834. ////////////////////////////////////////////////////////////////////////////////
  5835. static CThing* SetSel( // Returns CThing that previously was selected.
  5836. CThing* pthingSel, // In: CThing to be selected.
  5837. RHot* photSel) // In: Hotbox of CThing to be selected.
  5838. {
  5839. CThing* pthingRes = ms_pthingSel;
  5840. ms_pthingSel = pthingSel;
  5841. ms_photSel = photSel;
  5842. // If this is an actual CThing . . .
  5843. if (ms_pthingSel != NULL)
  5844. {
  5845. // Don't allow GUI focus.
  5846. RGuiItem::SetFocus(NULL);
  5847. // If the corresponding hotbox was not specified . . .
  5848. if (photSel == NULL)
  5849. {
  5850. // Get it.
  5851. ms_photSel = ms_pthingSel->m_phot;
  5852. }
  5853. }
  5854. UpdateSelectionInfo(true);
  5855. return pthingRes;
  5856. }
  5857. ////////////////////////////////////////////////////////////////////////////////
  5858. // Delete the specified item.
  5859. ////////////////////////////////////////////////////////////////////////////////
  5860. static void DelThing( // Returns nothing.
  5861. CThing* pthingDel, // In: CThing to be deleted.
  5862. RHot* photDel, // In: Hotbox of CThing to be deleted.
  5863. CRealm* prealm) // In: Current Realm
  5864. {
  5865. if (pthingDel != NULL)
  5866. {
  5867. // If hot not specified . . .
  5868. if (photDel == NULL)
  5869. {
  5870. photDel = pthingDel->m_phot;
  5871. }
  5872. CNavigationNet* pNavNet = NULL;
  5873. switch (pthingDel->GetClassID())
  5874. {
  5875. case CThing::CHoodID:
  5876. // *** LOCALIZE ***
  5877. rspMsgBox(
  5878. RSP_MB_ICN_STOP | RSP_MB_BUT_OK,
  5879. "Delete Hood",
  5880. "You may not delete the hood.");
  5881. SetSel(NULL, NULL);
  5882. pthingDel = NULL;
  5883. photDel = NULL;
  5884. break;
  5885. case CThing::CGameEditThingID:
  5886. // *** LOCALIZE ***
  5887. rspMsgBox(
  5888. RSP_MB_ICN_STOP | RSP_MB_BUT_OK,
  5889. "Delete Hood",
  5890. "You may not delete the CGameEditThing.");
  5891. SetSel(NULL, NULL);
  5892. pthingDel = NULL;
  5893. photDel = NULL;
  5894. break;
  5895. case CThing::CPylonID:
  5896. // Destroy its associated trigger region.
  5897. ms_argns[((CPylon*)pthingDel)->m_ucID].Destroy();
  5898. break;
  5899. case CThing::CBouyID:
  5900. // If it is a Bouy, unlink the bouy from the network and
  5901. // update the network.
  5902. ((CBouy*) ms_pthingSel)->Unlink();
  5903. pNavNet = prealm->GetCurrentNavNet();
  5904. pNavNet->RemoveBouy(((CBouy*) ms_pthingSel)->m_ucID);
  5905. pNavNet->UpdateRoutingTables();
  5906. // If you deleted one that the connection line was being
  5907. // drawn to, then clear the connection line.
  5908. if ((CBouy*) ms_pthingSel == m_pBouyLink0 ||
  5909. (CBouy*) ms_pthingSel == m_pBouyLink1)
  5910. m_pBouyLink0 = m_pBouyLink1 = NULL;
  5911. // If the network lines are being shown, update them, otherwise
  5912. // they will get updated when view lines is turned on.
  5913. if (ms_bDrawNetwork)
  5914. UpdateNetLines(pNavNet);
  5915. break;
  5916. case CThing::CNavigationNetID:
  5917. // If it is a NavNet, delete all of the Bouys associated
  5918. // with the NavNet. Make sure its not the last NavNet,
  5919. // and make sure there is still a current NavNet for the
  5920. // realm after it is deleted.
  5921. if (prealm->m_asClassNumThings[CThing::CNavigationNetID] > 1)
  5922. {
  5923. // Remove the Net from the list box
  5924. RListBox* plbRemove = (RListBox*) ms_pguiNavNets->GetItemFromId(GUI_ID_NAVNET_LIST);
  5925. plbRemove->RemoveItem(plbRemove->GetItemFromId(ms_pthingSel->GetInstanceID()));
  5926. plbRemove->Compose();
  5927. // Delete the network and select a new current Net if this was the one.
  5928. ((CNavigationNet*) ms_pthingSel)->DeleteNetwork();
  5929. if (ms_pthingSel == prealm->GetCurrentNavNet())
  5930. {
  5931. CListNode<CThing>* pNext = prealm->m_aclassHeads[CThing::CNavigationNetID].m_pnNext;
  5932. bool bSearching = true;
  5933. CNavigationNet* pNet = NULL;
  5934. while (bSearching && pNext->m_powner != NULL)
  5935. {
  5936. pNet = (CNavigationNet*) pNext->m_powner;
  5937. if (ms_pthingSel != pNet)
  5938. {
  5939. pNet->SetAsDefault();
  5940. bSearching = false;
  5941. RListBox* plb = (RListBox*) ms_pguiNavNets->GetItemFromId(GUI_ID_NAVNET_LIST);
  5942. plb->SetSel(plb->GetItemFromId(pNet->GetInstanceID()));
  5943. UpdateNetLines(pNet);
  5944. }
  5945. pNext = pNext->m_pnNext;
  5946. }
  5947. }
  5948. if (ms_bDrawNetwork)
  5949. UpdateNetLines((CNavigationNet*) ms_pthingSel);
  5950. }
  5951. else
  5952. {
  5953. // *** LOCALIZE ***
  5954. rspMsgBox(RSP_MB_ICN_STOP | RSP_MB_BUT_OK,
  5955. "Delete Navigation Net",
  5956. "You may not delete the last remaining Navigation Net.");
  5957. SetSel(NULL, NULL);
  5958. pthingDel = NULL;
  5959. photDel = NULL;
  5960. }
  5961. break;
  5962. }
  5963. // If we still have anything to delete . . .
  5964. if (pthingDel)
  5965. {
  5966. // If there is an editor thing . . .
  5967. if (ms_pgething != NULL)
  5968. {
  5969. // If this item was being tracked by camera . . .
  5970. if (pthingDel->GetInstanceID() == ms_pgething->m_u16CameraTrackId)
  5971. {
  5972. // Done with that.
  5973. ms_pgething->m_u16CameraTrackId = CIdBank::IdNil;
  5974. }
  5975. }
  5976. // If this is the selection . . .
  5977. if (pthingDel == ms_pthingSel)
  5978. {
  5979. SetSel(NULL, NULL);
  5980. }
  5981. }
  5982. // If we were moving . . .
  5983. if (ms_sMoving != FALSE)
  5984. {
  5985. // If nothing left to move . . .
  5986. if (ms_pthingSel == NULL)
  5987. {
  5988. // Stop moving.
  5989. ms_sMoving = FALSE;
  5990. // Show mouse cursor.
  5991. rspShowMouseCursor();
  5992. }
  5993. }
  5994. }
  5995. // Safe if NULL.
  5996. delete pthingDel;
  5997. delete photDel;
  5998. }
  5999. ////////////////////////////////////////////////////////////////////////////////
  6000. // Delete all the items in the currently selected class.
  6001. ////////////////////////////////////////////////////////////////////////////////
  6002. static void DelClass( // Returns nothing.
  6003. CThing* pthingDel, // In: CThing to be deleted.
  6004. CRealm* prealm) // In: Current realm
  6005. {
  6006. char szTitle[512];
  6007. sprintf(
  6008. szTitle,
  6009. "Delete entire \"%s\" class",
  6010. (pthingDel != NULL)
  6011. ? CThing::ms_aClassInfo[pthingDel->GetClassID()].pszClassName
  6012. : "CThing"
  6013. );
  6014. // VERIFY . . .
  6015. if (rspMsgBox(
  6016. RSP_MB_ICN_QUERY | RSP_MB_BUT_YESNO,
  6017. szTitle,
  6018. "Are you sure you want to perform this group delete?!"
  6019. ) == RSP_MB_RET_YES)
  6020. {
  6021. CListNode<CThing>* plnDel;
  6022. CListNode<CThing>* plnTail;
  6023. // If thing specified . . .
  6024. if (pthingDel != NULL)
  6025. {
  6026. // Use category of item.
  6027. plnDel = prealm->m_aclassHeads[pthingDel->GetClassID()].m_pnNext;
  6028. plnTail = &(prealm->m_aclassTails[pthingDel->GetClassID()]);
  6029. }
  6030. else
  6031. {
  6032. // Use all CThings.
  6033. plnDel = prealm->m_everythingHead.m_pnNext;
  6034. plnTail = &(prealm->m_everythingTail);
  6035. }
  6036. CListNode<CThing>* plnNext;
  6037. while (plnDel != plnTail)
  6038. {
  6039. plnNext = plnDel->m_pnNext;
  6040. DelThing(plnDel->m_powner, NULL, prealm);
  6041. plnDel = plnNext;
  6042. }
  6043. }
  6044. }
  6045. ////////////////////////////////////////////////////////////////////////////////
  6046. // Delete all but the pylons, bouys, soundthings and soundrelays.
  6047. // This is useful for making a template of a level that is already fully \
  6048. // populated.
  6049. ////////////////////////////////////////////////////////////////////////////////
  6050. static void DelMost( // Returns nothing.
  6051. CRealm* prealm) // In: Current realm
  6052. {
  6053. char szTitle[512];
  6054. sprintf(
  6055. szTitle,
  6056. "Delete Everything except bouys, pylons, warps, soundthings and soundrelays?"
  6057. );
  6058. // VERIFY . . .
  6059. if (rspMsgBox(
  6060. RSP_MB_ICN_QUERY | RSP_MB_BUT_YESNO,
  6061. szTitle,
  6062. "Are you sure you want to perform such a delete?"
  6063. ) == RSP_MB_RET_YES)
  6064. {
  6065. CListNode<CThing>* plnDel;
  6066. CListNode<CThing>* plnTail;
  6067. CThing::ClassIDType classType;
  6068. // Use all CThings.
  6069. plnDel = prealm->m_everythingHead.m_pnNext;
  6070. plnTail = &(prealm->m_everythingTail);
  6071. CListNode<CThing>* plnNext;
  6072. while (plnDel != plnTail)
  6073. {
  6074. plnNext = plnDel->m_pnNext;
  6075. classType = plnDel->m_powner->GetClassID();
  6076. switch (classType)
  6077. {
  6078. default:
  6079. DelThing(plnDel->m_powner, NULL, prealm);
  6080. break;
  6081. case CThing::CHoodID:
  6082. case CThing::CPylonID:
  6083. case CThing::CBouyID:
  6084. case CThing::CNavigationNetID:
  6085. case CThing::CSoundThingID:
  6086. case CThing::CSndRelayID:
  6087. case CThing::CGameEditThingID:
  6088. case CThing::CWarpID:
  6089. break;
  6090. }
  6091. plnDel = plnNext;
  6092. }
  6093. }
  6094. }
  6095. ////////////////////////////////////////////////////////////////////////////////
  6096. // Copy a thing to the paste buffer.
  6097. ////////////////////////////////////////////////////////////////////////////////
  6098. static short CopyItem( // Returns 0 on success.
  6099. CThing* pthingCopy) // In: CThing to copy.
  6100. {
  6101. short sRes = 0; // Assume success.
  6102. // If anything to copy . . .
  6103. if (pthingCopy != NULL)
  6104. {
  6105. // Switch for exceptions by type.
  6106. switch (pthingCopy->GetClassID() )
  6107. {
  6108. case CThing::CBouyID:
  6109. case CThing::CPylonID:
  6110. case CThing::CNavigationNetID:
  6111. case CThing::CHoodID:
  6112. rspMsgBox(
  6113. RSP_MB_ICN_INFO | RSP_MB_BUT_OK,
  6114. "Cannot Copy",
  6115. "Cannot Copy %s",
  6116. CThing::ms_aClassInfo[pthingCopy->GetClassID()].pszClassName);
  6117. break;
  6118. default:
  6119. {
  6120. // If paste buffer open . . .
  6121. if (ms_filePaste.IsOpen() != FALSE)
  6122. {
  6123. ms_filePaste.Close();
  6124. }
  6125. // Open paste buffer.
  6126. if (ms_filePaste.Open(
  6127. PASTE_BUFFER_INITIAL_SIZE,
  6128. PASTE_BUFFER_GROW_SIZE,
  6129. RFile::NeutralEndian) == 0)
  6130. {
  6131. if (pthingCopy->Save(&ms_filePaste, ms_sFileCount--) == 0)
  6132. {
  6133. // Success. Store the type.
  6134. ms_idPaste = pthingCopy->GetClassID();
  6135. }
  6136. else
  6137. {
  6138. TRACE("CopyItem(): pthingCopy->Save() failed.\n");
  6139. sRes = -2;
  6140. }
  6141. }
  6142. else
  6143. {
  6144. TRACE("CopyItem(): Failed to open paste buffer.\n");
  6145. sRes = -1;
  6146. }
  6147. break;
  6148. }
  6149. }
  6150. // If any errors . . .
  6151. if (sRes != 0)
  6152. {
  6153. ms_filePaste.Close();
  6154. }
  6155. }
  6156. else
  6157. {
  6158. sRes = 1;
  6159. }
  6160. return sRes;
  6161. }
  6162. ////////////////////////////////////////////////////////////////////////////////
  6163. // Copy a thing to the paste buffer.
  6164. ////////////////////////////////////////////////////////////////////////////////
  6165. static short PasteItem( // Returns 0 on success.
  6166. CRealm* prealm, // In: The realm to paste into.
  6167. short sX, // In: Location for new thing.
  6168. short sY, // In: Location for new thing.
  6169. short sZ) // In: Location for new thing.
  6170. {
  6171. short sRes = 0; // Assume success.
  6172. // Drop anything we currently are holding onto.
  6173. DragDrop(
  6174. sX,
  6175. sY,
  6176. sZ);
  6177. // If open . . .
  6178. if (ms_filePaste.IsOpen() != FALSE)
  6179. {
  6180. // Go to beginning.
  6181. ms_filePaste.Seek(0, SEEK_SET);
  6182. // Create the thing using the paste buffer . . .
  6183. if (CreateNewThing( // Returns 0 on success.
  6184. prealm, // Realm to create in.
  6185. ms_idPaste, // ID to create.
  6186. sX, // x
  6187. sY, // y
  6188. sZ, // z
  6189. &ms_pthingSel, // New thing.
  6190. &ms_photSel, // New hotbox for thing.
  6191. &ms_filePaste) == 0) // RFile src.
  6192. {
  6193. // Success.
  6194. // Start moving/placing object.
  6195. ms_sMoving = TRUE;
  6196. // Disable drag view scrolling.
  6197. ms_bDragScroll = false;
  6198. // Enter drag. Cheesy...Just need to get this to Bill and
  6199. // Then I'll clean up.
  6200. ms_sDragState = 4;
  6201. if (rspGetMouseCursorShowLevel() > 0)
  6202. {
  6203. rspHideMouseCursor();
  6204. }
  6205. }
  6206. else
  6207. {
  6208. TRACE("PasteItem(): CreateNewThing() failed.\n");
  6209. sRes = -1;
  6210. }
  6211. }
  6212. return sRes;
  6213. }
  6214. ////////////////////////////////////////////////////////////////////////////////
  6215. // Map a screen coordinate to a realm coordinate.
  6216. // Note that this function's *psRealmY output is always
  6217. // the height specified by the realm's attribute map
  6218. // at the resulting *psRealmX, *psRealmZ.
  6219. ////////////////////////////////////////////////////////////////////////////////
  6220. static void MapScreen2Realm( // Returns nothing.
  6221. CRealm* prealm, // In: Realm.
  6222. CCamera* pcamera, // In: View of prealm.
  6223. short sScreenX, // In: Screen x coord.
  6224. short sScreenY, // In: Screen y coord.
  6225. short* psRealmX, // Out: Realm x coord.
  6226. short* psRealmY, // Out: Realm y coord (always via realm's height map).
  6227. short* psRealmZ) // Out: Realm z coord.
  6228. {
  6229. // Get coordinate on 2D viewing plane.
  6230. short sRealmX2 = sScreenX + pcamera->m_sScene2FilmX;
  6231. short sRealmY2 = sScreenY + pcamera->m_sScene2FilmY;
  6232. // If there's a hood . . .
  6233. if (prealm->m_phood != NULL)
  6234. {
  6235. // Map to realm's X/Z plane:
  6236. // Z is stretched.
  6237. prealm->MapY2DtoZ3D(sRealmY2, psRealmZ);
  6238. // X is trivial.
  6239. *psRealmX = sRealmX2;
  6240. // If there is an attribute map . . .
  6241. if (prealm->m_pTerrainMap != NULL)
  6242. {
  6243. // The realm y is the height indicated by the attribute map
  6244. // in the given location on the X/Z plane.
  6245. *psRealmY = prealm->GetHeight(
  6246. *psRealmX,
  6247. *psRealmZ);
  6248. }
  6249. else
  6250. {
  6251. // Safety.
  6252. *psRealmY = 0;
  6253. }
  6254. }
  6255. else
  6256. {
  6257. // Safety.
  6258. *psRealmX = sRealmX2;
  6259. *psRealmY = 0;
  6260. *psRealmZ = sRealmY2;
  6261. }
  6262. }
  6263. ////////////////////////////////////////////////////////////////////////////////
  6264. // Map a realm coordinate to a screen coordinate.
  6265. ////////////////////////////////////////////////////////////////////////////////
  6266. static void Maprealm2Screen( // Returns nothing.
  6267. CRealm* prealm, // In: Realm.
  6268. CCamera* pcamera, // In: View of prealm.
  6269. short sRealmX, // In: Realm x coord.
  6270. short sRealmY, // In: Realm y coord.
  6271. short sRealmZ, // In: Realm z coord.
  6272. short* psScreenX, // Out: Screen x coord.
  6273. short* psScreenY) // Out: Screen y coord.
  6274. {
  6275. // Map coordinate onto 2D viewing plane.
  6276. short sViewX2;
  6277. short sViewY2;
  6278. prealm->Map3Dto2D(
  6279. sRealmX,
  6280. sRealmY,
  6281. sRealmZ,
  6282. &sViewX2,
  6283. &sViewY2);
  6284. // Offset to screen.
  6285. *psScreenX = sViewX2 - pcamera->m_sScene2FilmX;
  6286. *psScreenY = sViewY2 - pcamera->m_sScene2FilmY;
  6287. }
  6288. ////////////////////////////////////////////////////////////////////////////////
  6289. // Blit attribute areas lit by the specified mask into the specified image.
  6290. ////////////////////////////////////////////////////////////////////////////////
  6291. static void AttribBlit( // Returns nothing.
  6292. RMultiGrid* pmg, // In: Multigrid of attributes.
  6293. U16 u16Mask, // In: Mask of important attributes.
  6294. RImage* pimDst, // In: Destination image.
  6295. short sSrcX, // In: Where in Multigrid to start.
  6296. short sSrcY, // In: Where in Multigrid to start.
  6297. short sW, // In: How much of multigrid to use.
  6298. short sH) // In: How much of multigrid to use.
  6299. {
  6300. // Keep it at the edge of the film.
  6301. ms_spriteAttributes.m_sX2 = sSrcX;
  6302. ms_spriteAttributes.m_sY2 = sSrcY;
  6303. ASSERT(pimDst->m_sDepth == 8);
  6304. ASSERT(pimDst->m_sWidth >= sW);
  6305. ASSERT(pimDst->m_sHeight >= sH);
  6306. // Get dst start.
  6307. U8* pu8RowDst = pimDst->m_pData;
  6308. U8* pu8Dst;
  6309. long lPitch;
  6310. short sGridW, sGridH;
  6311. pmg->GetGridDimensions(&sGridW, &sGridH);
  6312. short sIterX;
  6313. while (sH--)
  6314. {
  6315. lPitch = pimDst->m_lPitch;
  6316. sIterX = sSrcX;
  6317. pu8Dst = pu8RowDst;
  6318. while (lPitch--)
  6319. {
  6320. if (pmg->GetVal(sIterX++, sSrcY, 0x0000) & u16Mask)
  6321. {
  6322. *pu8Dst = SHOW_ATTRIBS_DRAW_INDEX;
  6323. }
  6324. pu8Dst++;
  6325. }
  6326. pu8RowDst += pimDst->m_lPitch;
  6327. sSrcY++;
  6328. }
  6329. }
  6330. ////////////////////////////////////////////////////////////////////////////////
  6331. // Callback for attrib mask multibtns.
  6332. ////////////////////////////////////////////////////////////////////////////////
  6333. static void AttribMaskBtnPressed( // Returns nothing.
  6334. RGuiItem* pgui_pmb) // In: Ptr to the pressed GUI (which is a multibtn).
  6335. {
  6336. ASSERT(pgui_pmb->m_type == RGuiItem::MultiBtn);
  6337. RMultiBtn* pmb = (RMultiBtn*)pgui_pmb;
  6338. // Get mask to affect.
  6339. U16* pu16AttribMask = (U16*)(pmb->m_ulUserInstance);
  6340. // Add or subtract mask dependent on state.
  6341. switch (pmb->m_sState)
  6342. {
  6343. case 0: // Pressing.
  6344. break;
  6345. case 1: // Off.
  6346. *pu16AttribMask &= ~pmb->m_ulUserData;
  6347. break;
  6348. case 2: // On.
  6349. *pu16AttribMask |= pmb->m_ulUserData;
  6350. break;
  6351. }
  6352. // If we now have a mask value . . .
  6353. if (*pu16AttribMask)
  6354. {
  6355. // If there's no image . . .
  6356. if (ms_spriteAttributes.m_pImage == NULL)
  6357. {
  6358. short sErr = 0;
  6359. // Create it . . .
  6360. ms_spriteAttributes.m_pImage = new RImage;
  6361. if (ms_spriteAttributes.m_pImage)
  6362. {
  6363. sErr = SizeShowAttribsSprite();
  6364. // If an error occurred after allocating the image . . .
  6365. if (sErr)
  6366. {
  6367. delete ms_spriteAttributes.m_pImage;
  6368. ms_spriteAttributes.m_pImage = NULL;
  6369. }
  6370. }
  6371. else
  6372. {
  6373. TRACE("AttribMaskBtnPressed(): Error allocating RImage.\n");
  6374. sErr = 1;
  6375. }
  6376. // If an error occurred . . .
  6377. if (sErr)
  6378. {
  6379. // Clear mask so we don't use it later.
  6380. *pu16AttribMask = 0;
  6381. }
  6382. }
  6383. }
  6384. else
  6385. {
  6386. // If no more attribute masks . . .
  6387. if (ms_u16TerrainMask == 0 && ms_u16LayerMask == 0)
  6388. {
  6389. // If there is an image, delete it. No longer needed.
  6390. delete ms_spriteAttributes.m_pImage;
  6391. ms_spriteAttributes.m_pImage = NULL;
  6392. }
  6393. }
  6394. }
  6395. ////////////////////////////////////////////////////////////////////////////////
  6396. // Resizes the attribute sprite, if allocated.
  6397. ////////////////////////////////////////////////////////////////////////////////
  6398. static short SizeShowAttribsSprite(void) // Returns 0 on success.
  6399. {
  6400. short sRes = 0; // Assume success.
  6401. if (ms_spriteAttributes.m_pImage)
  6402. {
  6403. ms_spriteAttributes.m_pImage->DestroyData();
  6404. if (ms_spriteAttributes.m_pImage->CreateImage(
  6405. ms_pcameraCur->m_sViewW,
  6406. ms_pcameraCur->m_sViewH,
  6407. RImage::BMP8) == 0)
  6408. {
  6409. ms_spriteAttributes.m_sLayer = CRealm::LayerSprite16;
  6410. ms_spriteAttributes.m_sPriority = 32767; // Always on top.
  6411. }
  6412. else
  6413. {
  6414. TRACE("SizeShowAttribsSprite(): RImage::CreateImage() failed.\n");
  6415. sRes = -1;
  6416. }
  6417. // If an error occurred . . .
  6418. if (sRes)
  6419. {
  6420. delete ms_spriteAttributes.m_pImage;
  6421. ms_spriteAttributes.m_pImage = NULL;
  6422. }
  6423. }
  6424. return sRes;
  6425. }
  6426. ////////////////////////////////////////////////////////////////////////////////
  6427. //
  6428. // Our RFile callback
  6429. //
  6430. ////////////////////////////////////////////////////////////////////////////////
  6431. static void MyRFileCallback(long lBytes)
  6432. {
  6433. ms_lFileBytesSoFar += lBytes;
  6434. long lNow = rspGetMilliseconds();
  6435. if ((lNow - ms_lRFileCallbackTime) > MY_RFILE_CALLBACK_INTERVAL)
  6436. {
  6437. // Do an update
  6438. UpdateSystem();
  6439. // Lock the composite buffer for access.
  6440. rspLockBuffer();
  6441. // Clear area. Note that this function locks and unlocks the display
  6442. // when necessary.
  6443. rspRect(
  6444. RSP_BLACK_INDEX,
  6445. g_pimScreenBuf,
  6446. ms_sFileOpTextX,
  6447. ms_sFileOpTextY,
  6448. ms_sFileOpTextW,
  6449. ms_sFileOpTextH);
  6450. // Draw text in cleared area.
  6451. ms_printFile.print(
  6452. g_pimScreenBuf,
  6453. ms_sFileOpTextX,
  6454. ms_sFileOpTextY,
  6455. ms_szFileOpDescriptionFrmt,
  6456. ms_lFileBytesSoFar);
  6457. // Done with buffer other than to update the screen with it.
  6458. rspUnlockBuffer();
  6459. // Update the display.
  6460. rspUpdateDisplay(
  6461. ms_sFileOpTextX,
  6462. ms_sFileOpTextY,
  6463. ms_sFileOpTextW,
  6464. ms_sFileOpTextH);
  6465. // Save new time
  6466. ms_lRFileCallbackTime = rspGetMilliseconds();
  6467. }
  6468. }
  6469. ////////////////////////////////////////////////////////////////////////////////
  6470. // Init load/save counter. You should call KillFileCounter() after
  6471. // done with the file access.
  6472. ////////////////////////////////////////////////////////////////////////////////
  6473. static void InitFileCounter( // Returns nothing.
  6474. char* pszDescriptionFrmt) // In: sprintf format for description of
  6475. // operation.
  6476. {
  6477. // Make sure string (with some digits) will fit . . .
  6478. if (strlen(pszDescriptionFrmt) < sizeof(ms_szFileOpDescriptionFrmt) - 10 )
  6479. {
  6480. strcpy(ms_szFileOpDescriptionFrmt, pszDescriptionFrmt);
  6481. }
  6482. else
  6483. {
  6484. strcpy(ms_szFileOpDescriptionFrmt, "Progress: %ld bytes");
  6485. }
  6486. // Hook the RFile callback and reset the timer. The callback does nothing
  6487. // more than call Update() every once in a while, which gives the system
  6488. // a bit of time (very important on Mac) and also allows update events to
  6489. // be processed, which is nice for both Mac and Win32.
  6490. RFile::ms_criticall = MyRFileCallback;
  6491. ms_lRFileCallbackTime = rspGetMilliseconds();
  6492. ms_lFileBytesSoFar = 0;
  6493. // A little feedback would be nice.
  6494. rspSetCursor(RSP_CURSOR_WAIT);
  6495. // Setup printer.
  6496. ms_printFile.SetWordWrap(TRUE);
  6497. ms_printFile.SetJustifyLeft();
  6498. ms_printFile.SetColor(249, 0, 0);
  6499. ms_printFile.SetFont(19, &g_fontBig);
  6500. // Determine size and position of text.
  6501. // Create sample string.
  6502. char szSample[sizeof(ms_szFileOpDescriptionFrmt)];
  6503. sprintf(szSample, ms_szFileOpDescriptionFrmt, LONG_MAX);
  6504. // Just use entire width for now.
  6505. ms_sFileOpTextW = ms_printFile.GetWidth(szSample);
  6506. // Get height.
  6507. ms_printFile.GetPos(NULL, NULL, NULL, &ms_sFileOpTextH);
  6508. ms_sFileOpTextX = PROGRESS_X;
  6509. ms_sFileOpTextY = PROGRESS_Y - (ms_sFileOpTextH + 5);
  6510. RRect rect(ms_sFileOpTextX, ms_sFileOpTextY, ms_sFileOpTextW, ms_sFileOpTextH);
  6511. ms_printFile.SetDestination(g_pimScreenBuf, &rect);
  6512. // Don't need keys that occurred before the operation.
  6513. rspClearAllInputEvents();
  6514. }
  6515. ////////////////////////////////////////////////////////////////////////////////
  6516. // Kill load/save counter. Can be called multiple times w/o corresponding
  6517. // Init().
  6518. ////////////////////////////////////////////////////////////////////////////////
  6519. static void KillFileCounter(void) // Returns nothing.
  6520. {
  6521. // Unhook the RFile callback
  6522. RFile::ms_criticall = 0;
  6523. // Restore arrow cursor.
  6524. rspSetCursor(RSP_CURSOR_ARROW);
  6525. // Clear op descriptor.
  6526. ms_szFileOpDescriptionFrmt[0] = '\0';
  6527. // Don't need keys that occurred during the operation.
  6528. rspClearAllInputEvents();
  6529. }
  6530. ////////////////////////////////////////////////////////////////////////////////
  6531. // Helper function explicity for UpdateSelectionInfo().
  6532. ////////////////////////////////////////////////////////////////////////////////
  6533. inline
  6534. void SetPosInfo( // Returns nothing.
  6535. RGuiItem* pgui, // In: GUI to update. NULL is safe.
  6536. double dVal) // In: Value to udpate to GUI.
  6537. {
  6538. if (pgui)
  6539. {
  6540. if (dVal != CThing::InvalidPosition)
  6541. {
  6542. pgui->SetText("%g", dVal);
  6543. }
  6544. else
  6545. {
  6546. pgui->SetText("%s", "N/A");
  6547. }
  6548. pgui->Compose();
  6549. }
  6550. }
  6551. ////////////////////////////////////////////////////////////////////////////////
  6552. // Update selection info in the info GUI.
  6553. ////////////////////////////////////////////////////////////////////////////////
  6554. static void UpdateSelectionInfo( // Returns nothing.
  6555. bool bTitle /*= false*/) // In: true to update the title info as well.
  6556. {
  6557. if (ms_pguiInfo)
  6558. {
  6559. if (bTitle == true)
  6560. {
  6561. // Update the title info.
  6562. if (ms_pthingSel)
  6563. {
  6564. ms_pguiInfo->SetText(
  6565. "Info for \"%s\" [%u]",
  6566. CThing::ms_aClassInfo[ms_pthingSel->GetClassID()].pszClassName,
  6567. ms_pthingSel->GetInstanceID() );
  6568. }
  6569. else
  6570. {
  6571. ms_pguiInfo->SetText("No selection");
  6572. }
  6573. ms_pguiInfo->Compose();
  6574. }
  6575. // Always update other fields.
  6576. if (ms_pthingSel)
  6577. {
  6578. SetPosInfo(ms_pguiInfoXPos, ms_pthingSel->GetX() );
  6579. SetPosInfo(ms_pguiInfoYPos, ms_pthingSel->GetY() );
  6580. SetPosInfo(ms_pguiInfoZPos, ms_pthingSel->GetZ() );
  6581. }
  6582. else
  6583. {
  6584. SetPosInfo(ms_pguiInfoXPos, CThing::InvalidPosition);
  6585. SetPosInfo(ms_pguiInfoYPos, CThing::InvalidPosition);
  6586. SetPosInfo(ms_pguiInfoZPos, CThing::InvalidPosition);
  6587. }
  6588. }
  6589. }
  6590. ////////////////////////////////////////////////////////////////////////////////
  6591. //
  6592. // Get a temporary file name
  6593. //
  6594. ////////////////////////////////////////////////////////////////////////////////
  6595. static short TmpFileName( // Returns 0 if successfull, non-zero otherwise
  6596. char* pszFileName, // Out: Temp file name returned here
  6597. short sMaxSize) // In: Maximum size of file name
  6598. {
  6599. short sResult = 0;
  6600. #if defined(WIN32)
  6601. char szPath[RSP_MAX_PATH];
  6602. ULONG ulLen = GetTempPath(sizeof(szPath), szPath);
  6603. if (ulLen >= sizeof(szPath) )
  6604. {
  6605. TRACE("TmpFileName(): GetTempPath() could not fit the path and filename into our string.\n");
  6606. sResult = -1;
  6607. }
  6608. else if (ulLen == 0)
  6609. {
  6610. TRACE("TmpFileName(): GetTempPath() failed.\n");
  6611. sResult = -1;
  6612. }
  6613. if (GetTempFileName(szPath, "RLM", 0, pszFileName) == FALSE)
  6614. {
  6615. TRACE("TmpFileName(): GetTempFileName() failed.\n");
  6616. sResult = -1;
  6617. }
  6618. #else
  6619. // Impliment for some other system!
  6620. ASSERT(0);
  6621. #endif
  6622. return sResult;
  6623. }
  6624. ////////////////////////////////////////////////////////////////////////////////
  6625. // Helper for ShowRealmStatistics() to display an item position or N/A,
  6626. // if invalid.
  6627. ////////////////////////////////////////////////////////////////////////////////
  6628. inline
  6629. void Pos2Str( // Returns nothing.
  6630. double dPos, // In: CThing position.
  6631. char* pszStr) // Out: String representation.
  6632. {
  6633. if (dPos != CThing::InvalidPosition)
  6634. {
  6635. sprintf(pszStr, "%g", dPos);
  6636. }
  6637. else
  6638. {
  6639. strcpy(pszStr, "N/A");
  6640. }
  6641. }
  6642. ////////////////////////////////////////////////////////////////////////////////
  6643. // Show statistics for the specified realm.
  6644. ////////////////////////////////////////////////////////////////////////////////
  6645. static short ShowRealmStatistics( // Returns 0 on success.
  6646. CRealm* prealm, // In: Realm to get stats on.
  6647. CThing** ppthing) // Out: Selected thing, if not NULL.
  6648. {
  6649. short sRes = 0; // Assume success.
  6650. // Store cursor show level so we can restore it when done.
  6651. short sOrigCursorShowLevel = rspGetMouseCursorShowLevel();
  6652. // Set the mouse so we can see it.
  6653. rspSetMouseCursorShowLevel(1);
  6654. // Get GUI . . .
  6655. RGuiItem* pguiRoot = RGuiItem::LoadInstantiate(FullPath(GAME_PATH_VD, REALM_STATISTICS_GUI_FILE) );
  6656. if (pguiRoot)
  6657. {
  6658. // Get list box . . .
  6659. RListBox* plb = (RListBox*)pguiRoot->GetItemFromId(GUI_ID_REALM_STATISTICS);
  6660. if (plb)
  6661. {
  6662. ASSERT(plb->m_type == RGuiItem::ListBox);
  6663. // Go through the list of everything adding each item to the list.
  6664. char szThingDescription[2048];
  6665. char szX[256];
  6666. char szY[256];
  6667. char szZ[256];
  6668. double dX, dY, dZ;
  6669. long lNum = 0;
  6670. CListNode<CThing>* pthingnode = prealm->m_everythingHead.m_pnNext;
  6671. CThing* pthing;
  6672. while (pthingnode != &(prealm->m_everythingTail))
  6673. {
  6674. lNum++;
  6675. pthing = pthingnode->m_powner;
  6676. dX = pthing->GetX();
  6677. dY = pthing->GetY();
  6678. dZ = pthing->GetZ();
  6679. Pos2Str(dX, szX);
  6680. Pos2Str(dY, szY);
  6681. Pos2Str(dZ, szZ);
  6682. sprintf(
  6683. szThingDescription,
  6684. "%ld) \"%s\" ID: %u X: %s Y: %s Z: %s",
  6685. lNum,
  6686. CThing::ms_aClassInfo[pthing->GetClassID()].pszClassName,
  6687. pthing->GetInstanceID(),
  6688. szX,
  6689. szY,
  6690. szZ);
  6691. RGuiItem* pguiThing = plb->AddString(szThingDescription);
  6692. if (pguiThing)
  6693. {
  6694. // Success.
  6695. pguiThing->m_lId = (long)pthing;
  6696. }
  6697. else
  6698. {
  6699. TRACE("ShowRealmStatistics(): Error adding <<%s>> to the list box.\n", szThingDescription);
  6700. sRes = -3;
  6701. }
  6702. pthingnode = pthingnode->m_pnNext;
  6703. }
  6704. // Repaginate now.
  6705. plb->AdjustContents();
  6706. // Display until dismissed.
  6707. CThing::DoGui(pguiRoot);
  6708. if (ppthing)
  6709. {
  6710. // If there's a selection . . .
  6711. RGuiItem* pguiSel = plb->GetSel();
  6712. if (pguiSel)
  6713. {
  6714. *ppthing = (CThing*)(pguiSel->m_lId);
  6715. }
  6716. else
  6717. {
  6718. *ppthing = NULL;
  6719. }
  6720. }
  6721. }
  6722. else
  6723. {
  6724. TRACE("ShowRealmStatistics(): Failed to get realm stats listbox.\n");
  6725. sRes = -2;
  6726. }
  6727. delete pguiRoot;
  6728. pguiRoot = NULL;
  6729. }
  6730. else
  6731. {
  6732. TRACE("ShowRealmStatistics(): Failed to load realm stats GUI.\n");
  6733. sRes = -1;
  6734. }
  6735. // Clear queues.
  6736. rspClearAllInputEvents();
  6737. // Re-init input.
  6738. ClearLocalInput();
  6739. // Restore cursor show level.
  6740. rspSetMouseCursorShowLevel(sOrigCursorShowLevel);
  6741. return sRes;
  6742. }
  6743. ////////////////////////////////////////////////////////////////////////////////
  6744. // Callback from realm during time intensive operations.
  6745. ////////////////////////////////////////////////////////////////////////////////
  6746. static bool RealmOpProgress( // Returns true to continue; false to
  6747. // abort operation.
  6748. short sLastItemProcessed, // In: Number of items processed so far.
  6749. short sTotalItemsToProcess) // In: Total items to process.
  6750. {
  6751. static long lLastProgressPos;
  6752. static long lProgressX, lProgressY, lProgressW, lProgressH;
  6753. static long lLastCallTime;
  6754. // Just need to get the key status array once.
  6755. U8* pau8KeyStatus = rspGetKeyStatusArray();
  6756. bool bContinue = true; // Assume we want to continue.
  6757. // If new operation . . .
  6758. if (sLastItemProcessed == 0)
  6759. {
  6760. lLastProgressPos = 0;
  6761. lProgressX = PROGRESS_X;
  6762. lProgressY = PROGRESS_Y;
  6763. lProgressW = PROGRESS_W;
  6764. lProgressH = PROGRESS_H;
  6765. lLastCallTime = 0;
  6766. // Clear key status array.
  6767. memset(pau8KeyStatus, 0, 128);
  6768. // Lock the composite buffer for access.
  6769. rspLockBuffer();
  6770. // Draw initial outline.
  6771. rspRect(
  6772. 1,
  6773. PROGRESS_OUTLINE_COLOR_INDEX,
  6774. g_pimScreenBuf,
  6775. lProgressX - 1,
  6776. lProgressY - 1,
  6777. lProgressW + 2,
  6778. lProgressH + 2);
  6779. // Done with buffer other than to update the screen with it.
  6780. rspUnlockBuffer();
  6781. rspUpdateDisplay(
  6782. lProgressX - 1,
  6783. lProgressY - 1,
  6784. lProgressW + 2,
  6785. lProgressH + 2);
  6786. }
  6787. long lNow = rspGetMilliseconds();
  6788. if ((lNow - lLastCallTime) > PROGRESS_CALLBACK_INTERVAL)
  6789. {
  6790. // Do an update
  6791. UpdateSystem();
  6792. // Compute new position.
  6793. long lNewProgressPos;
  6794. if (sTotalItemsToProcess > 0)
  6795. {
  6796. lNewProgressPos = (long)sLastItemProcessed * lProgressW / (long)sTotalItemsToProcess;
  6797. }
  6798. else
  6799. {
  6800. lNewProgressPos = lProgressW;
  6801. }
  6802. // Lock the composite buffer.
  6803. rspLockBuffer();
  6804. rspRect(
  6805. PROGRESS_COLOR_INDEX,
  6806. g_pimScreenBuf,
  6807. lProgressX + lLastProgressPos,
  6808. lProgressY,
  6809. lNewProgressPos - lLastProgressPos,
  6810. lProgressH);
  6811. // Done with buffer other than to update the screen with it.
  6812. rspUnlockBuffer();
  6813. // Update display.
  6814. rspUpdateDisplay(
  6815. lProgressX + lLastProgressPos,
  6816. lProgressY,
  6817. lNewProgressPos - lLastProgressPos,
  6818. lProgressH);
  6819. lLastProgressPos = lNewProgressPos;
  6820. // If escape hit . . .
  6821. if (pau8KeyStatus[KEY_ABORT_REALM_OPERATION])
  6822. {
  6823. if (rspMsgBox(
  6824. RSP_MB_ICN_QUERY | RSP_MB_BUT_YESNO,
  6825. g_pszAppName,
  6826. "Are you sure you want to abort this operation?")
  6827. == RSP_MB_RET_YES)
  6828. {
  6829. bContinue = false;
  6830. }
  6831. }
  6832. // Don't use lNow here...let's not count time we spent drawing.
  6833. lLastCallTime = rspGetMilliseconds();
  6834. }
  6835. return bContinue;
  6836. }
  6837. #endif // !defined(EDITOR_DISABLED)
  6838. ////////////////////////////////////////////////////////////////////////////////
  6839. // EOF
  6840. ////////////////////////////////////////////////////////////////////////////////