123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081 |
- /**
- * @file llviewerwindow.cpp
- * @brief Implementation of the LLViewerWindow class.
- *
- * $LicenseInfo:firstyear=2001&license=viewergpl$
- *
- * Copyright (c) 2001-2009, Linden Research, Inc.
- *
- * Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
- *
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
- *
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
- *
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
- * $/LicenseInfo$
- */
- #include "llviewerprecompiledheaders.h"
- // system library includes
- #include <stdio.h>
- #include <iostream>
- #include <fstream>
- #if LL_WINDOWS
- #include <tchar.h> // For Unicode conversion methods
- #endif
- #include "llviewerwindow.h"
- #include "llapp.h"
- #include "llaudioengine.h" // gAudiop
- #include "llconsole.h"
- #include "llcubemaparray.h"
- #include "lldir.h"
- #include "llfontfreetype.h"
- #include "llimagebmp.h"
- #include "llimagedecodethread.h"
- #include "llimagegl.h"
- #include "llimagej2c.h"
- #include "llmenugl.h"
- #include "llmemory.h"
- #include "llmodaldialog.h"
- #include "llmousehandler.h"
- #include "llrender.h"
- #include "llrenderutils.h" // For gBox, gSphere
- #include "lltextbox.h"
- #include "lltrans.h"
- #include "lluictrlfactory.h"
- #include "llmessage.h"
- #include "llraytrace.h"
- #include "llagent.h"
- #include "llappviewer.h"
- #include "llchatbar.h"
- #include "lldebugview.h"
- #include "lldrawable.h"
- #include "lldrawpoolalpha.h"
- #include "lldrawpoolbump.h"
- #include "lldrawpoolwater.h"
- #include "llface.h"
- #include "llfeaturemanager.h"
- #include "llfloaterchat.h"
- #include "llfloaterchatterbox.h"
- #include "llfloatercustomize.h"
- #include "llfloatereditui.h" // HACK for UI editor
- #include "llfloaternotificationsconsole.h"
- #include "llfloatersnapshot.h"
- #include "hbfloaterteleporthistory.h"
- #include "llfloatertools.h"
- #include "llfloaterworldmap.h"
- #include "llgesturemgr.h"
- #include "llhoverview.h"
- #include "llhudtext.h"
- #include "llhudview.h"
- #include "llimmgr.h"
- #include "llmaniptranslate.h"
- #include "llmeshrepository.h"
- #include "llmorphview.h"
- #include "llnotify.h"
- #include "lloverlaybar.h"
- #include "llpanellogin.h"
- #include "llpanelworldmap.h"
- #include "llpipeline.h"
- #include "llpreviewnotecard.h" // refreshCachedSettings()
- #include "llpreviewscript.h" // refreshCachedSettings()
- #include "llprogressview.h"
- //MK
- #include "mkrlinterface.h"
- //mk
- #include "llselectmgr.h"
- #include "llsky.h" // gSky
- #include "llstartup.h"
- #include "llstatusbar.h"
- #include "llsurface.h"
- #include "lltexturecache.h"
- #include "lltexturefetch.h"
- #include "lltoolbar.h"
- #include "lltoolcomp.h"
- #include "lltooldraganddrop.h"
- #if LL_DARWIN
- # include "lltoolfocus.h"
- #endif
- #include "lltoolmgr.h"
- #include "lltoolpie.h"
- #include "llurldispatcher.h" // SLURL from other app instance
- #include "llvelocitybar.h"
- #include "llvieweraudio.h" // audio_update_volume()
- #include "hbviewerautomation.h"
- #include "llviewercamera.h"
- #include "llviewercontrol.h"
- #include "llviewerdisplay.h"
- #include "llviewergesture.h" // gGestureList
- #include "llviewerkeyboard.h"
- #include "llviewerjoystick.h"
- #include "llviewermediafocus.h"
- #include "llviewermenu.h"
- #include "llviewermessage.h" // send_sound_trigger()
- #include "llviewerobjectlist.h"
- #include "llviewerparcelmgr.h"
- #include "llviewerregion.h"
- #include "llviewershadermgr.h"
- #include "llviewerstats.h"
- #include "llviewertexturelist.h"
- #include "llvisualparamhint.h"
- #include "llvoavatarself.h"
- #include "llvoiceclient.h"
- #include "llvopartgroup.h"
- #include "llvovolume.h"
- #include "llwearablelist.h"
- #include "llworld.h"
- //
- // Globals
- //
- LLBottomPanel* gBottomPanelp = NULL;
- LLViewerWindow* gViewerWindowp = NULL;
- LLFrameTimer gMouseIdleTimer;
- LLFrameTimer gAwayTimer;
- LLFrameTimer gAwayTriggerTimer;
- LLFrameTimer gAlphaFadeTimer;
- LLViewerObject* gDebugRaycastObject = NULL;
- LLVOPartGroup* gDebugRaycastParticle = NULL;
- LLVector4a gDebugRaycastParticleIntersection;
- LLVector4a gDebugRaycastIntersection;
- LLVector2 gDebugRaycastTexCoord;
- LLVector4a gDebugRaycastNormal;
- LLVector4a gDebugRaycastTangent;
- S32 gDebugRaycastFaceHit = -1;
- S32 gDebugRaycastGLTFNodeHit = -1;
- S32 gDebugRaycastGLTFPrimHit = -1;
- LLVector4a gDebugRaycastStart;
- LLVector4a gDebugRaycastEnd;
- // HUD display lines in lower right
- bool gDisplayWindInfo = false;
- bool gDisplayCameraPos = false;
- bool gDisplayFOV = false;
- bool gSnapshotNoPost = false;
- constexpr U8 NO_FACE = 255;
- bool gQuietSnapshot = false;
- // Minimum time after setting away state before coming back:
- constexpr F32 MIN_AFK_TIME = 2.f;
- constexpr F32 MIN_DISPLAY_SCALE = 0.75f;
- // Static members
- LLStat LLViewerWindow::sMouseVelocityStat;
- std::string LLViewerWindow::sSnapshotBaseName;
- std::string LLViewerWindow::sSnapshotDir;
- std::string LLViewerWindow::sMovieBaseName;
- ////////////////////////////////////////////////////////////////////////////
- // *HACK: easy way for console.cpp to retrieve the window size...
- S32 viewer_window_width()
- {
- return gViewerWindowp ? gViewerWindowp->getWindowWidth() : 100;
- }
- S32 viewer_window_height()
- {
- return gViewerWindowp ? gViewerWindowp->getWindowHeight() : 100;
- }
- // *HACK: prevent double handling of accelerator keys...
- static KEY sLastAcceleratorKey = 0;
- ////////////////////////////////////////////////////////////////////////////
- // LLDebugText class
- ////////////////////////////////////////////////////////////////////////////
- class LLDebugText
- {
- public:
- LLDebugText()
- : mFont(LLFontGL::getFontMonospace()),
- // Draw the statistics in a light gray and in a thin font
- mTextColor(LLColor4(0.86f, 0.86f, 0.86f, 1.f)),
- mMinX(U32_MAX)
- {
- mLineHeight = mFont->getLineHeight();
- mIncY = 16 * mLineHeight / 10 + 1;
- mMaginX = 16 * mFont->getWidth(std::string("0")) / 10 + 1;
- }
- LL_INLINE void addText(U32 x, U32 y, const std::string& text)
- {
- mLineList.emplace_back(text, x, y);
- if (x < mMinX)
- {
- mMinX = x;
- }
- }
- void update()
- {
- if (!gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
- {
- // Do not display debug info when not rendering UI (important for
- // the "snapshot to disk" feature).
- return;
- }
- // Draw stuff growing up from right lower corner of screen
- U32 xpos = 0;
- U32 window_width = gViewerWindowp->getWindowWidth();
- static LLCachedControl<U32> hud_right_margin(gSavedSettings,
- "HUDInfoRightMargin");
- U32 right_margin = llmax((U32)hud_right_margin, 256U);
- if (window_width > right_margin)
- {
- xpos = window_width - right_margin;
- }
- mMaxX = window_width - mMaginX;
- U32 ypos = 20;
- if (gToolBarp && gToolBarp->getVisible())
- {
- ypos += TOOL_BAR_HEIGHT;
- }
- if (gChatBarp && gChatBarp->getVisible())
- {
- ypos += CHAT_BAR_HEIGHT;
- }
- if (gOverlayBarp && gOverlayBarp->getVisible())
- {
- ypos += OVERLAY_BAR_HEIGHT;
- }
- mMinY = ypos - mLineHeight - 4;
- static LLCachedControl<bool> debug_show_size(gSavedSettings,
- "DebugShowResizing");
- S32 size_x = 0;
- S32 size_y = 0;
- if (debug_show_size && LLFloater::resizing(size_x, size_y))
- {
- addText(window_width - 168, ypos,
- llformat("Floater size: %d x %d", size_x, size_y));
- ypos += mIncY;
- }
- static LLCachedControl<bool> debug_show_fps(gSavedSettings,
- "DebugShowFPS");
- if (debug_show_fps)
- {
- addText(window_width - 60, ypos,
- llformat("%d fps",
- (S32)(gViewerStats.mFPSStat.getMeanPerSec() +
- 0.5f)));
- ypos += mIncY;
- }
- // Avoid text collision with the velocity bar...
- mVelocityBarShown = gVelocityBarp && gVelocityBarp->getVisible();
- if (mVelocityBarShown)
- {
- ypos = VELOCITY_TOP;
- }
- static LLCachedControl<bool> debug_show_time(gSavedSettings,
- "DebugShowTime");
- if (debug_show_time)
- {
- F32 time = gTextureTimer.getElapsedTimeF32();
- S32 thours = (S32)(time / 3600);
- S32 tmins = (S32)((time - thours * 3600) / 60);
- S32 tsecs = (S32)(time - thours * 3600 - tmins * 60);
- time = gFrameTimeSeconds;
- S32 hours = (S32)(time / 3600);
- S32 mins = (S32)((time - hours * 3600) / 60);
- S32 secs = (S32)(time - hours * 3600 - mins * 60);
- addText(xpos, ypos,
- llformat("Online time: %d:%02d:%02d - Texture fecthing time: %d:%02d:%02d",
- hours, mins, secs, thours, tmins, tsecs));
- ypos += mIncY;
- }
- static LLCachedControl<bool> debug_poll_age(gSavedSettings,
- "DebugShowPollRequestAge");
- if (debug_poll_age)
- {
- LLViewerRegion* regionp = gAgent.getRegion();
- if (regionp)
- {
- mTempStr = llformat("Poll request age: %.1fs",
- regionp->getEventPollRequestAge());
- if (!regionp->isEventPollInFlight())
- {
- mTempStr.append(" *");
- }
- addText(window_width - 172, ypos, mTempStr);
- ypos += mIncY;
- }
- }
- if (gDisplayCameraPos)
- {
- // Update camera center, camera view, wind info every other frame
- LLVector3d tvector = gAgent.getPositionGlobal();
- mTempStr = llformat("AgentCenter %f %f %f",
- (F32)tvector.mdV[VX], (F32)tvector.mdV[VY],
- (F32)tvector.mdV[VZ]);
- addText(xpos, ypos, mTempStr);
- ypos += mIncY;
- if (isAgentAvatarValid())
- {
- tvector =
- gAgent.getPosGlobalFromAgent(gAgentAvatarp->mRoot->getWorldPosition());
- mTempStr = llformat("AgentRootCenter %f %f %f",
- (F32)tvector.mdV[VX], (F32)tvector.mdV[VY],
- (F32)tvector.mdV[VZ]);
- }
- else
- {
- mTempStr = "---";
- }
- addText(xpos, ypos, mTempStr);
- ypos += mIncY;
- tvector = LLVector4(gAgent.getFrameAgent().getAtAxis());
- mTempStr = llformat("AgentAtAxis %f %f %f",
- (F32)tvector.mdV[VX], (F32)tvector.mdV[VY],
- (F32)tvector.mdV[VZ]);
- addText(xpos, ypos, mTempStr);
- ypos += mIncY;
- tvector = LLVector4(gAgent.getFrameAgent().getLeftAxis());
- mTempStr = llformat("AgentLeftAxis %f %f %f",
- (F32)tvector.mdV[VX], (F32)tvector.mdV[VY],
- (F32)tvector.mdV[VZ]);
- addText(xpos, ypos, mTempStr);
- ypos += mIncY;
- tvector = gAgent.getCameraPositionGlobal();
- mTempStr = llformat("CameraCenter %f %f %f",
- (F32)tvector.mdV[VX], (F32)tvector.mdV[VY],
- (F32)tvector.mdV[VZ]);
- addText(xpos, ypos, mTempStr);
- ypos += mIncY;
- tvector = LLVector4(gViewerCamera.getAtAxis());
- mTempStr = llformat("CameraAtAxis %f %f %f",
- (F32)tvector.mdV[VX], (F32)tvector.mdV[VY],
- (F32)tvector.mdV[VZ]);
- addText(xpos, ypos, mTempStr);
- ypos += mIncY;
- mTempStr = llformat("Near clip: %f - Far clip: %f",
- gViewerCamera.getNear(),
- gViewerCamera.getFar());
- addText(xpos, ypos, mTempStr);
- ypos += mIncY;
- mTempStr = "Camera mode: ";
- #define SETENUM(E) case E: mTempStr += #E; break
- switch (gAgent.getCameraMode())
- {
- SETENUM(CAMERA_MODE_THIRD_PERSON);
- SETENUM(CAMERA_MODE_MOUSELOOK);
- SETENUM(CAMERA_MODE_CUSTOMIZE_AVATAR);
- SETENUM(CAMERA_MODE_FOLLOW);
- default:
- mTempStr += llformat("%d", gAgent.getCameraMode());
- }
- #undef SETENUM
- addText(xpos, ypos, mTempStr);
- ypos += mIncY;
- }
- if (gDisplayWindInfo)
- {
- mTempStr = llformat("Wind velocity %.2f m/s", gWindVec.length());
- addText(xpos, ypos, mTempStr);
- ypos += mIncY;
- mTempStr = llformat("Wind vector %.2f %.2f %.2f",
- gWindVec.mV[0], gWindVec.mV[1],
- gWindVec.mV[2]);
- addText(xpos, ypos, mTempStr);
- ypos += mIncY;
- mTempStr = llformat("RWind vel %.2f m/s",
- gRelativeWindVec.length());
- addText(xpos, ypos, mTempStr);
- ypos += mIncY;
- mTempStr = llformat("RWind vec %.2f %.2f %.2f",
- gRelativeWindVec.mV[0], gRelativeWindVec.mV[1],
- gRelativeWindVec.mV[2]);
- addText(xpos, ypos, mTempStr);
- ypos += mIncY;
- if (gAudiop)
- {
- mTempStr = llformat("Audio for wind: %d",
- gAudiop->isWindEnabled());
- }
- addText(xpos, ypos, mTempStr);
- ypos += mIncY;
- }
- if (gDisplayFOV)
- {
- addText(xpos, ypos,
- llformat("FOV: %2.1f deg",
- RAD_TO_DEG * gViewerCamera.getView()));
- ypos += mIncY;
- }
- #if 0
- if (LLViewerJoystick::getInstance()->getOverrideCamera())
- {
- addText(xpos + 250, ypos, "Flycam");
- ypos += mIncY;
- }
- #endif
- static LLCachedControl<bool> debug_show_render_info(gSavedSettings,
- "DebugShowRenderInfo");
- if (debug_show_render_info)
- {
- if (!gPipeline.canUseShaders())
- {
- addText(xpos, ypos, "Shaders disabled");
- ypos += mIncY;
- }
- if (gGLManager.mHasATIMemInfo)
- {
- S32 meminfo[4];
- glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, meminfo);
- addText(xpos, ypos, llformat("%.2f MB texture memory free",
- meminfo[0] / 1024.f));
- ypos += mIncY;
- glGetIntegerv(GL_VBO_FREE_MEMORY_ATI, meminfo);
- addText(xpos, ypos, llformat("%.2f MB VBO memory free",
- meminfo[0] / 1024.f));
- ypos += mIncY;
- }
- else if (gGLManager.mHasNVXMemInfo)
- {
- S32 free_memory;
- glGetIntegerv(GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX,
- &free_memory);
- addText(xpos, ypos, llformat("%.2f MB video memory free",
- free_memory / 1024.f));
- ypos += mIncY;
- }
- // Show streaming cost/triangle count of known prims in current
- // region OR selection
- {
- F32 cost = 0.f;
- S32 count = 0;
- S32 vcount = 0;
- S32 object_count = 0;
- S32 total_bytes = 0;
- S32 visible_bytes = 0;
- LLObjectSelectionHandle selected_objects =
- gSelectMgr.getSelection();
- if (selected_objects->getObjectCount() == 0)
- {
- LLViewerRegion* regionp = gAgent.getRegion();
- if (regionp)
- {
- for (U32 i = 0, count = gObjectList.getNumObjects();
- i < count; ++i)
- {
- LLViewerObject* objectp = gObjectList.getObject(i);
- if (objectp && objectp->getRegion() == regionp &&
- objectp->getVolume())
- {
- ++object_count;
- S32 bytes = 0;
- S32 visible = 0;
- cost += objectp->getStreamingCost(&bytes,
- &visible);
- S32 vt = 0;
- count += objectp->getTriangleCount(&vt);
- vcount += vt;
- total_bytes += bytes;
- visible_bytes += visible;
- }
- }
- }
- addText(xpos, ypos,
- llformat("Region streaming cost: %.1f", cost));
- }
- else
- {
- cost =
- selected_objects->getSelectedObjectStreamingCost(&total_bytes,
- &visible_bytes);
- count =
- selected_objects->getSelectedObjectTriangleCount(&vcount);
- object_count = selected_objects->getObjectCount();
- addText(xpos, ypos,
- llformat("Selection streaming cost: %.1f", cost));
- }
- ypos += mIncY;
- addText(xpos, ypos,
- llformat("%.1f KTris, %.3f KVerts, %.1f/%.1f KB, %d objects",
- count / 1000.f, vcount / 1000.f,
- visible_bytes / 1024.f, total_bytes / 1024.f,
- object_count));
- ypos += mIncY;
- }
- addText(xpos, ypos,
- llformat("%d vertex buffers",
- LLVertexBuffer::getGLCount()));
- ypos += mIncY;
- addText(xpos, ypos,
- llformat("%d vertex buffer binds",
- LLVertexBuffer::getBindCount()));
- ypos += mIncY;
- addText(xpos, ypos,
- llformat("%d vertex buffer sets",
- LLVertexBuffer::getSetCount()));
- ypos += mIncY;
- addText(xpos, ypos,
- llformat("%d texture binds", LLImageGL::sBindCount));
- ypos += mIncY;
- addText(xpos, ypos,
- llformat("%d unique textures", LLImageGL::sUniqueCount));
- ypos += mIncY;
- addText(xpos, ypos,
- llformat("%d render calls", gPipeline.mBatchCount));
- ypos += mIncY;
- addText(xpos, ypos, llformat("Batch min/max/mean: %d/%d/%d",
- gPipeline.mMinBatchSize,
- gPipeline.mMaxBatchSize,
- gPipeline.mTrianglesDrawn /
- gPipeline.mBatchCount));
- ypos += mIncY;
- gPipeline.mMinBatchSize = gPipeline.mMaxBatchSize = 0;
- gPipeline.mBatchCount = 0;
- addText(xpos, ypos,
- llformat("%d/%d objects active",
- gObjectList.getNumActiveObjects(),
- gObjectList.getNumObjects()));
- ypos += mIncY;
- addText(xpos, ypos,
- llformat("%d matrix ops", gPipeline.mMatrixOpCount));
- ypos += mIncY;
- gPipeline.mMatrixOpCount = 0;
- addText(xpos, ypos,
- llformat("%d texture matrix ops",
- gPipeline.mTextureMatrixOps));
- ypos += mIncY;
- gPipeline.mTextureMatrixOps = 0;
- addText(xpos, ypos,
- llformat("%d/%d nodes visible", gPipeline.mNumVisibleNodes,
- LLSpatialGroup::sNodeCount));
- ypos += mIncY;
- addText(xpos, ypos,
- llformat("%d avatars visible",
- LLVOAvatar::sNumVisibleAvatars));
- ypos += mIncY;
- addText(xpos, ypos,
- llformat("%d lights visible",
- LLPipeline::sVisibleLightCount));
- ypos += mIncY;
- if (gMeshRepo.meshRezEnabled())
- {
- constexpr F32 MEGABYTE = 1048576.f;
- addText(xpos, ypos,
- llformat("%.3f MB mesh data received",
- LLMeshRepository::sBytesReceived / MEGABYTE));
- ypos += mIncY;
- addText(xpos, ypos,
- llformat("%d/%d mesh HTTP requests/retries",
- LLMeshRepository::sHTTPRequestCount,
- LLMeshRepository::sHTTPRetryCount));
- ypos += mIncY;
- addText(xpos, ypos,
- llformat("%d/%d mesh LOD pending/processing",
- (S32)LLMeshRepository::sLODPending,
- (S32)LLMeshRepository::sLODProcessing));
- ypos += mIncY;
- addText(xpos, ypos,
- llformat("%.3f/%.3f MB mesh cache read/write ",
- LLMeshRepository::sCacheBytesRead / MEGABYTE,
- LLMeshRepository::sCacheBytesWritten / MEGABYTE));
- ypos += mIncY;
- }
- // Reset per-frame statistics.
- LLVertexBuffer::resetPerFrameStats();
- LLImageGL::sBindCount = LLImageGL::sUniqueCount =
- gPipeline.mNumVisibleNodes =
- LLPipeline::sVisibleLightCount = 0;
- }
- static LLCachedControl<bool> debug_show_avatars_info(gSavedSettings,
- "DebugShowAvatarRenderInfo");
- if (debug_show_avatars_info)
- {
- std::map<std::string, LLVOAvatar*> sorted_avs;
- for (S32 i = 0, count = LLCharacter::sInstances.size(); i < count;
- ++i)
- {
- LLVOAvatar* avatarp = (LLVOAvatar*)LLCharacter::sInstances[i];
- if (avatarp && !avatarp->isDead() && !avatarp->mIsDummy &&
- !avatarp->isOrphaned() && avatarp->isFullyLoaded(true))
- {
- sorted_avs[avatarp->getFullname(true)] = avatarp;
- }
- }
- //MK
- bool hide_names = gRLenabled && gRLInterface.mContainsShownames;
- if (hide_names)
- {
- mTempStr = "(Hidden)";
- }
- //mk
- for (std::map<std::string, LLVOAvatar*>::reverse_iterator
- rit = sorted_avs.rbegin(), rend = sorted_avs.rend();
- rit != rend; ++rit)
- {
- //MK
- if (!hide_names)
- //mk
- {
- mTempStr = utf8str_truncate(rit->first, 16);
- }
- LLVOAvatar* avatarp = rit->second;
- addText(xpos, ypos,
- llformat("%s: complexity %d, %d m2, %.1f MB",
- mTempStr.c_str(),
- avatarp->getVisualComplexity(),
- (S32)avatarp->getAttachmentSurfaceArea(),
- (F32)avatarp->getAttachmentSurfaceBytes() /
- 1048576.f));
- ypos += mIncY;
- }
- }
- static LLCachedControl<bool> debug_show_render_matrices(gSavedSettings,
- "DebugShowRenderMatrices");
- if (debug_show_render_matrices)
- {
- F32* m = gGLProjection.getF32ptr();
- addText(xpos, ypos, llformat("%.4f .%4f %.4f %.4f",
- m[12], m[13], m[14], m[15]));
- ypos += mIncY;
- addText(xpos, ypos, llformat("%.4f .%4f %.4f %.4f",
- m[8], m[9], m[10], m[11]));
- ypos += mIncY;
- addText(xpos, ypos, llformat("%.4f .%4f %.4f %.4f",
- m[4], m[5], m[6], m[7]));
- ypos += mIncY;
- addText(xpos, ypos, llformat("%.4f .%4f %.4f %.4f",
- m[0], m[1], m[2], m[3]));
- ypos += mIncY;
- m = gGLModelView.getF32ptr();
- addText(xpos, ypos, "Projection matrix");
- ypos += mIncY;
- addText(xpos, ypos, llformat("%.4f .%4f %.4f %.4f",
- m[12], m[13], m[14], m[15]));
- ypos += mIncY;
- addText(xpos, ypos, llformat("%.4f .%4f %.4f %.4f",
- m[8], m[9], m[10], m[11]));
- ypos += mIncY;
- addText(xpos, ypos, llformat("%.4f .%4f %.4f %.4f",
- m[4], m[5], m[6], m[7]));
- ypos += mIncY;
- addText(xpos, ypos, llformat("%.4f .%4f %.4f %.4f",
- m[0], m[1], m[2], m[3]));
- ypos += mIncY;
- addText(xpos, ypos, "View Matrix");
- ypos += mIncY;
- }
- static LLCachedControl<bool> debug_show_color(gSavedSettings,
- "DebugShowColor");
- if (debug_show_color)
- {
- static U8 color[4];
- LLCoordGL coord = gViewerWindowp->getCurrentMouse();
- const LLVector2& scaler = gViewerWindowp->getDisplayScale();
- S32 x = ll_round((F32)coord.mX * scaler.mV[VX]);
- S32 y = ll_round((F32)coord.mY * scaler.mV[VY]);
- glReadPixels(x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, color);
- addText(xpos, ypos, llformat("Pixel <%1d, %1d> R:%d G:%d B:%d A:%d",
- x, y, color[0], color[1], color[2],
- color[3]));
- ypos += mIncY;
- }
- // Only display these messages if we are actually rendering beacons at
- // this moment
- static LLCachedControl<bool> beacons_always_on(gSavedSettings,
- "BeaconAlwaysOn");
- if (LLPipeline::sRenderBeacons &&
- //MK
- !(gRLenabled && gRLInterface.mContainsEdit) &&
- //mk
- (LLPipeline::sRenderBeaconsFloaterOpen || beacons_always_on))
- {
- if (LLPipeline::sRenderScriptedBeacons)
- {
- addText(xpos, ypos, "Viewing scripted object beacons (red)");
- ypos += mIncY;
- }
- else if (LLPipeline::sRenderScriptedTouchBeacons)
- {
- addText(xpos, ypos,
- "Viewing scripted object with touch function beacons (red)");
- ypos += mIncY;
- }
- if (LLPipeline::sRenderPhysicalBeacons)
- {
- addText(xpos, ypos, "Viewing physical object beacons (green)");
- ypos += mIncY;
- }
- if (LLPipeline::sRenderPermanentBeacons)
- {
- addText(xpos, ypos,
- "Viewing navmesh affecting object beacons (cyan)");
- ypos += mIncY;
- }
- if (LLPipeline::sRenderCharacterBeacons)
- {
- addText(xpos, ypos,
- "Viewing pathfinding character object beacons (grey)");
- ypos += mIncY;
- }
- if (LLPipeline::sRenderSoundBeacons)
- {
- addText(xpos, ypos, "Viewing sound beacons (yellow)");
- ypos += mIncY;
- }
- if (LLPipeline::sRenderParticleBeacons)
- {
- addText(xpos, ypos, "Viewing particle beacons (light blue)");
- ypos += mIncY;
- if (LLPipeline::toggleRenderTypeControlNegated((void*)LLPipeline::RENDER_TYPE_PARTICLES))
- {
- addText(xpos, ypos, " (note: particles hidden)");
- ypos += mIncY;
- }
- }
- if (LLPipeline::sRenderMOAPBeacons)
- {
- addText(xpos, ypos, "Viewing shared media beacons (white)");
- ypos += mIncY;
- }
- }
- static LLCachedControl<bool> sun_beacon(gSavedSettings, "sunbeacon");
- if (sun_beacon)
- {
- addText(xpos, ypos, "Viewing Sun direction beacon (orange)");
- ypos += mIncY;
- }
- static LLCachedControl<bool> moon_beacon(gSavedSettings, "moonbeacon");
- if (moon_beacon)
- {
- addText(xpos, ypos, "Viewing Moon direction beacon (purple)");
- ypos += mIncY;
- }
- static LLCachedControl<bool> debug_show_mesh_queue(gSavedSettings,
- "DebugShowMeshQueue");
- if (debug_show_mesh_queue)
- {
- if (!gMeshRepo.mUploads.empty())
- {
- for (std::vector<LLMeshUploadThread*>::iterator
- iter = gMeshRepo.mUploads.begin(),
- end = gMeshRepo.mUploads.end();
- iter != end; ++iter)
- {
- LLMeshUploadThread* thread = *iter;
- addText(xpos, ypos,
- llformat("Mesh uploads: %d",
- thread->mPendingUploads));
- ypos += mIncY;
- }
- }
- S32 pending = 0;
- S32 delayed = 0;
- S32 header = 0;
- S32 lod = 0;
- S32 ahead = 0;
- S32 alod = 0;
- LLMeshRepoThread* mthread = gMeshRepo.mThread;
- if (mthread)
- {
- // Note: no need to lock the mesh repository mutexes here: we
- // do not care if the (fast changing) numbers are inaccurate
- // once in a blue moon... HB
- pending = gMeshRepo.mPendingRequests.size();
- #if !LL_PENDING_MESH_REQUEST_SORTING
- delayed = gMeshRepo.mDelayedPendingRequests.size();
- #endif
- header = mthread->mHeaderReqQ.size();
- lod = mthread->mLODReqQ.size();
- ahead = LLMeshRepoThread::sActiveHeaderRequests;
- alod = LLMeshRepoThread::sActiveLODRequests;
- }
- if (delayed)
- {
- addText(xpos, ypos,
- llformat("Mesh queue: %d pending + %d delayed (%d:%d header | %d:%d LOD)",
- pending, delayed, ahead, header, alod, lod));
- }
- else if (pending || header || lod || ahead || alod)
- {
- addText(xpos, ypos,
- llformat("Mesh queue: %d pending (%d:%d header | %d:%d LOD)",
- pending, ahead, header, alod, lod));
- ypos += mIncY;
- }
- }
- mMaxY = ypos + 4 - mIncY;
- }
- void draw()
- {
- if (mLineList.empty())
- {
- return;
- }
- // Note: do not show the background while the velocity bar is shown
- static LLCachedControl<bool> hud_info_bg(gSavedSettings,
- "HUDInfoBackground");
- if (!mVelocityBarShown && hud_info_bg)
- {
- mMinX -= mMaginX;
- LLUIImage::sRoundedSquare->drawSolid(mMinX, mMinY,
- mMaxX - mMinX, mMaxY - mMinY,
- LLConsole::getBackground());
- }
- for (line_list_t::iterator iter = mLineList.begin(),
- end = mLineList.end();
- iter != end; ++iter)
- {
- const Line& line = *iter;
- mFont->renderUTF8(line.text, 0, (F32)line.x, (F32)line.y,
- mTextColor, LLFontGL::LEFT, LLFontGL::TOP,
- LLFontGL::NORMAL, S32_MAX, S32_MAX, NULL, false);
- }
- mLineList.clear();
- mMinX = S32_MAX;
- }
- private:
- LLFontGL* mFont;
- LLColor4 mTextColor;
- U32 mLineHeight;
- U32 mMaginX;
- U32 mIncY;
- U32 mMinX;
- U32 mMaxX;
- U32 mMinY;
- U32 mMaxY;
- std::string mTempStr;
- struct Line
- {
- Line(const std::string& in_text, U32 in_x, U32 in_y)
- : text(in_text),
- x(in_x),
- y(in_y)
- {
- }
- U32 x;
- U32 y;
- std::string text;
- };
- typedef std::vector<Line> line_list_t;
- line_list_t mLineList;
- bool mVelocityBarShown;
- };
- ////////////////////////////////////////////////////////////////////////////
- // LLViewerWindow class
- ////////////////////////////////////////////////////////////////////////////
- LLViewerWindow::LLViewerWindow(const std::string& title, S32 x, S32 y,
- U32 width, U32 height, bool fullscreen)
- : mActive(true),
- mWindowRect(0, height, width, 0),
- mVirtualWindowRect(0, height, width, 0),
- mLeftMouseDown(false),
- mMiddleMouseDown(false),
- mRightMouseDown(false),
- #if LL_DARWIN
- mAllowMouseDragging(true),
- #endif
- mDebugText(NULL),
- mToolTip(NULL),
- mToolTipBlocked(false),
- mMouseInWindow(false),
- mLastMask(MASK_NONE),
- mToolStored(NULL),
- mSuppressToolbox(false),
- mCursorHidden(false),
- mIgnoreActivate(false),
- mHoverPick(),
- mResDirty(false),
- mStatesDirty(false),
- mCurrResolutionIndex(0)
- {
- gNotifications.initClass();
- LLNotificationChannel::buildChannel("VW_alerts", "Visible",
- LLNotificationFilters::filterBy<std::string>(&LLNotification::getType,
- "alert"));
- LLNotificationChannel::buildChannel("VW_alertmodal", "Visible",
- LLNotificationFilters::filterBy<std::string>(&LLNotification::getType,
- "alertmodal"));
- gNotifications.getChannel("VW_alerts")->connectChanged(&LLViewerWindow::onAlert);
- gNotifications.getChannel("VW_alertmodal")->connectChanged(&LLViewerWindow::onAlert);
- // Default to application directory.
- LLViewerWindow::sSnapshotBaseName = "Snapshot";
- LLViewerWindow::sMovieBaseName = "SLmovie";
- resetSnapshotLoc();
- // Create window
- LLWindow::createWindow(title, x, y, width, height, 0, fullscreen,
- gSavedSettings.getBool("DisableVerticalSync"),
- gSavedSettings.getU32("RenderFSAASamples"));
- if (!gAppViewerp->restoreErrorTrap())
- {
- llwarns << " Someone took over my signal/exception handler !"
- << llendl;
- }
- if (!gWindowp)
- {
- llwarns << "Unable to create window, be sure screen is set at 32 bits color."
- << llendl;
- gAppViewerp->forceExit();
- }
- #if LL_DEBUG || LL_NO_FORCE_INLINE
- gWindowp->setWindowTitle(title + " [DEVEL]");
- #endif
- // Immediately create the shader manager.
- LLViewerShaderMgr::createInstance();
- // Get the real window rect the window was created with (since there are
- // various OS-dependent reasons why the size of a window or fullscreen
- // context may have been adjusted slightly...)
- F32 ui_scale_factor = gSavedSettings.getF32("UIScaleFactor") *
- gWindowp->getSystemUISize();
- // HiDPI scaling can be 4x. UI scaling in prefs is up to 2x, so max is 8x
- ui_scale_factor = llclamp(ui_scale_factor, 0.75f, 8.f);
- mDisplayScale.set(llmax(1.f / gWindowp->getPixelAspectRatio(), 1.f),
- llmax(gWindowp->getPixelAspectRatio(), 1.f));
- mDisplayScale *= ui_scale_factor;
- F32 divisor_x = 1.f / mDisplayScale.mV[VX];
- F32 divisor_y = 1.f / mDisplayScale.mV[VY];
- mDisplayScaleDivisor.set(divisor_x, divisor_y);
- LLUI::sGLScaleFactor = mDisplayScale;
- LLCoordWindow size;
- gWindowp->getSize(&size);
- mWindowRect.set(0, size.mY, size.mX, 0);
- mVirtualWindowRect.set(0, ll_roundp((F32)size.mY * divisor_y),
- ll_roundp((F32)size.mX * divisor_x), 0);
- LLFontManager::initClass();
- // We want to set this stuff up BEFORE we initialize the pipeline, so we
- // can turn off stuff like AGP if we think that it will crash the viewer.
- LL_DEBUGS("Window") << "Loading feature tables." << LL_ENDL;
- gFeatureManager.init();
- // Initialize OpenGL Renderer
- LLVertexBuffer::initClass();
- llinfos << "LLVertexBuffer initialization done." << llendl;
- gGL.init();
- if (gFeatureManager.isSafe() ||
- gSavedSettings.getS32("LastFeatureVersion") != gFeatureManager.getVersion() ||
- gSavedSettings.getBool("ProbeHardwareOnStartup"))
- {
- gFeatureManager.applyRecommendedSettings();
- gSavedSettings.setBool("ProbeHardwareOnStartup", false);
- }
- // If we crashed while initializing GL stuff last time, disable certain
- // features.
- if (gSavedSettings.getBool("RenderInitError"))
- {
- mInitAlert = "DisplaySettingsNoShaders";
- gFeatureManager.setGraphicsLevel(0, false);
- gSavedSettings.setU32("RenderQualityPerformance", 0);
- gSavedSettings.setBool("RenderUsePBR", false);
- }
- // Set callbacks
- gWindowp->setCallbacks(this);
- LLImageGL::initThread(gWindowp, gSavedSettings.getS32("GLWorkerThreads"));
- // Init the image list. Must happen after GL is initialized and before the
- // images that LLViewerWindow needs are requested.
- gTextureList.init();
- LLViewerTextureManager::init();
- // Init default fonts
- initFonts();
- // Create container for all sub-views
- mRootView = new LLRootView("root", mVirtualWindowRect, false);
- // Make avatar head look forward at start
- mCurrentMousePoint.mX = getWindowWidth() / 2;
- mCurrentMousePoint.mY = getWindowHeight() / 2;
- // Sync the keyboard setting with the saved setting
- gSavedSettings.getControl("NumpadControl")->firePropertyChanged();
- mDebugText = new LLDebugText();
- }
- void LLViewerWindow::initGLDefaults()
- {
- gGL.setSceneBlendType(LLRender::BT_ALPHA);
- glPixelStorei(GL_PACK_ALIGNMENT, 1);
- glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
- gGL.setAmbientLightColor(LLColor4::black);
- glCullFace(GL_BACK);
- // RN: need this for translation and stretch manip.
- gBox.prerender();
- }
- void LLViewerWindow::initBase()
- {
- // Set the gamma
- F32 gamma = gSavedSettings.getF32("DisplayGamma");
- if (!gWindowp->setGamma(gamma))
- {
- llwarns << "Failed to set the display gamma to " << gamma
- << ". Restoring the default gamma." << llendl;
- gWindowp->restoreGamma();
- }
- // Create global views
- // Create the floater view at the start so that other views can add
- // children to it (but wait to add it as a child of the root view so that
- // it will be in front of the other views).
- // Constrain floaters to inside the menu and status bar regions.
- S32 height = getWindowHeight();
- S32 width = getWindowWidth();
- LLRect full_window(0, height, width, 0);
- LLRect floater_view_rect = full_window;
- // Make space for the menu bar...
- floater_view_rect.mTop -= gMenuBarHeight;
- // ... and for the tool bar, the chat bar and the overlay bar...
- if (gSavedSettings.getBool("ShowToolBar"))
- {
- floater_view_rect.mBottom += TOOL_BAR_HEIGHT;
- }
- if (gSavedSettings.getBool("ChatVisible"))
- {
- floater_view_rect.mBottom += CHAT_BAR_HEIGHT;
- }
- floater_view_rect.mBottom += OVERLAY_BAR_HEIGHT;
- // Check for non-first startup
- S32 floater_view_bottom = gSavedSettings.getS32("FloaterViewBottom");
- if (floater_view_bottom >= 0)
- {
- floater_view_rect.mBottom = floater_view_bottom;
- }
- gFloaterViewp = new LLFloaterView("Floater View", floater_view_rect);
- gFloaterViewp->setVisible(true);
- gSnapshotFloaterViewp = new LLSnapshotFloaterView("Snapshot Floater View",
- full_window);
- // Snapshot floater must start invisible otherwise it eats all the tooltips
- gSnapshotFloaterViewp->setVisible(false);
- // Console
- llassert(!gConsolep);
- gConsolep = new LLConsole("console", getChatConsoleRect(),
- gSavedSettings.getS32("ChatFontSize"),
- gSavedSettings.getU32("ChatConsoleMaxLines"),
- gSavedSettings.getF32("ChatPersistTime"));
- gConsolep->setFollows(FOLLOWS_LEFT | FOLLOWS_RIGHT | FOLLOWS_BOTTOM);
- mRootView->addChild(gConsolep);
- // Debug view over the console
- gDebugViewp = new LLDebugView("gDebugViewp", full_window);
- gDebugViewp->setFollowsAll();
- gDebugViewp->setVisible(true);
- mRootView->addChild(gDebugViewp);
- // HUD elements just below floaters
- LLRect hud_rect = full_window;
- hud_rect.mTop -= 24;
- hud_rect.mBottom += gStatusBarHeight;
- gHUDViewp = new LLHUDView("hud_view", hud_rect);
- gHUDViewp->setFollowsAll();
- mRootView->addChild(gHUDViewp);
- // Add floater view at the end so it will be on top, and give it tab
- // priority over others
- mRootView->addChild(gFloaterViewp, -1);
- mRootView->addChild(gSnapshotFloaterViewp);
- // Notify above floaters !
- LLRect notify_rect = full_window;
- #if 0
- notify_rect.mTop -= 24;
- #endif
- notify_rect.mBottom += gStatusBarHeight;
- gNotifyBoxViewp = new LLNotifyBoxView("notify_container", notify_rect,
- false, FOLLOWS_ALL);
- mRootView->addChild(gNotifyBoxViewp, -2);
- // Tooltips go above floaters
- mToolTip = new LLTextBox(std::string("tool tip"), LLRect(0, 1, 1, 0));
- mToolTip->setHPad(4);
- mToolTip->setVPad(2);
- mToolTip->setColor(gColors.getColor("ToolTipTextColor"));
- mToolTip->setBorderColor(gColors.getColor("ToolTipBorderColor"));
- mToolTip->setBorderVisible(false);
- mToolTip->setBackgroundColor(gColors.getColor("ToolTipBgColor"));
- mToolTip->setBackgroundVisible(true);
- mToolTip->setFontStyle(LLFontGL::NORMAL);
- mToolTip->setBorderDropshadowVisible(true);
- mToolTip->setVisible(false);
- // Add the progress bar view (startup view), which overrides everything
- mProgressView = new LLProgressView("ProgressView", full_window);
- mRootView->addChild(mProgressView);
- setShowProgress(false);
- setProgressCancelButtonVisible(false);
- #if LL_DARWIN
- // *HACK: to get a redraw and take into account Retina mode (or not)...
- mResDirty = true;
- #endif
- }
- void adjust_rect_top_left(const char* control, const LLRect& view)
- {
- LLRect r = gSavedSettings.getRect(control);
- if (r.mLeft || r.mBottom)
- {
- return;
- }
- r.setLeftTopAndSize(0, view.getHeight(), r.getWidth(), r.getHeight());
- gSavedSettings.setRect(control, r);
- }
- void adjust_rect_top_center(const char* control, const LLRect& view)
- {
- LLRect r = gSavedSettings.getRect(control);
- if (r.mLeft || r.mBottom)
- {
- return;
- }
- r.setLeftTopAndSize((view.getWidth() - r.getWidth()) / 2, view.getHeight(),
- r.getWidth(), r.getHeight());
- gSavedSettings.setRect(control, r);
- }
- void adjust_rect_top_right(const char* control, const LLRect& view,
- S32 delta_y = 0)
- {
- LLRect r = gSavedSettings.getRect(control);
- if (r.mLeft || r.mBottom)
- {
- return;
- }
- r.setLeftTopAndSize(view.getWidth() - r.getWidth(),
- view.getHeight() - delta_y,
- r.getWidth(), r.getHeight());
- gSavedSettings.setRect(control, r);
- }
- void adjust_rect_center(const char* control, const LLRect& view)
- {
- LLRect r = gSavedSettings.getRect(control);
- if (r.mLeft || r.mBottom)
- {
- return;
- }
- r.setLeftTopAndSize((view.getWidth() - r.getWidth()) / 2,
- view.getHeight() -
- (view.getHeight() - r.getHeight()) / 2,
- r.getWidth(), r.getHeight());
- gSavedSettings.setRect(control, r);
- }
- void adjust_rect_left_center(const char* control, const LLRect& view)
- {
- LLRect r = gSavedSettings.getRect(control);
- if (r.mLeft || r.mBottom)
- {
- return;
- }
- r.setLeftTopAndSize(0,
- view.getHeight() -
- (view.getHeight() - r.getHeight()) / 2,
- r.getWidth(), r.getHeight());
- gSavedSettings.setRect(control, r);
- }
- void adjust_rect_right_center(const char* control, const LLRect& view)
- {
- LLRect r = gSavedSettings.getRect(control);
- if (r.mLeft || r.mBottom)
- {
- return;
- }
- r.setLeftTopAndSize(view.getWidth() - r.getWidth(),
- view.getHeight() -
- (view.getHeight() - r.getHeight()) / 2,
- r.getWidth(), r.getHeight());
- gSavedSettings.setRect(control, r);
- }
- void adjust_rect_bottom_left(const char* control, const LLRect& view)
- {
- LLRect r = gSavedSettings.getRect(control);
- if (r.mLeft || r.mBottom)
- {
- return;
- }
- r.setOriginAndSize(0, view.mBottom, r.getWidth(), r.getHeight());
- gSavedSettings.setRect(control, r);
- }
- void adjust_rect_bottom_center(const char* control, const LLRect& view)
- {
- LLRect r = gSavedSettings.getRect(control);
- if (r.mLeft || r.mBottom)
- {
- return;
- }
- r.setOriginAndSize((view.getWidth() - r.getWidth()) / 2, view.mBottom,
- r.getWidth(), r.getHeight());
- gSavedSettings.setRect(control, r);
- }
- void adjust_rect_bottom_right(const char* control, const LLRect& view)
- {
- LLRect r = gSavedSettings.getRect(control);
- if (r.mLeft || r.mBottom)
- {
- return;
- }
- r.setOriginAndSize(view.getWidth() - r.getWidth(), view.mBottom,
- r.getWidth(), r.getHeight());
- gSavedSettings.setRect(control, r);
- }
- // Many rectangles cannot be placed until we know the screen size. These
- // rectangles have their bottom-left corner as 0,0 in the default settings.
- void LLViewerWindow::adjustRectanglesForFirstUse()
- {
- if (!gFloaterViewp) return;
- const LLRect& view_rect = gFloaterViewp->getRect();
- // *NOTE: the width and height of non-resizable floaters must be identical
- // in settings.xml and their relevant floater.xml files, otherwise the
- // adjustment will not work properly.
- // The camera controls floater goes at the top right corner...
- adjust_rect_top_right("FloaterCameraRect3a", view_rect);
- // ... then, just under, the movements controls floater...
- LLRect r = gSavedSettings.getRect("FloaterCameraRect3a");
- S32 delta_y = r.getHeight();
- adjust_rect_top_right("FloaterMoveRect2", view_rect, delta_y);
- // ... then, yet under, the mini-map...
- r = gSavedSettings.getRect("FloaterMoveRect2");
- delta_y += r.getHeight();
- adjust_rect_top_right("FloaterMiniMapRect", view_rect, delta_y);
- // ... finally, under the mini-map, all three friends list, groups list
- // and radar floaters, at the same level...
- r = gSavedSettings.getRect("FloaterMiniMapRect");
- delta_y += r.getHeight();
- adjust_rect_top_right("FloaterFriendsRect", view_rect, delta_y);
- adjust_rect_top_right("FloaterGroupsRect", view_rect, delta_y);
- adjust_rect_top_right("FloaterRadarRect", view_rect, delta_y);
- // The inventory floater goes at the bottom right
- adjust_rect_bottom_right("FloaterInventoryRect", view_rect);
- // Chat history at the bottom left (replaces the console when opened)
- adjust_rect_bottom_left("FloaterChatRect", view_rect);
- // Communicate window at the top left (keeps the console visible while
- // IMing)
- adjust_rect_top_left("ChatterboxRect", view_rect);
- // Chat and IM text input editor
- adjust_rect_bottom_center("ChatInputEditorRect", view_rect);
- adjust_rect_top_center("IMInputEditorRect", view_rect);
- // Active speakers at the bottom right, above the voice controls
- adjust_rect_bottom_right("FloaterActiveSpeakersRect", view_rect);
- // Audio volume at the bottom right, above the master volume toggle
- adjust_rect_bottom_right("FloaterAudioVolumeRect", view_rect);
- // Same thing for the nearby media floater, above the media controls...
- adjust_rect_bottom_right("FloaterNearbyMediaRect", view_rect);
- adjust_rect_right_center("FloaterStatisticsRect", view_rect);
- adjust_rect_right_center("FloaterPostcardRect", view_rect);
- adjust_rect_bottom_right("FloaterLagMeter", view_rect);
- // Build floater, top left
- adjust_rect_top_left("ToolboxRect", view_rect);
- // Script queue floater, top left
- adjust_rect_top_left("CompileOutputRect", view_rect);
- adjust_rect_top_left("FloaterCustomizeAppearanceRect", view_rect);
- // Land/region/parcel related floaters go on top centre, below the status
- // bar that shows the region and parcel names
- adjust_rect_top_center("FloaterLandRect5", view_rect);
- adjust_rect_top_center("FloaterRegionInfoRect", view_rect);
- adjust_rect_top_left("FloaterLandHoldingsRect", view_rect);
- adjust_rect_top_center("FloaterRegionDebugConsoleRect", view_rect);
- adjust_rect_top_center("FloaterDebugTagsRect", view_rect);
- adjust_rect_top_center("FloaterBumpRect", view_rect);
- adjust_rect_top_center("FloaterWindlightRect", view_rect);
- adjust_rect_top_center("FloaterObjectBackuptRect", view_rect);
- adjust_rect_top_center("FloaterTeleportHistoryRect", view_rect);
- adjust_rect_top_center("FloaterInspectAvatarRect", view_rect);
- adjust_rect_top_center("FloaterInspectRect", view_rect);
- adjust_rect_top_left("FloaterRLVRect", view_rect);
- adjust_rect_top_left("FloaterDebugSettingsRect", view_rect);
- adjust_rect_center("FloaterFindRect2", view_rect);
- adjust_rect_center("FloaterLocalEnvEditorRect", view_rect);
- adjust_rect_top_left("FloaterExperienceProfileRect", view_rect);
- adjust_rect_center("FloaterExperiencesRect", view_rect);
- adjust_rect_center("FloaterAreaSearchRect", view_rect);
- adjust_rect_center("FloaterWorldMapRect2", view_rect);
- adjust_rect_center("FloaterGroupTitlesRect", view_rect);
- adjust_rect_center("MediaFilterRect", view_rect);
- adjust_rect_center("FloaterSoundsListRect", view_rect);
- adjust_rect_center("DirSelectorRect", view_rect);
- adjust_rect_center("FileSelectorRect", view_rect);
- adjust_rect_center("FloaterMarketplaceAssociationRect", view_rect);
- adjust_rect_center("FloaterMarketplaceValidationRect", view_rect);
- adjust_rect_left_center("FloaterAvatarProfileRect", view_rect);
- adjust_rect_left_center("FloaterBeaconsRect", view_rect);
- adjust_rect_left_center("FloaterMuteRect3", view_rect);
- adjust_rect_left_center("FloaterGestureRect2", view_rect);
- adjust_rect_center("PathFindingCharactersRect", view_rect);
- adjust_rect_center("PathFindingLinksetsRect", view_rect);
- adjust_rect_center("FloaterLuaDialogRect", view_rect);
- }
- void LLViewerWindow::initWorldUI()
- {
- pre_init_menus();
- S32 height = mRootView->getRect().getHeight();
- S32 width = mRootView->getRect().getWidth();
- LLRect full_window(0, height, width, 0);
- if (!gToolBarp) // Do not re-enter if objects are alreay created
- {
- if (gAudiop)
- {
- // Do not play the floaters opening sound
- gAudiop->setMuted(true);
- }
- LLRect bar_rect(-1, gStatusBarHeight, width + 1, -1);
- new LLToolBar(bar_rect);
- LLRect chat_bar_rect(-1, CHAT_BAR_HEIGHT, width + 1, -1);
- chat_bar_rect.translate(0, gStatusBarHeight - 1);
- gChatBarp = new LLChatBar("chat", chat_bar_rect);
- bar_rect.translate(0, gStatusBarHeight - 1);
- bar_rect.translate(0, CHAT_BAR_HEIGHT - 1);
- new LLOverlayBar(bar_rect);
- // Panel containing chatbar, toolbar, and overlay, over floaters
- LLRect bottom_rect(-1, 2 * gStatusBarHeight + CHAT_BAR_HEIGHT,
- width + 1, -1);
- gBottomPanelp = new LLBottomPanel(bottom_rect);
- // The order here is important
- gBottomPanelp->addChild(gChatBarp);
- gBottomPanelp->addChild(gToolBarp);
- gBottomPanelp->addChild(gOverlayBarp);
- mRootView->addChild(gBottomPanelp);
- mRootView->addChild(new HBLuaSideBar());
- mRootView->sendChildToBack(gLuaSideBarp);
- // View for hover information
- gHoverViewp = new LLHoverView(full_window);
- gHoverViewp->setVisible(true);
- mRootView->addChild(gHoverViewp);
- new LLIMMgr();
- LLRect morph_view_rect = full_window;
- morph_view_rect.stretch(-gStatusBarHeight);
- morph_view_rect.mTop = full_window.mTop - 32;
- gMorphViewp = new LLMorphView(morph_view_rect);
- mRootView->addChild(gMorphViewp);
- gMorphViewp->setVisible(false);
- LLPanelWorldMap::initClass();
- gFloaterWorldMapp = new LLFloaterWorldMap();
- // Open teleport history floater and hide it initially
- gFloaterTeleportHistoryp = new HBFloaterTeleportHistory();
- //
- // Tools for building
- //
- // Toolbox floater
- init_menus();
- gFloaterToolsp = new LLFloaterTools();
- // Status bar
- S32 menu_bar_height = gMenuBarViewp->getRect().getHeight();
- LLRect root_rect = mRootView->getRect();
- LLRect status_rect(0, root_rect.getHeight(), root_rect.getWidth(),
- root_rect.getHeight() - menu_bar_height);
- gStatusBarp = new LLStatusBar(status_rect);
- gStatusBarp->setFollows(FOLLOWS_LEFT | FOLLOWS_RIGHT | FOLLOWS_TOP);
- gStatusBarp->reshape(root_rect.getWidth(),
- gStatusBarp->getRect().getHeight(), true);
- gStatusBarp->translate(0,
- root_rect.getHeight() -
- gStatusBarp->getRect().getHeight());
- // Sync bg color with menu bar
- gStatusBarp->setBackgroundColor(gMenuBarViewp->getBackgroundColor());
- LLFloaterChatterBox::createInstance(LLSD());
- mRootView->addChild(gStatusBarp);
- // Menu holder must be a child of the root view as well
- mRootView->addChild(gMenuHolderp);
- // Menu holder appears on top to get first pass at all mouse events
- mRootView->sendChildToFront(gMenuHolderp);
- if (gAudiop)
- {
- gAudiop->setMuted(false);
- }
- }
- }
- // Destroy the UI
- void LLViewerWindow::shutdownViews()
- {
- gSavedSettings.setS32("FloaterViewBottom",
- gFloaterViewp->getRect().mBottom);
- gFocusMgr.unlockFocus();
- gFocusMgr.setMouseCapture(NULL);
- gFocusMgr.setKeyboardFocus(NULL);
- gFocusMgr.setTopCtrl(NULL);
- if (gWindowp)
- {
- gWindowp->allowLanguageTextInput(NULL, false);
- }
- // Cleanup global views
- if (gMorphViewp)
- {
- gMorphViewp->setVisible(false);
- }
- // DEV-40930: clear sModalStack. Otherwise, any LLModalDialog left open
- // will crump with llerrs.
- LLModalDialog::shutdownModals();
- llinfos << "LLModalDialog shut down." << llendl;
- cleanup_menus();
- llinfos << "Menus destroyed" << llendl;
- delete gFloaterTeleportHistoryp;
- delete gFloaterWorldMapp;
- delete gFloaterToolsp;
- // Delete all child views.
- if (mRootView)
- {
- delete mRootView;
- mRootView = NULL;
- // Automatically deleted as children of mRootView:
- mProgressView = NULL;
- gFloaterViewp = NULL;
- gSnapshotFloaterViewp = NULL;
- gConsolep = NULL;
- gChatBarp = NULL;
- llinfos << "Root view and children destroyed." << llendl;
- }
- else
- {
- llwarns << "Root view was already destroyed." << llendl;
- }
- llinfos << "Destroying IM manager." << llendl;
- delete gIMMgrp;
- }
- // Shuts down GL cleanly. Order is very important here.
- void LLViewerWindow::shutdownGL()
- {
- stop_glerror();
- LLFontGL::destroyDefaultFonts();
- LLFontManager::cleanupClass();
- llinfos << "Fonts destroyed" << llendl;
- gSky.cleanup();
- stop_glerror();
- llinfos << "Sky cleaned up" << llendl;
- gPipeline.cleanup();
- stop_glerror();
- llinfos << "Pipeline cleaned up" << llendl;
- // MUST clean up pipeline before cleaning up wearables
- LLWearableList::getInstance()->cleanup();
- llinfos << "Wearables cleaned up" << llendl;
- gTextureList.shutdown();
- stop_glerror();
- llinfos << "Texture list shut down" << llendl;
- gBumpImageList.destroyGL();
- stop_glerror();
- llinfos << "Cleaned up bump map images" << llendl;
- LLViewerTextureManager::cleanup();
- llinfos << "Cleaned up textures and GL images" << llendl;
- gSelectMgr.cleanup();
- llinfos << "Cleaned up select manager" << llendl;
- llinfos << "Stopping GL during shutdown" << llendl;
- stopGL(false);
- gGL.shutdown();
- llinfos << "GL shutdown" << llendl;
- LLVertexBuffer::cleanupClass();
- llinfos << "LLVertexBuffer cleaned up." << llendl;
- stop_glerror();
- }
- // Note: shutdownViews() and shutdownGL() need to be called first
- LLViewerWindow::~LLViewerWindow()
- {
- llinfos << "Destroying Window" << llendl;
- destroyWindow();
- if (mDebugText)
- {
- delete mDebugText;
- mDebugText = NULL;
- llinfos << "Debug text deleted." << llendl;
- }
- if (mToolTip)
- {
- delete mToolTip;
- mToolTip = NULL;
- llinfos << "Tool tip deleted." << llendl;
- }
- LLViewerShaderMgr::releaseInstance();
- llinfos << "LLViewerShaderMgr instance released." << llendl;
- LLImageGL::stopThread();
- }
- void LLViewerWindow::setCursor(ECursorType c)
- {
- gWindowp->setCursor(c);
- }
- void LLViewerWindow::showCursor()
- {
- gWindowp->showCursor();
- mCursorHidden = false;
- }
- void LLViewerWindow::hideCursor()
- {
- // Hide tooltips
- if (mToolTip)
- {
- mToolTip->setVisible(false);
- }
- // Also hide hover info
- if (gHoverViewp)
- {
- gHoverViewp->cancelHover();
- }
- // And hide the cursor
- gWindowp->hideCursor();
- mCursorHidden = true;
- }
- void LLViewerWindow::sendShapeToSim()
- {
- LLMessageSystem* msg = gMessageSystemp;
- if (!msg) return;
- msg->newMessageFast(_PREHASH_AgentHeightWidth);
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgentID);
- msg->addUUIDFast(_PREHASH_SessionID, gAgentSessionID);
- msg->addU32Fast(_PREHASH_CircuitCode, msg->mOurCircuitCode);
- msg->nextBlockFast(_PREHASH_HeightWidthBlock);
- msg->addU32Fast(_PREHASH_GenCounter, 0);
- U16 height16 = (U16)mWindowRect.getHeight();
- U16 width16 = (U16)mWindowRect.getWidth();
- msg->addU16Fast(_PREHASH_Height, height16);
- msg->addU16Fast(_PREHASH_Width, width16);
- gAgent.sendReliableMessage();
- }
- // Must be called after the window is created to set up agent camera variables
- // and UI variables.
- void LLViewerWindow::reshape(S32 width, S32 height)
- {
- // Destroying the window at quit time generates spurious reshape messages.
- // We do not care about these, and we do not want to send messages because
- // the message system may have been destructed.
- if (!LLApp::isExiting())
- {
- if (gMenuHolderp)
- {
- gMenuHolderp->hideMenus();
- }
- glViewport(0, 0, width, height);
- if (height > 0)
- {
- gViewerCamera.setViewHeightInPixels(height);
- if (gWindowp->getFullscreen())
- {
- // Force to 4:3 aspect for odd resolutions
- gViewerCamera.setAspect(getDisplayAspectRatio());
- }
- else
- {
- gViewerCamera.setAspect(width / (F32) height);
- }
- }
- // Update our window rectangle
- mWindowRect.mRight = mWindowRect.mLeft + width;
- mWindowRect.mTop = mWindowRect.mBottom + height;
- calcDisplayScale();
- bool display_scale_changed = mDisplayScale != LLUI::sGLScaleFactor;
- LLUI::sGLScaleFactor = mDisplayScale;
- // Update our window rectangle
- F32 divisor_x = mDisplayScaleDivisor.mV[VX];
- F32 divisor_y = mDisplayScaleDivisor.mV[VY];
- mVirtualWindowRect.mRight = mVirtualWindowRect.mLeft +
- ll_roundp((F32)width * divisor_x);
- mVirtualWindowRect.mTop = mVirtualWindowRect.mBottom +
- ll_roundp((F32)height * divisor_y);
- setupViewport();
- // Inform lower views of the change; round up when converting
- // coordinates to make sure there are no gaps at edge of window.
- LLView::sForceReshape = display_scale_changed;
- mRootView->reshape(llceil((F32)width * divisor_x),
- llceil((F32)height * divisor_y));
- LLView::sForceReshape = false;
- // Clear font width caches
- if (display_scale_changed)
- {
- LLHUDText::reshape();
- }
- sendShapeToSim();
- // Store new settings for the mode we are in, regardless
- if (!gWindowp->getFullscreen())
- {
- // Only save size if not maximized
- bool maximized = gWindowp->getMaximized();
- gSavedSettings.setBool("WindowMaximized", maximized);
- LLCoordScreen window_size;
- if (!maximized && gWindowp->getSize(&window_size))
- {
- gSavedSettings.setS32("WindowWidth", window_size.mX);
- gSavedSettings.setS32("WindowHeight", window_size.mY);
- }
- }
- gViewerStats.setStat(LLViewerStats::ST_WINDOW_WIDTH, (F64)width);
- gViewerStats.setStat(LLViewerStats::ST_WINDOW_HEIGHT, (F64)height);
- gResizeScreenTexture = gScreenIsDirty = true;
- }
- }
- // Hide normal UI when a logon fails
- void LLViewerWindow::setNormalControlsVisible(bool visible)
- {
- if (gBottomPanelp)
- {
- gBottomPanelp->setVisible(visible);
- gBottomPanelp->setEnabled(visible);
- }
- if (gMenuBarViewp)
- {
- gMenuBarViewp->setVisible(visible);
- gMenuBarViewp->setEnabled(visible);
- // ...and set the menu color appropriately.
- setMenuBackgroundColor();
- }
- if (gStatusBarp)
- {
- gStatusBarp->setVisible(visible);
- gStatusBarp->setEnabled(visible);
- }
- }
- void LLViewerWindow::setMenuBackgroundColor()
- {
- LLColor4 new_bg_color;
- if (gAgent.getGodLevel() > GOD_NOT)
- {
- if (gIsInProductionGrid)
- {
- new_bg_color = gColors.getColor("MenuBarGodBgColor");
- }
- else
- {
- new_bg_color = gColors.getColor("MenuNonProductionGodBgColor");
- }
- }
- else if (gIsInProductionGrid)
- {
- new_bg_color = gColors.getColor("MenuBarBgColor");
- }
- else
- {
- new_bg_color = gColors.getColor("MenuNonProductionBgColor");
- }
- if (gMenuBarViewp)
- {
- gMenuBarViewp->setBackgroundColor(new_bg_color);
- }
- if (gStatusBarp)
- {
- gStatusBarp->setBackgroundColor(new_bg_color);
- }
- }
- void LLViewerWindow::updateDebugText()
- {
- if (mDebugText)
- {
- mDebugText->update();
- }
- }
- void LLViewerWindow::drawDebugText()
- {
- gUIProgram.bind();
- gGL.color4f(1.f, 1.f, 1.f, 1.f);
- gGL.pushMatrix();
- gGL.pushUIMatrix();
- // Scale view by UI global scale factor and aspect ratio correction factor
- gGL.scaleUI(mDisplayScale.mV[VX], mDisplayScale.mV[VY], 1.f);
- if (mDebugText)
- {
- mDebugText->draw();
- }
- gGL.popUIMatrix();
- gGL.popMatrix();
- gGL.flush();
- gUIProgram.unbind();
- }
- void LLViewerWindow::draw()
- {
- if (!mRootView) return;
- LLUI::setLineWidth(1.f);
- LLUI::setLineWidth(1.f);
- // Reset any left-over transforms
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- gGL.loadIdentity();
- // *HACK: for timecode debugging
- static LLCachedControl<bool> display_timecode(gSavedSettings,
- "DisplayTimecode");
- if (display_timecode)
- {
- // Draw timecode block
- std::string text;
- gGL.loadIdentity();
- microsecondsToTimecodeString(gFrameTime,text);
- static const LLFontGL* font = LLFontGL::getFontSansSerif();
- font->renderUTF8(text, 0,
- ll_roundp(getWindowWidth() / 2 - 100.f),
- ll_roundp(getWindowHeight() - 60.f),
- LLColor4(1.f, 1.f, 1.f, 1.f),
- LLFontGL::LEFT, LLFontGL::TOP);
- }
- // Draw all nested UI views.
- // No translation needed, this view is glued to 0,0
- gUIProgram.bind();
- gGL.color4f(1.f, 1.f, 1.f, 1.f);
- gGL.pushMatrix();
- LLUI::pushMatrix();
- {
- // Scale view by UI global scale factor and aspect ratio correction
- // factor
- gGL.scaleUI(mDisplayScale.mV[VX], mDisplayScale.mV[VY], 1.f);
- LLVector2 old_scale_factor = LLUI::sGLScaleFactor;
- // Apply camera zoom transform (for high res screenshots)
- F32 zoom_factor = gViewerCamera.getZoomFactor();
- S16 sub_region = gViewerCamera.getZoomSubRegion();
- if (zoom_factor > 1.f)
- {
- // Decompose subregion number to x and y values
- S32 pos_y = sub_region / llceil(zoom_factor);
- S32 pos_x = sub_region - pos_y * llceil(zoom_factor);
- // offset for this tile
- gGL.translatef((F32)getWindowWidth() * -(F32)pos_x,
- (F32)getWindowHeight() * -(F32)pos_y, 0.f);
- gGL.scalef(zoom_factor, zoom_factor, 1.f);
- LLUI::sGLScaleFactor *= zoom_factor;
- }
- // Draw tool specific overlay on world
- gToolMgr.getCurrentTool()->draw();
- if (gAgent.cameraMouselook())
- {
- drawMouselookInstructions();
- }
- // Draw all nested UI views.
- // No translation needed, this view is glued to 0,0
- mRootView->draw();
- // Draw optional on-top-of-everyone view
- LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl();
- if (top_ctrl && top_ctrl->getVisible())
- {
- S32 screen_x, screen_y;
- top_ctrl->localPointToScreen(0, 0, &screen_x, &screen_y);
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- LLUI::pushMatrix();
- LLUI::translate((F32) screen_x, (F32) screen_y, 0.f);
- top_ctrl->draw();
- LLUI::popMatrix();
- }
- // Draw tooltips; adjust their rectangle so they do not go off the top
- // or bottom of the screen.
- if (mToolTip && mToolTip->getVisible() && !mToolTipBlocked)
- {
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- LLUI::pushMatrix();
- {
- S32 tip_height = mToolTip->getRect().getHeight();
- S32 screen_x, screen_y;
- mToolTip->localPointToScreen(0, -24 - tip_height,
- &screen_x, &screen_y);
- // If tooltip would draw off the bottom of the screen, show it
- // from the cursor tip position.
- if (screen_y < tip_height)
- {
- mToolTip->localPointToScreen(0, 0, &screen_x, &screen_y);
- }
- LLUI::translate((F32) screen_x, (F32) screen_y, 0);
- mToolTip->draw();
- }
- LLUI::popMatrix();
- }
- LLUI::sGLScaleFactor = old_scale_factor;
- }
- LLUI::popMatrix();
- gGL.popMatrix();
- gUIProgram.unbind();
- stop_glerror();
- }
- static bool focus_chatbar_if_needed()
- {
- if (!gChatBarp || gFocusMgr.childHasKeyboardFocus(gChatBarp) ||
- gAgent.cameraMouselook() || !gSavedSettings.getBool("AutoFocusChat"))
- {
- return false;
- }
- if (gChatBarp->getVisible() || LLFloaterChat::isFocused())
- {
- if (LLView::sDebugKeys)
- {
- llinfos << "Printable character detected, focusing chat bar"
- << llendl;
- }
- LLChatBar::startChat(NULL);
- return gFocusMgr.childHasKeyboardFocus(gChatBarp);
- }
- return false;
- }
- // Takes a single keydown event, usually when UI is visible
- //virtual
- bool LLViewerWindow::handleKey(KEY key, MASK mask)
- {
- sLastAcceleratorKey = 0;
- if (LLView::sDebugKeys)
- {
- llinfos << "key = " << std::hex << (U32)key << std::dec << " - mask = "
- << mask << llendl;
- }
- // Hide tooltips on keypress. Block until next time mouse is moved.
- mToolTipBlocked = true;
- // Also hide hover info on keypress
- if (gHoverViewp)
- {
- gHoverViewp->cancelHover();
- gHoverViewp->setTyping(true);
- }
- LLFocusableElement* keyboard_focus = gFocusMgr.getKeyboardFocus();
- if (keyboard_focus && !(mask & (MASK_CONTROL | MASK_ALT)) &&
- !gFocusMgr.getKeystrokesOnly())
- {
- if (keyboard_focus->wantsKeyUpKeyDown()) // Media element
- {
- if (LLView::sDebugKeys)
- {
- llinfos << "Key handling passed to the focused media element"
- << llendl;
- }
- return keyboard_focus->handleKey(key, mask, false);
- }
- if (key < 0x80)
- {
- // We have keyboard focus, and it is not an accelerator neither a
- // special key, so likely (we hope) to generate a character. Let it
- // fall through to character handler first.
- if (LLView::sDebugKeys)
- {
- llinfos << "Key handling passed to the keyboard character handler"
- << llendl;
- }
- return true;
- }
- }
- // *HACK: look for UI editing keys
- if (LLView::sEditingUI && LLFloaterEditUI::processKeystroke(key, mask))
- {
- if (LLView::sDebugKeys)
- {
- llinfos << "Key handled by the UI editor" << llendl;
- }
- return true;
- }
- // Handle shift-escape key (reset camera view)
- if (key == KEY_ESCAPE && mask == MASK_SHIFT)
- {
- if (LLView::sDebugKeys)
- {
- llinfos << "Key handling for SHIFT ESC: resetting view" << llendl;
- }
- handle_reset_view();
- return true;
- }
- // Let menus handle navigation keys
- if (gLoginMenuBarViewp && gLoginMenuBarViewp->handleKey(key, mask, true))
- {
- if (LLView::sDebugKeys)
- {
- llinfos << "Key handled by the login menu bar" << llendl;
- }
- sLastAcceleratorKey = key;
- return true;
- }
- if (gMenuBarViewp && gMenuBarViewp->handleKey(key, mask, true))
- {
- if (LLView::sDebugKeys)
- {
- llinfos << "Key handled by the menu bar" << llendl;
- }
- sLastAcceleratorKey = key;
- return true;
- }
- // Traverses up the hierarchy
- if (keyboard_focus)
- {
- // Arrow keys move avatar while chatting hack
- if (gChatBarp && gChatBarp->inputEditorHasFocus())
- {
- if (gChatBarp->hasTextEditor() ||
- gChatBarp->getCurrentChat().empty() ||
- gSavedSettings.getBool("ArrowKeysMoveAvatar"))
- {
- switch (key)
- {
- case KEY_LEFT:
- case KEY_RIGHT:
- case KEY_UP:
- case KEY_DOWN:
- // Let CTRL-key pass through for chat line history
- if (MASK_CONTROL == mask)
- {
- break;
- }
- case KEY_PAGE_UP:
- case KEY_PAGE_DOWN:
- case KEY_HOME:
- // When chatbar is empty or ArrowKeysMoveAvatar set,
- // pass arrow keys on to avatar...
- if (LLView::sDebugKeys)
- {
- llinfos << "Key handling aborted as per ArrowKeysMoveAvatar"
- << llendl;
- }
- return false;
- default:
- break;
- }
- }
- }
- if (keyboard_focus->handleKey(key, mask, false))
- {
- if (LLView::sDebugKeys)
- {
- llinfos << "Key handled by the keyboard focus holder"
- << llendl;
- }
- return true;
- }
- }
- if (gToolMgr.getCurrentTool()->handleKey(key, mask))
- {
- if (LLView::sDebugKeys)
- {
- llinfos << "Key handled by the tool manager" << llendl;
- }
- return true;
- }
- // Try for a new-format gesture
- if (gGestureManager.triggerGesture(key, mask))
- {
- if (LLView::sDebugKeys)
- {
- llinfos << "Key handled by the gesture manager (1)" << llendl;
- }
- return true;
- }
- // See if this is a gesture trigger. If so, eat the key and do not pass it
- // down to the menus.
- if (gGestureList.trigger(key, mask))
- {
- if (LLView::sDebugKeys)
- {
- llinfos << "Key handled by the gesture manager (2)" << llendl;
- }
- return true;
- }
- // Give floaters first chance to handle TAB key so that frontmost floater
- // gets focus. If nothing has focus, go to first or last UI element as
- // appropriate.
- if (key == KEY_TAB && ((mask & MASK_CONTROL) || !keyboard_focus))
- {
- if (LLView::sDebugKeys)
- {
- llinfos << "Key handling of the TAB key for focus cycling"
- << llendl;
- }
- if (gMenuHolderp)
- {
- gMenuHolderp->hideMenus();
- }
- // If CTRL-tabbing (and not just TAB with no focus), go into window
- // cycle mode
- if (gFloaterViewp)
- {
- gFloaterViewp->setCycleMode((mask & MASK_CONTROL) != 0);
- }
- // Do CTRL-TAB and CTRL-SHIFT-TAB logic
- if (mRootView)
- {
- if (mask & MASK_SHIFT)
- {
- mRootView->focusPrevRoot();
- }
- else
- {
- mRootView->focusNextRoot();
- }
- return true;
- }
- }
- // Give menus a chance to handle accelerator keys
- if (gLoginMenuBarViewp &&
- gLoginMenuBarViewp->handleAcceleratorKey(key, mask))
- {
- if (LLView::sDebugKeys)
- {
- llinfos << "Key handled by the login menu accelerators" << llendl;
- }
- sLastAcceleratorKey = key;
- return true;
- }
- if (gMenuBarViewp && gMenuBarViewp->handleAcceleratorKey(key, mask))
- {
- if (LLView::sDebugKeys)
- {
- llinfos << "Key handled by the menu accelerators" << llendl;
- }
- sLastAcceleratorKey = key;
- return true;
- }
- // See if chat bar needs to be auto-focused.
- if (key > 31 && key < 127 && (mask == MASK_NONE || mask == MASK_SHIFT))
- {
- if (focus_chatbar_if_needed())
- {
- keyboard_focus = gFocusMgr.getKeyboardFocus();
- if (keyboard_focus->handleKey(key, mask, false))
- {
- if (LLView::sDebugKeys)
- {
- llinfos << "Key handled by the chat bar"<< llendl;
- }
- return true;
- }
- }
- }
- // Do not pass keys on to world when something in UI has focus
- return gFocusMgr.childHasKeyboardFocus(mRootView) ||
- LLMenuGL::getKeyboardMode() ||
- (gMenuBarViewp && gMenuBarViewp->getHighlightedItem() &&
- gMenuBarViewp->getHighlightedItem()->isActive());
- }
- //virtual
- bool LLViewerWindow::handleKeyUp(KEY key, MASK mask)
- {
- LLFocusableElement* keyboard_focus = gFocusMgr.getKeyboardFocus();
- if (keyboard_focus && !(mask & (MASK_CONTROL | MASK_ALT)) &&
- !gFocusMgr.getKeystrokesOnly())
- {
- if (keyboard_focus->wantsKeyUpKeyDown())
- {
- if (LLView::sDebugKeys)
- {
- llinfos << "Key Up handling passed to the media plugin"
- << llendl;
- }
- return keyboard_focus->handleKeyUp(key, mask, false);
- }
- if (key < 0x80)
- {
- // We have keyboard focus, and it is not an accelerator neither a
- // special key, so likely (we hope) to generate a character. Let it
- // fall through to character handler first.
- if (LLView::sDebugKeys)
- {
- llinfos << "Key Up handling passed to the keyboard character handler"
- << llendl;
- }
- return true;
- }
- }
- if (keyboard_focus)
- {
- if (keyboard_focus->handleKeyUp(key, mask, false))
- {
- if (LLView::sDebugKeys)
- {
- llinfos << "Key Up handled by the keyboard focus holder"
- << llendl;
- }
- return true;
- }
- }
- // Do not pass keys on to world when something in UI has focus
- return gFocusMgr.childHasKeyboardFocus(mRootView) ||
- LLMenuGL::getKeyboardMode() ||
- (gMenuBarViewp && gMenuBarViewp->getHighlightedItem() &&
- gMenuBarViewp->getHighlightedItem()->isActive());
- }
- //virtual
- bool LLViewerWindow::handleUnicodeChar(llwchar uni_char, MASK mask)
- {
- if (!gKeyboardp) return true;
- if (LLView::sDebugKeys)
- {
- llinfos << "key = " << std::hex << (U32)uni_char << std::dec
- << " - mask = " << mask << " - Last accelerator key = "
- << std::hex << (U32)sLastAcceleratorKey << std::dec << llendl;
- }
- // Do not eat-up accelerator keys: give menus a chance to handle keys.
- if (mask & (MASK_CONTROL | MASK_ALT))
- {
- // *HACK: do not process twice the same key, when it was already
- // accounted for as an accelerator key in handleKey()... HB
- if (sLastAcceleratorKey)
- {
- if (LLView::sDebugKeys)
- {
- llinfos << "Key already handled by the menu accelerators in handleKey(), ignoring..."
- << llendl;
- }
- sLastAcceleratorKey = 0;
- return true;
- }
- if (gLoginMenuBarViewp)
- {
- KEY key = uni_char & 0xFFFF;
- if (gLoginMenuBarViewp->handleAcceleratorKey(key, mask))
- {
- if (LLView::sDebugKeys)
- {
- llinfos << "Key handled by the login menu accelerators"
- << llendl;
- }
- sLastAcceleratorKey = 0;
- return true;
- }
- if (gLoginMenuBarViewp->handleUnicodeChar(uni_char, true))
- {
- if (LLView::sDebugKeys)
- {
- llinfos << "Key handled as a login menu jump key"
- << llendl;
- }
- sLastAcceleratorKey = 0;
- return true;
- }
- }
- if (gMenuBarViewp)
- {
- KEY key = uni_char & 0xFFFF;
- if (gMenuBarViewp->handleAcceleratorKey(key, mask))
- {
- if (LLView::sDebugKeys)
- {
- llinfos << "Key handled by the menu accelerators" << llendl;
- }
- sLastAcceleratorKey = 0;
- return true;
- }
- if (gMenuBarViewp->handleUnicodeChar(uni_char, true))
- {
- if (LLView::sDebugKeys)
- {
- llinfos << "Key handled as a menu jump key" << llendl;
- }
- sLastAcceleratorKey = 0;
- return true;
- }
- }
- }
- sLastAcceleratorKey = 0;
- // *HACK: We delay processing of return keys until they arrive as a Unicode
- // char, so that if you are typing chat text at low frame rate, we do not
- // send the chat until all keystrokes have been entered. JC
- // *HACK: Numeric keypad <enter> on Mac is Unicode 3
- // *HACK: Control-M on Windows is Unicode 13
- if ((uni_char == 13 && mask != MASK_CONTROL) ||
- (uni_char == 3 && mask == MASK_NONE))
- {
- return gViewerKeyboard.handleKey(KEY_RETURN, mask,
- gKeyboardp->getKeyRepeated(KEY_RETURN));
- }
- // Traverse up the hierarchy
- LLFocusableElement* keyboard_focus = gFocusMgr.getKeyboardFocus();
- if (keyboard_focus)
- {
- if (LLView::sDebugKeys)
- {
- llinfos << "Traversing up the focused view hierarchy..." << llendl;
- }
- if (keyboard_focus->handleUnicodeChar(uni_char, false))
- {
- if (LLView::sDebugKeys)
- {
- llinfos << "Key got handled up in the hierarchy." << llendl;
- }
- return true;
- }
- else if (LLView::sDebugKeys)
- {
- llinfos << "Key was not handled up in the hierarchy." << llendl;
- }
- }
- // See if the chat bar needs to be auto-focused. HB
- bool is_media = keyboard_focus && keyboard_focus->wantsKeyUpKeyDown();
- if (!is_media && uni_char > 31 && uni_char < 256 && uni_char != 127 &&
- (mask == MASK_NONE || mask == MASK_SHIFT))
- {
- if (focus_chatbar_if_needed())
- {
- keyboard_focus = gFocusMgr.getKeyboardFocus();
- if (keyboard_focus->handleUnicodeChar(uni_char, false))
- {
- if (LLView::sDebugKeys)
- {
- llinfos << "Key handled by the chat bar" << llendl;
- }
- return true;
- }
- }
- }
- return false;
- }
- //virtual
- void LLViewerWindow::handleScrollWheel(S32 clicks)
- {
- LLView::sMouseHandlerMessage.clear();
- gMouseIdleTimer.reset();
- // Hide tooltips
- if (mToolTip)
- {
- mToolTip->setVisible(false);
- }
- LLMouseHandler* mouse_captor = gFocusMgr.getMouseCapture();
- if (mouse_captor)
- {
- S32 local_x;
- S32 local_y;
- mouse_captor->screenPointToLocal(mCurrentMousePoint.mX,
- mCurrentMousePoint.mY,
- &local_x, &local_y);
- mouse_captor->handleScrollWheel(local_x, local_y, clicks);
- if (LLView::sDebugMouseHandling)
- {
- llinfos << "Scroll wheel handled by captor "
- << mouse_captor->getName() << llendl;
- }
- return;
- }
- LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl();
- if (top_ctrl)
- {
- S32 local_x;
- S32 local_y;
- top_ctrl->screenPointToLocal(mCurrentMousePoint.mX,
- mCurrentMousePoint.mY,
- &local_x, &local_y);
- if (top_ctrl->handleScrollWheel(local_x, local_y, clicks))
- {
- return;
- }
- }
- if (mRootView->handleScrollWheel(mCurrentMousePoint.mX,
- mCurrentMousePoint.mY, clicks))
- {
- if (LLView::sDebugMouseHandling)
- {
- llinfos << "Scroll wheel" << LLView::sMouseHandlerMessage
- << llendl;
- }
- return;
- }
- if (LLView::sDebugMouseHandling)
- {
- llinfos << "Scroll wheel not handled by view" << llendl;
- }
- // Zoom the camera in and out behavior
- gAgent.handleScrollWheel(clicks);
- }
- void LLViewerWindow::moveCursorToCenter()
- {
- S32 x = mVirtualWindowRect.getWidth() / 2;
- S32 y = mVirtualWindowRect.getHeight() / 2;
- // On a forced move, all deltas get zeroed out to prevent jumping
- mCurrentMousePoint.set(x, y);
- mLastMousePoint.set(x, y);
- mCurrentMouseDelta.set(0, 0);
- LLUI::setCursorPositionScreen(x, y);
- }
- bool LLViewerWindow::shouldShowToolTipFor(LLMouseHandler* mh)
- {
- if (mToolTip && mh)
- {
- LLMouseHandler::EShowToolTip showlevel = mh->getShowToolTip();
- return (showlevel == LLMouseHandler::SHOW_ALWAYS ||
- (showlevel == LLMouseHandler::SHOW_IF_NOT_BLOCKED &&
- !mToolTipBlocked));
- }
- return false;
- }
- //virtual
- bool LLViewerWindow::handleAnyMouseClick(LLWindow* window, LLCoordGL pos,
- MASK mask,
- LLMouseHandler::EClickType clicktype,
- bool down)
- {
- std::string buttonname;
- std::string buttonstatestr = down ? "down" : "up";
- bool handled = false;
- S32 x = pos.mX;
- S32 y = pos.mY;
- x = ll_round((F32)x * mDisplayScaleDivisor.mV[VX]);
- y = ll_round((F32)y * mDisplayScaleDivisor.mV[VY]);
- switch (clicktype)
- {
- case LLMouseHandler::CLICK_LEFT:
- {
- mLeftMouseDown = down;
- buttonname = "Left";
- break;
- }
- case LLMouseHandler::CLICK_RIGHT:
- {
- mRightMouseDown = down;
- buttonname = "Right";
- break;
- }
- case LLMouseHandler::CLICK_MIDDLE:
- {
- mMiddleMouseDown = down;
- buttonname = "Middle";
- break;
- }
- case LLMouseHandler::CLICK_DOUBLELEFT:
- {
- mLeftMouseDown = down;
- buttonname = "Left Double Click";
- }
- }
- LLView::sMouseHandlerMessage.clear();
- if (gMenuBarViewp)
- {
- // Stop ALT-key access to menu
- gMenuBarViewp->resetMenuTrigger();
- }
- if (gDebugClicks)
- {
- llinfos << "ViewerWindow " << buttonname << " mouse " << buttonstatestr
- << " at " << x << "," << y << llendl;
- }
- // Make sure we get a corresponding mouse-up event, even if the mouse
- // leaves the window
- if (down)
- {
- gWindowp->captureMouse();
- }
- else
- {
- gWindowp->releaseMouse();
- }
- // Indicate mouse was active
- gMouseIdleTimer.reset();
- // Hide tooltips on mousedown
- if (mToolTip && down)
- {
- mToolTipBlocked = true;
- mToolTip->setVisible(false);
- }
- // Also hide hover info on mousedown/mouseup
- if (gHoverViewp)
- {
- gHoverViewp->cancelHover();
- }
- // Do not let the user move the mouse out of the window until mouse up.
- if (gToolMgr.getCurrentTool()->clipMouseWhenDown())
- {
- gWindowp->setMouseClipping(down);
- }
- LLMouseHandler* mouse_captor = gFocusMgr.getMouseCapture();
- if (mouse_captor)
- {
- S32 local_x;
- S32 local_y;
- mouse_captor->screenPointToLocal(x, y, &local_x, &local_y);
- if (LLView::sDebugMouseHandling)
- {
- llinfos << buttonname << " Mouse " << buttonstatestr
- << " handled by captor " << mouse_captor->getName()
- << llendl;
- }
- return mouse_captor->handleAnyMouseClick(local_x, local_y, mask,
- clicktype, down);
- }
- // Topmost view gets a chance before the hierarchy
- LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl();
- if (top_ctrl)
- {
- S32 local_x, local_y;
- top_ctrl->screenPointToLocal(x, y, &local_x, &local_y);
- if (down)
- {
- if (top_ctrl->pointInView(local_x, local_y))
- {
- return top_ctrl->handleAnyMouseClick(local_x, local_y, mask,
- clicktype, down);
- }
- else
- {
- gFocusMgr.setTopCtrl(NULL);
- }
- }
- else
- {
- handled = top_ctrl->pointInView(local_x, local_y) &&
- top_ctrl->handleMouseUp(local_x, local_y, mask);
- }
- }
- // Give the UI views a chance to process the click
- if (mRootView->handleAnyMouseClick(x, y, mask, clicktype, down))
- {
- if (LLView::sDebugMouseHandling)
- {
- llinfos << buttonname << " Mouse " << buttonstatestr << " "
- << LLView::sMouseHandlerMessage << llendl;
- }
- return true;
- }
- else if (LLView::sDebugMouseHandling)
- {
- llinfos << buttonname << " Mouse " << buttonstatestr
- << " not handled by view" << llendl;
- }
- if (down)
- {
- if (gDisconnected)
- {
- return false;
- }
- if (gToolMgr.getCurrentTool()->handleAnyMouseClick(x, y, mask,
- clicktype, down))
- {
- // This is necessary to force clicks in the world to cause edit
- // boxes that might have keyboard focus to relinquish it, and hence
- // cause a commit to update their value. JC
- gFocusMgr.setKeyboardFocus(NULL);
- return true;
- }
- }
- else
- {
- gWindowp->releaseMouse();
- LLTool* tool = gToolMgr.getCurrentTool();
- if (!handled)
- {
- handled = mRootView->handleAnyMouseClick(x, y, mask, clicktype, down);
- }
- if (!handled && tool)
- {
- handled = tool->handleAnyMouseClick(x, y, mask, clicktype, down);
- }
- }
- return !down;
- }
- //virtual
- bool LLViewerWindow::handleMouseDown(LLWindow* window, LLCoordGL pos,
- MASK mask)
- {
- #if LL_DARWIN
- mAllowMouseDragging = false;
- if (!mMouseDownTimer.getStarted())
- {
- mMouseDownTimer.start();
- }
- else
- {
- mMouseDownTimer.reset();
- }
- #endif
- return handleAnyMouseClick(window, pos, mask, LLMouseHandler::CLICK_LEFT,
- true); // down
- }
- //virtual
- bool LLViewerWindow::handleDoubleClick(LLWindow* window, LLCoordGL pos,
- MASK mask)
- {
- // try handling as a double-click first, then a single-click if that wasn't
- // handled.
- return handleAnyMouseClick(window, pos, mask,
- LLMouseHandler::CLICK_DOUBLELEFT, true) ||
- handleMouseDown(window, pos, mask);
- }
- //virtual
- bool LLViewerWindow::handleMouseUp(LLWindow* window, LLCoordGL pos, MASK mask)
- {
- #if LL_DARWIN
- if (mMouseDownTimer.getStarted())
- {
- mMouseDownTimer.stop();
- }
- #endif
- return handleAnyMouseClick(window, pos, mask, LLMouseHandler::CLICK_LEFT,
- false); // up
- }
- //virtual
- bool LLViewerWindow::handleRightMouseDown(LLWindow* window, LLCoordGL pos,
- MASK mask)
- {
- S32 x = pos.mX;
- S32 y = pos.mY;
- x = ll_round((F32)x * mDisplayScaleDivisor.mV[VX]);
- y = ll_round((F32)y * mDisplayScaleDivisor.mV[VY]);
- LLView::sMouseHandlerMessage.clear();
- if (handleAnyMouseClick(window, pos, mask, LLMouseHandler::CLICK_RIGHT,
- true))
- {
- return true;
- }
- // *HACK: this should be rolled into the composite tool logic, not
- // hardcoded at the top level.
- if (gAgent.getCameraMode() != CAMERA_MODE_CUSTOMIZE_AVATAR &&
- !gToolMgr.isCurrentTool(&gToolPie))
- {
- // If the current tool did not process the click, we should show the
- // pie menu. This can be done by passing the event to the pie menu
- // tool.
- gToolPie.handleRightMouseDown(x, y, mask);
- }
- return true;
- }
- //virtual
- bool LLViewerWindow::handleRightMouseUp(LLWindow* window, LLCoordGL pos,
- MASK mask)
- {
- return handleAnyMouseClick(window,pos,mask,LLMouseHandler::CLICK_RIGHT,
- false); // Up
- }
- //virtual
- bool LLViewerWindow::handleMiddleMouseDown(LLWindow* window, LLCoordGL pos,
- MASK mask)
- {
- if (gVoiceClient.ready())
- {
- gVoiceClient.middleMouseState(true);
- }
- handleAnyMouseClick(window, pos, mask, LLMouseHandler::CLICK_MIDDLE, true);
- // Always handled as far as the OS is concerned.
- return true;
- }
- //virtual
- bool LLViewerWindow::handleMiddleMouseUp(LLWindow* window, LLCoordGL pos,
- MASK mask)
- {
- if (gVoiceClient.ready())
- {
- gVoiceClient.middleMouseState(false);
- }
- handleAnyMouseClick(window, pos, mask, LLMouseHandler::CLICK_MIDDLE,
- false);
- // Always handled as far as the OS is concerned.
- return true;
- }
- // WARNING: this is potentially called multiple times per frame
- //virtual
- void LLViewerWindow::handleMouseMove(LLWindow* window, LLCoordGL pos,
- MASK mask)
- {
- S32 x = pos.mX;
- S32 y = pos.mY;
- x = ll_round((F32)x * mDisplayScaleDivisor.mV[VX]);
- y = ll_round((F32)y * mDisplayScaleDivisor.mV[VY]);
- mMouseInWindow = true;
- // Save mouse point for access during idle() and display()
- LLCoordGL prev_saved_mouse_point = mCurrentMousePoint;
- LLCoordGL mouse_point(x, y);
- saveLastMouse(mouse_point);
- bool actually_moved = // mouse is not currenty captured:
- !gFocusMgr.getMouseCapture() &&
- // mouse moved from last recorded position:
- (prev_saved_mouse_point.mX != mCurrentMousePoint.mX ||
- prev_saved_mouse_point.mY != mCurrentMousePoint.mY);
- gMouseIdleTimer.reset();
- gWindowp->showCursorFromMouseMove();
- if (gAwayTimer.getElapsedTimeF32() > MIN_AFK_TIME)
- {
- gAgent.clearAFK();
- }
- if (actually_moved)
- {
- mToolTipBlocked = false;
- }
- // Activate the hover picker on mouse move.
- if (gHoverViewp)
- {
- gHoverViewp->setTyping(false);
- }
- }
- #if LL_DARWIN
- //virtual
- void LLViewerWindow::handleMouseDragged(LLWindow* window, LLCoordGL pos,
- MASK mask)
- {
- if (mMouseDownTimer.getStarted())
- {
- if (mMouseDownTimer.getElapsedTimeF32() > 0.1)
- {
- mAllowMouseDragging = true;
- mMouseDownTimer.stop();
- }
- }
- if (mAllowMouseDragging || !gToolFocus.hasMouseCapture())
- {
- handleMouseMove(window, pos, mask);
- }
- }
- #endif
- //virtual
- void LLViewerWindow::handleMouseLeave(LLWindow* window)
- {
- // Note: we would not get this if we had captured the mouse.
- llassert(gFocusMgr.getMouseCapture() == NULL);
- mMouseInWindow = false;
- if (mToolTip)
- {
- mToolTip->setVisible(false);
- }
- }
- //virtual
- bool LLViewerWindow::handleCloseRequest(LLWindow* window)
- {
- // User has indicated they want to close, but we may need to ask about
- // modified documents.
- gAppViewerp->userQuit();
- // Do not quit immediately
- return false;
- }
- //virtual
- void LLViewerWindow::handleQuit(LLWindow* window)
- {
- llinfos << "Quit window event received." << llendl;
- gAppViewerp->forceQuit();
- }
- //virtual
- void LLViewerWindow::handleResize(LLWindow* window, S32 width, S32 height)
- {
- reshape(width, height);
- mResDirty = true;
- }
- // The top-level window has gained focus (e.g. via ALT-TAB)
- //virtual
- void LLViewerWindow::handleFocus(LLWindow* window)
- {
- gFocusMgr.setAppHasFocus(true);
- LLModalDialog::onAppFocusGained();
- gAgent.onAppFocusGained();
- gToolMgr.onAppFocusGained();
- gShowTextEditCursor = true;
- // See if we are coming in with modifier keys held down
- if (gKeyboardp)
- {
- gKeyboardp->resetMaskKeys();
- }
- }
- // The top-level window has lost focus (e.g. via ALT-TAB)
- //virtual
- void LLViewerWindow::handleFocusLost(LLWindow* window)
- {
- gFocusMgr.setAppHasFocus(false);
- gToolMgr.onAppFocusLost();
- gFocusMgr.setMouseCapture(NULL);
- if (gMenuBarViewp)
- {
- // Stop ALT-key access to menu
- gMenuBarViewp->resetMenuTrigger();
- }
- // Restore mouse cursor
- showCursor();
- gWindowp->setMouseClipping(false);
- gShowTextEditCursor = false;
- // If losing focus while keys are down, reset them.
- if (gKeyboardp)
- {
- gKeyboardp->resetKeys();
- }
- }
- //virtual
- bool LLViewerWindow::handleTranslatedKeyDown(KEY key, MASK mask, bool repeated)
- {
- // Let the voice chat code check for its PTT key. Note that this never
- // affects event processing.
- if (gVoiceClient.ready())
- {
- gVoiceClient.keyDown(key, mask);
- }
- if (gAwayTimer.getElapsedTimeF32() > MIN_AFK_TIME)
- {
- gAgent.clearAFK();
- }
- // *NOTE: we want to interpret KEY_RETURN later when it arrives as a
- // Unicode char, not as a keydown. Otherwise when client frame rate is
- // really low, hitting return sends your chat text before it is all
- // entered/processed.
- if (key == KEY_RETURN && mask == MASK_NONE)
- {
- // RIDER: although, at times some of the controls (in particular the
- // CEF viewer would like to know about the KEYDOWN for an enter key...
- // So ask and pass it along.
- LLFocusableElement* keyboard_focus = gFocusMgr.getKeyboardFocus();
- if (!keyboard_focus || !keyboard_focus->wantsReturnKey())
- {
- return false;
- }
- }
- return gViewerKeyboard.handleKey(key, mask, repeated);
- }
- //virtual
- bool LLViewerWindow::handleTranslatedKeyUp(KEY key, MASK mask)
- {
- // Let the voice chat code check for its PTT key. Note that this never
- // affects event processing.
- if (gVoiceClient.ready())
- {
- gVoiceClient.keyUp(key, mask);
- }
- return gViewerKeyboard.handleKeyUp(key, mask);
- }
- //virtual
- void LLViewerWindow::handleScanKey(KEY key, bool key_down, bool key_up,
- bool key_level)
- {
- LLViewerJoystick::getInstance()->setCameraNeedsUpdate(true);
- return gViewerKeyboard.scanKey(key, key_down, key_up, key_level);
- }
- //virtual
- bool LLViewerWindow::handleActivate(LLWindow* window, bool activated)
- {
- if (activated)
- {
- mActive = true;
- LLWorld::sendAgentResume();
- gAgent.clearAFK();
- if (gWindowp->getFullscreen() && !mIgnoreActivate)
- {
- if (!LLApp::isExiting())
- {
- if (LLStartUp::isLoggedIn())
- {
- // If we are in world, show a progress bar to hide
- // reloading of textures
- llinfos << "Restoring GL during activate" << llendl;
- restoreGL("Restoring...");
- }
- else
- {
- // Otherwise restore immediately
- restoreGL();
- }
- }
- else
- {
- llwarns << "Activating while quitting" << llendl;
- }
- }
- // Unmute audio
- audio_update_volume();
- }
- else
- {
- mActive = false;
- gAppViewerp->idleAFKCheck(true);
- if (gAgent.cameraMouselook())
- {
- // Switch back to mouselook toolset
- gToolMgr.setCurrentToolset(gMouselookToolset);
- gSelectMgr.deselectAll();
- gViewerWindowp->hideCursor();
- gViewerWindowp->moveCursorToCenter();
- }
- LLWorld::sendAgentPause();
- if (gWindowp->getFullscreen() && !mIgnoreActivate)
- {
- llinfos << "Stopping GL during deactivation" << llendl;
- stopGL();
- }
- // Mute audio
- audio_update_volume();
- }
- return true;
- }
- //virtual
- bool LLViewerWindow::handleActivateApp(LLWindow* window, bool activating)
- {
- LLViewerJoystick::getInstance()->setNeedsReset(true);
- return false;
- }
- //virtual
- void LLViewerWindow::handleMenuSelect(LLWindow* window, S32 menu_item)
- {
- }
- //virtual
- bool LLViewerWindow::handlePaint(LLWindow* window, S32 x, S32 y, S32 width,
- S32 height)
- {
- return false;
- }
- //virtual
- void LLViewerWindow::handleScrollWheel(LLWindow* window, S32 clicks)
- {
- handleScrollWheel(clicks);
- }
- //virtual
- void LLViewerWindow::handleWindowBlock(LLWindow* window)
- {
- LLWorld::sendAgentPause();
- }
- //virtual
- void LLViewerWindow::handleWindowUnblock(LLWindow* window)
- {
- LLWorld::sendAgentResume();
- }
- //virtual
- void LLViewerWindow::handleDataCopy(LLWindow*, S32 data_type, void* data)
- {
- constexpr S32 SLURL_MESSAGE_TYPE = 0;
- if (data_type == SLURL_MESSAGE_TYPE)
- {
- // Received URL
- std::string url = (const char*)data;
- if (LLURLDispatcher::dispatch(url, "", NULL, false))
- {
- // Bring window to foreground, as it has just been "launched" from
- // an URL.
- gWindowp->bringToFront();
- }
- }
- }
- #if LL_WINDOWS
- //virtual
- bool LLViewerWindow::handleTimerEvent(LLWindow* window)
- {
- LLViewerJoystick* joystick = LLViewerJoystick::getInstance();
- if (joystick->getOverrideCamera())
- {
- joystick->updateStatus();
- return true;
- }
- return false;
- }
- //virtual
- bool LLViewerWindow::handleDeviceChange(LLWindow* window)
- {
- // Give a chance to use a joystick after startup (hot-plugging)
- LLViewerJoystick* joystick = LLViewerJoystick::getInstance();
- if (!joystick->isJoystickInitialized())
- {
- joystick->init(true);
- return true;
- }
- return false;
- }
- //virtual
- bool LLViewerWindow::handleDPIChanged(LLWindow* window, F32 ui_scale_factor,
- S32 window_width, S32 window_height)
- {
- if (LLApp::isExiting())
- {
- LL_DEBUGS("Window") << "Application is exiting, not reshaping the window."
- << LL_ENDL;
- return false;
- }
- // HiDPI scaling can be 4x. UI scaling in prefs is up to 2x, so max is 8x
- if (ui_scale_factor < 0.75f || ui_scale_factor > 8.f)
- {
- llwarns << "DPI change caused UI scale to go out of bounds: "
- << ui_scale_factor << ". Not reshaping window." << llendl;
- return false;
- }
- LL_DEBUGS("Window") << "Reshaping the window..." << LL_ENDL;
- reshape(window_width, window_height);
- mResDirty = true;
- return true;
- }
- #endif
- //virtual
- bool LLViewerWindow::handleWindowDidChangeScreen(LLWindow* window)
- {
- LLCoordScreen size;
- gWindowp->getSize(&size);
- reshape(size.mX, size.mY);
- return true;
- }
- ///////////////////////////////////////////////////////////////////////////////
- //
- // Hover handlers
- //
- // Update UI based on stored mouse position from mouse-move event processing.
- bool LLViewerWindow::handlePerFrameHover()
- {
- static std::string last_handle_msg;
- LLView::sMouseHandlerMessage.clear();
- if (!gFloaterViewp || !gKeyboardp) return true;
- const S32 x = mCurrentMousePoint.mX;
- const S32 y = mCurrentMousePoint.mY;
- MASK mask = gKeyboardp->currentMask(true);
- // RN: fix for asynchronous notification of mouse leaving window not
- // working
- LLCoordWindow mouse_pos;
- gWindowp->getCursorPosition(&mouse_pos);
- if (mouse_pos.mX < 0 || mouse_pos.mY < 0 ||
- mouse_pos.mX > mWindowRect.getWidth() ||
- mouse_pos.mY > mWindowRect.getHeight())
- {
- mMouseInWindow = false;
- }
- else
- {
- mMouseInWindow = true;
- }
- S32 dx = lltrunc((F32)(mCurrentMousePoint.mX - mLastMousePoint.mX) *
- LLUI::sGLScaleFactor.mV[VX]);
- S32 dy = lltrunc((F32)(mCurrentMousePoint.mY - mLastMousePoint.mY) *
- LLUI::sGLScaleFactor.mV[VY]);
- LLVector2 mouse_vel;
- static LLCachedControl<bool> mouse_smooth(gSavedSettings, "MouseSmooth");
- if (mouse_smooth)
- {
- static F32 fdx = 0.f;
- static F32 fdy = 0.f;
- F32 amount = llmin(gFrameIntervalSeconds * 16.f, 1.f);
- fdx = fdx + ((F32)dx - fdx) * amount;
- fdy = fdy + ((F32)dy - fdy) * amount;
- mCurrentMouseDelta.set(ll_round(fdx), ll_round(fdy));
- mouse_vel.set(fdx, fdy);
- }
- else
- {
- mCurrentMouseDelta.set(dx, dy);
- mouse_vel.set((F32)dx, (F32)dy);
- }
- sMouseVelocityStat.addValue(mouse_vel.length());
- // Clean up current focus
- LLUICtrl* cur_focus = gFocusMgr.getKeyboardFocusUICtrl();
- if (cur_focus)
- {
- if (!cur_focus->isInVisibleChain() || !cur_focus->isInEnabledChain())
- {
- gFocusMgr.releaseFocusIfNeeded(cur_focus);
- LLUICtrl* parent = cur_focus->getParentUICtrl();
- const LLUICtrl* focus_root = cur_focus->findRootMostFocusRoot();
- while (parent)
- {
- if (parent->isCtrl() &&
- (parent->hasTabStop() || parent == focus_root) &&
- !parent->getIsChrome() &&
- parent->isInVisibleChain() &&
- parent->isInEnabledChain())
- {
- if (!parent->focusFirstItem())
- {
- parent->setFocus(true);
- }
- break;
- }
- parent = parent->getParentUICtrl();
- }
- }
- else if (cur_focus->isFocusRoot())
- {
- // Focus roots keep trying to delegate focus to their first valid
- // descendant; this assumes that focus roots are not valid focus
- // holders on their own.
- cur_focus->focusFirstItem();
- }
- }
- bool handled = false;
- bool handled_by_top_ctrl = false;
- LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl();
- LLMouseHandler* mouse_captor = gFocusMgr.getMouseCapture();
- if (mouse_captor)
- {
- // Pass hover events to object capturing mouse events.
- S32 local_x;
- S32 local_y;
- mouse_captor->screenPointToLocal(x, y, &local_x, &local_y);
- handled = mouse_captor->handleHover(local_x, local_y, mask);
- if (LLView::sDebugMouseHandling)
- {
- llinfos << "Hover handled by captor " << mouse_captor->getName()
- << llendl;
- }
- if (!handled)
- {
- LL_DEBUGS("UserInput") << "hover not handled by mouse captor"
- << LL_ENDL;
- }
- }
- else
- {
- if (top_ctrl)
- {
- S32 local_x, local_y;
- top_ctrl->screenPointToLocal(x, y, &local_x, &local_y);
- handled = top_ctrl->pointInView(local_x, local_y) &&
- top_ctrl->handleHover(local_x, local_y, mask);
- handled_by_top_ctrl = true;
- }
- if (!handled)
- {
- // x and y are from last time mouse was in window
- // mMouseInWindow tracks *actual* mouse location
- if (mMouseInWindow && mRootView->handleHover(x, y, mask))
- {
- if (LLView::sDebugMouseHandling &&
- LLView::sMouseHandlerMessage != last_handle_msg)
- {
- last_handle_msg = LLView::sMouseHandlerMessage;
- llinfos << "Hover" << LLView::sMouseHandlerMessage
- << llendl;
- }
- handled = true;
- }
- else if (LLView::sDebugMouseHandling)
- {
- if (last_handle_msg != LLStringUtil::null)
- {
- last_handle_msg.clear();
- llinfos << "Hover not handled by view" << llendl;
- }
- }
- }
- if (!handled)
- {
- LL_DEBUGS("UserInput") << "hover not handled by top view or root"
- << LL_ENDL;
- }
- }
- LLToolPie* toolpie = &gToolPie;
- // *NOTE: sometimes tools handle the mouse as a captor, so this logic is a
- // little confusing
- LLTool* tool = NULL;
- if (gHoverViewp)
- {
- tool = gToolMgr.getCurrentTool();
- if (!handled && tool)
- {
- handled = tool->handleHover(x, y, mask);
- if (!gWindowp->isCursorHidden())
- {
- gHoverViewp->updateHover(tool);
- }
- }
- else
- {
- // Cancel hovering if any UI element handled the event.
- gHoverViewp->cancelHover();
- }
- // Suppress the toolbox view if our source tool was the pie tool and
- // we have overridden to something else.
- mSuppressToolbox = gToolMgr.getBaseTool() == toolpie &&
- gToolMgr.getCurrentTool() != toolpie;
- }
- // Show a new tool tip (or update one that is alrady shown)
- bool tool_tip_handled = false;
- std::string tool_tip_msg;
- static LLCachedControl<F32> normal_tool_tip_delay(gSavedSettings,
- "ToolTipDelay");
- static LLCachedControl<F32> dad_tool_tip_delay(gSavedSettings,
- "DragAndDropToolTipDelay");
- F32 tooltip_delay = normal_tool_tip_delay;
- // *HACK: hack for tool-based tooltips which need to pop up more quickly
- // Also for show xui names as tooltips debug mode
- if ((mouse_captor && !mouse_captor->isView()) || LLUI::sShowXUINames)
- {
- tooltip_delay = dad_tool_tip_delay;
- }
- if (handled && !gWindowp->isCursorHidden() &&
- gMouseIdleTimer.getElapsedTimeF32() > tooltip_delay)
- {
- LLRect screen_sticky_rect;
- LLMouseHandler *mh;
- S32 local_x, local_y;
- if (mouse_captor)
- {
- mouse_captor->screenPointToLocal(x, y, &local_x, &local_y);
- mh = mouse_captor;
- }
- else if (handled_by_top_ctrl)
- {
- top_ctrl->screenPointToLocal(x, y, &local_x, &local_y);
- mh = top_ctrl;
- }
- else
- {
- local_x = x; local_y = y;
- mh = mRootView;
- }
- bool tooltip_vis = false;
- if (shouldShowToolTipFor(mh))
- {
- tool_tip_handled = mh->handleToolTip(local_x, local_y,
- tool_tip_msg,
- &screen_sticky_rect);
- if (mToolTip && tool_tip_handled && !tool_tip_msg.empty())
- {
- mToolTipStickyRect = screen_sticky_rect;
- mToolTip->setWrappedText(tool_tip_msg, 200);
- mToolTip->reshapeToFitText();
- mToolTip->setOrigin(x, y);
- LLRect virtual_window_rect(0, getWindowHeight(),
- getWindowWidth(), 0);
- mToolTip->translateIntoRect(virtual_window_rect, false);
- tooltip_vis = true;
- }
- }
- if (mToolTip)
- {
- mToolTip->setVisible(tooltip_vis);
- }
- }
- if (gFloaterToolsp && tool && tool != gToolNull &&
- tool != &gToolCompInspect && tool != &gToolDragAndDrop &&
- !LLPipeline::sFreezeTime)
- {
- LLMouseHandler* captor = gFocusMgr.getMouseCapture();
- // With the null, inspect, or drag and drop tool, do not muck with
- // visibility.
- if (gFloaterToolsp->isMinimized() ||
- (tool != toolpie && // Not default tool
- // Not coming out of mouselook
- tool != &gToolCompGun &&
- // Not override in third person
- !mSuppressToolbox &&
- // Not in a special mode
- gToolMgr.getCurrentToolset() != gFaceEditToolset &&
- gToolMgr.getCurrentToolset() != gMouselookToolset &&
- // Not dragging
- (!captor || captor->isView())))
- {
- // Force floater tools to be visible (unless minimized)
- if (!LLFloaterTools::isVisible())
- {
- gFloaterToolsp->open();
- }
- // Update the location of the blue box tool popup
- LLCoordGL select_center_screen;
- gFloaterToolsp->updatePopup(select_center_screen, mask);
- }
- else
- {
- gFloaterToolsp->setVisible(false);
- }
- }
- if (gToolBarp)
- {
- gToolBarp->refresh();
- }
- if (gChatBarp)
- {
- gChatBarp->refresh();
- }
- if (gOverlayBarp)
- {
- if (gOverlayBarp->getVisible())
- {
- if (gAgent.cameraMouselook())
- {
- // Turn off the whole bar in mouselook
- gOverlayBarp->setVisible(false);
- }
- }
- else if (!gAgent.cameraMouselook())
- {
- // Turn on the bar when no more in mouse-look
- gOverlayBarp->setVisible(true);
- }
- }
- if (gLuaSideBarp)
- {
- if (gLuaSideBarp->getVisible())
- {
- if (gAgent.cameraMouselook())
- {
- // Turn off the whole bar in mouselook
- gLuaSideBarp->setVisible(false);
- }
- }
- else if (!gAgent.cameraMouselook())
- {
- // Turn on the bar when no more in mouse-look
- gLuaSideBarp->setVisible(true);
- }
- }
- // Update rectangles for the various toolbars
- if (gOverlayBarp && gNotifyBoxViewp && gFloaterViewp && gConsolep &&
- gToolBarp && gChatBarp)
- {
- LLRect bar_rect(-1, gStatusBarHeight, getWindowWidth() + 1, -1);
- if (gToolBarp->getVisible())
- {
- gToolBarp->setRect(bar_rect);
- bar_rect.translate(0, gStatusBarHeight - 1);
- }
- if (gChatBarp->getVisible())
- {
- // Fix up the height
- LLRect chat_bar_rect = bar_rect;
- chat_bar_rect.mTop = chat_bar_rect.mBottom + CHAT_BAR_HEIGHT + 1;
- gChatBarp->setRect(chat_bar_rect);
- bar_rect.translate(0, CHAT_BAR_HEIGHT - 1);
- }
- LLRect notify_box_rect = gNotifyBoxViewp->getRect();
- notify_box_rect.mBottom = bar_rect.mBottom;
- gNotifyBoxViewp->reshape(notify_box_rect.getWidth(),
- notify_box_rect.getHeight());
- gNotifyBoxViewp->setRect(notify_box_rect);
- // Make sure floaters snap to visible rect by adjusting floater view
- // rect
- LLRect floater_rect = gFloaterViewp->getRect();
- if (floater_rect.mBottom != bar_rect.mBottom + 1)
- {
- floater_rect.mBottom = bar_rect.mBottom + 1;
- // Don't bounce the floaters up and down.
- gFloaterViewp->reshapeFloater(floater_rect.getWidth(),
- floater_rect.getHeight(),
- true, ADJUST_VERTICAL_NO);
- gFloaterViewp->setRect(floater_rect);
- }
- if (gOverlayBarp->getVisible())
- {
- LLRect overlay_rect = bar_rect;
- overlay_rect.mTop = overlay_rect.mBottom + OVERLAY_BAR_HEIGHT;
- // Fitt's Law: push buttons flush with bottom of screen if nothing
- // else visible.
- if (!gToolBarp->getVisible() && !gChatBarp->getVisible())
- {
- // *NOTE: this is highly depenent on the XML describing the
- // position of the buttons
- overlay_rect.translate(0, 0);
- }
- gOverlayBarp->setRect(overlay_rect);
- gOverlayBarp->updateBoundingRect();
- bar_rect.translate(0, gOverlayBarp->getRect().getHeight());
- gFloaterViewp->setSnapOffsetBottom(OVERLAY_BAR_HEIGHT);
- }
- else
- {
- gFloaterViewp->setSnapOffsetBottom(0);
- }
- // Fix rectangle of bottom panel focus indicator
- if (gBottomPanelp && gBottomPanelp->getFocusIndicator())
- {
- LLRect focus_rect = gBottomPanelp->getFocusIndicator()->getRect();
- focus_rect.mTop = (gToolBarp->getVisible() ? gStatusBarHeight : 0) +
- (gChatBarp->getVisible() ? CHAT_BAR_HEIGHT : 0) - 2;
- gBottomPanelp->getFocusIndicator()->setRect(focus_rect);
- }
- // Always update console
- LLRect console_rect = getChatConsoleRect();
- console_rect.mBottom = bar_rect.mBottom - 8;
- gConsolep->reshape(console_rect.getWidth(), console_rect.getHeight());
- gConsolep->setRect(console_rect);
- }
- mLastMousePoint = mCurrentMousePoint;
- // Last ditch force of edit menu to selection manager
- if (!gEditMenuHandlerp && gSelectMgr.getSelection()->getObjectCount())
- {
- gEditMenuHandlerp = &gSelectMgr;
- }
- if (gFloaterViewp->getCycleMode())
- {
- // sync all floaters with their focus state
- gFloaterViewp->highlightFocusedFloater();
- gSnapshotFloaterViewp->highlightFocusedFloater();
- // When user is holding down CTRL, do not update tab order of floaters
- if ((gKeyboardp->currentMask(true) & MASK_CONTROL) == 0)
- {
- // Control key no longer held down, finish cycle mode
- gFloaterViewp->setCycleMode(false);
- gFloaterViewp->syncFloaterTabOrder();
- }
- }
- else
- {
- // Update focused floater
- gFloaterViewp->highlightFocusedFloater();
- gSnapshotFloaterViewp->highlightFocusedFloater();
- // Make sure floater visible order is in sync with tab order
- gFloaterViewp->syncFloaterTabOrder();
- }
- static LLCachedControl<bool> chat_bar_steals_focus(gSavedSettings,
- "ChatBarStealsFocus");
- if (chat_bar_steals_focus && gChatBarp &&
- gFocusMgr.getKeyboardFocus() == NULL &&
- gChatBarp->isInVisibleChain())
- {
- LLChatBar::startChat(NULL);
- }
- // Cleanup unused selections when no modal dialogs are open
- if (LLModalDialog::activeCount() == 0)
- {
- gViewerParcelMgr.deselectUnused();
- }
- if (LLModalDialog::activeCount() == 0)
- {
- gSelectMgr.deselectUnused();
- }
- if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_RAYCAST))
- {
- gDebugRaycastFaceHit = gDebugRaycastGLTFNodeHit =
- gDebugRaycastGLTFPrimHit = -1;
- gDebugRaycastObject = cursorIntersect(-1, -1, 512.f, NULL, -1,
- false, false,
- &gDebugRaycastFaceHit,
- &gDebugRaycastGLTFNodeHit,
- &gDebugRaycastGLTFPrimHit,
- &gDebugRaycastIntersection,
- &gDebugRaycastTexCoord,
- &gDebugRaycastNormal,
- &gDebugRaycastTangent,
- &gDebugRaycastStart,
- &gDebugRaycastEnd);
- gDebugRaycastParticle =
- gPipeline.lineSegmentIntersectParticle(gDebugRaycastStart,
- gDebugRaycastEnd,
- &gDebugRaycastParticleIntersection,
- NULL);
- }
- // Per frame picking for tooltips and changing cursor over interactive
- // objects
- static S32 previous_x = -1;
- static S32 previous_y = -1;
- bool mouse_moved_since_pick = previous_x != x || previous_y != y;
- bool do_pick = false;
- static LLCachedControl<F32> picks_moving(gSavedSettings,
- "PicksPerSecondMouseMoving");
- if (mouse_moved_since_pick && picks_moving > 0.f &&
- mPickTimer.getElapsedTimeF32() > 1.f / picks_moving)
- {
- do_pick = true;
- }
- static LLCachedControl<F32> picks_stationary(gSavedSettings,
- "PicksPerSecondMouseStationary");
- if (!mouse_moved_since_pick && picks_stationary > 0.f &&
- mPickTimer.getElapsedTimeF32() > 1.f / picks_stationary)
- {
- do_pick = true;
- }
- if (getCursorHidden())
- {
- do_pick = false;
- }
- if (LLViewerMediaFocus::getInstance()->getFocus())
- {
- // When in-world media is in focus, pick every frame so that browser
- // mouse-overs, dragging scrollbars, etc. work properly.
- do_pick = true;
- }
- if (do_pick)
- {
- mPickTimer.reset();
- static LLCachedControl<bool> pick_transparent(gSavedSettings,
- "AllowPickTransparent");
- pickAsync(x, y, mask, hoverPickCallback, pick_transparent,
- false, false, true);
- }
- previous_x = x;
- previous_y = y;
- return handled;
- }
- //static
- void LLViewerWindow::hoverPickCallback(const LLPickInfo& pick_info)
- {
- gViewerWindowp->mHoverPick = pick_info;
- }
- void LLViewerWindow::saveLastMouse(const LLCoordGL& point)
- {
- // Store last mouse location; if the mouse leaves the window, pretend last
- // point was on edge of window.
- if (point.mX < 0)
- {
- mCurrentMousePoint.mX = 0;
- }
- else if (point.mX > getWindowWidth())
- {
- mCurrentMousePoint.mX = getWindowWidth();
- }
- else
- {
- mCurrentMousePoint.mX = point.mX;
- }
- if (point.mY < 0)
- {
- mCurrentMousePoint.mY = 0;
- }
- else if (point.mY > getWindowHeight())
- {
- mCurrentMousePoint.mY = getWindowHeight();
- }
- else
- {
- mCurrentMousePoint.mY = point.mY;
- }
- }
- // Draws the selection outlines for the currently selected objects. Must be
- // called after displayObjects is called, which sets the mGLName parameter
- // NOTE: This function gets called 3 times:
- // render_ui_3d: false, false, true
- // renderObjectsForSelect: true, pick_parcel_wall, false
- // render_hud_elements: false, false, false
- void LLViewerWindow::renderSelections(bool for_gl_pick, bool pick_parcel_walls,
- bool for_hud)
- {
- if (!for_hud && !for_gl_pick)
- {
- // Call this once and only once
- gSelectMgr.updateSilhouettes();
- }
- // Draw fence around land selections
- if (for_gl_pick)
- {
- if (pick_parcel_walls)
- {
- gViewerParcelMgr.renderParcelCollision();
- }
- stop_glerror();
- return;
- }
- LLObjectSelectionHandle selection = gSelectMgr.getSelection();
- bool is_hud = selection->getSelectType() == SELECT_TYPE_HUD;
- if (for_hud != is_hud)
- {
- return;
- }
- gSelectMgr.renderSilhouettes(for_hud);
- bool in_edit = gToolMgr.inEdit();
- // *FIXME: this is a total hack (borrowed from Firestorm, Beq's code). The
- // proper fix to the 0 LOD on some edited mesh objects would be to find
- // why in the first place that low LOD gets wrongly used. So far, I did not
- // find where this happens. HB
- static LLCachedControl<S32> edit_lod(gSavedSettings, "EditedMeshLOD");
- if (in_edit && !is_hud && edit_lod >= 0)
- {
- struct LLFunctorApplyLOD : public LLSelectedObjectFunctor
- {
- LLFunctorApplyLOD(S32 lod)
- : mLOD(lod)
- {
- }
- bool apply(LLViewerObject* objectp) override
- {
- if (objectp && objectp->isMesh())
- {
- ((LLVOVolume*)objectp)->tempSetLOD(mLOD);
- }
- return true;
- }
- S32 mLOD;
- };
- LLFunctorApplyLOD func(llmin((S32)edit_lod, 3));
- selection->applyToObjects(&func);
- }
- // Setup HUD render
- if (for_hud && gSelectMgr.getSelection()->getObjectCount())
- {
- LLBBox hud_bbox = gAgentAvatarp->getHUDBBox();
- // Set-up transform to encompass bounding box of HUD
- gGL.matrixMode(LLRender::MM_PROJECTION);
- gGL.pushMatrix();
- gGL.loadIdentity();
- F32 depth = llmax(1.f, hud_bbox.getExtentLocal().mV[VX] * 1.1f);
- F32 aspect = gViewerCamera.getAspect();
- gGL.ortho(-0.5f * aspect, 0.5f * aspect, -0.5f, 0.5f, 0.f, depth);
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- gGL.pushMatrix();
- gGL.loadIdentity();
- // Load Cory's favorite reference frame
- gGL.loadMatrix(OGL_TO_CFR_ROT4A);
- gGL.translatef(-hud_bbox.getCenterLocal().mV[VX] + depth * 0.5f, 0.f,
- 0.f);
- }
- // Render light for editing
- if (in_edit && LLSelectMgr::sRenderLightRadius)
- {
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- LLGLEnable gls_blend(GL_BLEND);
- LLGLEnable gls_cull(GL_CULL_FACE);
- LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- gGL.pushMatrix();
- if (selection->getSelectType() == SELECT_TYPE_HUD)
- {
- F32 zoom = gAgent.mHUDCurZoom;
- gGL.scalef(zoom, zoom, zoom);
- }
- struct f final : public LLSelectedObjectFunctor
- {
- bool apply(LLViewerObject* object) override
- {
- LLDrawable* drawable = object->mDrawable;
- if (drawable && drawable->isLight())
- {
- LLVOVolume* vovolume = drawable->getVOVolume();
- gGL.pushMatrix();
- LLVector3 center = drawable->getPositionAgent();
- gGL.translatef(center[0], center[1], center[2]);
- F32 scale = vovolume->getLightRadius();
- gGL.scalef(scale, scale, scale);
- LLColor4 color(vovolume->getLightSRGBColor(), 0.5f);
- gGL.color4fv(color.mV);
- // Render Outside
- gSphere.render();
- // Render Inside
- glCullFace(GL_FRONT);
- gSphere.render();
- glCullFace(GL_BACK);
- gGL.popMatrix();
- }
- return true;
- }
- } func;
- gSelectMgr.getSelection()->applyToObjects(&func);
- gGL.popMatrix();
- }
- // NOTE: The average position for the axis arrows of the selected objects
- // should not be recalculated at this time. If they are, then group
- // rotations will break.
- // Draw arrows at average center of all selected objects
- LLTool* tool = gToolMgr.getCurrentTool();
- if (!tool)
- {
- stop_glerror();
- return;
- }
- if (tool->isAlwaysRendered())
- {
- tool->render();
- }
- else if (!gSelectMgr.getSelection()->isEmpty())
- {
- bool sel_can_move, sel_is_mod_ok;
- // *TODO: This might be costly to do on each frame and when a lot of
- // objects are selected. We might be better off with some kind of
- // memory for selection and/or states: consider optimizing, perhaps
- // even some kind of selection generation at level of LLSelectMgr to
- // make whole viewer benefit.
- gSelectMgr.selectGetEditMoveLinksetPermissions(sel_can_move,
- sel_is_mod_ok);
- bool draw_handles = true;
- if (!sel_is_mod_ok && tool == &gToolCompScale)
- {
- draw_handles = false;
- }
- else if (!sel_can_move &&
- (tool == &gToolCompTranslate || tool == &gToolCompRotate))
- {
- draw_handles = false;
- }
- if (draw_handles)
- {
- tool->render();
- }
- }
- if (is_hud && selection->getObjectCount())
- {
- gGL.matrixMode(LLRender::MM_PROJECTION);
- gGL.popMatrix();
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- gGL.popMatrix();
- }
- stop_glerror();
- }
- // Return a point near the clicked object representative of the place the
- // object was clicked.
- LLVector3d LLViewerWindow::clickPointInWorldGlobal(S32 x, S32 y_from_bot,
- LLViewerObject* clicked_object) const
- {
- // Create a normalized vector pointing from the camera center into the
- // world at the location of the mouse click
- LLVector3 mouse_direction_global = mouseDirectionGlobal(x, y_from_bot);
- LLVector3d relative_object = clicked_object->getPositionGlobal() -
- gAgent.getCameraPositionGlobal();
- // Make mouse vector as long as object vector, so it touchs a point near
- // where the user clicked on the object
- mouse_direction_global *= (F32) relative_object.length();
- LLVector3d new_pos;
- new_pos.set(mouse_direction_global);
- // Transform mouse vector back to world coords
- new_pos += gAgent.getCameraPositionGlobal();
- return new_pos;
- }
- void LLViewerWindow::pickAsync(S32 x, S32 y_from_bot, MASK mask,
- void (*callback)(const LLPickInfo& info),
- bool pick_transparent, bool pick_rigged,
- bool pick_particle, bool get_surface_info)
- {
- // Push back pick info object
- if (LLFloaterTools::isVisible() || LLDrawPoolAlpha::sShowDebugAlpha)
- {
- // Build mode allows interaction with all transparent objects
- // "Show Debug Alpha" means no object actually transparent
- pick_transparent = true;
- }
- LLPickInfo pick_info(LLCoordGL(x, y_from_bot), mask, pick_transparent,
- pick_rigged, pick_particle, get_surface_info,
- callback);
- schedulePick(pick_info);
- }
- void LLViewerWindow::schedulePick(LLPickInfo& pick_info)
- {
- if (mPicks.size() >= 1024 || gWindowp->getMinimized())
- {
- // Something went wrong, picks are being scheduled but not processed
- if (pick_info.mPickCallback)
- {
- pick_info.mPickCallback(pick_info);
- }
- return;
- }
- mPicks.emplace_back(pick_info);
- // Delay further event processing until we receive results of pick
- gWindowp->delayInputProcessing();
- }
- void LLViewerWindow::performPick()
- {
- if (!mPicks.empty())
- {
- for (pick_info_list_t::iterator it = mPicks.begin(),
- end = mPicks.end();
- it != end; ++it)
- {
- it->fetchResults();
- }
- mLastPick = mPicks.back();
- mPicks.clear();
- }
- }
- void LLViewerWindow::returnEmptyPicks()
- {
- for (pick_info_list_t::iterator it = mPicks.begin(), end = mPicks.end();
- it != end; ++it)
- {
- mLastPick = *it;
- // Just trigger callback with empty results
- if (it->mPickCallback)
- {
- it->mPickCallback(*it);
- }
- }
- mPicks.clear();
- }
- // Performs the GL object/land pick.
- LLPickInfo LLViewerWindow::pickImmediate(S32 x, S32 y_from_bot,
- bool pick_transparent)
- {
- if (LLFloaterTools::isVisible() || LLDrawPoolAlpha::sShowDebugAlpha)
- {
- // Build mode allows interaction with all transparent objects
- // "Show Debug Alpha" means no object actually transparent
- pick_transparent = true;
- }
- // Shortcut queueing in mPicks and just update mLastPick in place
- MASK key_mask = gKeyboardp ? gKeyboardp->currentMask(true) : 0;
- mLastPick = LLPickInfo(LLCoordGL(x, y_from_bot), key_mask,
- pick_transparent, false, false, true, NULL);
- mLastPick.fetchResults();
- return mLastPick;
- }
- LLHUDIcon* LLViewerWindow::cursorIntersectIcon(S32 mouse_x, S32 mouse_y,
- F32 depth,
- LLVector4a* intersection)
- {
- S32 x = mouse_x;
- S32 y = mouse_y;
- if (mouse_x == -1 && mouse_y == -1) // use current mouse position
- {
- x = getCurrentMouseX();
- y = getCurrentMouseY();
- }
- // World coordinates of mouse
- // *TODO: VECTORIZE THIS
- LLVector3 mouse_direction_global = mouseDirectionGlobal(x,y);
- LLVector3 mouse_point_global = gViewerCamera.getOrigin();
- LLVector3 mouse_world_start = mouse_point_global;
- LLVector3 mouse_world_end = mouse_point_global +
- mouse_direction_global * depth;
- LLVector4a start, end;
- start.load3(mouse_world_start.mV);
- end.load3(mouse_world_end.mV);
- return LLHUDIcon::lineSegmentIntersectAll(start, end, intersection);
- }
- LLViewerObject* LLViewerWindow::cursorIntersect(S32 mouse_x, S32 mouse_y,
- F32 depth,
- LLViewerObject* this_object,
- S32 this_face,
- bool pick_transparent,
- bool pick_rigged,
- S32* face_hit,
- S32* gltf_node_hit,
- S32* gltf_prim_hit,
- LLVector4a* intersection,
- LLVector2* uv,
- LLVector4a* normal,
- LLVector4a* tangent,
- LLVector4a* start,
- LLVector4a* end)
- {
- S32 x = mouse_x;
- S32 y = mouse_y;
- if (mouse_x == -1 && mouse_y == -1) // use current mouse position
- {
- x = getCurrentMouseX();
- y = getCurrentMouseY();
- }
- // HUD coordinates of mouse
- LLVector3 mouse_point_hud = mousePointHUD(x, y);
- LLVector3 mouse_hud_start = mouse_point_hud - LLVector3(depth, 0, 0);
- LLVector3 mouse_hud_end = mouse_point_hud + LLVector3(depth, 0, 0);
- // World coordinates of mouse
- LLVector3 mouse_direction_global = mouseDirectionGlobal(x,y);
- LLVector3 mouse_point_global = gViewerCamera.getOrigin();
- // Get near clip plane
- LLVector3 n = gViewerCamera.getAtAxis();
- LLVector3 p = mouse_point_global + n * gViewerCamera.getNear();
- // Project mouse point onto plane
- LLVector3 pos;
- line_plane(mouse_point_global, mouse_direction_global, p, n, pos);
- mouse_point_global = pos;
- LLVector3 mouse_world_start = mouse_point_global;
- LLVector3 mouse_world_end = mouse_point_global +
- mouse_direction_global * depth;
- if (!LLViewerJoystick::getInstance()->getOverrideCamera())
- {
- // Always set raycast intersection to mouse_world_end unless flycam is
- // on (for DoF effect)
- gDebugRaycastIntersection.load3(mouse_world_end.mV);
- }
- LLVector4a mw_start;
- mw_start.load3(mouse_world_start.mV);
- LLVector4a mw_end;
- mw_end.load3(mouse_world_end.mV);
- LLVector4a mh_start;
- mh_start.load3(mouse_hud_start.mV);
- LLVector4a mh_end;
- mh_end.load3(mouse_hud_end.mV);
- if (start)
- {
- *start = mw_start;
- }
- if (end)
- {
- *end = mw_end;
- }
- LLViewerObject* found = NULL;
- if (this_object) // Check only this object
- {
- if (this_object->isHUDAttachment()) // Is it a HUD object ?
- {
- if (this_object->lineSegmentIntersect(mh_start, mh_end, this_face,
- pick_transparent,
- pick_rigged, face_hit,
- intersection, uv, normal,
- tangent))
- {
- found = this_object;
- }
- }
- else // It is a world object
- {
- if (this_object->lineSegmentIntersect(mw_start, mw_end, this_face,
- pick_transparent,
- pick_rigged, face_hit,
- intersection, uv, normal,
- tangent))
- {
- found = this_object;
- }
- //MK
- if (gRLenabled && gRLInterface.mContainsInteract)
- {
- found = NULL;
- }
- //mk
- }
- }
- else // Check ALL objects
- {
- found = gPipeline.lineSegmentIntersectInHUD(mh_start, mh_end,
- pick_transparent,
- face_hit, intersection,
- uv, normal, tangent);
- //MK
- // *HACK: do not allow focusing on HUDs while we are right-clicking on
- // something while not in mouse look: useful for "blinding" HUDs that
- // cover the whole screen, even when transparent.
- if (gRLenabled && !gAgent.cameraMouselook() &&
- gRLInterface.mHasLockedHuds)
- {
- MASK mask = gKeyboardp ? gKeyboardp->currentMask(true) : 0;
- if (mask & MASK_ALT)
- {
- found = NULL;
- }
- }
- //mk
- if (!found) // If not found in HUD, look in world:
- {
- found = gPipeline.lineSegmentIntersectInWorld(mw_start, mw_end,
- pick_transparent,
- pick_rigged,
- face_hit,
- gltf_node_hit,
- gltf_prim_hit,
- intersection,
- uv, normal, tangent);
- if (found && !pick_transparent)
- {
- gDebugRaycastIntersection = *intersection;
- }
- }
- }
- return found;
- }
- // Returns unit vector relative to camera
- // indicating direction of point on screen x,y
- LLVector3 LLViewerWindow::mouseDirectionGlobal(S32 x, S32 y) const
- {
- // Find vertical field of view
- F32 fov = gViewerCamera.getView();
- // Find screen resolution
- S32 height = getWindowHeight();
- S32 width = getWindowWidth();
- // Calculate pixel distance to screen
- F32 t = 2.f * tanf(fov * 0.5f);
- F32 distance = t == 0.f ? F32_MAX : height / t;
- // Calculate click point relative to middle of screen
- F32 click_x = x - width * 0.5f;
- F32 click_y = y - height * 0.5f;
- // Compute mouse vector
- LLVector3 mouse_vector = distance * gViewerCamera.getAtAxis() -
- click_x * gViewerCamera.getLeftAxis() +
- click_y * gViewerCamera.getUpAxis();
- mouse_vector.normalize();
- return mouse_vector;
- }
- LLVector3 LLViewerWindow::mousePointHUD(S32 x, S32 y) const
- {
- // Find screen resolution
- S32 height = getWindowHeight();
- S32 width = getWindowWidth();
- // Remap with uniform scale (1/height) so that top is -0.5, bottom is +0.5
- F32 hud_x = -((F32)x - (F32)width * 0.5f) / height;
- F32 hud_y = ((F32)y - (F32)height * 0.5f) / height;
- return LLVector3(0.f, hud_x / gAgent.mHUDCurZoom,
- hud_y / gAgent.mHUDCurZoom);
- }
- // Returns unit vector relative to camera in camera space indicating direction
- // of point on screen x,y
- LLVector3 LLViewerWindow::mouseDirectionCamera(S32 x, S32 y) const
- {
- // Find vertical field of view
- F32 fov_height = gViewerCamera.getView();
- F32 fov_width = fov_height * gViewerCamera.getAspect();
- // Find screen resolution
- S32 height = getWindowHeight();
- S32 width = getWindowWidth();
- // Calculate click point relative to middle of screen
- F32 click_x = ((F32)x / (F32)width - 0.5f) * fov_width * -1.f;
- F32 click_y = ((F32)y / (F32)height - 0.5f) * fov_height;
- // compute mouse vector
- LLVector3 mouse_vector = LLVector3(0.f, 0.f, -1.f);
- LLQuaternion mouse_rotate;
- mouse_rotate.setEulerAngles(click_y, click_x, 0.f);
- mouse_vector = mouse_vector * mouse_rotate;
- // project to z = -1 plane;
- mouse_vector = mouse_vector * (-1.f / mouse_vector.mV[VZ]);
- return mouse_vector;
- }
- bool LLViewerWindow::mousePointOnPlaneGlobal(LLVector3d& point, S32 x, S32 y,
- const LLVector3d& plane_point_global,
- const LLVector3& plane_normal_global)
- {
- LLVector3d mouse_direction_global_d;
- mouse_direction_global_d.set(mouseDirectionGlobal(x, y));
- LLVector3d plane_normal_global_d;
- plane_normal_global_d.set(plane_normal_global);
- F64 plane_mouse_dot = plane_normal_global_d * mouse_direction_global_d;
- LLVector3d plane_origin_camera_rel = plane_point_global -
- gAgent.getCameraPositionGlobal();
- F64 mouse_look_at_scale = plane_normal_global_d * plane_origin_camera_rel /
- plane_mouse_dot;
- if (fabs(plane_mouse_dot) < 0.00001)
- {
- // If mouse is parallel to plane, return closest point on line through
- // plane origin that is parallel to camera plane by scaling mouse
- // direction vector by distance to plane origin, modulated by deviation
- // of mouse direction from plane origin
- LLVector3d plane_origin_dir = plane_origin_camera_rel;
- plane_origin_dir.normalize();
- mouse_look_at_scale = plane_origin_camera_rel.length() /
- (plane_origin_dir * mouse_direction_global_d);
- }
- point = gAgent.getCameraPositionGlobal() +
- mouse_look_at_scale * mouse_direction_global_d;
- return mouse_look_at_scale > 0.0;
- }
- // Returns global position
- bool LLViewerWindow::mousePointOnLandGlobal(S32 x, S32 y,
- LLVector3d* land_position_global)
- {
- LLVector3 mouse_direction_global = mouseDirectionGlobal(x, y);
- F32 mouse_dir_scale;
- bool hit_land = false;
- LLViewerRegion* regionp;
- F32 land_z;
- constexpr F32 FIRST_PASS_STEP = 1.f; // meters
- constexpr F32 SECOND_PASS_STEP = 0.1f; // meters
- LLVector3d camera_pos_global;
- camera_pos_global = gAgent.getCameraPositionGlobal();
- LLVector3d probe_point_global;
- LLVector3 probe_point_region;
- F32 max_distance = gAgent.noCameraConstraints() ? 1024.f
- : gAgent.mDrawDistance;
- // Walk forwards to find the point
- for (mouse_dir_scale = FIRST_PASS_STEP;
- mouse_dir_scale < max_distance;
- mouse_dir_scale += FIRST_PASS_STEP)
- {
- LLVector3d mouse_direction_global_d;
- mouse_direction_global_d.set(mouse_direction_global * mouse_dir_scale);
- probe_point_global = camera_pos_global + mouse_direction_global_d;
- regionp = gWorld.resolveRegionGlobal(probe_point_region,
- probe_point_global);
- if (!regionp)
- {
- // ...we are outside the world somehow
- continue;
- }
- S32 i = (S32)(probe_point_region.mV[VX] /
- regionp->getLand().getMetersPerGrid());
- S32 j = (S32)(probe_point_region.mV[VY] /
- regionp->getLand().getMetersPerGrid());
- S32 grids_per_edge = (S32)regionp->getLand().mGridsPerEdge;
- if (i >= grids_per_edge || j >= grids_per_edge)
- {
- continue;
- }
- land_z = regionp->getLand().resolveHeightRegion(probe_point_region);
- if (probe_point_region.mV[VZ] < land_z)
- {
- hit_land = true;
- break;
- }
- }
- if (hit_land)
- {
- // Do not go more than one step beyond where we stopped above. This
- // cannot just be "mouse_vec_scale" because floating point error will
- // stop the loop before the last increment...
- // X - 1.0 + 0.1 + 0.1 + ... + 0.1 != X
- F32 stop_mouse_dir_scale = mouse_dir_scale + FIRST_PASS_STEP;
- // Take a step backwards, then walk forwards again to refine position
- for (mouse_dir_scale -= FIRST_PASS_STEP;
- mouse_dir_scale <= stop_mouse_dir_scale;
- mouse_dir_scale += SECOND_PASS_STEP)
- {
- LLVector3d mouse_direction_global_d;
- mouse_direction_global_d.set(mouse_direction_global *
- mouse_dir_scale);
- probe_point_global = camera_pos_global + mouse_direction_global_d;
- regionp = gWorld.resolveRegionGlobal(probe_point_region,
- probe_point_global);
- if (!regionp)
- {
- // ...we are outside the world somehow
- continue;
- }
- #if 0
- i = (S32)(local_probe_point.mV[VX] /
- regionp->getLand().getMetersPerGrid());
- j = (S32)(local_probe_point.mV[VY] /
- regionp->getLand().getMetersPerGrid());
- if (i >= regionp->getLand().mGridsPerEdge ||
- j >= regionp->getLand().mGridsPerEdge)
- {
- llwarns << "probe_point is out of region" << llendl;
- continue;
- }
- land_z =
- regionp->getLand().mSurfaceZ[i + j *
- (regionp->getLand().mGridsPerEdge)];
- #endif
- land_z =
- regionp->getLand().resolveHeightRegion(probe_point_region);
- if (probe_point_region.mV[VZ] < land_z)
- {
- // ...just went under land again
- *land_position_global = probe_point_global;
- return true;
- }
- }
- }
- return false;
- }
- void LLViewerWindow::setSnapshotLoc(std::string filepath)
- {
- LLViewerWindow::sSnapshotBaseName = gDirUtil.getBaseFileName(filepath,
- true);
- LLViewerWindow::sSnapshotDir = gDirUtil.getDirName(filepath);
- }
- // Saves an image to the harddrive as "SnapshotX" where X >= 1.
- bool LLViewerWindow::saveImageNumbered(LLImageFormatted* image)
- {
- if (!image || !isSnapshotLocSet())
- {
- return false;
- }
- // Look for an unused file name
- const std::string extension = "." + image->getExtension();
- std::string filepath;
- const std::string base_path = sSnapshotDir + LL_DIR_DELIM_STR +
- sSnapshotBaseName;
- S32 i = 1;
- do
- {
- filepath = base_path + llformat("_%.3d", i++) + extension;
- }
- // Search until the file is not found
- while (LLFile::isfile(filepath));
- bool result = image->save(filepath);
- if (result)
- {
- playSnapshotAnimAndSound();
- }
- return result;
- }
- void LLViewerWindow::resetSnapshotLoc()
- {
- sSnapshotDir.clear();
- }
- void LLViewerWindow::resizeWindow(S32 new_width, S32 new_height)
- {
- static S32 border_width = 0;
- static S32 border_height = 0;
- LLCoordScreen size;
- gWindowp->getSize(&size);
- if (size.mX != new_width + border_width ||
- size.mY != new_height + border_height)
- {
- // Use the actual display dimensions, not the virtual UI dimensions
- border_width = size.mX - getWindowDisplayWidth();
- border_height = size.mY - getWindowDisplayHeight();
- LLCoordScreen new_size(new_width + border_width,
- new_height + border_height);
- bool disable_sync = gSavedSettings.getBool("DisableVerticalSync");
- if (gWindowp->getFullscreen())
- {
- changeDisplaySettings(new_size, disable_sync, true);
- }
- else
- {
- gWindowp->setSize(new_size);
- }
- }
- mResDirty = true;
- }
- bool LLViewerWindow::saveSnapshot(const std::string& filepath,
- S32 image_width, S32 image_height,
- bool show_ui, bool do_rebuild,
- U32 type)
- {
- llinfos << "Saving snapshot to: " << filepath << llendl;
- LLPointer<LLImageRaw> raw = new LLImageRaw;
- bool success = rawSnapshot(raw, image_width, image_height, true, false,
- show_ui, do_rebuild);
- if (success)
- {
- LLPointer<LLImageBMP> bmp_image = new LLImageBMP;
- success = bmp_image->encode(raw);
- if (success)
- {
- success = bmp_image->save(filepath);
- }
- else
- {
- llwarns << "Unable to encode bmp snapshot" << llendl;
- }
- }
- else
- {
- llwarns << "Unable to capture raw snapshot" << llendl;
- }
- return success;
- }
- void LLViewerWindow::playSnapshotAnimAndSound()
- {
- if (!gSavedSettings.getBool("QuietSnapshotsToDisk"))
- {
- gAgent.sendAnimationRequest(ANIM_AGENT_SNAPSHOT, ANIM_REQUEST_START);
- if (gSavedSettings.getBool("UISndSnapshotEnable"))
- {
- send_sound_trigger(LLUUID(gSavedSettings.getString("UISndSnapshot")),
- 1.f);
- }
- }
- }
- bool LLViewerWindow::thumbnailSnapshot(LLImageRaw* raw, S32 preview_width,
- S32 preview_height, bool show_ui,
- bool do_rebuild, U32 type)
- {
- return rawSnapshot(raw, preview_width, preview_height, false, false,
- show_ui, do_rebuild, type);
- }
- // Saves the image from the screen to the specified filename and path.
- bool LLViewerWindow::rawSnapshot(LLImageRaw* raw,
- S32 image_width, S32 image_height,
- bool keep_window_aspect, bool is_texture,
- bool show_ui, bool do_rebuild,
- U32 type, S32 max_size)
- {
- if (!raw)
- {
- return false;
- }
- // Check if there is enough memory for the snapshot image
- if (LLMemory::gotFailedAllocation())
- {
- llwarns << "Snapshots disabled due to past memory allocation falures."
- << llendl;
- return false;
- }
- #if LL_LINUX
- // Avoids unrefreshed rectangles in screen shots when other applications
- // windows are overlapping ours. HB
- gWindowp->bringToFront();
- // Let some time to the window manager to bring us back to front.
- ms_sleep(100);
- #endif
- // PRE SNAPSHOT
- gDisplaySwapBuffers = false;
- if (gUsePBRShaders)
- {
- gSnapshotNoPost = gSavedSettings.getBool("RenderSnapshotNoPost");
- glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
- }
- else
- {
- glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT |
- GL_STENCIL_BUFFER_BIT);
- }
- setCursor(UI_CURSOR_WAIT);
- // Hide all the UI widgets first and draw a frame
- bool prev_draw_ui =
- gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI);
- if (prev_draw_ui != show_ui)
- {
- LLPipeline::toggleRenderDebugFeature((void*)LLPipeline::RENDER_DEBUG_FEATURE_UI);
- }
- //MK
- if (gRLenabled && gRLInterface.mHasLockedHuds)
- {
- gSavedSettings.setBool("RenderHUDInSnapshot", true);
- }
- //mk
- bool hide_hud = LLPipeline::sShowHUDAttachments &&
- !gSavedSettings.getBool("RenderHUDInSnapshot");
- if (hide_hud)
- {
- LLPipeline::sShowHUDAttachments = false;
- }
- // Copy screen to a buffer; crop sides or top and bottom, if taking a
- // snapshot of different aspect ratio from window
- S32 snapshot_width = mWindowRect.getWidth();
- S32 snapshot_height = mWindowRect.getHeight();
- S32 window_width = mWindowRect.getWidth();
- S32 window_height = mWindowRect.getHeight();
- // Note: Scaling of the UI is currently *not* supported so we limit the
- // output size if UI is requested
- if (show_ui)
- {
- // If the user wants the UI, limit the output size to the available
- // screen size
- image_width = llmin(image_width, window_width);
- image_height = llmin(image_height, window_height);
- }
- F32 scale_factor = 1.f;
- S32 max_width = llmin(window_width, gGLManager.mGLMaxTextureSize);
- S32 max_height = llmin(window_height, gGLManager.mGLMaxTextureSize);
- if (!keep_window_aspect || image_width > max_width ||
- image_height > max_height)
- {
- // If image cropping or need to enlarge the scene, compute a
- // scale_factor
- F32 ratio = llmin((F32)max_width / image_width ,
- (F32)max_height / image_height);
- snapshot_width = (S32)(ratio * image_width);
- snapshot_height = (S32)(ratio * image_height);
- scale_factor = llmax(1.f, 1.f / ratio);
- }
- if (show_ui && scale_factor > 1.f)
- {
- // Note: we should never get there...
- llwarns << "Over scaling UI not supported." << llendl;
- }
- S32 buffer_x_offset = llfloor((window_width - snapshot_width) *
- scale_factor * 0.5f);
- S32 buffer_y_offset = llfloor((window_height - snapshot_height) *
- scale_factor * 0.5f);
- S32 image_buffer_x = llfloor(snapshot_width*scale_factor);
- S32 image_buffer_y = llfloor(snapshot_height *scale_factor);
- // Boundary check to avoid memory overflow
- if (image_buffer_x > max_size || image_buffer_y > max_size)
- {
- scale_factor *= llmin((F32)max_size / image_buffer_x,
- (F32)max_size / image_buffer_y);
- image_buffer_x = llfloor(snapshot_width*scale_factor);
- image_buffer_y = llfloor(snapshot_height *scale_factor);
- }
- if (image_buffer_x > 0 && image_buffer_y > 0)
- {
- raw->resize(image_buffer_x, image_buffer_y, 3);
- }
- else
- {
- gSnapshotNoPost = false;
- return false;
- }
- if (raw->isBufferInvalid())
- {
- gSnapshotNoPost = false;
- return false;
- }
- bool high_res = scale_factor > 1.f;
- #if 0
- if (high_res)
- {
- LLWorld::sendAgentPause();
- if (show_ui || !hide_hud)
- {
- // Rescale fonts
- initFonts(scale_factor);
- LLHUDText::reshape();
- }
- }
- #endif
- S32 output_buffer_offset_y = 0;
- F32 dnear = gViewerCamera.getNear();
- F32 dfar = gViewerCamera.getFar();
- F32 divisor = 2.f * dnear * dfar;
- F32 depth_conv_factor_1 = (dfar + dnear) / divisor;
- F32 depth_conv_factor_2 = (dfar - dnear) / divisor;
- // Sub-images are in fact partial rendering of the final view. This happens
- // when the final view is bigger than the screen. In most common cases,
- // scale_factor is 1 and there is no more than 1 iteration on x and y
- for (S32 subimage_y = 0; subimage_y < scale_factor; ++subimage_y)
- {
- S32 subimage_y_offset =
- llclamp(buffer_y_offset - subimage_y * window_height, 0,
- window_height);
- // Handle fractional columns
- U32 read_height = llmax(0,
- window_height - subimage_y_offset -
- llmax(0,
- window_height * (subimage_y + 1) -
- buffer_y_offset - raw->getHeight()));
- S32 output_buffer_offset_x = 0;
- for (S32 subimage_x = 0; subimage_x < scale_factor; ++subimage_x)
- {
- gDisplaySwapBuffers = false;
- gDepthDirty = true;
- S32 subimage_x_offset =
- llclamp(buffer_x_offset - subimage_x * window_width, 0,
- window_width);
- // Handle fractional rows
- U32 read_width =
- llmax(0,
- window_width - subimage_x_offset -
- llmax(0,
- window_width * (subimage_x + 1) -
- buffer_x_offset - raw->getWidth()));
- // Skip rendering and sampling altogether if either width or height
- // is degenerated to 0 (common in cropping cases)
- if (read_width && read_height)
- {
- const U32 subfield = subimage_x +
- subimage_y * llceil(scale_factor);
- display(do_rebuild, scale_factor, subfield, true);
- if (!LLPipeline::sRenderDeferred)
- {
- // Required for showing the GUI in snapshots and performing
- // bloom composite overlay. Call even if show_ui is false
- render_ui(scale_factor);
- }
- glFinish(); // Ensure everything got drawn
- for (U32 out_y = 0; out_y < read_height; ++out_y)
- {
- S32 output_buffer_offset =
- raw->getComponents() *
- // iterated y...
- (out_y * raw->getWidth() +
- // ...plus subimage start in x...
- window_width * subimage_x +
- // ...plus subimage start in y...
- raw->getWidth() * window_height * subimage_y -
- // ...minus buffer padding x...
- output_buffer_offset_x -
- // ...minus buffer padding y...
- output_buffer_offset_y * raw->getWidth());
- if (type == SNAPSHOT_TYPE_COLOR)
- {
- glReadPixels(subimage_x_offset,
- out_y + subimage_y_offset, read_width, 1,
- GL_RGB, GL_UNSIGNED_BYTE,
- raw->getData() + output_buffer_offset);
- }
- else // SNAPSHOT_TYPE_DEPTH
- {
- LLPointer<LLImageRaw> depth_line_buffer;
- depth_line_buffer = new LLImageRaw(read_width, 1,
- // need to store floats
- sizeof(GL_FLOAT));
- glReadPixels(subimage_x_offset,
- out_y + subimage_y_offset, read_width, 1,
- GL_DEPTH_COMPONENT, GL_FLOAT,
- // current output pixel is beginning
- // of buffer
- depth_line_buffer->getData());
- for (S32 i = 0; i < (S32)read_width; ++i)
- {
- F32 depth_float =
- *(F32*)(depth_line_buffer->getData() +
- i * sizeof(F32));
- F32 linear_depth_float =
- 1.f / (depth_conv_factor_1 -
- depth_float * depth_conv_factor_2);
- U8 depth_byte = F32_to_U8(linear_depth_float,
- dnear, dfar);
- // Write converted scanline out to result image
- for (S32 j = 0, count = raw->getComponents();
- j < count; ++j)
- {
- *(raw->getData() + output_buffer_offset +
- i * raw->getComponents() + j) = depth_byte;
- }
- }
- }
- }
- }
- output_buffer_offset_x += subimage_x_offset;
- }
- output_buffer_offset_y += subimage_y_offset;
- }
- gDisplaySwapBuffers = false;
- gDepthDirty = true;
- gSnapshotNoPost = false;
- // Post snapshot
- if (prev_draw_ui &&
- !gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
- {
- LLPipeline::toggleRenderDebugFeature((void*)LLPipeline::RENDER_DEBUG_FEATURE_UI);
- }
- if (hide_hud)
- {
- LLPipeline::sShowHUDAttachments = true;
- }
- #if 0
- if (high_res)
- {
- initFonts(1.f);
- LLHUDObject::reshapeAll();
- }
- #endif
- // Pre-pad image to number of pixels such that the line length is a
- // multiple of 4 bytes (for BMP encoding). Note: this formula depends on
- // the number of components being 3. Not obvious, but it's correct.
- image_width += (image_width * 3) % 4;
- bool ret = true;
- // Resize image
- if (abs(image_width - image_buffer_x) > 4 ||
- abs(image_height - image_buffer_y) > 4)
- {
- ret = raw->scale(image_width, image_height);
- }
- else if (image_width != image_buffer_x || image_height != image_buffer_y)
- {
- ret = raw->scale(image_width, image_height, false);
- }
- setCursor(UI_CURSOR_ARROW);
- if (do_rebuild)
- {
- // If we had to do a rebuild, that means that the lists of drawables to
- // be rendered was empty before we started. Need to reset these,
- // otherwise we call state sort on it again when render gets called the
- // next time and we stand a good chance of crashing on rebuild because
- // the render drawable arrays have multiple copies of objects on them.
- gPipeline.resetDrawOrders();
- }
- if (high_res)
- {
- LLWorld::sendAgentResume();
- }
- stop_glerror();
- return ret;
- }
- void LLViewerWindow::cubeSnapshot(const LLVector3& origin,
- LLCubeMapArray* cubemapp, S32 face,
- F32 near_clip, bool dynamic_render)
- {
- if (!gUsePBRShaders)
- {
- return;
- }
- LLDisableOcclusionCulling no_occlusion;
- // Store current projection/modelview matrix
- const LLMatrix4a saved_proj = gGLProjection;
- const LLMatrix4a saved_view = gGLModelView;
- U32 res = gPipeline.mRT->mDeferredScreen.getWidth();
- LLViewerCamera saved_camera = gViewerCamera;
- // Camera constants for the square, cube map capture image
- // We must set aspect ratio first to avoid undesirable clamping of vertical
- // FoV.
- gViewerCamera.setAspect(1.f);
- gViewerCamera.setViewNoBroadcast(F_PI_BY_TWO);
- gViewerCamera.yaw(0.f);
- gViewerCamera.setOrigin(origin);
- gViewerCamera.setNear(near_clip);
- glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
- static const U32 dynamic_render_types[] =
- {
- LLPipeline::RENDER_TYPE_AVATAR,
- LLPipeline::RENDER_TYPE_PUPPET,
- LLPipeline::RENDER_TYPE_PARTICLES
- };
- static const U32 render_types_count = LL_ARRAY_SIZE(dynamic_render_types);
- bool prev_dynamic_render_type[render_types_count];
- if (!dynamic_render)
- {
- for (U32 i = 0; i < render_types_count; ++i)
- {
- bool enabled = gPipeline.hasRenderType(dynamic_render_types[i]);
- prev_dynamic_render_type[i] = enabled;
- if (enabled)
- {
- gPipeline.toggleRenderType(dynamic_render_types[i]);
- }
- }
- }
- constexpr U32 ui_mask = LLPipeline::RENDER_DEBUG_FEATURE_UI;
- bool draw_ui = gPipeline.hasRenderDebugFeatureMask(ui_mask);
- if (draw_ui)
- {
- LLPipeline::toggleRenderDebugFeature((void*)ui_mask);
- }
- bool show_huds = LLPipeline::sShowHUDAttachments;
- if (show_huds)
- {
- LLPipeline::sShowHUDAttachments = false;
- }
- LLRect window_rect = mWindowRect;
- mWindowRect.set(0, res, res, 0);
- // See LLCubeMapArray::sTargets
- static const LLVector3 look_dirs[6] =
- {
- LLVector3::x_axis,
- LLVector3::x_axis_neg,
- LLVector3::y_axis,
- LLVector3::y_axis_neg,
- LLVector3::z_axis,
- LLVector3::z_axis_neg
- };
- static const LLVector3 look_upvecs[6] =
- {
- LLVector3::y_axis_neg,
- LLVector3::y_axis_neg,
- LLVector3::z_axis,
- LLVector3::z_axis_neg,
- LLVector3::y_axis_neg,
- LLVector3::y_axis_neg
- };
- // Set up camera to look at the right direction
- gViewerCamera.lookDir(look_dirs[face], look_upvecs[face]);
- // Turning this flag off here prohibits the screen swap to present the new
- // frame to the viewer: this avoids a black flash in between captures when
- // the number of render passes is more than 1. We need to also set it here
- // because code in llviewerdisplay.cpp resets it to true each time.
- gDisplaySwapBuffers = false;
- gCubeSnapshot = true;
- display_cube_face();
- gCubeSnapshot = false;
- gDisplaySwapBuffers = true;
- mWindowRect = window_rect;
- setupViewport();
- if (draw_ui && !gPipeline.hasRenderDebugFeatureMask(ui_mask))
- {
- LLPipeline::toggleRenderDebugFeature((void*)ui_mask);
- }
- if (!dynamic_render)
- {
- for (size_t i = 0; i < render_types_count; ++i)
- {
- if (prev_dynamic_render_type[i])
- {
- gPipeline.toggleRenderType(dynamic_render_types[i]);
- }
- }
- }
- if (show_huds)
- {
- LLPipeline::sShowHUDAttachments = true;
- }
- gPipeline.resetDrawOrders();
- gViewerCamera = saved_camera;
- gGLProjection = saved_proj;
- gGLModelView = saved_view;
- }
- void LLViewerWindow::destroyWindow()
- {
- LLWindow::destroyWindow();
- }
- void LLViewerWindow::drawMouselookInstructions()
- {
- // Draw instructions for mouselook ("Press SHIFT ESC to leave Mouselook"
- // in a box at the top of the screen).
- static const LLWString instructions = LLTrans::getWString("mouselook");
- static const LLFontGL* font = LLFontGL::getFontSansSerif();
- constexpr S32 INSTRUCTIONS_PAD = 5;
- static const S32 inst_width = font->getWidth(instructions.c_str()) +
- 2 * INSTRUCTIONS_PAD;
- static const S32 inst_height = font->getLineHeight() +
- 2 * INSTRUCTIONS_PAD;
- static LLCachedControl<U32> fade_ml_exit_tip(gSavedSettings,
- "FadeMouselookExitTip");
- F32 opaque_time = (F32)fade_ml_exit_tip;
- if (opaque_time != 0.f && opaque_time < 5.f)
- {
- opaque_time = 5.f;
- }
- constexpr F32 INSTRUCTIONS_FADE_TIME = 5.f;
- F32 timer = mMouselookTipFadeTimer.getElapsedTimeF32();
- if (opaque_time && timer >= opaque_time + INSTRUCTIONS_FADE_TIME)
- {
- // Faded out already
- return;
- }
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- F32 alpha = 1.f;
- if (opaque_time && timer >= opaque_time)
- {
- // Instructions are fading
- alpha = 1.f - (timer - opaque_time) / INSTRUCTIONS_FADE_TIME;
- }
- gGL.color4f(0.9f, 0.9f, 0.9f, alpha);
- LLRect rect;
- rect.setLeftTopAndSize(INSTRUCTIONS_PAD,
- getWindowHeight() - INSTRUCTIONS_PAD,
- inst_width, inst_height);
- gl_rect_2d(rect);
- font->render(instructions, 0,
- rect.mLeft + INSTRUCTIONS_PAD, rect.mTop - INSTRUCTIONS_PAD,
- LLColor4(0.f, 0.f, 0.f, alpha),
- LLFontGL::LEFT, LLFontGL::TOP);
- }
- void LLViewerWindow::setupViewport(S32 x_offset, S32 y_offset)
- {
- #if 0 // mWindowRect.mLeft = mWindowRect.mBottom = 0
- gGLViewport[0] = mWindowRect.mLeft + x_offset;
- gGLViewport[1] = mWindowRect.mBottom + y_offset;
- gGLViewport[2] = mWindowRect.getWidth();
- gGLViewport[3] = mWindowRect.getHeight();
- #else
- gGLViewport[0] = x_offset;
- gGLViewport[1] = y_offset;
- gGLViewport[2] = mWindowRect.mRight;
- gGLViewport[3] = mWindowRect.mTop;
- #endif
- glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
- }
- void LLViewerWindow::setup3DRender()
- {
- gViewerCamera.setPerspective(NOT_FOR_SELECTION, 0, 0,
- mWindowRect.getWidth(),
- mWindowRect.getHeight(), false,
- gViewerCamera.getNear(), MAX_FAR_CLIP * 2.f);
- #if 0 // Redundant
- setupViewport();
- #endif
- }
- void LLViewerWindow::setup2DRender()
- {
- gl_state_for_2d(mWindowRect.getWidth(), mWindowRect.getHeight());
- #if 0 // Redundant
- setupViewport();
- #endif
- }
- void LLViewerWindow::setShowProgress(bool show)
- {
- if (mProgressView)
- {
- mProgressView->setVisible(show);
- }
- }
- void LLViewerWindow::moveProgressViewToFront()
- {
- if (mProgressView && mRootView)
- {
- mRootView->removeChild(mProgressView);
- mRootView->addChild(mProgressView);
- }
- }
- void LLViewerWindow::setProgressString(const std::string& string)
- {
- if (mProgressView)
- {
- mProgressView->setText(string);
- }
- }
- void LLViewerWindow::setProgressMessage(const std::string& msg)
- {
- if (mProgressView)
- {
- mProgressView->setMessage(msg);
- }
- }
- void LLViewerWindow::setProgressPercent(F32 percent)
- {
- if (mProgressView)
- {
- mProgressView->setPercent(percent);
- }
- }
- void LLViewerWindow::setProgressCancelButtonVisible(bool show,
- const std::string& label)
- {
- if (mProgressView)
- {
- mProgressView->setCancelButtonVisible(show, label);
- }
- }
- void LLViewerWindow::dumpState()
- {
- llinfos << "LLViewerWindow active: " << (mActive ? "true": "false")
- << " - gWindowp visible: "
- << (gWindowp->getVisible() ? "true": "false")
- << " - minimized: "
- << (gWindowp->getMinimized() ? "true": "false") << llendl;
- }
- // Note: if not necessary, do not change the order of the function calls in
- // this function. If you change something, make sure it will not break
- // anything; be especially careful to put anything behind
- // LLViewerTextureList::destroyGL(save_state)
- void LLViewerWindow::stopGL(bool save_state)
- {
- if (!gGLManager.mIsDisabled)
- {
- llinfos << "Shutting down GL..." << llendl;
- // *HACK: That flag *MUST* be set before stopping GL and can only be
- // reset after GL is restarted. Else, you will crash because the GL
- // textures will have their size set to weird numbers and/or will be
- // recreated with GL stopped ! HB
- LLImageGL::sPreserveDiscard = true;
- // Pause texture decode threads (will get unpaused during main loop)
- LLAppViewer::pauseTextureFetch();
- gSky.destroyGL();
- stop_glerror();
- LLManipTranslate::destroyGL();
- stop_glerror();
- gBumpImageList.destroyGL();
- stop_glerror();
- LLFontGL::destroyAllGL();
- stop_glerror();
- LLVOAvatar::destroyGL();
- stop_glerror();
- if (gPipeline.isInit())
- {
- gPipeline.destroyGL();
- }
- gBox.cleanupGL();
- LLViewerTextureList::destroyGL(save_state);
- stop_glerror();
- LLImageGL::stopThread();
- gGLManager.mIsDisabled = true;
- stop_glerror();
- while (LLGLSLShader::sInstances.size())
- {
- LLGLSLShader* shader = *(LLGLSLShader::sInstances.begin());
- shader->unload();
- }
- stop_glerror();
- llinfos << "Remaining allocated texture memory: "
- << LLImageGL::sGlobalTexMemBytes << " bytes." << llendl;
- }
- }
- // Note: if not necessary, do not change the order of the function calls in
- // this function. When changing something, make sure it will not break
- // anything. Be especially careful when putting something before
- // LLViewerTextureList::restoreGL()
- void LLViewerWindow::restoreGL(const std::string& progress_message)
- {
- if (gGLManager.mIsDisabled)
- {
- llinfos << "Restoring GL..." << llendl;
- gGLManager.mIsDisabled = false;
- initGLDefaults();
- LLGLState::restoreGL();
- bool aniso = gSavedSettings.getBool("RenderAnisotropic");
- if (LLImageGL::sGlobalUseAnisotropic != aniso)
- {
- LLImageGL::sGlobalUseAnisotropic = aniso;
- LLImageGL::dirtyTexOptions();
- }
- LLImageGL::initThread(gWindowp,
- gSavedSettings.getS32("GLWorkerThreads"));
- LLViewerTextureList::restoreGL();
- #if 0 // For future support of non-square pixels, and fonts that are properly
- // stretched
- LLFontGL::destroyDefaultFonts();
- #endif
- initFonts();
- gPipeline.restoreGL();
- gSky.restoreGL();
- LLDrawPoolWater::restoreGL();
- LLManipTranslate::restoreGL();
- gBumpImageList.restoreGL();
- LLVOAvatar::restoreGL();
- gResizeScreenTexture = true;
- if (LLFloaterCustomize::isVisible())
- {
- LLVisualParamHint::requestHintUpdates();
- }
- if (!progress_message.empty())
- {
- gRestoreGLTimer.reset();
- gRestoreGL = true;
- setShowProgress(true);
- setProgressString(progress_message);
- }
- // *HACK: now that GL is restarted, we can reset that flag. HB
- LLImageGL::sPreserveDiscard = false;
- llinfos << "...Restoring GL done" << llendl;
- if (!gAppViewerp->restoreErrorTrap())
- {
- llwarns << "Someone took over my signal/exception handler !"
- << llendl;
- }
- }
- }
- void LLViewerWindow::initFonts(F32 zoom_factor)
- {
- LLFontGL::destroyAllGL();
- // Initialize with possibly different zoom factor
- LLFontManager::initClass();
- LLFontGL::initClass(gSavedSettings.getF32("FontScreenDPI"),
- mDisplayScale.mV[VX] * zoom_factor,
- mDisplayScale.mV[VY] * zoom_factor,
- LLUICtrlFactory::getXUIPaths());
- // Force font reloads, which can be very slow
- LLFontGL::loadDefaultFonts();
- // Setup custom fonts.
- LLPreviewNotecard::refreshCachedSettings();
- LLPreviewScript::refreshCachedSettings();
- }
- void LLViewerWindow::getTargetWindow(bool full_screen, U32& width, U32& height)
- {
- // Sadly, width and height settings have been historically stored as signed
- // integers, where it does not make any sense... HB
- S32 signed_width, signed_height;
- if (full_screen)
- {
- signed_width = gSavedSettings.getS32("FullScreenWidth");
- signed_height = gSavedSettings.getS32("FullScreenHeight");
- }
- else
- {
- signed_width = gSavedSettings.getS32("WindowWidth");
- signed_height = gSavedSettings.getS32("WindowHeight");
- }
- width = signed_width >= 0 ? (U32)signed_width : 800;
- height = signed_height >= 0 ? (U32)signed_height : 600;
- }
- void LLViewerWindow::requestResolutionUpdate()
- {
- mResDirty = true;
- }
- bool LLViewerWindow::checkSettings()
- {
- if (mStatesDirty)
- {
- gGL.refreshState();
- gViewerShaderMgrp->setShaders();
- mStatesDirty = false;
- }
- // We want to update the resolution AFTER the states getting refreshed not
- // before.
- if (mResDirty)
- {
- if (gSavedSettings.getBool("FullScreenAutoDetectAspectRatio"))
- {
- gWindowp->setNativeAspectRatio(0.f);
- }
- else
- {
- gWindowp->setNativeAspectRatio(gSavedSettings.getF32("FullScreenAspectRatio"));
- }
- reshape(getWindowDisplayWidth(), getWindowDisplayHeight());
- // Force aspect ratio
- if (gWindowp->getFullscreen())
- {
- gViewerCamera.setAspect(getDisplayAspectRatio());
- }
- mResDirty = false;
- }
- return false;
- }
- void LLViewerWindow::restartDisplay()
- {
- llinfos << "Restarting GL" << llendl;
- stopGL();
- if (LLStartUp::isLoggedIn())
- {
- restoreGL("Changing resolution...");
- }
- else
- {
- restoreGL();
- if (LLPanelLogin::getInstance())
- {
- // Force a refresh of the fonts and GL images
- LLPanelLogin::getInstance()->refresh();
- }
- }
- }
- bool LLViewerWindow::changeDisplaySettings(LLCoordScreen size,
- bool disable_vsync,
- bool show_progress_bar)
- {
- bool was_maximized = gSavedSettings.getBool("WindowMaximized");
- bool fullscreen = gWindowp->getFullscreen();
- gResizeScreenTexture = true;
- U32 fsaa = gSavedSettings.getU32("RenderFSAASamples");
- U32 old_fsaa = gWindowp->getFSAASamples();
- if (!fullscreen)
- {
- // If not maximized, use the request size
- if (!gWindowp->getMaximized())
- {
- gWindowp->setSize(size);
- }
- if (fsaa == old_fsaa)
- {
- return true;
- }
- }
- // Close floaters that do not handle settings change
- LLFloaterSnapshot::hide(NULL);
- bool result_first_try = false;
- bool result_second_try = false;
- LLFocusableElement* keyboard_focus = gFocusMgr.getKeyboardFocus();
- LLWorld::sendAgentPause();
- llinfos << "Stopping GL during changeDisplaySettings" << llendl;
- stopGL();
- mIgnoreActivate = true;
- LLCoordScreen old_size;
- gWindowp->getSize(&old_size);
- gWindowp->setFSAASamples(fsaa);
- result_first_try = gWindowp->switchContext(fullscreen, size,
- disable_vsync);
- if (!result_first_try)
- {
- // Try to switch back
- gWindowp->setFSAASamples(old_fsaa);
- result_second_try = gWindowp->switchContext(fullscreen, old_size,
- disable_vsync);
- if (!result_second_try)
- {
- // We are stuck... try once again with a minimal resolution ?
- LLWorld::sendAgentResume();
- mIgnoreActivate = false;
- gFocusMgr.setKeyboardFocus(keyboard_focus);
- return false;
- }
- }
- LLWorld::sendAgentResume();
- llinfos << "Restoring GL during resolution change" << llendl;
- if (show_progress_bar)
- {
- restoreGL("Changing resolution...");
- }
- else
- {
- restoreGL();
- }
- if (!result_first_try)
- {
- LLSD args;
- args["RESX"] = llformat("%d", size.mX);
- args["RESY"] = llformat("%d", size.mY);
- gNotifications.add("ResolutionSwitchFail", args);
- size = old_size; // For reshape below
- }
- bool success = result_first_try || result_second_try;
- if (success)
- {
- #if LL_WINDOWS
- // Only trigger a reshape after switching to fullscreen; otherwise rely
- // on the windows callback (otherwise size is wrong; this is the entire
- // window size, reshape wants the visible window size)
- if (fullscreen && result_first_try)
- #endif
- {
- reshape(size.mX, size.mY);
- }
- }
- if (!fullscreen && success)
- {
- // Maximize window if was maximized, else reposition
- if (was_maximized)
- {
- gWindowp->maximize();
- }
- else
- {
- S32 window_x = gSavedSettings.getS32("WindowX");
- S32 window_y = gSavedSettings.getS32("WindowY");
- gWindowp->setPosition(LLCoordScreen(window_x, window_y));
- }
- }
- mIgnoreActivate = false;
- gFocusMgr.setKeyboardFocus(keyboard_focus);
- return success;
- }
- F32 LLViewerWindow::getDisplayAspectRatio() const
- {
- if (gWindowp->getFullscreen())
- {
- if (gSavedSettings.getBool("FullScreenAutoDetectAspectRatio"))
- {
- return gWindowp->getNativeAspectRatio();
- }
- else
- {
- return gSavedSettings.getF32("FullScreenAspectRatio");
- }
- }
- return gWindowp->getNativeAspectRatio();
- }
- void LLViewerWindow::calcDisplayScale()
- {
- F32 ui_scale_factor = gSavedSettings.getF32("UIScaleFactor") *
- gWindowp->getSystemUISize();
- // HiDPI scaling can be 4x. UI scaling in prefs is up to 2x, so max is 8x
- ui_scale_factor = llclamp(ui_scale_factor, 0.75f, 8.f);
- LLVector2 display_scale;
- display_scale.set(llmax(1.f / gWindowp->getPixelAspectRatio(), 1.f),
- llmax(gWindowp->getPixelAspectRatio(), 1.f));
- F32 height_normalization = 1.f;
- if (gSavedSettings.getBool("UIAutoScale"))
- {
- height_normalization = (F32)mWindowRect.getHeight() /
- display_scale.mV[VY] / 768.f;
- }
- if (gWindowp->getFullscreen())
- {
- display_scale *= (ui_scale_factor * height_normalization);
- }
- else
- {
- display_scale *= ui_scale_factor;
- }
- // Limit minimum display scale
- if (display_scale.mV[VX] < MIN_DISPLAY_SCALE ||
- display_scale.mV[VY] < MIN_DISPLAY_SCALE)
- {
- display_scale *= MIN_DISPLAY_SCALE / llmin(display_scale.mV[VX],
- display_scale.mV[VY]);
- }
- if (gWindowp->getFullscreen())
- {
- display_scale.mV[0] = ll_round(display_scale.mV[0],
- 2.f / (F32)mWindowRect.getWidth());
- display_scale.mV[1] = ll_round(display_scale.mV[1],
- 2.f / (F32)mWindowRect.getHeight());
- }
- if (display_scale != mDisplayScale)
- {
- llinfos << "Setting display scale to " << display_scale << llendl;
- mDisplayScale = display_scale;
- mDisplayScaleDivisor.set(1.f / mDisplayScale.mV[VX],
- 1.f / mDisplayScale.mV[VY]);
- // Init default fonts
- initFonts();
- }
- }
- S32 LLViewerWindow::getChatConsoleBottomPad()
- {
- S32 offset = 0;
- if (gToolBarp && gToolBarp->getVisible())
- {
- offset += TOOL_BAR_HEIGHT;
- }
- return offset;
- }
- LLRect LLViewerWindow::getChatConsoleRect()
- {
- LLRect full_window(0, getWindowHeight(), getWindowWidth(), 0);
- LLRect console_rect = full_window;
- constexpr S32 CONSOLE_PADDING_TOP = 24;
- constexpr S32 CONSOLE_PADDING_BOTTOM = 24;
- console_rect.mTop -= CONSOLE_PADDING_TOP;
- console_rect.mBottom += getChatConsoleBottomPad() + CONSOLE_PADDING_BOTTOM;
- console_rect.mLeft += CONSOLE_PADDING_LEFT;
- static LLCachedControl<bool> chat_full_width(gSavedSettings,
- "ChatFullWidth");
- if (chat_full_width)
- {
- console_rect.mRight -= CONSOLE_PADDING_RIGHT;
- }
- else
- {
- // Make console rect somewhat narrow so having inventory open is
- // less of a problem.
- console_rect.mRight = console_rect.mLeft + 2 * getWindowWidth() / 3;
- }
- return console_rect;
- }
- //static
- bool LLViewerWindow::onAlert(const LLSD& notify)
- {
- LLNotificationPtr notification =
- gNotifications.find(notify["id"].asUUID());
- // If we are in mouselook, the mouse is hidden and so the user cannot click
- // the dialog buttons. In that case, change to First Person instead.
- if (gAgent.cameraMouselook())
- {
- gAgent.changeCameraToDefault();
- }
- return false;
- }
- ////////////////////////////////////////////////////////////////////////////
- LLBottomPanel::LLBottomPanel(const LLRect& rect)
- : LLPanel("bottom panel", rect, false),
- mIndicator(NULL)
- {
- // Bottom panel is focus root, so Tab moves through the toolbar and button
- // bar, and overlay
- setFocusRoot(true);
- // Do not capture mouse clicks that do not hit a child
- setMouseOpaque(false);
- setFollows(FOLLOWS_LEFT | FOLLOWS_RIGHT | FOLLOWS_BOTTOM);
- // Flag this panel as chrome so buttons do not grab keyboard focus
- setIsChrome(true);
- }
- LLBottomPanel::~LLBottomPanel()
- {
- gBottomPanelp = NULL;
- }
- void LLBottomPanel::setFocusIndicator(LLView* indicator)
- {
- mIndicator = indicator;
- }
- void LLBottomPanel::draw()
- {
- if (mIndicator)
- {
- bool hasFocus = gFocusMgr.childHasKeyboardFocus(this);
- mIndicator->setVisible(hasFocus);
- mIndicator->setEnabled(hasFocus);
- }
- LLPanel::draw();
- }
- //
- // LLPickInfo
- //
- LLPickInfo::LLPickInfo()
- : mKeyMask(MASK_NONE),
- mPickCallback(NULL),
- mPickType(PICK_INVALID),
- mWantSurfaceInfo(false),
- mObjectFace(-1),
- mGLTFNodeIndex(-1),
- mGLTFPrimIndex(-1),
- mUVCoords(-1.f, -1.f),
- mSTCoords(-1.f, -1.f),
- mXYCoords(-1, -1),
- mIntersection(),
- mNormal(),
- mTangent(),
- mBinormal(),
- mHUDIcon(NULL),
- mPickTransparent(false),
- mPickRigged(false),
- mPickParticle(false)
- {
- }
- LLPickInfo::LLPickInfo(const LLCoordGL& mouse_pos,
- MASK keyboard_mask,
- bool pick_transparent,
- bool pick_rigged,
- bool pick_particle,
- bool pick_uv_coords,
- void (*pick_callback)(const LLPickInfo&))
- : mMousePt(mouse_pos),
- mKeyMask(keyboard_mask),
- mPickCallback(pick_callback),
- mPickType(PICK_INVALID),
- mWantSurfaceInfo(pick_uv_coords),
- mObjectFace(-1),
- mGLTFNodeIndex(-1),
- mGLTFPrimIndex(-1),
- mUVCoords(-1.f, -1.f),
- mSTCoords(-1.f, -1.f),
- mXYCoords(-1, -1),
- mNormal(),
- mTangent(),
- mBinormal(),
- mHUDIcon(NULL),
- mPickTransparent(pick_transparent),
- mPickRigged(pick_rigged),
- mPickParticle(pick_particle)
- {
- }
- void LLPickInfo::fetchResults()
- {
- static LLVector4a intersection;
- LLHUDIcon* hit_icon =
- gViewerWindowp->cursorIntersectIcon(mMousePt.mX, mMousePt.mY, 512.f,
- &intersection);
- static LLVector4a origin;
- origin.load3(gViewerCamera.getOrigin().mV);
- static LLVector4a delta;
- F32 icon_dist = 0.f;
- if (hit_icon)
- {
- delta.setSub(intersection, origin);
- icon_dist = delta.getLength3().getF32();
- }
- S32 face_hit = -1;
- static LLVector4a normal;
- static LLVector4a tangent;
- static LLVector4a start;
- static LLVector4a end;
- static LLVector4a particle_end;
- static LLVector2 uv;
- LLViewerObject* objectp =
- gViewerWindowp->cursorIntersect(mMousePt.mX, mMousePt.mY, 512.f, NULL,
- -1, mPickTransparent, mPickRigged,
- &face_hit,
- &gDebugRaycastGLTFNodeHit,
- &gDebugRaycastGLTFPrimHit,
- &intersection, &uv, &normal,
- &tangent, &start, &end);
- if (objectp && objectp->isDead())
- {
- return;
- }
- mPickPt = mMousePt;
- U32 te_offset = face_hit > -1 ? face_hit : 0;
- if (mPickParticle)
- {
- // Get the end point of line segment to use for particle raycast
- if (objectp)
- {
- particle_end = intersection;
- }
- else
- {
- particle_end = end;
- }
- }
- // Un-project relative clicked coordinate from window coordinate using GL
- delta.setSub(origin, intersection);
- if (hit_icon && (!objectp || icon_dist < delta.getLength3().getF32()))
- {
- // Was this name referring to a hud icon ?
- mHUDIcon = hit_icon;
- mPickType = PICK_ICON;
- mPosGlobal = mHUDIcon->getPositionGlobal();
- }
- else if (objectp)
- {
- if (objectp->getPCode() == LLViewerObject::LL_VO_SURFACE_PATCH)
- {
- // Hit land
- mPickType = PICK_LAND;
- mObjectID.setNull(); // land has no id
- // put global position into land_pos
- static LLVector3d land_pos;
- if (!gViewerWindowp->mousePointOnLandGlobal(mPickPt.mX, mPickPt.mY,
- &land_pos))
- {
- // The selected point is beyond the draw distance or is
- // otherwise not selectable. Return before calling
- // mPickCallback().
- return;
- }
- // Fudge the land focus a little bit above ground.
- mPosGlobal = land_pos + LLVector3d::z_axis * 0.1f;
- }
- else
- {
- if (isFlora(objectp))
- {
- mPickType = PICK_FLORA;
- }
- else
- {
- mPickType = PICK_OBJECT;
- }
- LLVector3 v_intersection(intersection.getF32ptr());
- mObjectOffset = gAgent.calcFocusOffset(objectp, v_intersection,
- mPickPt.mX, mPickPt.mY);
- mObjectID = objectp->mID;
- mObjectFace = te_offset == NO_FACE ? -1 : (S32)te_offset;
- mPosGlobal = gAgent.getPosGlobalFromAgent(v_intersection);
- if (mWantSurfaceInfo)
- {
- getSurfaceInfo();
- }
- }
- }
- if (mPickParticle)
- {
- // Search for closest particle to click origin out to intersection
- // point
- S32 part_face = -1;
- LLVOPartGroup* groupp =
- gPipeline.lineSegmentIntersectParticle(start, particle_end, NULL,
- &part_face);
- if (groupp)
- {
- mParticleOwnerID = groupp->getPartOwner(part_face);
- mParticleSourceID = groupp->getPartSource(part_face);
- }
- }
- if (mPickCallback)
- {
- mPickCallback(*this);
- }
- }
- LLPointer<LLViewerObject> LLPickInfo::getObject() const
- {
- return gObjectList.findObject(mObjectID);
- }
- void LLPickInfo::updateXYCoords()
- {
- if (mObjectFace > -1)
- {
- const LLTextureEntry* tep = getObject()->getTE(mObjectFace);
- if (!tep) return;
- LLPointer<LLViewerTexture> imagep =
- LLViewerTextureManager::getFetchedTexture(tep->getID());
- if (imagep.notNull() && mUVCoords.mV[VX] >= 0.f &&
- mUVCoords.mV[VY] >= 0.f)
- {
- mXYCoords.mX = ll_round(mUVCoords.mV[VX] *
- (F32)imagep->getWidth());
- mXYCoords.mY = ll_round((1.f - mUVCoords.mV[VY]) *
- (F32)imagep->getHeight());
- }
- }
- }
- void LLPickInfo::getSurfaceInfo()
- {
- // Set values to uninitialized: this is what we return if no intersection
- // is found
- mObjectFace = -1;
- mUVCoords = LLVector2(-1.f, -1.f);
- mSTCoords = LLVector2(-1.f, -1.f);
- mXYCoords = LLCoordScreen(-1.f, -1.f);
- mIntersection.setZero();
- mNormal.setZero();
- mBinormal.setZero();
- mTangent.setZero();
- LLViewerObject* objectp = getObject();
- if (!objectp) return;
- static LLVector4a tangent;
- static LLVector4a intersection;
- static LLVector4a normal;
- tangent.clear();
- normal.clear();
- intersection.clear();
- if (gViewerWindowp->cursorIntersect(ll_round((F32)mMousePt.mX),
- ll_round((F32)mMousePt.mY), 1024.f,
- objectp, -1, mPickTransparent,
- mPickRigged, &mObjectFace,
- &mGLTFNodeIndex, &mGLTFPrimIndex,
- &intersection, &mSTCoords, &normal,
- &tangent))
- {
- // If we succeeded with the intersect above, compute the texture
- // coordinates:
- if (objectp->mDrawable.notNull() && mObjectFace > -1)
- {
- LLFace* facep = objectp->mDrawable->getFace(mObjectFace);
- if (facep)
- {
- mUVCoords = facep->surfaceToTexture(mSTCoords, intersection,
- normal);
- }
- }
- mIntersection.set(intersection.getF32ptr());
- mNormal.set(normal.getF32ptr());
- mTangent.set(tangent.getF32ptr());
- // Extrapoloate binormal from normal and tangent
- static LLVector4a binormal;
- binormal.setCross3(normal, tangent);
- binormal.mul(tangent.getF32ptr()[3]);
- mBinormal.set(binormal.getF32ptr());
- mBinormal.normalize();
- mNormal.normalize();
- mTangent.normalize();
- // and XY coords:
- updateXYCoords();
- }
- }
- //static
- bool LLPickInfo::isFlora(LLViewerObject* object)
- {
- if (!object) return false;
- LLPCode pcode = object->getPCode();
- return pcode == LL_PCODE_LEGACY_GRASS || pcode == LL_PCODE_LEGACY_TREE;
- }
- ///////////////////////////////////////////////////////////////////////////////
- // HBTempWindowTitle class
- ///////////////////////////////////////////////////////////////////////////////
- HBTempWindowTitle::HBTempWindowTitle(const std::string& message)
- {
- if (gWindowp && !message.empty())
- {
- std::string title = gSecondLife + " - " + message;
- LLStringUtil::truncate(title, 255);
- gWindowp->setWindowTitle(title);
- }
- }
- HBTempWindowTitle::~HBTempWindowTitle()
- {
- if (gWindowp)
- {
- gWindowp->setWindowTitle(gWindowTitle);
- }
- }
|