diff options
Diffstat (limited to 'indra/newview')
230 files changed, 21769 insertions, 7812 deletions
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index b31b99f47c..eb88a6b251 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -13,6 +13,7 @@ include(EXPAT) include(FMOD) include(OPENAL) include(FindOpenGL) +include(Hunspell) include(JsonCpp) include(LLAudio) include(LLCharacter) @@ -30,7 +31,6 @@ include(LLUI) include(LLVFS) include(LLWindow) include(LLXML) -include(LLXUIXML) include(LScript) include(Linking) include(NDOF) @@ -66,12 +66,12 @@ include_directories( ${LLVFS_INCLUDE_DIRS} ${LLWINDOW_INCLUDE_DIRS} ${LLXML_INCLUDE_DIRS} - ${LLXUIXML_INCLUDE_DIRS} ${LSCRIPT_INCLUDE_DIRS} ${LSCRIPT_INCLUDE_DIRS}/lscript_compile ${LLLOGIN_INCLUDE_DIRS} ${UPDATER_INCLUDE_DIRS} ${LIBS_PREBUILT_DIR}/include/collada + ${LIBS_PREBUILD_DIR}/include/hunspell ${OPENAL_LIB_INCLUDE_DIRS} ${LIBS_PREBUILT_DIR}/include/collada/1.4 ) @@ -98,6 +98,7 @@ set(viewer_SOURCE_FILES llassetuploadresponders.cpp llattachmentsmgr.cpp llaudiosourcevo.cpp + llautoreplace.cpp llavataractions.cpp llavatariconctrl.cpp llavatarlist.cpp @@ -171,6 +172,7 @@ set(viewer_SOURCE_FILES llfloaterabout.cpp llfloaterbvhpreview.cpp llfloaterauction.cpp + llfloaterautoreplacesettings.cpp llfloateravatar.cpp llfloateravatarpicker.cpp llfloateravatartextures.cpp @@ -214,7 +216,6 @@ set(viewer_SOURCE_FILES llfloatermemleak.cpp llfloatermodelpreview.cpp llfloatermodeluploadbase.cpp - llfloatermodelwizard.cpp llfloaternamedesc.cpp llfloaternotificationsconsole.cpp llfloaterobjectweights.cpp @@ -236,9 +237,11 @@ set(viewer_SOURCE_FILES llfloatersidepanelcontainer.cpp llfloatersnapshot.cpp llfloatersounddevices.cpp + llfloaterspellchecksettings.cpp llfloatertelehub.cpp llfloatertestinspectors.cpp llfloatertestlistview.cpp + llfloatertexturefetchdebugger.cpp llfloatertools.cpp llfloatertopobjects.cpp llfloatertos.cpp @@ -491,6 +494,7 @@ set(viewer_SOURCE_FILES lltoastnotifypanel.cpp lltoastpanel.cpp lltoastscripttextbox.cpp + lltoastscriptquestion.cpp lltool.cpp lltoolbarview.cpp lltoolbrush.cpp @@ -655,6 +659,7 @@ set(viewer_HEADER_FILES llassetuploadresponders.h llattachmentsmgr.h llaudiosourcevo.h + llautoreplace.h llavataractions.h llavatariconctrl.h llavatarlist.h @@ -728,6 +733,7 @@ set(viewer_HEADER_FILES llfloaterabout.h llfloaterbvhpreview.h llfloaterauction.h + llfloaterautoreplacesettings.h llfloateravatar.h llfloateravatarpicker.h llfloateravatartextures.h @@ -771,7 +777,6 @@ set(viewer_HEADER_FILES llfloatermemleak.h llfloatermodelpreview.h llfloatermodeluploadbase.h - llfloatermodelwizard.h llfloaternamedesc.h llfloaternotificationsconsole.h llfloaterobjectweights.h @@ -793,9 +798,11 @@ set(viewer_HEADER_FILES llfloatersidepanelcontainer.h llfloatersnapshot.h llfloatersounddevices.h + llfloaterspellchecksettings.h llfloatertelehub.h llfloatertestinspectors.h llfloatertestlistview.h + llfloatertexturefetchdebugger.h llfloatertools.h llfloatertopobjects.h llfloatertos.h @@ -1038,6 +1045,7 @@ set(viewer_HEADER_FILES lltoastnotifypanel.h lltoastpanel.h lltoastscripttextbox.h + lltoastscriptquestion.h lltool.h lltoolbarview.h lltoolbrush.h @@ -1573,6 +1581,9 @@ if (WINDOWS) ${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/msvcp100.dll ${SHARED_LIB_STAGING_DIR}/Debug/msvcr100d.dll ${SHARED_LIB_STAGING_DIR}/Debug/msvcp100d.dll + ${SHARED_LIB_STAGING_DIR}/Release/libhunspell.dll + ${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/libhunspell.dll + ${SHARED_LIB_STAGING_DIR}/Debug/libhunspell.dll ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/SLVoice.exe ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/vivoxsdk.dll ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/ortp.dll @@ -1747,11 +1758,11 @@ target_link_libraries(${VIEWER_BINARY_NAME} ${LLVFS_LIBRARIES} ${LLWINDOW_LIBRARIES} ${LLXML_LIBRARIES} - ${LLXUIXML_LIBRARIES} ${LSCRIPT_LIBRARIES} ${LLMATH_LIBRARIES} ${LLCOMMON_LIBRARIES} ${NDOF_LIBRARY} + ${HUNSPELL_LIBRARY} ${viewer_LIBRARIES} ${BOOST_PROGRAM_OPTIONS_LIBRARY} ${BOOST_REGEX_LIBRARY} diff --git a/indra/newview/app_settings/autoreplace.xml b/indra/newview/app_settings/autoreplace.xml new file mode 100644 index 0000000000..09d19f7b04 --- /dev/null +++ b/indra/newview/app_settings/autoreplace.xml @@ -0,0 +1,8330 @@ +<llsd> + <array> + <map> + <key>name</key> + <string>Abbreviations</string> + <key>replacements</key> + <map> + <key>afaic</key> + <string>As far as I am concerned</string> + <key>afaik</key> + <string>As far as I know</string> + <key>afk</key> + <string>away from keyboard</string> + <key>atm</key> + <string>at the moment</string> + <key>bbiab</key> + <string>be back in a bit</string> + <key>bbl</key> + <string>be back later</string> + <key>brb</key> + <string>be right back</string> + <key>btw</key> + <string>by the way</string> + <key>fyi</key> + <string>For your information</string> + <key>fwiw</key> + <string>For what its worth</string> + <key>gtg</key> + <string>got to go</string> + <key>idk</key> + <string>I don't know</string> + <key>iirc</key> + <string>if I recall correctly</string> + <key>imho</key> + <string>in my humble opinion</string> + <key>imo</key> + <string>in my opinion</string> + <key>irl</key> + <string>in real life</string> + <key>np</key> + <string>no problem</string> + <key>nsfw</key> + <string>not safe for work</string> + <key>nvm</key> + <string>nevermind</string> + <key>tc</key> + <string>take care</string> + <key>thx</key> + <string>thanks</string> + <key>ttfn</key> + <string>ta-ta for now</string> + <key>ttyl</key> + <string>talk to you later</string> + <key>ty</key> + <string>thank you</string> + <key>tyvm</key> + <string>thank you very much</string> + <key>wb</key> + <string>welcome back</string> + <key>yw</key> + <string>you're welcome</string> + <key>yvw</key> + <string>you're very welcome</string> + </map> + </map> + <map> + <key>name</key> + <string>Spelling Corrections</string> + <key>replacements</key> + <map> + <key>Amercia</key> + <string>America</string> + <key>Bernouilli</key> + <string>Bernoulli</string> + <key>Blitzkreig</key> + <string>Blitzkrieg</string> + <key>Bonnano</key> + <string>Bonanno</string> + <key>Brasillian</key> + <string>Brazilian</string> + <key>Britian</key> + <string>Britain</string> + <key>Brittish</key> + <string>British</string> + <key>Buddah</key> + <string>Buddha</string> + <key>Buddist</key> + <string>Buddhist</string> + <key>Cambrige</key> + <string>Cambridge</string> + <key>Capetown</key> + <string>Cape Town</string> + <key>Carmalite</key> + <string>Carmelite</string> + <key>Carnagie</key> + <string>Carnegie</string> + <key>Carnagie-Mellon</key> + <string>Carnegie-Mellon</string> + <key>Carnigie</key> + <string>Carnegie</string> + <key>Carnigie-Mellon</key> + <string>Carnegie-Mellon</string> + <key>Carribbean</key> + <string>Caribbean</string> + <key>Carribean</key> + <string>Caribbean</string> + <key>Carthagian</key> + <string>Carthaginian</string> + <key>Cataline</key> + <string>Catiline</string> + <key>Ceasar</key> + <string>Caesar</string> + <key>Celcius</key> + <string>Celsius</string> + <key>Champange</key> + <string>Champagne</string> + <key>Cincinatti</key> + <string>Cincinnati</string> + <key>Cincinnatti</key> + <string>Cincinnati</string> + <key>Conneticut</key> + <string>Connecticut</string> + <key>Dardenelles</key> + <string>Dardanelles</string> + <key>Dravadian</key> + <string>Dravidian</string> + <key>Enlish</key> + <string>English</string> + <key>Europian</key> + <string>European</string> + <key>Europians</key> + <string>Europeans</string> + <key>Eurpean</key> + <string>European</string> + <key>Eurpoean</key> + <string>European</string> + <key>Farenheit</key> + <string>Fahrenheit</string> + <key>Febuary</key> + <string>February</string> + <key>Feburary</key> + <string>February</string> + <key>Flemmish</key> + <string>Flemish</string> + <key>Formalhaut</key> + <string>Fomalhaut</string> + <key>Foundland</key> + <string>Newfoundland</string> + <key>Fransiscan</key> + <string>Franciscan</string> + <key>Fransiscans</key> + <string>Franciscans</string> + <key>Galations</key> + <string>Galatians</string> + <key>Gameboy</key> + <string>Game Boy</string> + <key>Ghandi</key> + <string>Gandhi</string> + <key>Godounov</key> + <string>Godunov</string> + <key>Gothenberg</key> + <string>Gothenburg</string> + <key>Gottleib</key> + <string>Gottlieb</string> + <key>Guaduloupe</key> + <string>Guadalupe</string> + <key>Guadulupe</key> + <string>Guadalupe</string> + <key>Guatamala</key> + <string>Guatemala</string> + <key>Guatamalan</key> + <string>Guatemalan</string> + <key>Guilia</key> + <string>Giulia</string> + <key>Guilio</key> + <string>Giulio</string> + <key>Guiness</key> + <string>Guinness</string> + <key>Guiseppe</key> + <string>Giuseppe</string> + <key>Habsbourg</key> + <string>Habsburg</string> + <key>Hallowean</key> + <string>Halloween</string> + <key>Heidelburg</key> + <string>Heidelberg</string> + <key>Ihaca</key> + <string>Ithaca</string> + <key>Israelies</key> + <string>Israelis</string> + <key>Janurary</key> + <string>January</string> + <key>Januray</key> + <string>January</string> + <key>Japanes</key> + <string>Japanese</string> + <key>Johanine</key> + <string>Johannine</string> + <key>Jospeh</key> + <string>Joseph</string> + <key>Juadaism</key> + <string>Judaism</string> + <key>Juadism</key> + <string>Judaism</string> + <key>Lybia</key> + <string>Libya</string> + <key>Malcom</key> + <string>Malcolm</string> + <key>Massachussets</key> + <string>Massachusetts</string> + <key>Massachussetts</key> + <string>Massachusetts</string> + <key>Mediteranean</key> + <string>Mediterranean</string> + <key>Michagan</key> + <string>Michigan</string> + <key>Misouri</key> + <string>Missouri</string> + <key>Missisipi</key> + <string>Mississippi</string> + <key>Missisippi</key> + <string>Mississippi</string> + <key>Monserrat</key> + <string>Montserrat</string> + <key>Montnana</key> + <string>Montana</string> + <key>Morisette</key> + <string>Morissette</string> + <key>Morrisette</key> + <string>Morissette</string> + <key>Mythraic</key> + <string>Mithraic</string> + <key>Naploeon</key> + <string>Napoleon</string> + <key>Napolean</key> + <string>Napoleon</string> + <key>Napoleonian</key> + <string>Napoleonic</string> + <key>Nazereth</key> + <string>Nazareth</string> + <key>Newyorker</key> + <string>New Yorker</string> + <key>Novermber</key> + <string>November</string> + <key>Nullabour</key> + <string>Nullarbor</string> + <key>Nuremburg</key> + <string>Nuremberg</string> + <key>Palistian</key> + <string>Palestinian</string> + <key>Palistinian</key> + <string>Palestinian</string> + <key>Palistinians</key> + <string>Palestinians</string> + <key>Papanicalou</key> + <string>Papanicolaou</string> + <key>Peloponnes</key> + <string>Peloponnesus</string> + <key>Pennyslvania</key> + <string>Pennsylvania</string> + <key>Pharoah</key> + <string>Pharaoh</string> + <key>Philipines</key> + <string>Philippines</string> + <key>Phillipine</key> + <string>Philippine</string> + <key>Phillipines</key> + <string>Philippines</string> + <key>Phillippines</key> + <string>Philippines</string> + <key>Phonecian</key> + <string>Phoenecian</string> + <key>Portugese</key> + <string>Portuguese</string> + <key>Postdam</key> + <string>Potsdam</string> + <key>Premonasterians</key> + <string>Premonstratensians</string> + <key>Pucini</key> + <string>Puccini</string> + <key>Puertorrican</key> + <string>Puerto Rican</string> + <key>Puertorricans</key> + <string>Puerto Ricans</string> + <key>Queenland</key> + <string>Queensland</string> + <key>Rockerfeller</key> + <string>Rockefeller</string> + <key>Russion</key> + <string>Russian</string> + <key>Sanhedrim</key> + <string>Sanhedrin</string> + <key>Saterday</key> + <string>Saturday</string> + <key>Saterdays</key> + <string>Saturdays</string> + <key>Sionist</key> + <string>Zionist</string> + <key>Sionists</key> + <string>Zionists</string> + <key>Sixtin</key> + <string>Sistine</string> + <key>Skagerak</key> + <string>Skagerrak</string> + <key>Tolkein</key> + <string>Tolkien</string> + <key>Tuscon</key> + <string>Tucson</string> + <key>Ukranian</key> + <string>Ukrainian</string> + <key>UnitesStates</key> + <string>UnitedStates</string> + <key>Yementite</key> + <string>Yemenite</string> + <key>abandonned</key> + <string>abandoned</string> + <key>aberation</key> + <string>aberration</string> + <key>abilties</key> + <string>abilities</string> + <key>abilty</key> + <string>ability</string> + <key>abondon</key> + <string>abandon</string> + <key>abondoned</key> + <string>abandoned</string> + <key>abondoning</key> + <string>abandoning</string> + <key>abondons</key> + <string>abandons</string> + <key>aborigene</key> + <string>aborigine</string> + <key>abortificant</key> + <string>abortifacient</string> + <key>abreviate</key> + <string>abbreviate</string> + <key>abreviated</key> + <string>abbreviated</string> + <key>abreviation</key> + <string>abbreviation</string> + <key>abritrary</key> + <string>arbitrary</string> + <key>absail</key> + <string>abseil</string> + <key>absailing</key> + <string>abseiling</string> + <key>absense</key> + <string>absence</string> + <key>absolutly</key> + <string>absolutely</string> + <key>absorbsion</key> + <string>absorption</string> + <key>absorbtion</key> + <string>absorption</string> + <key>abundacies</key> + <string>abundances</string> + <key>abundancies</key> + <string>abundances</string> + <key>abundunt</key> + <string>abundant</string> + <key>abutts</key> + <string>abuts</string> + <key>acadamy</key> + <string>academy</string> + <key>acadmic</key> + <string>academic</string> + <key>accademic</key> + <string>academic</string> + <key>accademy</key> + <string>academy</string> + <key>acccused</key> + <string>accused</string> + <key>accelleration</key> + <string>acceleration</string> + <key>accension</key> + <string>ascension</string> + <key>acceptence</key> + <string>acceptance</string> + <key>acceptible</key> + <string>acceptable</string> + <key>accessable</key> + <string>accessible</string> + <key>accidentaly</key> + <string>accidentally</string> + <key>accidently</key> + <string>accidentally</string> + <key>acclimitization</key> + <string>acclimatization</string> + <key>accomadate</key> + <string>accommodate</string> + <key>accomadated</key> + <string>accommodated</string> + <key>accomadates</key> + <string>accommodates</string> + <key>accomadating</key> + <string>accommodating</string> + <key>accomadation</key> + <string>accommodation</string> + <key>accomadations</key> + <string>accommodations</string> + <key>accomdate</key> + <string>accommodate</string> + <key>accomodate</key> + <string>accommodate</string> + <key>accomodated</key> + <string>accommodated</string> + <key>accomodates</key> + <string>accommodates</string> + <key>accomodating</key> + <string>accommodating</string> + <key>accomodation</key> + <string>accommodation</string> + <key>accomodations</key> + <string>accommodations</string> + <key>accompanyed</key> + <string>accompanied</string> + <key>accordeon</key> + <string>accordion</string> + <key>accordian</key> + <string>accordion</string> + <key>accoring</key> + <string>according</string> + <key>accoustic</key> + <string>acoustic</string> + <key>accquainted</key> + <string>acquainted </string> + <key>accrediation</key> + <string>accreditation</string> + <key>accredidation</key> + <string>accreditation</string> + <key>accross</key> + <string>across</string> + <key>accussed</key> + <string>accused</string> + <key>acedemic</key> + <string>academic</string> + <key>acheive</key> + <string>achieve</string> + <key>acheived</key> + <string>achieved</string> + <key>acheivement</key> + <string>achievement</string> + <key>acheivements</key> + <string>achievements</string> + <key>acheives</key> + <string>achieves</string> + <key>acheiving</key> + <string>achieving</string> + <key>acheivment</key> + <string>achievement</string> + <key>acheivments</key> + <string>achievements</string> + <key>achievment</key> + <string>achievement</string> + <key>achievments</key> + <string>achievements</string> + <key>achivement</key> + <string>achievement</string> + <key>achivements</key> + <string>achievements</string> + <key>acknowldeged</key> + <string>acknowledged</string> + <key>acknowledgeing</key> + <string>acknowledging</string> + <key>ackward</key> + <string>awkward</string> + <key>acommodate</key> + <string>accommodate</string> + <key>acomplish</key> + <string>accomplish</string> + <key>acomplished</key> + <string>accomplished</string> + <key>acomplishment</key> + <string>accomplishment</string> + <key>acomplishments</key> + <string>accomplishments</string> + <key>acording</key> + <string>according</string> + <key>acordingly</key> + <string>accordingly</string> + <key>acquaintence</key> + <string>acquaintance</string> + <key>acquaintences</key> + <string>acquaintances</string> + <key>acquiantence</key> + <string>acquaintance</string> + <key>acquiantences</key> + <string>acquaintances</string> + <key>acquited</key> + <string>acquitted</string> + <key>activites</key> + <string>activities</string> + <key>activly</key> + <string>actively</string> + <key>actualy</key> + <string>actually</string> + <key>acuracy</key> + <string>accuracy</string> + <key>acused</key> + <string>accused</string> + <key>acustom</key> + <string>accustom</string> + <key>acustommed</key> + <string>accustomed</string> + <key>adavanced</key> + <string>advanced</string> + <key>adbandon</key> + <string>abandon</string> + <key>additinally</key> + <string>additionally</string> + <key>additionaly</key> + <string>additionally</string> + <key>additonal</key> + <string>additional</string> + <key>additonally</key> + <string>additionally</string> + <key>addmission</key> + <string>admission</string> + <key>addopt</key> + <string>adopt</string> + <key>addopted</key> + <string>adopted</string> + <key>addoptive</key> + <string>adoptive</string> + <key>addres</key> + <string>address</string> + <key>addresable</key> + <string>addressable</string> + <key>addresed</key> + <string>addressed</string> + <key>addresing</key> + <string>addressing</string> + <key>addressess</key> + <string>addresses</string> + <key>addtion</key> + <string>addition</string> + <key>addtional</key> + <string>additional</string> + <key>adecuate</key> + <string>adequate</string> + <key>adequit</key> + <string>adequate</string> + <key>adhearing</key> + <string>adhering</string> + <key>adherance</key> + <string>adherence</string> + <key>admendment</key> + <string>amendment</string> + <key>admininistrative</key> + <string>administrative</string> + <key>adminstered</key> + <string>administered</string> + <key>adminstrate</key> + <string>administrate</string> + <key>adminstration</key> + <string>administration</string> + <key>adminstrative</key> + <string>administrative</string> + <key>adminstrator</key> + <string>administrator</string> + <key>admissability</key> + <string>admissibility</string> + <key>admissable</key> + <string>admissible</string> + <key>admited</key> + <string>admitted</string> + <key>admitedly</key> + <string>admittedly</string> + <key>adn</key> + <string>and</string> + <key>adolecent</key> + <string>adolescent</string> + <key>adquire</key> + <string>acquire</string> + <key>adquired</key> + <string>acquired</string> + <key>adquires</key> + <string>acquires</string> + <key>adquiring</key> + <string>acquiring</string> + <key>adres</key> + <string>address</string> + <key>adresable</key> + <string>addressable</string> + <key>adresing</key> + <string>addressing</string> + <key>adress</key> + <string>address</string> + <key>adressable</key> + <string>addressable</string> + <key>adressed</key> + <string>addressed</string> + <key>adressing</key> + <string>addressing</string> + <key>adventrous</key> + <string>adventurous</string> + <key>advertisment</key> + <string>advertisement</string> + <key>advertisments</key> + <string>advertisements</string> + <key>advesary</key> + <string>adversary</string> + <key>adviced</key> + <string>advised</string> + <key>aeriel</key> + <string>aerial</string> + <key>aeriels</key> + <string>aerials</string> + <key>afair</key> + <string>affair</string> + <key>afficianados</key> + <string>aficionados</string> + <key>afficionado</key> + <string>aficionado</string> + <key>afficionados</key> + <string>aficionados</string> + <key>affilate</key> + <string>affiliate</string> + <key>affilliate</key> + <string>affiliate</string> + <key>affort</key> + <string>afford</string> + <key>aforememtioned</key> + <string>aforementioned</string> + <key>againnst</key> + <string>against</string> + <key>agains</key> + <string>against</string> + <key>agaisnt</key> + <string>against</string> + <key>aganist</key> + <string>against</string> + <key>aggaravates</key> + <string>aggravates</string> + <key>aggreed</key> + <string>agreed</string> + <key>aggreement</key> + <string>agreement</string> + <key>aggregious</key> + <string>egregious</string> + <key>aggresive</key> + <string>aggressive</string> + <key>agian</key> + <string>again</string> + <key>agianst</key> + <string>against</string> + <key>agin</key> + <string>again</string> + <key>agina</key> + <string>again</string> + <key>aginst</key> + <string>against</string> + <key>agravate</key> + <string>aggravate</string> + <key>agre</key> + <string>agree</string> + <key>agred</key> + <string>agreed</string> + <key>agreeement</key> + <string>agreement</string> + <key>agreemnt</key> + <string>agreement</string> + <key>agregate</key> + <string>aggregate</string> + <key>agregates</key> + <string>aggregates</string> + <key>agreing</key> + <string>agreeing</string> + <key>agression</key> + <string>aggression</string> + <key>agressive</key> + <string>aggressive</string> + <key>agressively</key> + <string>aggressively</string> + <key>agressor</key> + <string>aggressor</string> + <key>agricuture</key> + <string>agriculture</string> + <key>agrieved</key> + <string>aggrieved</string> + <key>ahev</key> + <string>have</string> + <key>ahppen</key> + <string>happen</string> + <key>ahve</key> + <string>have</string> + <key>aicraft</key> + <string>aircraft</string> + <key>aiport</key> + <string>airport</string> + <key>airbourne</key> + <string>airborne</string> + <key>aircaft</key> + <string>aircraft</string> + <key>aircrafts</key> + <string>aircraft</string> + <key>airporta</key> + <string>airports</string> + <key>airrcraft</key> + <string>aircraft</string> + <key>aisian</key> + <string>asian</string> + <key>albiet</key> + <string>albeit</string> + <key>alchohol</key> + <string>alcohol</string> + <key>alchoholic</key> + <string>alcoholic</string> + <key>alchol</key> + <string>alcohol</string> + <key>alcholic</key> + <string>alcoholic</string> + <key>alcohal</key> + <string>alcohol</string> + <key>alcoholical</key> + <string>alcoholic</string> + <key>aledge</key> + <string>allege</string> + <key>aledged</key> + <string>alleged</string> + <key>aledges</key> + <string>alleges</string> + <key>alege</key> + <string>allege</string> + <key>aleged</key> + <string>alleged</string> + <key>alegience</key> + <string>allegiance</string> + <key>algebraical</key> + <string>algebraic</string> + <key>algorhitms</key> + <string>algorithms</string> + <key>algoritm</key> + <string>algorithm</string> + <key>algoritms</key> + <string>algorithms</string> + <key>alientating</key> + <string>alienating</string> + <key>alledge</key> + <string>allege</string> + <key>alledged</key> + <string>alleged</string> + <key>alledgedly</key> + <string>allegedly</string> + <key>alledges</key> + <string>alleges</string> + <key>allegedely</key> + <string>allegedly</string> + <key>allegedy</key> + <string>allegedly</string> + <key>allegely</key> + <string>allegedly</string> + <key>allegence</key> + <string>allegiance</string> + <key>allegience</key> + <string>allegiance</string> + <key>allign</key> + <string>align</string> + <key>alligned</key> + <string>aligned</string> + <key>alliviate</key> + <string>alleviate</string> + <key>allopone</key> + <string>allophone</string> + <key>allopones</key> + <string>allophones</string> + <key>allready</key> + <string>already</string> + <key>allthough</key> + <string>although</string> + <key>alltime</key> + <string>all-time</string> + <key>alltogether</key> + <string>altogether</string> + <key>almsot</key> + <string>almost</string> + <key>alochol</key> + <string>alcohol</string> + <key>alomst</key> + <string>almost</string> + <key>alot</key> + <string>a lot</string> + <key>alotted</key> + <string>allotted</string> + <key>alowed</key> + <string>allowed</string> + <key>alowing</key> + <string>allowing</string> + <key>alreayd</key> + <string>already</string> + <key>alse</key> + <string>else</string> + <key>alsot</key> + <string>also</string> + <key>alternitives</key> + <string>alternatives</string> + <key>altho</key> + <string>although</string> + <key>althought</key> + <string>although</string> + <key>altough</key> + <string>although</string> + <key>alusion</key> + <string>allusion</string> + <key>alwasy</key> + <string>always</string> + <key>alwyas</key> + <string>always</string> + <key>amalgomated</key> + <string>amalgamated</string> + <key>amatuer</key> + <string>amateur</string> + <key>amature</key> + <string>armature</string> + <key>amendmant</key> + <string>amendment</string> + <key>amerliorate</key> + <string>ameliorate</string> + <key>amke</key> + <string>make</string> + <key>amking</key> + <string>making</string> + <key>ammend</key> + <string>amend</string> + <key>ammended</key> + <string>amended</string> + <key>ammendment</key> + <string>amendment</string> + <key>ammendments</key> + <string>amendments</string> + <key>ammount</key> + <string>amount</string> + <key>ammused</key> + <string>amused</string> + <key>amoung</key> + <string>among</string> + <key>amoungst</key> + <string>amongst</string> + <key>amung</key> + <string>among</string> + <key>amunition</key> + <string>ammunition</string> + <key>analagous</key> + <string>analogous</string> + <key>analitic</key> + <string>analytic</string> + <key>analogeous</key> + <string>analogous</string> + <key>anarchim</key> + <string>anarchism</string> + <key>anarchistm</key> + <string>anarchism</string> + <key>anbd</key> + <string>and</string> + <key>ancestory</key> + <string>ancestry</string> + <key>ancilliary</key> + <string>ancillary</string> + <key>androgenous</key> + <string>androgynous</string> + <key>androgeny</key> + <string>androgyny</string> + <key>anihilation</key> + <string>annihilation</string> + <key>aniversary</key> + <string>anniversary</string> + <key>annoint</key> + <string>anoint</string> + <key>annointed</key> + <string>anointed</string> + <key>annointing</key> + <string>anointing</string> + <key>annoints</key> + <string>anoints</string> + <key>annouced</key> + <string>announced</string> + <key>annualy</key> + <string>annually</string> + <key>annuled</key> + <string>annulled</string> + <key>anohter</key> + <string>another</string> + <key>anomolies</key> + <string>anomalies</string> + <key>anomolous</key> + <string>anomalous</string> + <key>anomoly</key> + <string>anomaly</string> + <key>anonimity</key> + <string>anonymity</string> + <key>anounced</key> + <string>announced</string> + <key>anouncement</key> + <string>announcement</string> + <key>ansalisation</key> + <string>nasalisation</string> + <key>ansalization</key> + <string>nasalization</string> + <key>ansestors</key> + <string>ancestors</string> + <key>antartic</key> + <string>antarctic</string> + <key>anthromorphization</key> + <string>anthropomorphization</string> + <key>anthropolgist</key> + <string>anthropologist</string> + <key>anthropolgy</key> + <string>anthropology</string> + <key>anual</key> + <string>annual</string> + <key>anulled</key> + <string>annulled</string> + <key>anwsered</key> + <string>answered</string> + <key>anyhwere</key> + <string>anywhere</string> + <key>anyother</key> + <string>any other</string> + <key>anytying</key> + <string>anything</string> + <key>aparent</key> + <string>apparent</string> + <key>aparment</key> + <string>apartment</string> + <key>apenines</key> + <string>apennines</string> + <key>aplication</key> + <string>application</string> + <key>aplied</key> + <string>applied</string> + <key>apolegetics</key> + <string>apologetics</string> + <key>apon</key> + <string>apron</string> + <key>apparant</key> + <string>apparent</string> + <key>apparantly</key> + <string>apparently</string> + <key>appart</key> + <string>apart</string> + <key>appartment</key> + <string>apartment</string> + <key>appartments</key> + <string>apartments</string> + <key>appealling</key> + <string>appealing</string> + <key>appeareance</key> + <string>appearance</string> + <key>appearence</key> + <string>appearance</string> + <key>appearences</key> + <string>appearances</string> + <key>apperance</key> + <string>appearance</string> + <key>apperances</key> + <string>appearances</string> + <key>appereance</key> + <string>appearance</string> + <key>appereances</key> + <string>appearances</string> + <key>applicaiton</key> + <string>application</string> + <key>applicaitons</key> + <string>applications</string> + <key>appologies</key> + <string>apologies</string> + <key>appology</key> + <string>apology</string> + <key>apprearance</key> + <string>appearance</string> + <key>apprieciate</key> + <string>appreciate</string> + <key>approachs</key> + <string>approaches</string> + <key>appropiate</key> + <string>appropriate</string> + <key>appropraite</key> + <string>appropriate</string> + <key>appropropiate</key> + <string>appropriate</string> + <key>approproximate</key> + <string>approximate</string> + <key>approxamately</key> + <string>approximately</string> + <key>approxiately</key> + <string>approximately</string> + <key>approximitely</key> + <string>approximately</string> + <key>aprehensive</key> + <string>apprehensive</string> + <key>apropriate</key> + <string>appropriate</string> + <key>aproximate</key> + <string>approximate</string> + <key>aproximately</key> + <string>approximately</string> + <key>aquaduct</key> + <string>aqueduct</string> + <key>aquaintance</key> + <string>acquaintance</string> + <key>aquainted</key> + <string>acquainted</string> + <key>aquiantance</key> + <string>acquaintance</string> + <key>aquire</key> + <string>acquire</string> + <key>aquired</key> + <string>acquired</string> + <key>aquiring</key> + <string>acquiring</string> + <key>aquisition</key> + <string>acquisition</string> + <key>aquitted</key> + <string>acquitted</string> + <key>aranged</key> + <string>arranged</string> + <key>arangement</key> + <string>arrangement</string> + <key>arbitarily</key> + <string>arbitrarily</string> + <key>arbitary</key> + <string>arbitrary</string> + <key>archaelogists</key> + <string>archaeologists</string> + <key>archaelogy</key> + <string>archaeology</string> + <key>archaoelogy</key> + <string>archaeology</string> + <key>archaology</key> + <string>archaeology</string> + <key>archeaologist</key> + <string>archaeologist</string> + <key>archeaologists</key> + <string>archaeologists</string> + <key>archetect</key> + <string>architect</string> + <key>archetects</key> + <string>architects</string> + <key>archetectural</key> + <string>architectural</string> + <key>archetecturally</key> + <string>architecturally</string> + <key>archetecture</key> + <string>architecture</string> + <key>archiac</key> + <string>archaic</string> + <key>archictect</key> + <string>architect</string> + <key>archimedian</key> + <string>archimedean</string> + <key>architecht</key> + <string>architect</string> + <key>architechturally</key> + <string>architecturally</string> + <key>architechture</key> + <string>architecture</string> + <key>architechtures</key> + <string>architectures</string> + <key>architectual</key> + <string>architectural</string> + <key>archtype</key> + <string>archetype</string> + <key>archtypes</key> + <string>archetypes</string> + <key>aready</key> + <string>already</string> + <key>areodynamics</key> + <string>aerodynamics</string> + <key>argubly</key> + <string>arguably</string> + <key>arguement</key> + <string>argument</string> + <key>arguements</key> + <string>arguments</string> + <key>arised</key> + <string>arose</string> + <key>arival</key> + <string>arrival</string> + <key>armamant</key> + <string>armament</string> + <key>armistace</key> + <string>armistice</string> + <key>arogant</key> + <string>arrogant</string> + <key>arogent</key> + <string>arrogant</string> + <key>aroud</key> + <string>around</string> + <key>arrangment</key> + <string>arrangement</string> + <key>arrangments</key> + <string>arrangements</string> + <key>arround</key> + <string>around</string> + <key>artical</key> + <string>article</string> + <key>artice</key> + <string>article</string> + <key>articel</key> + <string>article</string> + <key>artifical</key> + <string>artificial</string> + <key>artifically</key> + <string>artificially</string> + <key>artillary</key> + <string>artillery</string> + <key>arund</key> + <string>around</string> + <key>asetic</key> + <string>ascetic</string> + <key>asfar</key> + <string>as far</string> + <key>asign</key> + <string>assign</string> + <key>aslo</key> + <string>also</string> + <key>asociated</key> + <string>associated</string> + <key>asorbed</key> + <string>absorbed</string> + <key>asphyxation</key> + <string>asphyxiation</string> + <key>assasin</key> + <string>assassin</string> + <key>assasinate</key> + <string>assassinate</string> + <key>assasinated</key> + <string>assassinated</string> + <key>assasinates</key> + <string>assassinates</string> + <key>assasination</key> + <string>assassination</string> + <key>assasinations</key> + <string>assassinations</string> + <key>assasined</key> + <string>assassinated</string> + <key>assasins</key> + <string>assassins</string> + <key>assassintation</key> + <string>assassination</string> + <key>assemple</key> + <string>assemble</string> + <key>assertation</key> + <string>assertion</string> + <key>asside</key> + <string>aside</string> + <key>assisnate</key> + <string>assassinate</string> + <key>assit</key> + <string>assist</string> + <key>assitant</key> + <string>assistant</string> + <key>assocation</key> + <string>association</string> + <key>assoicate</key> + <string>associate</string> + <key>assoicated</key> + <string>associated</string> + <key>assoicates</key> + <string>associates</string> + <key>assosication</key> + <string>assassination</string> + <key>asssassans</key> + <string>assassins</string> + <key>assualt</key> + <string>assault</string> + <key>assualted</key> + <string>assaulted</string> + <key>assymetric</key> + <string>asymmetric</string> + <key>assymetrical</key> + <string>asymmetrical</string> + <key>asteriod</key> + <string>asteroid</string> + <key>asthetic</key> + <string>aesthetic</string> + <key>asthetical</key> + <string>aesthetical</string> + <key>asthetically</key> + <string>aesthetically</string> + <key>asume</key> + <string>assume</string> + <key>aswell</key> + <string>as well</string> + <key>atain</key> + <string>attain</string> + <key>atempting</key> + <string>attempting</string> + <key>atheistical</key> + <string>atheistic</string> + <key>athenean</key> + <string>athenian</string> + <key>atheneans</key> + <string>athenians</string> + <key>athiesm</key> + <string>atheism</string> + <key>athiest</key> + <string>atheist</string> + <key>atorney</key> + <string>attorney</string> + <key>atribute</key> + <string>attribute</string> + <key>atributed</key> + <string>attributed</string> + <key>atributes</key> + <string>attributes</string> + <key>attaindre</key> + <string>attainder</string> + <key>attemp</key> + <string>attempt</string> + <key>attemped</key> + <string>attempted</string> + <key>attemt</key> + <string>attempt</string> + <key>attemted</key> + <string>attempted</string> + <key>attemting</key> + <string>attempting</string> + <key>attemts</key> + <string>attempts</string> + <key>attendence</key> + <string>attendance</string> + <key>attendent</key> + <string>attendant</string> + <key>attendents</key> + <string>attendants</string> + <key>attened</key> + <string>attended</string> + <key>attension</key> + <string>attention</string> + <key>attitide</key> + <string>attitude</string> + <key>attributred</key> + <string>attributed</string> + <key>attrocities</key> + <string>atrocities</string> + <key>audeince</key> + <string>audience</string> + <key>auromated</key> + <string>automated</string> + <key>austrailia</key> + <string>Australia</string> + <key>austrailian</key> + <string>Australian</string> + <key>auther</key> + <string>author</string> + <key>authobiographic</key> + <string>autobiographic</string> + <key>authobiography</key> + <string>autobiography</string> + <key>authorative</key> + <string>authoritative</string> + <key>authorites</key> + <string>authorities</string> + <key>authorithy</key> + <string>authority</string> + <key>authoritiers</key> + <string>authorities</string> + <key>authoritive</key> + <string>authoritative</string> + <key>authrorities</key> + <string>authorities</string> + <key>autochtonous</key> + <string>autochthonous</string> + <key>autoctonous</key> + <string>autochthonous</string> + <key>automaticly</key> + <string>automatically</string> + <key>automibile</key> + <string>automobile</string> + <key>automonomous</key> + <string>autonomous</string> + <key>autor</key> + <string>author</string> + <key>autority</key> + <string>authority</string> + <key>auxilary</key> + <string>auxiliary</string> + <key>auxillaries</key> + <string>auxiliaries</string> + <key>auxillary</key> + <string>auxiliary</string> + <key>auxilliaries</key> + <string>auxiliaries</string> + <key>auxilliary</key> + <string>auxiliary</string> + <key>availabe</key> + <string> available</string> + <key>availablity</key> + <string>availability</string> + <key>availaible</key> + <string>available</string> + <key>availble</key> + <string>available</string> + <key>availiable</key> + <string>available</string> + <key>availible</key> + <string>available</string> + <key>avalable</key> + <string>available</string> + <key>avalance</key> + <string>avalanche</string> + <key>avaliable</key> + <string>available</string> + <key>avation</key> + <string>aviation</string> + <key>avengence</key> + <string>a vengeance</string> + <key>averageed</key> + <string>averaged</string> + <key>avilable</key> + <string>available</string> + <key>awared</key> + <string>awarded</string> + <key>awya</key> + <string>away</string> + <key>baceause</key> + <string>because</string> + <key>backgorund</key> + <string>background</string> + <key>backrounds</key> + <string>backgrounds</string> + <key>bakc</key> + <string>back</string> + <key>banannas</key> + <string>bananas</string> + <key>bandwith</key> + <string>bandwidth</string> + <key>bankrupcy</key> + <string>bankruptcy</string> + <key>banruptcy</key> + <string>bankruptcy</string> + <key>baout</key> + <string>about</string> + <key>basicaly</key> + <string>basically</string> + <key>basicly</key> + <string>basically</string> + <key>bcak</key> + <string>back</string> + <key>beachead</key> + <string>beachhead</string> + <key>beacuse</key> + <string>because</string> + <key>beastiality</key> + <string>bestiality</string> + <key>beatiful</key> + <string>beautiful</string> + <key>beaurocracy</key> + <string>bureaucracy</string> + <key>beaurocratic</key> + <string>bureaucratic</string> + <key>beautyfull</key> + <string>beautiful</string> + <key>becamae</key> + <string>became</string> + <key>becames</key> + <string>becomes</string> + <key>becasue</key> + <string>because</string> + <key>beccause</key> + <string>because</string> + <key>becomeing</key> + <string>becoming</string> + <key>becomming</key> + <string>becoming</string> + <key>becouse</key> + <string>because</string> + <key>becuase</key> + <string>because</string> + <key>bedore</key> + <string>before</string> + <key>befoer</key> + <string>before</string> + <key>beggin</key> + <string>begin</string> + <key>begginer</key> + <string>beginner</string> + <key>begginers</key> + <string>beginners</string> + <key>beggining</key> + <string>beginning</string> + <key>begginings</key> + <string>beginnings</string> + <key>beggins</key> + <string>begins</string> + <key>begining</key> + <string>beginning</string> + <key>beginnig</key> + <string>beginning</string> + <key>behavour</key> + <string>behavior</string> + <key>beleagured</key> + <string>beleaguered</string> + <key>beleif</key> + <string>belief</string> + <key>beleive</key> + <string>believe</string> + <key>beleived</key> + <string>believed</string> + <key>beleives</key> + <string>believes</string> + <key>beleiving</key> + <string>believing</string> + <key>beligum</key> + <string>belgium</string> + <key>belive</key> + <string>believe</string> + <key>belived</key> + <string>believed</string> + <key>belives</key> + <string>believes</string> + <key>belligerant</key> + <string>belligerent</string> + <key>bellweather</key> + <string>bellwether</string> + <key>bemusemnt</key> + <string>bemusement</string> + <key>beneficary</key> + <string>beneficiary</string> + <key>beng</key> + <string>being</string> + <key>benificial</key> + <string>beneficial</string> + <key>benifit</key> + <string>benefit</string> + <key>benifits</key> + <string>benefits</string> + <key>bergamont</key> + <string>bergamot</string> + <key>beseige</key> + <string>besiege</string> + <key>beseiged</key> + <string>besieged</string> + <key>beseiging</key> + <string>besieging</string> + <key>betwen</key> + <string>between</string> + <key>beween</key> + <string>between</string> + <key>bewteen</key> + <string>between</string> + <key>bilateraly</key> + <string>bilaterally</string> + <key>billingualism</key> + <string>bilingualism</string> + <key>binominal</key> + <string>binomial</string> + <key>bizzare</key> + <string>bizarre</string> + <key>blaim</key> + <string>blame</string> + <key>blaimed</key> + <string>blamed</string> + <key>blessure</key> + <string>blessing</string> + <key>bodydbuilder</key> + <string>bodybuilder</string> + <key>bombardement</key> + <string>bombardment</string> + <key>bombarment</key> + <string>bombardment</string> + <key>bondary</key> + <string>boundary</string> + <key>borke</key> + <string>broke</string> + <key>boundry</key> + <string>boundary</string> + <key>bouyancy</key> + <string>buoyancy</string> + <key>bouyant</key> + <string>buoyant</string> + <key>boyant</key> + <string>buoyant</string> + <key>breakthough</key> + <string>breakthrough</string> + <key>breakthroughts</key> + <string>breakthroughs</string> + <key>breif</key> + <string>brief</string> + <key>breifly</key> + <string>briefly</string> + <key>brethen</key> + <string>brethren</string> + <key>bretheren</key> + <string>brethren</string> + <key>briliant</key> + <string>brilliant</string> + <key>brillant</key> + <string>brilliant</string> + <key>brimestone</key> + <string>brimstone</string> + <key>broacasted</key> + <string>broadcast</string> + <key>broadacasting</key> + <string>broadcasting</string> + <key>broady</key> + <string>broadly</string> + <key>buisness</key> + <string>business</string> + <key>buisnessman</key> + <string>businessman</string> + <key>buoancy</key> + <string>buoyancy</string> + <key>burried</key> + <string>buried</string> + <key>busineses</key> + <string>businesses</string> + <key>busness</key> + <string>business</string> + <key>bussiness</key> + <string>business</string> + <key>caculater</key> + <string>calculator</string> + <key>cacuses</key> + <string>caucuses</string> + <key>cahracters</key> + <string>characters</string> + <key>calaber</key> + <string>caliber</string> + <key>calculater</key> + <string>calculator</string> + <key>calculs</key> + <string>calculus</string> + <key>calenders</key> + <string>calendars</string> + <key>caligraphy</key> + <string>calligraphy</string> + <key>caluclate</key> + <string>calculate</string> + <key>caluclated</key> + <string>calculated</string> + <key>caluculate</key> + <string>calculate</string> + <key>caluculated</key> + <string>calculated</string> + <key>calulate</key> + <string>calculate</string> + <key>calulated</key> + <string>calculated</string> + <key>calulater</key> + <string>calculator</string> + <key>camoflage</key> + <string>camouflage</string> + <key>campain</key> + <string>campaign</string> + <key>campains</key> + <string>campaigns</string> + <key>candadate</key> + <string>candidate</string> + <key>candiate</key> + <string>candidate</string> + <key>candidiate</key> + <string>candidate</string> + <key>cannister</key> + <string>canister</string> + <key>cannisters</key> + <string>canisters</string> + <key>cannnot</key> + <string>cannot</string> + <key>cannonical</key> + <string>canonical</string> + <key>cannotation</key> + <string>connotation</string> + <key>cannotations</key> + <string>connotations</string> + <key>cant</key> + <string>can't</string> + <key>caost</key> + <string>coast</string> + <key>caperbility</key> + <string>capability</string> + <key>capible</key> + <string>capable</string> + <key>captial</key> + <string>capital</string> + <key>captued</key> + <string>captured</string> + <key>capturd</key> + <string>captured</string> + <key>carachter</key> + <string>character</string> + <key>caracterized</key> + <string>characterized</string> + <key>carcas</key> + <string>carcass</string> + <key>carefull</key> + <string>careful</string> + <key>careing</key> + <string>caring</string> + <key>carismatic</key> + <string>charismatic</string> + <key>carnege</key> + <string>carnage</string> + <key>carnige</key> + <string>carnage</string> + <key>carniverous</key> + <string>carnivorous</string> + <key>carreer</key> + <string>career</string> + <key>carrers</key> + <string>careers</string> + <key>cartdridge</key> + <string>cartridge</string> + <key>carthographer</key> + <string>cartographer</string> + <key>cartilege</key> + <string>cartilage</string> + <key>cartilidge</key> + <string>cartilage</string> + <key>cartrige</key> + <string>cartridge</string> + <key>casette</key> + <string>cassette</string> + <key>casion</key> + <string>caisson</string> + <key>cassawory</key> + <string>cassowary</string> + <key>cassowarry</key> + <string>cassowary</string> + <key>casulaties</key> + <string>casualties</string> + <key>casulaty</key> + <string>casualty</string> + <key>catagories</key> + <string>categories</string> + <key>catagorized</key> + <string>categorized</string> + <key>catagory</key> + <string>category</string> + <key>catapillar</key> + <string>caterpillar</string> + <key>catapillars</key> + <string>caterpillars</string> + <key>catapiller</key> + <string>caterpillar</string> + <key>catapillers</key> + <string>caterpillars</string> + <key>catepillar</key> + <string>caterpillar</string> + <key>catepillars</key> + <string>caterpillars</string> + <key>catergorize</key> + <string>categorize</string> + <key>catergorized</key> + <string>categorized</string> + <key>caterpilar</key> + <string>caterpillar</string> + <key>caterpilars</key> + <string>caterpillars</string> + <key>caterpiller</key> + <string>caterpillar</string> + <key>caterpillers</key> + <string>caterpillars</string> + <key>cathlic</key> + <string>catholic</string> + <key>catholocism</key> + <string>catholicism</string> + <key>catterpilar</key> + <string>caterpillar</string> + <key>catterpilars</key> + <string>caterpillars</string> + <key>catterpillar</key> + <string>caterpillar</string> + <key>catterpillars</key> + <string>caterpillars</string> + <key>cattleship</key> + <string>battleship</string> + <key>causalities</key> + <string>casualties</string> + <key>cellpading</key> + <string>cellpadding</string> + <key>cementary</key> + <string>cemetery</string> + <key>cemetarey</key> + <string>cemetery</string> + <key>cemetaries</key> + <string>cemeteries</string> + <key>cemetary</key> + <string>cemetery</string> + <key>cencus</key> + <string>census</string> + <key>censur</key> + <string>censor</string> + <key>cententenial</key> + <string>centennial</string> + <key>centruies</key> + <string>centuries</string> + <key>centruy</key> + <string>century</string> + <key>ceratin</key> + <string>certain</string> + <key>cerimonial</key> + <string>ceremonial</string> + <key>cerimonies</key> + <string>ceremonies</string> + <key>cerimonious</key> + <string>ceremonious</string> + <key>cerimony</key> + <string>ceremony</string> + <key>ceromony</key> + <string>ceremony</string> + <key>certainity</key> + <string>certainty</string> + <key>certian</key> + <string>certain</string> + <key>chalenging</key> + <string>challenging</string> + <key>challange</key> + <string>challenge</string> + <key>challanged</key> + <string>challenged</string> + <key>challege</key> + <string>challenge</string> + <key>changable</key> + <string>changeable</string> + <key>charachter</key> + <string>character</string> + <key>charachters</key> + <string>characters</string> + <key>charactersistic</key> + <string>characteristic</string> + <key>charactor</key> + <string>character </string> + <key>charactors</key> + <string>characters</string> + <key>charasmatic</key> + <string>charismatic</string> + <key>charaterized</key> + <string>characterized</string> + <key>chariman</key> + <string>chairman</string> + <key>charistics</key> + <string>characteristics</string> + <key>cheif</key> + <string>chief</string> + <key>cheifs</key> + <string>chiefs</string> + <key>chemcial</key> + <string>chemical</string> + <key>chemcially</key> + <string>chemically</string> + <key>chemestry</key> + <string>chemistry</string> + <key>chemicaly</key> + <string>chemically</string> + <key>childbird</key> + <string>childbirth</string> + <key>childen</key> + <string>children</string> + <key>choosen</key> + <string>chosen</string> + <key>chracter</key> + <string>character</string> + <key>chuch</key> + <string>church</string> + <key>churchs</key> + <string>churches</string> + <key>circulaton</key> + <string>circulation</string> + <key>circumsicion</key> + <string>circumcision</string> + <key>circut</key> + <string>circuit</string> + <key>ciricuit</key> + <string>circuit</string> + <key>ciriculum</key> + <string>curriculum</string> + <key>civillian</key> + <string>civilian</string> + <key>claer</key> + <string>clear</string> + <key>claerer</key> + <string>clearer</string> + <key>claerly</key> + <string>clearly</string> + <key>claimes</key> + <string>claims</string> + <key>clas</key> + <string>class</string> + <key>clasic</key> + <string>classic</string> + <key>clasical</key> + <string>classical</string> + <key>clasically</key> + <string>classically</string> + <key>cleareance</key> + <string>clearance</string> + <key>clera</key> + <string>clear</string> + <key>clincial</key> + <string>clinical</string> + <key>clinicaly</key> + <string>clinically</string> + <key>cmo</key> + <string>com</string> + <key>cmoputer</key> + <string>computer</string> + <key>co-incided</key> + <string>coincided</string> + <key>coctail</key> + <string>cocktail</string> + <key>coform</key> + <string>conform</string> + <key>cognizent</key> + <string>cognizant</string> + <key>coincedentally</key> + <string>coincidentally</string> + <key>colaborations</key> + <string>collaborations</string> + <key>colateral</key> + <string>collateral</string> + <key>colelctive</key> + <string>collective</string> + <key>collaberative</key> + <string>collaborative</string> + <key>collecton</key> + <string>collection</string> + <key>collegue</key> + <string>colleague</string> + <key>collegues</key> + <string>colleagues</string> + <key>collonade</key> + <string>colonnade</string> + <key>collonies</key> + <string>colonies</string> + <key>collony</key> + <string>colony </string> + <key>collosal</key> + <string>colossal</string> + <key>colonizators</key> + <string>colonizers</string> + <key>comander</key> + <string>commander</string> + <key>comando</key> + <string>commando</string> + <key>comandos</key> + <string>commandos</string> + <key>comany</key> + <string>company</string> + <key>comapany</key> + <string>company</string> + <key>comback</key> + <string>comeback</string> + <key>combanations</key> + <string>combinations</string> + <key>combinatins</key> + <string>combinations</string> + <key>combusion</key> + <string>combustion</string> + <key>comdemnation</key> + <string>condemnation</string> + <key>comemmorates</key> + <string>commemorates</string> + <key>comemoretion</key> + <string>commemoration</string> + <key>comision</key> + <string>commission</string> + <key>comisioned</key> + <string>commissioned</string> + <key>comisioner</key> + <string>commissioner</string> + <key>comisioning</key> + <string>commissioning</string> + <key>comisions</key> + <string>commissions</string> + <key>comission</key> + <string>commission</string> + <key>comissioned</key> + <string>commissioned</string> + <key>comissioner</key> + <string>commissioner</string> + <key>comissioning</key> + <string>commissioning</string> + <key>comissions</key> + <string>commissions</string> + <key>comited</key> + <string>committed</string> + <key>comiting</key> + <string>committing</string> + <key>comitted</key> + <string>committed</string> + <key>comittee</key> + <string>committee</string> + <key>comitting</key> + <string>committing</string> + <key>commandoes</key> + <string>commandos</string> + <key>commedic</key> + <string>comedic</string> + <key>commemerative</key> + <string>commemorative</string> + <key>commemmorate</key> + <string>commemorate</string> + <key>commemmorating</key> + <string>commemorating</string> + <key>commerical</key> + <string>commercial</string> + <key>commerically</key> + <string>commercially</string> + <key>commericial</key> + <string>commercial</string> + <key>commericially</key> + <string>commercially</string> + <key>commerorative</key> + <string>commemorative</string> + <key>comming</key> + <string>coming</string> + <key>comminication</key> + <string>communication</string> + <key>commision</key> + <string>commission</string> + <key>commisioned</key> + <string>commissioned</string> + <key>commisioner</key> + <string>commissioner</string> + <key>commisioning</key> + <string>commissioning</string> + <key>commisions</key> + <string>commissions</string> + <key>commited</key> + <string>committed</string> + <key>commitee</key> + <string>committee</string> + <key>commiting</key> + <string>committing</string> + <key>committe</key> + <string>committee</string> + <key>committment</key> + <string>commitment</string> + <key>committments</key> + <string>commitments</string> + <key>commmemorated</key> + <string>commemorated</string> + <key>commongly</key> + <string>commonly</string> + <key>commonweath</key> + <string>commonwealth</string> + <key>commuications</key> + <string>communications</string> + <key>commuinications</key> + <string>communications</string> + <key>communciation</key> + <string>communication</string> + <key>communiation</key> + <string>communication</string> + <key>communites</key> + <string>communities</string> + <key>compability</key> + <string>compatibility</string> + <key>comparision</key> + <string>comparison</string> + <key>comparisions</key> + <string>comparisons</string> + <key>comparitive</key> + <string>comparative</string> + <key>comparitively</key> + <string>comparatively</string> + <key>compatabilities</key> + <string>compatibilities</string> + <key>compatability</key> + <string>compatibility</string> + <key>compatable</key> + <string>compatible</string> + <key>compatablities</key> + <string>compatibilities</string> + <key>compatablity</key> + <string>compatibility</string> + <key>compatiable</key> + <string>compatible</string> + <key>compatiblities</key> + <string>compatibilities</string> + <key>compatiblity</key> + <string>compatibility</string> + <key>compeitions</key> + <string>competitions</string> + <key>compensantion</key> + <string>compensation</string> + <key>competance</key> + <string>competence</string> + <key>competant</key> + <string>competent</string> + <key>competative</key> + <string>competitive</string> + <key>competion</key> + <string>competition</string> + <key>competitiion</key> + <string>competition</string> + <key>competive</key> + <string>competitive</string> + <key>competiveness</key> + <string>competitiveness</string> + <key>comphrehensive</key> + <string>comprehensive</string> + <key>compitent</key> + <string>competent</string> + <key>completedthe</key> + <string>completed the</string> + <key>completelyl</key> + <string>completely</string> + <key>completetion</key> + <string>completion</string> + <key>complier</key> + <string>compiler</string> + <key>componant</key> + <string>component</string> + <key>comprable</key> + <string>comparable</string> + <key>comprimise</key> + <string>compromise</string> + <key>compulsary</key> + <string>compulsory</string> + <key>compulsery</key> + <string>compulsory</string> + <key>computarized</key> + <string>computerized</string> + <key>concensus</key> + <string>consensus</string> + <key>concider</key> + <string>consider</string> + <key>concidered</key> + <string>considered</string> + <key>concidering</key> + <string>considering</string> + <key>conciders</key> + <string>considers</string> + <key>concieted</key> + <string>conceited</string> + <key>concieved</key> + <string>conceived</string> + <key>concious</key> + <string>conscious</string> + <key>conciously</key> + <string>consciously</string> + <key>conciousness</key> + <string>consciousness</string> + <key>condamned</key> + <string>condemned</string> + <key>condemmed</key> + <string>condemned</string> + <key>condidtion</key> + <string>condition</string> + <key>condidtions</key> + <string>conditions</string> + <key>conditionsof</key> + <string>conditions of</string> + <key>conected</key> + <string>connected</string> + <key>conection</key> + <string>connection</string> + <key>conesencus</key> + <string>consensus</string> + <key>confidental</key> + <string>confidential</string> + <key>confidentally</key> + <string>confidentially</string> + <key>confids</key> + <string>confides</string> + <key>configureable</key> + <string>configurable</string> + <key>confortable</key> + <string>comfortable</string> + <key>congradulations</key> + <string>congratulations</string> + <key>congresional</key> + <string>congressional</string> + <key>conived</key> + <string>connived</string> + <key>conjecutre</key> + <string>conjecture</string> + <key>conjuction</key> + <string>conjunction</string> + <key>conotations</key> + <string>connotations</string> + <key>conquerd</key> + <string>conquered</string> + <key>conquerer</key> + <string>conqueror</string> + <key>conquerers</key> + <string>conquerors</string> + <key>conqured</key> + <string>conquered</string> + <key>conscent</key> + <string>consent</string> + <key>consciouness</key> + <string>consciousness</string> + <key>consdider</key> + <string>consider</string> + <key>consdidered</key> + <string>considered</string> + <key>consdiered</key> + <string>considered</string> + <key>consectutive</key> + <string>consecutive</string> + <key>consenquently</key> + <string>consequently</string> + <key>consentrate</key> + <string>concentrate</string> + <key>consentrated</key> + <string>concentrated</string> + <key>consentrates</key> + <string>concentrates</string> + <key>consept</key> + <string>concept</string> + <key>consequentually</key> + <string>consequently</string> + <key>consequeseces</key> + <string>consequences</string> + <key>consern</key> + <string>concern</string> + <key>conserned</key> + <string>concerned</string> + <key>conserning</key> + <string>concerning</string> + <key>conservitive</key> + <string>conservative</string> + <key>consiciousness</key> + <string>consciousness</string> + <key>consicousness</key> + <string>consciousness</string> + <key>considerd</key> + <string>considered</string> + <key>consideres</key> + <string>considered</string> + <key>consious</key> + <string>conscious</string> + <key>consistant</key> + <string>consistent</string> + <key>consistantly</key> + <string>consistently</string> + <key>consituencies</key> + <string>constituencies</string> + <key>consituency</key> + <string>constituency</string> + <key>consituted</key> + <string>constituted</string> + <key>consitution</key> + <string>constitution</string> + <key>consitutional</key> + <string>constitutional</string> + <key>consolodate</key> + <string>consolidate</string> + <key>consolodated</key> + <string>consolidated</string> + <key>consonent</key> + <string>consonant</string> + <key>consonents</key> + <string>consonants</string> + <key>consorcium</key> + <string>consortium</string> + <key>conspiracys</key> + <string>conspiracies</string> + <key>conspiriator</key> + <string>conspirator</string> + <key>constaints</key> + <string>constraints</string> + <key>constanly</key> + <string>constantly</string> + <key>constarnation</key> + <string>consternation</string> + <key>constatn</key> + <string>constant</string> + <key>constinually</key> + <string>continually</string> + <key>constituant</key> + <string>constituent</string> + <key>constituants</key> + <string>constituents</string> + <key>constituion</key> + <string>constitution</string> + <key>constituional</key> + <string>constitutional</string> + <key>consttruction</key> + <string>construction</string> + <key>constuction</key> + <string>construction</string> + <key>consulant</key> + <string>consultant</string> + <key>consumate</key> + <string>consummate</string> + <key>consumated</key> + <string>consummated</string> + <key>contaiminate</key> + <string>contaminate</string> + <key>containes</key> + <string>contains</string> + <key>contamporaries</key> + <string>contemporaries</string> + <key>contamporary</key> + <string>contemporary</string> + <key>contempoary</key> + <string>contemporary</string> + <key>contemporaneus</key> + <string>contemporaneous</string> + <key>contempory</key> + <string>contemporary</string> + <key>contendor</key> + <string>contender</string> + <key>contibute</key> + <string>contribute </string> + <key>contibuted</key> + <string>contributed </string> + <key>contibutes</key> + <string>contributes </string> + <key>contigent</key> + <string>contingent</string> + <key>contined</key> + <string>continued</string> + <key>continous</key> + <string>continuous</string> + <key>continously</key> + <string>continuously</string> + <key>continueing</key> + <string>continuing</string> + <key>contravercial</key> + <string>controversial</string> + <key>contraversy</key> + <string>controversy</string> + <key>contributer</key> + <string>contributor</string> + <key>contributers</key> + <string>contributors</string> + <key>contritutions</key> + <string>contributions</string> + <key>controled</key> + <string>controlled</string> + <key>controling</key> + <string>controlling</string> + <key>controll</key> + <string>control</string> + <key>controlls</key> + <string>controls</string> + <key>controvercial</key> + <string>controversial</string> + <key>controvercy</key> + <string>controversy</string> + <key>controveries</key> + <string>controversies</string> + <key>controversal</key> + <string>controversial</string> + <key>controversey</key> + <string>controversy</string> + <key>controvertial</key> + <string>controversial</string> + <key>controvery</key> + <string>controversy</string> + <key>contruction</key> + <string>construction</string> + <key>conveinent</key> + <string>convenient</string> + <key>convenant</key> + <string>covenant</string> + <key>convential</key> + <string>conventional</string> + <key>convertables</key> + <string>convertibles</string> + <key>convertion</key> + <string>conversion</string> + <key>conveyer</key> + <string>conveyor</string> + <key>conviced</key> + <string>convinced</string> + <key>convienient</key> + <string>convenient</string> + <key>coordiantion</key> + <string>coordination</string> + <key>coorperations</key> + <string>corporations</string> + <key>copmetitors</key> + <string>competitors</string> + <key>coputer</key> + <string>computer</string> + <key>copywrite</key> + <string>copyright</string> + <key>coridal</key> + <string>cordial</string> + <key>cornmitted</key> + <string>committed</string> + <key>corosion</key> + <string>corrosion</string> + <key>corparate</key> + <string>corporate</string> + <key>corperations</key> + <string>corporations</string> + <key>correcters</key> + <string>correctors</string> + <key>correponding</key> + <string>corresponding</string> + <key>correposding</key> + <string>corresponding</string> + <key>correspondant</key> + <string>correspondent</string> + <key>correspondants</key> + <string>correspondents</string> + <key>corridoors</key> + <string>corridors</string> + <key>corrispond</key> + <string>correspond</string> + <key>corrispondant</key> + <string>correspondent</string> + <key>corrispondants</key> + <string>correspondents</string> + <key>corrisponded</key> + <string>corresponded</string> + <key>corrisponding</key> + <string>corresponding</string> + <key>corrisponds</key> + <string>corresponds</string> + <key>costitution</key> + <string>constitution</string> + <key>coucil</key> + <string>council</string> + <key>counries</key> + <string>countries</string> + <key>countains</key> + <string>contains</string> + <key>countires</key> + <string>countries</string> + <key>coururier</key> + <string>courier</string> + <key>coverted</key> + <string>converted</string> + <key>cpoy</key> + <string>copy</string> + <key>creaeted</key> + <string>created</string> + <key>creedence</key> + <string>credence</string> + <key>critereon</key> + <string>criterion</string> + <key>criterias</key> + <string>criteria</string> + <key>criticists</key> + <string>critics</string> + <key>critising</key> + <string>criticising</string> + <key>critisising</key> + <string>criticising</string> + <key>critisism</key> + <string>criticism</string> + <key>critisisms</key> + <string>criticisms</string> + <key>critisize</key> + <string>criticise</string> + <key>critisized</key> + <string>criticised</string> + <key>critisizes</key> + <string>criticises</string> + <key>critisizing</key> + <string>criticising</string> + <key>critized</key> + <string>criticized</string> + <key>critizing</key> + <string>criticizing</string> + <key>crockodiles</key> + <string>crocodiles</string> + <key>crowm</key> + <string>crown</string> + <key>crtical</key> + <string>critical</string> + <key>crticised</key> + <string>criticised</string> + <key>crucifiction</key> + <string>crucifixion</string> + <key>crusies</key> + <string>cruises</string> + <key>crystalisation</key> + <string>crystallisation</string> + <key>culiminating</key> + <string>culminating</string> + <key>cumulatative</key> + <string>cumulative</string> + <key>curch</key> + <string>church</string> + <key>curcuit</key> + <string>circuit</string> + <key>currenly</key> + <string>currently</string> + <key>curriculem</key> + <string>curriculum</string> + <key>cxan</key> + <string>cyan</string> + <key>cyclinder</key> + <string>cylinder</string> + <key>dacquiri</key> + <string>daiquiri</string> + <key>dael</key> + <string>deal</string> + <key>dalmation</key> + <string>dalmatian</string> + <key>damenor</key> + <string>demeanor</string> + <key>dammage</key> + <string>damage</string> + <key>daugher</key> + <string>daughter</string> + <key>debateable</key> + <string>debatable</string> + <key>decendant</key> + <string>descendant</string> + <key>decendants</key> + <string>descendants</string> + <key>decendent</key> + <string>descendant</string> + <key>decendents</key> + <string>descendants</string> + <key>decideable</key> + <string>decidable</string> + <key>decidely</key> + <string>decidedly</string> + <key>decieved</key> + <string>deceived</string> + <key>decison</key> + <string>decision</string> + <key>decomissioned</key> + <string>decommissioned</string> + <key>decomposit</key> + <string>decompose</string> + <key>decomposited</key> + <string>decomposed</string> + <key>decompositing</key> + <string>decomposing</string> + <key>decomposits</key> + <string>decomposes</string> + <key>decress</key> + <string>decrees</string> + <key>decribe</key> + <string>describe</string> + <key>decribed</key> + <string>described</string> + <key>decribes</key> + <string>describes</string> + <key>decribing</key> + <string>describing</string> + <key>dectect</key> + <string>detect</string> + <key>defendent</key> + <string>defendant</string> + <key>defendents</key> + <string>defendants</string> + <key>deffensively</key> + <string>defensively</string> + <key>deffine</key> + <string>define</string> + <key>deffined</key> + <string>defined</string> + <key>definance</key> + <string>defiance</string> + <key>definate</key> + <string>definite</string> + <key>definately</key> + <string>definitely</string> + <key>definatly</key> + <string>definitely</string> + <key>definetly</key> + <string>definitely</string> + <key>definining</key> + <string>defining</string> + <key>definit</key> + <string>definite</string> + <key>definitly</key> + <string>definitely</string> + <key>definiton</key> + <string>definition</string> + <key>defintion</key> + <string>definition</string> + <key>degrate</key> + <string>degrade</string> + <key>delagates</key> + <string>delegates</string> + <key>delapidated</key> + <string>dilapidated</string> + <key>delerious</key> + <string>delirious</string> + <key>delevopment</key> + <string>development</string> + <key>deliberatly</key> + <string>deliberately</string> + <key>delusionally</key> + <string>delusively</string> + <key>demenor</key> + <string>demeanor</string> + <key>demographical</key> + <string>demographic</string> + <key>demolision</key> + <string>demolition</string> + <key>demorcracy</key> + <string>democracy</string> + <key>demostration</key> + <string>demonstration</string> + <key>denegrating</key> + <string>denigrating</string> + <key>densly</key> + <string>densely</string> + <key>deparment</key> + <string>department</string> + <key>deparmental</key> + <string>departmental</string> + <key>deparments</key> + <string>departments</string> + <key>dependance</key> + <string>dependence</string> + <key>dependancy</key> + <string>dependency</string> + <key>dependant</key> + <string>dependent</string> + <key>deram</key> + <string>dream</string> + <key>deriviated</key> + <string>derived</string> + <key>derivitive</key> + <string>derivative</string> + <key>derogitory</key> + <string>derogatory</string> + <key>descendands</key> + <string>descendants</string> + <key>descibed</key> + <string>described</string> + <key>descision</key> + <string>decision</string> + <key>descisions</key> + <string>decisions</string> + <key>descriibes</key> + <string>describes</string> + <key>descripters</key> + <string>descriptors</string> + <key>descripton</key> + <string>description</string> + <key>desctruction</key> + <string>destruction</string> + <key>descuss</key> + <string>discuss</string> + <key>desgined</key> + <string>designed</string> + <key>deside</key> + <string>decide</string> + <key>desigining</key> + <string>designing</string> + <key>desinations</key> + <string>destinations</string> + <key>desintegrated</key> + <string>disintegrated</string> + <key>desintegration</key> + <string>disintegration</string> + <key>desireable</key> + <string>desirable</string> + <key>desitned</key> + <string>destined</string> + <key>desktiop</key> + <string>desktop</string> + <key>desorder</key> + <string>disorder</string> + <key>desoriented</key> + <string>disoriented</string> + <key>desparate</key> + <string>desperate</string> + <key>despict</key> + <string>depict</string> + <key>despiration</key> + <string>desperation</string> + <key>dessicated</key> + <string>desiccated</string> + <key>dessigned</key> + <string>designed</string> + <key>destablized</key> + <string>destabilized</string> + <key>destory</key> + <string>destroy</string> + <key>detailled</key> + <string>detailed</string> + <key>detatched</key> + <string>detached</string> + <key>deteoriated</key> + <string>deteriorated</string> + <key>deteriate</key> + <string>deteriorate</string> + <key>deterioriating</key> + <string>deteriorating</string> + <key>determinining</key> + <string>determining</string> + <key>detremental</key> + <string>detrimental</string> + <key>devasted</key> + <string>devastated</string> + <key>develope</key> + <string>develop</string> + <key>developement</key> + <string>development</string> + <key>developped</key> + <string>developed</string> + <key>develpment</key> + <string>development</string> + <key>devels</key> + <string>delves</string> + <key>devestated</key> + <string>devastated</string> + <key>devestating</key> + <string>devastating</string> + <key>devide</key> + <string>divide</string> + <key>devided</key> + <string>divided</string> + <key>devistating</key> + <string>devastating</string> + <key>devolopement</key> + <string>development</string> + <key>diablical</key> + <string>diabolical</string> + <key>diamons</key> + <string>diamonds</string> + <key>diaster</key> + <string>disaster</string> + <key>dichtomy</key> + <string>dichotomy</string> + <key>diconnects</key> + <string>disconnects</string> + <key>dicover</key> + <string>discover</string> + <key>dicovered</key> + <string>discovered</string> + <key>dicovering</key> + <string>discovering</string> + <key>dicovers</key> + <string>discovers</string> + <key>dicovery</key> + <string>discovery</string> + <key>dicussed</key> + <string>discussed</string> + <key>didnt</key> + <string>didn't</string> + <key>diea</key> + <string>idea</string> + <key>dieing</key> + <string>dying</string> + <key>dieties</key> + <string>deities</string> + <key>diety</key> + <string>deity</string> + <key>diferent</key> + <string>different</string> + <key>diferrent</key> + <string>different</string> + <key>differentiatiations</key> + <string>differentiations</string> + <key>differnt</key> + <string>different</string> + <key>difficulity</key> + <string>difficulty</string> + <key>diffrent</key> + <string>different</string> + <key>dificulties</key> + <string>difficulties</string> + <key>dificulty</key> + <string>difficulty</string> + <key>dimenions</key> + <string>dimensions</string> + <key>dimention</key> + <string>dimension</string> + <key>dimentional</key> + <string>dimensional</string> + <key>dimentions</key> + <string>dimensions</string> + <key>dimesnional</key> + <string>dimensional</string> + <key>diminuitive</key> + <string>diminutive</string> + <key>dimunitive</key> + <string>diminutive</string> + <key>diosese</key> + <string>diocese</string> + <key>diphtong</key> + <string>diphthong</string> + <key>diphtongs</key> + <string>diphthongs</string> + <key>diplomancy</key> + <string>diplomacy</string> + <key>dipthong</key> + <string>diphthong</string> + <key>dipthongs</key> + <string>diphthongs</string> + <key>dirived</key> + <string>derived</string> + <key>disagreeed</key> + <string>disagreed</string> + <key>disapeared</key> + <string>disappeared</string> + <key>disapointing</key> + <string>disappointing</string> + <key>disappearred</key> + <string>disappeared</string> + <key>disaproval</key> + <string>disapproval</string> + <key>disasterous</key> + <string>disastrous</string> + <key>disatisfaction</key> + <string>dissatisfaction</string> + <key>disatisfied</key> + <string>dissatisfied</string> + <key>disatrous</key> + <string>disastrous</string> + <key>discontentment</key> + <string>discontent</string> + <key>discribe</key> + <string>describe</string> + <key>discribed</key> + <string>described</string> + <key>discribes</key> + <string>describes</string> + <key>discribing</key> + <string>describing</string> + <key>disctinction</key> + <string>distinction</string> + <key>disctinctive</key> + <string>distinctive</string> + <key>disemination</key> + <string>dissemination</string> + <key>disenchanged</key> + <string>disenchanted</string> + <key>disiplined</key> + <string>disciplined</string> + <key>disobediance</key> + <string>disobedience</string> + <key>disobediant</key> + <string>disobedient</string> + <key>disolved</key> + <string>dissolved</string> + <key>disover</key> + <string>discover</string> + <key>dispair</key> + <string>despair</string> + <key>disparingly</key> + <string>disparagingly</string> + <key>dispence</key> + <string>dispense</string> + <key>dispenced</key> + <string>dispensed</string> + <key>dispencing</key> + <string>dispensing</string> + <key>dispicable</key> + <string>despicable</string> + <key>dispite</key> + <string>despite</string> + <key>dispostion</key> + <string>disposition</string> + <key>disproportiate</key> + <string>disproportionate</string> + <key>disputandem</key> + <string>disputandum</string> + <key>disricts</key> + <string>districts</string> + <key>dissagreement</key> + <string>disagreement</string> + <key>dissapear</key> + <string>disappear</string> + <key>dissapearance</key> + <string>disappearance</string> + <key>dissapeared</key> + <string>disappeared</string> + <key>dissapearing</key> + <string>disappearing</string> + <key>dissapears</key> + <string>disappears</string> + <key>dissappear</key> + <string>disappear</string> + <key>dissappears</key> + <string>disappears</string> + <key>dissappointed</key> + <string>disappointed</string> + <key>dissarray</key> + <string>disarray</string> + <key>dissobediance</key> + <string>disobedience</string> + <key>dissobediant</key> + <string>disobedient</string> + <key>dissobedience</key> + <string>disobedience</string> + <key>dissobedient</key> + <string>disobedient</string> + <key>distiction</key> + <string>distinction</string> + <key>distingish</key> + <string>distinguish</string> + <key>distingished</key> + <string>distinguished</string> + <key>distingishes</key> + <string>distinguishes</string> + <key>distingishing</key> + <string>distinguishing</string> + <key>distingquished</key> + <string>distinguished</string> + <key>distrubution</key> + <string>distribution</string> + <key>distruction</key> + <string>destruction</string> + <key>distructive</key> + <string>destructive</string> + <key>ditributed</key> + <string>distributed</string> + <key>diversed</key> + <string>diverged</string> + <key>divice</key> + <string>device</string> + <key>divison</key> + <string>division</string> + <key>divisons</key> + <string>divisions</string> + <key>doccument</key> + <string>document</string> + <key>doccumented</key> + <string>documented</string> + <key>doccuments</key> + <string>documents</string> + <key>docrines</key> + <string>doctrines</string> + <key>doctines</key> + <string>doctrines</string> + <key>documenatry</key> + <string>documentary</string> + <key>doens</key> + <string>does</string> + <key>doesnt</key> + <string>doesn't</string> + <key>doign</key> + <string>doing</string> + <key>dominaton</key> + <string>domination</string> + <key>dominent</key> + <string>dominant</string> + <key>dominiant</key> + <string>dominant</string> + <key>donig</key> + <string>doing</string> + <key>dont</key> + <string>don't</string> + <key>dosen't</key> + <string>doesn't</string> + <key>doub</key> + <string>doubt</string> + <key>doulbe</key> + <string>double</string> + <key>dowloads</key> + <string>downloads</string> + <key>dramtic</key> + <string>dramatic</string> + <key>draughtman</key> + <string>draughtsman</string> + <key>dreasm</key> + <string>dreams</string> + <key>driectly</key> + <string>directly</string> + <key>drnik</key> + <string>drink</string> + <key>druming</key> + <string>drumming</string> + <key>drummless</key> + <string>drumless</string> + <key>dupicate</key> + <string>duplicate</string> + <key>durig</key> + <string>during</string> + <key>durring</key> + <string>during</string> + <key>duting</key> + <string>during</string> + <key>dyas</key> + <string>dryas</string> + <key>eahc</key> + <string>each</string> + <key>ealier</key> + <string>earlier</string> + <key>earlies</key> + <string>earliest</string> + <key>earnt</key> + <string>earned</string> + <key>ecclectic</key> + <string>eclectic</string> + <key>eceonomy</key> + <string>economy</string> + <key>ecidious</key> + <string>deciduous</string> + <key>eclispe</key> + <string>eclipse</string> + <key>ecomonic</key> + <string>economic</string> + <key>ect</key> + <string>etc</string> + <key>eearly</key> + <string>early</string> + <key>efel</key> + <string>evil</string> + <key>effeciency</key> + <string>efficiency</string> + <key>effecient</key> + <string>efficient</string> + <key>effeciently</key> + <string>efficiently</string> + <key>efficency</key> + <string>efficiency</string> + <key>efficent</key> + <string>efficient</string> + <key>efficently</key> + <string>efficiently</string> + <key>efford</key> + <string>effort</string> + <key>effords</key> + <string>efforts</string> + <key>effulence</key> + <string>effluence</string> + <key>eigth</key> + <string>eight</string> + <key>eiter</key> + <string>either</string> + <key>elction</key> + <string>election</string> + <key>electic</key> + <string>electric</string> + <key>electon</key> + <string>electron</string> + <key>electrial</key> + <string>electrical</string> + <key>electricly</key> + <string>electrically</string> + <key>electricty</key> + <string>electricity</string> + <key>elementay</key> + <string>elementary</string> + <key>eleminated</key> + <string>eliminated</string> + <key>eleminating</key> + <string>eliminating</string> + <key>eles</key> + <string>eels</string> + <key>eletricity</key> + <string>electricity</string> + <key>elicided</key> + <string>elicited</string> + <key>eligable</key> + <string>eligible</string> + <key>elimentary</key> + <string>elementary</string> + <key>ellected</key> + <string>elected</string> + <key>elphant</key> + <string>elephant</string> + <key>embarass</key> + <string>embarrass</string> + <key>embarassed</key> + <string>embarrassed</string> + <key>embarassing</key> + <string>embarrassing</string> + <key>embarassment</key> + <string>embarrassment</string> + <key>embargos</key> + <string>embargoes</string> + <key>embarras</key> + <string>embarrass</string> + <key>embarrased</key> + <string>embarrassed</string> + <key>embarrasing</key> + <string>embarrassing</string> + <key>embarrasment</key> + <string>embarrassment</string> + <key>embezelled</key> + <string>embezzled</string> + <key>emblamatic</key> + <string>emblematic</string> + <key>eminate</key> + <string>emanate</string> + <key>eminated</key> + <string>emanated</string> + <key>emision</key> + <string>emission</string> + <key>emited</key> + <string>emitted</string> + <key>emiting</key> + <string>emitting</string> + <key>emition</key> + <string>emission</string> + <key>emmediately</key> + <string>immediately</string> + <key>emmigrated</key> + <string>immigrated</string> + <key>emminently</key> + <string>eminently</string> + <key>emmisaries</key> + <string>emissaries</string> + <key>emmisarries</key> + <string>emissaries</string> + <key>emmisarry</key> + <string>emissary</string> + <key>emmisary</key> + <string>emissary</string> + <key>emmision</key> + <string>emission</string> + <key>emmisions</key> + <string>emissions</string> + <key>emmited</key> + <string>emitted</string> + <key>emmiting</key> + <string>emitting</string> + <key>emmitted</key> + <string>emitted</string> + <key>emmitting</key> + <string>emitting</string> + <key>emnity</key> + <string>enmity</string> + <key>emperical</key> + <string>empirical</string> + <key>emphaised</key> + <string>emphasised</string> + <key>emphsis</key> + <string>emphasis</string> + <key>emphysyma</key> + <string>emphysema</string> + <key>emprisoned</key> + <string>imprisoned</string> + <key>enameld</key> + <string>enameled</string> + <key>enchancement</key> + <string>enhancement</string> + <key>encouraing</key> + <string>encouraging</string> + <key>encryptiion</key> + <string>encryption</string> + <key>encylopedia</key> + <string>encyclopedia</string> + <key>endevors</key> + <string>endeavors</string> + <key>endevour</key> + <string>endeavour</string> + <key>endig</key> + <string>ending</string> + <key>endolithes</key> + <string>endoliths</string> + <key>enduce</key> + <string>induce</string> + <key>ened</key> + <string>need</string> + <key>enflamed</key> + <string>inflamed</string> + <key>enforceing</key> + <string>enforcing</string> + <key>engagment</key> + <string>engagement</string> + <key>engeneer</key> + <string>engineer</string> + <key>engeneering</key> + <string>engineering</string> + <key>engieneer</key> + <string>engineer</string> + <key>engieneers</key> + <string>engineers</string> + <key>enlargment</key> + <string>enlargement</string> + <key>enlargments</key> + <string>enlargements</string> + <key>enourmous</key> + <string>enormous</string> + <key>enourmously</key> + <string>enormously</string> + <key>ensconsed</key> + <string>ensconced</string> + <key>entaglements</key> + <string>entanglements</string> + <key>enteratinment</key> + <string>entertainment</string> + <key>enthusiatic</key> + <string>enthusiastic</string> + <key>entitity</key> + <string>entity</string> + <key>entitlied</key> + <string>entitled</string> + <key>entrepeneur</key> + <string>entrepreneur</string> + <key>entrepeneurs</key> + <string>entrepreneurs</string> + <key>enviorment</key> + <string>environment</string> + <key>enviormental</key> + <string>environmental</string> + <key>enviormentally</key> + <string>environmentally</string> + <key>enviorments</key> + <string>environments</string> + <key>enviornment</key> + <string>environment</string> + <key>enviornmental</key> + <string>environmental</string> + <key>enviornmentalist</key> + <string>environmentalist</string> + <key>enviornmentally</key> + <string>environmentally</string> + <key>enviornments</key> + <string>environments</string> + <key>enviroment</key> + <string>environment</string> + <key>enviromental</key> + <string>environmental</string> + <key>enviromentalist</key> + <string>environmentalist</string> + <key>enviromentally</key> + <string>environmentally</string> + <key>enviroments</key> + <string>environments</string> + <key>envolutionary</key> + <string>evolutionary</string> + <key>envrionments</key> + <string>environments</string> + <key>enxt</key> + <string>next</string> + <key>epidsodes</key> + <string>episodes</string> + <key>epsiode</key> + <string>episode</string> + <key>equialent</key> + <string>equivalent</string> + <key>equilibium</key> + <string>equilibrium</string> + <key>equilibrum</key> + <string>equilibrium</string> + <key>equiped</key> + <string>equipped</string> + <key>equippment</key> + <string>equipment</string> + <key>equitorial</key> + <string>equatorial</string> + <key>equivelant</key> + <string>equivalent</string> + <key>equivelent</key> + <string>equivalent</string> + <key>equivilant</key> + <string>equivalent</string> + <key>equivilent</key> + <string>equivalent</string> + <key>equivlalent</key> + <string>equivalent</string> + <key>erally</key> + <string>really</string> + <key>eratic</key> + <string>erratic</string> + <key>eratically</key> + <string>erratically</string> + <key>eraticly</key> + <string>erratically</string> + <key>errupted</key> + <string>erupted</string> + <key>esential</key> + <string>essential</string> + <key>esitmated</key> + <string>estimated</string> + <key>esle</key> + <string>else</string> + <key>especialy</key> + <string>especially</string> + <key>essencial</key> + <string>essential</string> + <key>essense</key> + <string>essence</string> + <key>essentail</key> + <string>essential</string> + <key>essentialy</key> + <string>essentially</string> + <key>essentual</key> + <string>essential</string> + <key>essesital</key> + <string>essential</string> + <key>estabishes</key> + <string>establishes</string> + <key>establising</key> + <string>establishing</string> + <key>ethnocentricm</key> + <string>ethnocentrism</string> + <key>ethose</key> + <string>those</string> + <key>evenhtually</key> + <string>eventually</string> + <key>eventally</key> + <string>eventually</string> + <key>eventhough</key> + <string>even though</string> + <key>eventially</key> + <string>eventually</string> + <key>eventualy</key> + <string>eventually</string> + <key>everthing</key> + <string>everything</string> + <key>everytime</key> + <string>every time</string> + <key>everyting</key> + <string>everything</string> + <key>eveyr</key> + <string>every</string> + <key>evidentally</key> + <string>evidently</string> + <key>exagerate</key> + <string>exaggerate</string> + <key>exagerated</key> + <string>exaggerated</string> + <key>exagerates</key> + <string>exaggerates</string> + <key>exagerating</key> + <string>exaggerating</string> + <key>exagerrate</key> + <string>exaggerate</string> + <key>exagerrated</key> + <string>exaggerated</string> + <key>exagerrates</key> + <string>exaggerates</string> + <key>exagerrating</key> + <string>exaggerating</string> + <key>examinated</key> + <string>examined</string> + <key>exampt</key> + <string>exempt</string> + <key>exapansion</key> + <string>expansion</string> + <key>excact</key> + <string>exact</string> + <key>excange</key> + <string>exchange</string> + <key>excecute</key> + <string>execute</string> + <key>excecuted</key> + <string>executed</string> + <key>excecutes</key> + <string>executes</string> + <key>excecuting</key> + <string>executing</string> + <key>excecution</key> + <string>execution</string> + <key>excedded</key> + <string>exceeded</string> + <key>excelent</key> + <string>excellent</string> + <key>excell</key> + <string>excel</string> + <key>excellance</key> + <string>excellence</string> + <key>excellant</key> + <string>excellent</string> + <key>excells</key> + <string>excels</string> + <key>excercise</key> + <string>exercise</string> + <key>exchanching</key> + <string>exchanging</string> + <key>excisted</key> + <string>existed</string> + <key>exculsivly</key> + <string>exclusively</string> + <key>execising</key> + <string>exercising</string> + <key>exection</key> + <string>execution</string> + <key>exectued</key> + <string>executed</string> + <key>exeedingly</key> + <string>exceedingly</string> + <key>exelent</key> + <string>excellent</string> + <key>exellent</key> + <string>excellent</string> + <key>exemple</key> + <string>example</string> + <key>exept</key> + <string>except</string> + <key>exeptional</key> + <string>exceptional</string> + <key>exerbate</key> + <string>exacerbate</string> + <key>exerbated</key> + <string>exacerbated</string> + <key>exerciese</key> + <string>exercises</string> + <key>exerpt</key> + <string>excerpt</string> + <key>exerpts</key> + <string>excerpts</string> + <key>exersize</key> + <string>exercise</string> + <key>exerternal</key> + <string>external</string> + <key>exhalted</key> + <string>exalted</string> + <key>exhibtion</key> + <string>exhibition</string> + <key>exibition</key> + <string>exhibition</string> + <key>exibitions</key> + <string>exhibitions</string> + <key>exicting</key> + <string>exciting</string> + <key>exinct</key> + <string>extinct</string> + <key>existance</key> + <string>existence</string> + <key>existant</key> + <string>existent</string> + <key>existince</key> + <string>existence</string> + <key>exliled</key> + <string>exiled</string> + <key>exludes</key> + <string>excludes</string> + <key>exmaple</key> + <string>example</string> + <key>exonorate</key> + <string>exonerate</string> + <key>exoskelaton</key> + <string>exoskeleton</string> + <key>expalin</key> + <string>explain</string> + <key>expatriot</key> + <string>expatriate</string> + <key>expeced</key> + <string>expected</string> + <key>expecially</key> + <string>especially</string> + <key>expeditonary</key> + <string>expeditionary</string> + <key>expeiments</key> + <string>experiments</string> + <key>expell</key> + <string>expel</string> + <key>expells</key> + <string>expels</string> + <key>experiance</key> + <string>experience</string> + <key>experianced</key> + <string>experienced</string> + <key>expiditions</key> + <string>expeditions</string> + <key>expierence</key> + <string>experience</string> + <key>explaination</key> + <string>explanation</string> + <key>explaning</key> + <string>explaining</string> + <key>explictly</key> + <string>explicitly</string> + <key>exploititive</key> + <string>exploitative</string> + <key>explotation</key> + <string>exploitation</string> + <key>expropiated</key> + <string>expropriated</string> + <key>expropiation</key> + <string>expropriation</string> + <key>exressed</key> + <string>expressed</string> + <key>extemely</key> + <string>extremely</string> + <key>extention</key> + <string>extension</string> + <key>extentions</key> + <string>extensions</string> + <key>extered</key> + <string>exerted</string> + <key>extermist</key> + <string>extremist</string> + <key>extint</key> + <string>extinct</string> + <key>extradiction</key> + <string>extradition</string> + <key>extraterrestial</key> + <string>extraterrestrial</string> + <key>extraterrestials</key> + <string>extraterrestrials</string> + <key>extravagent</key> + <string>extravagant</string> + <key>extrememly</key> + <string>extremely</string> + <key>extremeophile</key> + <string>extremophile</string> + <key>extremly</key> + <string>extremely</string> + <key>extrordinarily</key> + <string>extraordinarily</string> + <key>extrordinary</key> + <string>extraordinary</string> + <key>eyar</key> + <string>year</string> + <key>eyars</key> + <string>years</string> + <key>eyasr</key> + <string>years</string> + <key>faciliate</key> + <string>facilitate</string> + <key>faciliated</key> + <string>facilitated</string> + <key>faciliates</key> + <string>facilitates</string> + <key>facilites</key> + <string>facilities</string> + <key>facillitate</key> + <string>facilitate</string> + <key>facinated</key> + <string>fascinated</string> + <key>facist</key> + <string>fascist</string> + <key>familes</key> + <string>families</string> + <key>familliar</key> + <string>familiar</string> + <key>famoust</key> + <string>famous</string> + <key>fanatism</key> + <string>fanaticism</string> + <key>fatc</key> + <string>fact</string> + <key>faught</key> + <string>fought</string> + <key>favoutrable</key> + <string>favourable</string> + <key>feasable</key> + <string>feasible</string> + <key>fedreally</key> + <string>federally</string> + <key>feromone</key> + <string>pheromone</string> + <key>fertily</key> + <string>fertility</string> + <key>fianite</key> + <string>finite</string> + <key>fianlly</key> + <string>finally</string> + <key>ficticious</key> + <string>fictitious</string> + <key>fictious</key> + <string>fictitious</string> + <key>fidn</key> + <string>find</string> + <key>fiercly</key> + <string>fiercely</string> + <key>fightings</key> + <string>fighting</string> + <key>filiament</key> + <string>filament</string> + <key>fimilies</key> + <string>families</string> + <key>finacial</key> + <string>financial</string> + <key>finaly</key> + <string>finally</string> + <key>financialy</key> + <string>financially</string> + <key>firends</key> + <string>friends</string> + <key>firts</key> + <string>first</string> + <key>fisionable</key> + <string>fissionable</string> + <key>flamable</key> + <string>flammable</string> + <key>flawess</key> + <string>flawless</string> + <key>fleed</key> + <string>fled</string> + <key>florescent</key> + <string>fluorescent</string> + <key>flourescent</key> + <string>fluorescent</string> + <key>flourine</key> + <string>fluorine</string> + <key>fluorish</key> + <string>flourish</string> + <key>follwoing</key> + <string>following</string> + <key>folowing</key> + <string>following</string> + <key>fomed</key> + <string>formed</string> + <key>fomr</key> + <string>from</string> + <key>fonetic</key> + <string>phonetic</string> + <key>fontrier</key> + <string>fontier</string> + <key>foootball</key> + <string>football</string> + <key>forbad</key> + <string>forbade</string> + <key>forbiden</key> + <string>forbidden</string> + <key>foreward</key> + <string>foreword</string> + <key>forfiet</key> + <string>forfeit</string> + <key>forhead</key> + <string>forehead</string> + <key>foriegn</key> + <string>foreign</string> + <key>formallize</key> + <string>formalize</string> + <key>formallized</key> + <string>formalized</string> + <key>formaly</key> + <string>formally</string> + <key>formelly</key> + <string>formerly</string> + <key>formidible</key> + <string>formidable</string> + <key>formost</key> + <string>foremost</string> + <key>forsaw</key> + <string>foresaw</string> + <key>forseeable</key> + <string>foreseeable</string> + <key>fortelling</key> + <string>foretelling</string> + <key>forunner</key> + <string>forerunner</string> + <key>foucs</key> + <string>focus</string> + <key>foudn</key> + <string>found</string> + <key>fougth</key> + <string>fought</string> + <key>foundaries</key> + <string>foundries</string> + <key>foundary</key> + <string>foundry</string> + <key>fourties</key> + <string>forties</string> + <key>fourty</key> + <string>forty</string> + <key>fouth</key> + <string>fourth</string> + <key>foward</key> + <string>forward</string> + <key>freind</key> + <string>friend</string> + <key>freindly</key> + <string>friendly</string> + <key>frequentily</key> + <string>frequently</string> + <key>frome</key> + <string>from</string> + <key>fromed</key> + <string>formed</string> + <key>froniter</key> + <string>frontier</string> + <key>fucntion</key> + <string>function</string> + <key>fucntioning</key> + <string>functioning</string> + <key>fufill</key> + <string>fulfill</string> + <key>fufilled</key> + <string>fulfilled</string> + <key>fulfiled</key> + <string>fulfilled</string> + <key>fullfill</key> + <string>fulfill</string> + <key>fullfilled</key> + <string>fulfilled</string> + <key>fundametal</key> + <string>fundamental</string> + <key>fundametals</key> + <string>fundamentals</string> + <key>funguses</key> + <string>fungi</string> + <key>funtion</key> + <string>function</string> + <key>furuther</key> + <string>further</string> + <key>futher</key> + <string>further</string> + <key>futhermore</key> + <string>furthermore</string> + <key>galatic</key> + <string>galactic</string> + <key>gallaxies</key> + <string>galaxies</string> + <key>galvinized</key> + <string>galvanized</string> + <key>ganerate</key> + <string>generate</string> + <key>ganes</key> + <string>games</string> + <key>ganster</key> + <string>gangster</string> + <key>garantee</key> + <string>guarantee</string> + <key>garanteed</key> + <string>guaranteed</string> + <key>garantees</key> + <string>guarantees</string> + <key>garnison</key> + <string>garrison</string> + <key>gaurantee</key> + <string>guarantee</string> + <key>gauranteed</key> + <string>guaranteed</string> + <key>gaurantees</key> + <string>guarantees</string> + <key>gaurd</key> + <string>guard</string> + <key>gaurentee</key> + <string>guarantee</string> + <key>gaurenteed</key> + <string>guaranteed</string> + <key>gaurentees</key> + <string>guarantees</string> + <key>geneological</key> + <string>genealogical</string> + <key>geneologies</key> + <string>genealogies</string> + <key>geneology</key> + <string>genealogy</string> + <key>generaly</key> + <string>generally</string> + <key>generatting</key> + <string>generating</string> + <key>genialia</key> + <string>genitalia</string> + <key>geographicial</key> + <string>geographical</string> + <key>geometrician</key> + <string>geometer</string> + <key>geometricians</key> + <string>geometers</string> + <key>gerat</key> + <string>great</string> + <key>glight</key> + <string>flight</string> + <key>gnawwed</key> + <string>gnawed</string> + <key>godess</key> + <string>goddess</string> + <key>godesses</key> + <string>goddesses</string> + <key>gogin</key> + <string>going</string> + <key>goign</key> + <string>going</string> + <key>gonig</key> + <string>going</string> + <key>gouvener</key> + <string>governor</string> + <key>govement</key> + <string>government</string> + <key>govenment</key> + <string>government</string> + <key>govenrment</key> + <string>government</string> + <key>goverance</key> + <string>governance</string> + <key>goverment</key> + <string>government</string> + <key>govermental</key> + <string>governmental</string> + <key>governer</key> + <string>governor</string> + <key>governmnet</key> + <string>government</string> + <key>govorment</key> + <string>government</string> + <key>govormental</key> + <string>governmental</string> + <key>govornment</key> + <string>government</string> + <key>gracefull</key> + <string>graceful</string> + <key>graet</key> + <string>great</string> + <key>grafitti</key> + <string>graffiti</string> + <key>gramatically</key> + <string>grammatically</string> + <key>grammaticaly</key> + <string>grammatically</string> + <key>grammer</key> + <string>grammar</string> + <key>grat</key> + <string>great</string> + <key>gratuitious</key> + <string>gratuitous</string> + <key>greatful</key> + <string>grateful</string> + <key>greatfully</key> + <string>gratefully</string> + <key>greif</key> + <string>grief</string> + <key>gridles</key> + <string>griddles</string> + <key>gropu</key> + <string>group</string> + <key>grwo</key> + <string>grow</string> + <key>guage</key> + <string>gauge</string> + <key>guarentee</key> + <string>guarantee</string> + <key>guarenteed</key> + <string>guaranteed</string> + <key>guarentees</key> + <string>guarantees</string> + <key>guerilla</key> + <string>guerrilla</string> + <key>guerillas</key> + <string>guerrillas</string> + <key>guerrila</key> + <string>guerrilla</string> + <key>guerrilas</key> + <string>guerrillas</string> + <key>guidence</key> + <string>guidance</string> + <key>gunanine</key> + <string>guanine</string> + <key>gurantee</key> + <string>guarantee</string> + <key>guranteed</key> + <string>guaranteed</string> + <key>gurantees</key> + <string>guarantees</string> + <key>guttaral</key> + <string>guttural</string> + <key>gutteral</key> + <string>guttural</string> + <key>habaeus</key> + <string>habeas</string> + <key>habeus</key> + <string>habeas</string> + <key>haemorrage</key> + <string>haemorrhage</string> + <key>haev</key> + <string>have</string> + <key>halp</key> + <string>help</string> + <key>hapen</key> + <string>happen</string> + <key>hapened</key> + <string>happened</string> + <key>hapening</key> + <string>happening</string> + <key>happend</key> + <string>happened</string> + <key>happended</key> + <string>happened</string> + <key>happenned</key> + <string>happened</string> + <key>harased</key> + <string>harassed</string> + <key>harases</key> + <string>harasses</string> + <key>harasment</key> + <string>harassment</string> + <key>harasments</key> + <string>harassments</string> + <key>harassement</key> + <string>harassment</string> + <key>harras</key> + <string>harass</string> + <key>harrased</key> + <string>harassed</string> + <key>harrases</key> + <string>harasses</string> + <key>harrasing</key> + <string>harassing</string> + <key>harrasment</key> + <string>harassment</string> + <key>harrasments</key> + <string>harassments</string> + <key>harrassed</key> + <string>harassed</string> + <key>harrasses</key> + <string>harassed</string> + <key>harrassing</key> + <string>harassing</string> + <key>harrassment</key> + <string>harassment</string> + <key>harrassments</key> + <string>harassments</string> + <key>hasnt</key> + <string>hasn't</string> + <key>haviest</key> + <string>heaviest</string> + <key>headquarer</key> + <string>headquarter</string> + <key>headquater</key> + <string>headquarter</string> + <key>headquatered</key> + <string>headquartered</string> + <key>headquaters</key> + <string>headquarters</string> + <key>healthercare</key> + <string>healthcare</string> + <key>heared</key> + <string>heard</string> + <key>heathy</key> + <string>healthy</string> + <key>heigher</key> + <string>higher</string> + <key>heirarchy</key> + <string>hierarchy</string> + <key>heiroglyphics</key> + <string>hieroglyphics</string> + <key>helment</key> + <string>helmet</string> + <key>helpfull</key> + <string>helpful</string> + <key>helpped</key> + <string>helped</string> + <key>hemmorhage</key> + <string>hemorrhage</string> + <key>herad</key> + <string>heard</string> + <key>heridity</key> + <string>heredity</string> + <key>heroe</key> + <string>hero</string> + <key>heros</key> + <string>heroes</string> + <key>hertiage</key> + <string>heritage</string> + <key>hertzs</key> + <string>hertz</string> + <key>hesistant</key> + <string>hesitant</string> + <key>heterogenous</key> + <string>heterogeneous</string> + <key>hieght</key> + <string>height</string> + <key>hierachical</key> + <string>hierarchical</string> + <key>hierachies</key> + <string>hierarchies</string> + <key>hierachy</key> + <string>hierarchy</string> + <key>hierarcical</key> + <string>hierarchical</string> + <key>hierarcy</key> + <string>hierarchy</string> + <key>hieroglph</key> + <string>hieroglyph</string> + <key>hieroglphs</key> + <string>hieroglyphs</string> + <key>higer</key> + <string>higher</string> + <key>higest</key> + <string>highest</string> + <key>higway</key> + <string>highway</string> + <key>hillarious</key> + <string>hilarious</string> + <key>himselv</key> + <string>himself</string> + <key>hinderance</key> + <string>hindrance</string> + <key>hinderence</key> + <string>hindrance</string> + <key>hindrence</key> + <string>hindrance</string> + <key>hipopotamus</key> + <string>hippopotamus</string> + <key>hismelf</key> + <string>himself</string> + <key>histocompatability</key> + <string>histocompatibility</string> + <key>historicians</key> + <string>historians</string> + <key>hitsingles</key> + <string>hit singles</string> + <key>holliday</key> + <string>holiday</string> + <key>homestate</key> + <string>home state</string> + <key>homogeneize</key> + <string>homogenize</string> + <key>homogeneized</key> + <string>homogenized</string> + <key>honory</key> + <string>honorary</string> + <key>horrifing</key> + <string>horrifying</string> + <key>hosited</key> + <string>hoisted</string> + <key>hospitible</key> + <string>hospitable</string> + <key>hounour</key> + <string>honour</string> + <key>housr</key> + <string>hours</string> + <key>howver</key> + <string>however</string> + <key>hsitorians</key> + <string>historians</string> + <key>hstory</key> + <string>history</string> + <key>hten</key> + <string>then</string> + <key>htere</key> + <string>there</string> + <key>htey</key> + <string>they</string> + <key>htikn</key> + <string>think</string> + <key>hting</key> + <string>thing</string> + <key>htink</key> + <string>think</string> + <key>htis</key> + <string>this</string> + <key>humer</key> + <string>humor</string> + <key>humerous</key> + <string>humorous</string> + <key>huminoid</key> + <string>humanoid</string> + <key>humoural</key> + <string>humoral</string> + <key>humurous</key> + <string>humorous</string> + <key>husban</key> + <string>husband</string> + <key>hvae</key> + <string>have</string> + <key>hvaing</key> + <string>having</string> + <key>hvea</key> + <string>have</string> + <key>hwihc</key> + <string>which</string> + <key>hwile</key> + <string>while</string> + <key>hwole</key> + <string>whole</string> + <key>hydogen</key> + <string>hydrogen</string> + <key>hydropile</key> + <string>hydrophile</string> + <key>hydropilic</key> + <string>hydrophilic</string> + <key>hydropobe</key> + <string>hydrophobe</string> + <key>hydropobic</key> + <string>hydrophobic</string> + <key>hygeine</key> + <string>hygiene</string> + <key>hypocracy</key> + <string>hypocrisy</string> + <key>hypocrasy</key> + <string>hypocrisy</string> + <key>hypocricy</key> + <string>hypocrisy</string> + <key>hypocrit</key> + <string>hypocrite</string> + <key>hypocrits</key> + <string>hypocrites</string> + <key>i</key> + <string>I</string> + <key>iconclastic</key> + <string>iconoclastic</string> + <key>idaeidae</key> + <string>idea</string> + <key>idaes</key> + <string>ideas</string> + <key>idealogies</key> + <string>ideologies</string> + <key>idealogy</key> + <string>ideology</string> + <key>identicial</key> + <string>identical</string> + <key>identifers</key> + <string>identifiers</string> + <key>ideosyncratic</key> + <string>idiosyncratic</string> + <key>idesa</key> + <string>ideas</string> + <key>idiosyncracy</key> + <string>idiosyncrasy</string> + <key>illegimacy</key> + <string>illegitimacy</string> + <key>illegitmate</key> + <string>illegitimate</string> + <key>illess</key> + <string>illness</string> + <key>illiegal</key> + <string>illegal</string> + <key>illution</key> + <string>illusion</string> + <key>ilness</key> + <string>illness</string> + <key>ilogical</key> + <string>illogical</string> + <key>imagenary</key> + <string>imaginary</string> + <key>imagin</key> + <string>imagine</string> + <key>imaginery</key> + <string>imaginary</string> + <key>imcomplete</key> + <string>incomplete</string> + <key>imediately</key> + <string>immediately</string> + <key>imense</key> + <string>immense</string> + <key>immediatley</key> + <string>immediately</string> + <key>immediatly</key> + <string>immediately</string> + <key>immidately</key> + <string>immediately</string> + <key>immidiately</key> + <string>immediately</string> + <key>immitate</key> + <string>imitate</string> + <key>immitated</key> + <string>imitated</string> + <key>immitating</key> + <string>imitating</string> + <key>immitator</key> + <string>imitator</string> + <key>immunosupressant</key> + <string>immunosuppressant</string> + <key>impecabbly</key> + <string>impeccably</string> + <key>impedence</key> + <string>impedance</string> + <key>implamenting</key> + <string>implementing</string> + <key>impliment</key> + <string>implement</string> + <key>implimented</key> + <string>implemented</string> + <key>imploys</key> + <string>employs</string> + <key>importamt</key> + <string>important</string> + <key>imprioned</key> + <string>imprisoned</string> + <key>imprisonned</key> + <string>imprisoned</string> + <key>improvision</key> + <string>improvisation</string> + <key>improvments</key> + <string>improvements</string> + <key>inablility</key> + <string>inability</string> + <key>inaccessable</key> + <string>inaccessible</string> + <key>inadiquate</key> + <string>inadequate</string> + <key>inadquate</key> + <string>inadequate</string> + <key>inadvertant</key> + <string>inadvertent</string> + <key>inadvertantly</key> + <string>inadvertently</string> + <key>inagurated</key> + <string>inaugurated</string> + <key>inaguration</key> + <string>inauguration</string> + <key>inappropiate</key> + <string>inappropriate</string> + <key>inaugures</key> + <string>inaugurates</string> + <key>inbalance</key> + <string>imbalance</string> + <key>inbalanced</key> + <string>imbalanced</string> + <key>inbetween</key> + <string>between</string> + <key>incarcirated</key> + <string>incarcerated</string> + <key>incidentially</key> + <string>incidentally</string> + <key>incidently</key> + <string>incidentally</string> + <key>inclreased</key> + <string>increased</string> + <key>includ</key> + <string>include</string> + <key>includng</key> + <string>including</string> + <key>incompatabilities</key> + <string>incompatibilities</string> + <key>incompatability</key> + <string>incompatibility</string> + <key>incompatable</key> + <string>incompatible</string> + <key>incompatablities</key> + <string>incompatibilities</string> + <key>incompatablity</key> + <string>incompatibility</string> + <key>incompatiblities</key> + <string>incompatibilities</string> + <key>incompatiblity</key> + <string>incompatibility</string> + <key>incompetance</key> + <string>incompetence</string> + <key>incompetant</key> + <string>incompetent</string> + <key>incomptable</key> + <string>incompatible</string> + <key>incomptetent</key> + <string>incompetent</string> + <key>inconsistant</key> + <string>inconsistent</string> + <key>incoroporated</key> + <string>incorporated</string> + <key>incorperation</key> + <string>incorporation</string> + <key>incorportaed</key> + <string>incorporated</string> + <key>incorprates</key> + <string>incorporates</string> + <key>incorruptable</key> + <string>incorruptible</string> + <key>incramentally</key> + <string>incrementally</string> + <key>increadible</key> + <string>incredible</string> + <key>incredable</key> + <string>incredible</string> + <key>inctroduce</key> + <string>introduce</string> + <key>inctroduced</key> + <string>introduced</string> + <key>incuding</key> + <string>including</string> + <key>incunabla</key> + <string>incunabula</string> + <key>indefinately</key> + <string>indefinitely</string> + <key>indefineable</key> + <string>undefinable</string> + <key>indefinitly</key> + <string>indefinitely</string> + <key>indentical</key> + <string>identical</string> + <key>indepedantly</key> + <string>independently</string> + <key>indepedence</key> + <string>independence</string> + <key>independance</key> + <string>independence</string> + <key>independant</key> + <string>independent</string> + <key>independantly</key> + <string>independently</string> + <key>independece</key> + <string>independence</string> + <key>independendet</key> + <string>independent</string> + <key>indespensable</key> + <string>indispensable</string> + <key>indespensible</key> + <string>indispensable</string> + <key>indictement</key> + <string>indictment</string> + <key>indigineous</key> + <string>indigenous</string> + <key>indipendence</key> + <string>independence</string> + <key>indipendent</key> + <string>independent</string> + <key>indipendently</key> + <string>independently</string> + <key>indispensible</key> + <string>indispensable</string> + <key>indisputible</key> + <string>indisputable</string> + <key>indisputibly</key> + <string>indisputably</string> + <key>indite</key> + <string>indict</string> + <key>individualy</key> + <string>individually</string> + <key>indpendent</key> + <string>independent</string> + <key>indpendently</key> + <string>independently</string> + <key>indulgue</key> + <string>indulge</string> + <key>indutrial</key> + <string>industrial</string> + <key>indviduals</key> + <string>individuals</string> + <key>inefficienty</key> + <string>inefficiently</string> + <key>inevatible</key> + <string>inevitable</string> + <key>inevitible</key> + <string>inevitable</string> + <key>inevititably</key> + <string>inevitably</string> + <key>infalability</key> + <string>infallibility</string> + <key>infallable</key> + <string>infallible</string> + <key>infectuous</key> + <string>infectious</string> + <key>infered</key> + <string>inferred</string> + <key>infilitrate</key> + <string>infiltrate</string> + <key>infilitrated</key> + <string>infiltrated</string> + <key>infilitration</key> + <string>infiltration</string> + <key>infinit</key> + <string>infinite</string> + <key>inflamation</key> + <string>inflammation</string> + <key>influencial</key> + <string>influential</string> + <key>influented</key> + <string>influenced</string> + <key>infomation</key> + <string>information</string> + <key>informtion</key> + <string>information</string> + <key>infrantryman</key> + <string>infantryman</string> + <key>infrigement</key> + <string>infringement</string> + <key>ingenius</key> + <string>ingenious</string> + <key>ingreediants</key> + <string>ingredients</string> + <key>inhabitans</key> + <string>inhabitants</string> + <key>inherantly</key> + <string>inherently</string> + <key>inheritence</key> + <string>inheritance</string> + <key>inital</key> + <string>initial</string> + <key>initally</key> + <string>initially</string> + <key>initation</key> + <string>initiation</string> + <key>initiaitive</key> + <string>initiative</string> + <key>inlcuding</key> + <string>including</string> + <key>inmigrant</key> + <string>immigrant</string> + <key>inmigrants</key> + <string>immigrants</string> + <key>innoculated</key> + <string>inoculated</string> + <key>inocence</key> + <string>innocence</string> + <key>inofficial</key> + <string>unofficial</string> + <key>inot</key> + <string>into</string> + <key>inpeach</key> + <string>impeach</string> + <key>inpolite</key> + <string>impolite</string> + <key>inprisonment</key> + <string>imprisonment</string> + <key>inproving</key> + <string>improving</string> + <key>insectiverous</key> + <string>insectivorous</string> + <key>insensative</key> + <string>insensitive</string> + <key>inseperable</key> + <string>inseparable</string> + <key>insistance</key> + <string>insistence</string> + <key>insitution</key> + <string>institution</string> + <key>insitutions</key> + <string>institutions</string> + <key>inspite</key> + <string>in spite</string> + <key>instade</key> + <string>instead</string> + <key>instatance</key> + <string>instance</string> + <key>institue</key> + <string>institute</string> + <key>instuction</key> + <string>instruction</string> + <key>instuments</key> + <string>instruments</string> + <key>instutionalized</key> + <string>institutionalized</string> + <key>instutions</key> + <string>intuitions</string> + <key>insurence</key> + <string>insurance</string> + <key>intelectual</key> + <string>intellectual</string> + <key>inteligence</key> + <string>intelligence</string> + <key>inteligent</key> + <string>intelligent</string> + <key>intenational</key> + <string>international</string> + <key>intented</key> + <string>intended</string> + <key>intepretation</key> + <string>interpretation</string> + <key>intepretator</key> + <string>interpretor</string> + <key>interational</key> + <string>international</string> + <key>interbread</key> + <string>interbreed</string> + <key>interchangable</key> + <string>interchangeable</string> + <key>interchangably</key> + <string>interchangeably</string> + <key>intercontinetal</key> + <string>intercontinental</string> + <key>intered</key> + <string>interred</string> + <key>interelated</key> + <string>interrelated</string> + <key>interferance</key> + <string>interference</string> + <key>interfereing</key> + <string>interfering</string> + <key>intergrated</key> + <string>integrated</string> + <key>intergration</key> + <string>integration</string> + <key>interm</key> + <string>interim</string> + <key>internation</key> + <string>international</string> + <key>interpet</key> + <string>interpret</string> + <key>interrim</key> + <string>interim</string> + <key>interrugum</key> + <string>interregnum</string> + <key>intertaining</key> + <string>entertaining</string> + <key>interupt</key> + <string>interrupt</string> + <key>intervines</key> + <string>intervenes</string> + <key>intevene</key> + <string>intervene</string> + <key>intial</key> + <string>initial</string> + <key>intially</key> + <string>initially</string> + <key>intrduced</key> + <string>introduced</string> + <key>intrest</key> + <string>interest</string> + <key>introdued</key> + <string>introduced</string> + <key>intruduced</key> + <string>introduced</string> + <key>intrument</key> + <string>instrument</string> + <key>intrumental</key> + <string>instrumental</string> + <key>intruments</key> + <string>instruments</string> + <key>intrusted</key> + <string>entrusted</string> + <key>intutive</key> + <string>intuitive</string> + <key>intutively</key> + <string>intuitively</string> + <key>inudstry</key> + <string>industry</string> + <key>inventer</key> + <string>inventor</string> + <key>invertibrates</key> + <string>invertebrates</string> + <key>investingate</key> + <string>investigate</string> + <key>involvment</key> + <string>involvement</string> + <key>irelevent</key> + <string>irrelevant</string> + <key>iresistable</key> + <string>irresistible</string> + <key>iresistably</key> + <string>irresistibly</string> + <key>iresistible</key> + <string>irresistible</string> + <key>iresistibly</key> + <string>irresistibly</string> + <key>iritable</key> + <string>irritable</string> + <key>iritated</key> + <string>irritated</string> + <key>ironicly</key> + <string>ironically</string> + <key>irregardless</key> + <string>regardless</string> + <key>irrelevent</key> + <string>irrelevant</string> + <key>irreplacable</key> + <string>irreplaceable</string> + <key>irresistable</key> + <string>irresistible</string> + <key>irresistably</key> + <string>irresistibly</string> + <key>isnt</key> + <string>isn't</string> + <key>issueing</key> + <string>issuing</string> + <key>itnroduced</key> + <string>introduced</string> + <key>iunior</key> + <string>junior</string> + <key>iwll</key> + <string>will</string> + <key>iwth</key> + <string>with</string> + <key>jaques</key> + <string>jacques</string> + <key>jeapardy</key> + <string>jeopardy</string> + <key>jewllery</key> + <string>jewellery</string> + <key>jouney</key> + <string>journey</string> + <key>journied</key> + <string>journeyed</string> + <key>journies</key> + <string>journeys</string> + <key>jstu</key> + <string>just</string> + <key>jsut</key> + <string>just</string> + <key>judical</key> + <string>judicial</string> + <key>judisuary</key> + <string>judiciary</string> + <key>juducial</key> + <string>judicial</string> + <key>juristiction</key> + <string>jurisdiction</string> + <key>juristictions</key> + <string>jurisdictions</string> + <key>kindergarden</key> + <string>kindergarten</string> + <key>klenex</key> + <string>kleenex</string> + <key>knifes</key> + <string>knives</string> + <key>knive</key> + <string>knife</string> + <key>knowlege</key> + <string>knowledge</string> + <key>knowlegeable</key> + <string>knowledgeable</string> + <key>knwo</key> + <string>know</string> + <key>knwos</key> + <string>knows</string> + <key>konw</key> + <string>know</string> + <key>konws</key> + <string>knows</string> + <key>kwno</key> + <string>know</string> + <key>labatory</key> + <string>laboratory</string> + <key>labratory</key> + <string>laboratory</string> + <key>laguage</key> + <string>language</string> + <key>laguages</key> + <string>languages</string> + <key>larg</key> + <string>large</string> + <key>largst</key> + <string>largest</string> + <key>larrry</key> + <string>larry</string> + <key>lastr</key> + <string>last</string> + <key>lattitude</key> + <string>latitude</string> + <key>launhed</key> + <string>launched</string> + <key>lavae</key> + <string>larvae</string> + <key>layed</key> + <string>laid</string> + <key>lazyness</key> + <string>laziness</string> + <key>leage</key> + <string>league</string> + <key>leanr</key> + <string>learn</string> + <key>leathal</key> + <string>lethal</string> + <key>lefted</key> + <string>left</string> + <key>legitamate</key> + <string>legitimate</string> + <key>legitmate</key> + <string>legitimate</string> + <key>leibnitz</key> + <string>leibniz</string> + <key>lenght</key> + <string>length</string> + <key>leran</key> + <string>learn</string> + <key>lerans</key> + <string>learns</string> + <key>leutenant</key> + <string>lieutenant</string> + <key>levetate</key> + <string>levitate</string> + <key>levetated</key> + <string>levitated</string> + <key>levetates</key> + <string>levitates</string> + <key>levetating</key> + <string>levitating</string> + <key>levle</key> + <string>level</string> + <key>liasion</key> + <string>liaison</string> + <key>liason</key> + <string>liaison</string> + <key>liasons</key> + <string>liaisons</string> + <key>libary</key> + <string>library</string> + <key>libell</key> + <string>libel</string> + <key>libguistic</key> + <string>linguistic</string> + <key>libguistics</key> + <string>linguistics</string> + <key>libitarianisn</key> + <string>libertarianism</string> + <key>lieing</key> + <string>lying</string> + <key>liek</key> + <string>like</string> + <key>liekd</key> + <string>liked</string> + <key>liesure</key> + <string>leisure</string> + <key>lieuenant</key> + <string>lieutenant</string> + <key>lieved</key> + <string>lived</string> + <key>liftime</key> + <string>lifetime</string> + <key>lightyear</key> + <string>light year</string> + <key>lightyears</key> + <string>light years</string> + <key>likelyhood</key> + <string>likelihood</string> + <key>linnaena</key> + <string>linnaean</string> + <key>lippizaner</key> + <string>lipizzaner</string> + <key>liquify</key> + <string>liquefy</string> + <key>liscense</key> + <string>license</string> + <key>lisence</key> + <string>license</string> + <key>lisense</key> + <string>license</string> + <key>listners</key> + <string>listeners</string> + <key>litature</key> + <string>literature</string> + <key>literaly</key> + <string>literally</string> + <key>literture</key> + <string>literature</string> + <key>littel</key> + <string>little</string> + <key>litterally</key> + <string>literally</string> + <key>liuke</key> + <string>like</string> + <key>livley</key> + <string>lively</string> + <key>lmits</key> + <string>limits</string> + <key>loev</key> + <string>love</string> + <key>lonelyness</key> + <string>loneliness</string> + <key>longitudonal</key> + <string>longitudinal</string> + <key>lonley</key> + <string>lonely</string> + <key>lonly</key> + <string>lonely</string> + <key>loosing</key> + <string>losing</string> + <key>lotharingen</key> + <string>lothringen</string> + <key>lsat</key> + <string>last</string> + <key>lukid</key> + <string>likud</string> + <key>lveo</key> + <string>love</string> + <key>lvoe</key> + <string>love</string> + <key>maching</key> + <string>machine</string> + <key>mackeral</key> + <string>mackerel</string> + <key>magasine</key> + <string>magazine</string> + <key>magincian</key> + <string>magician</string> + <key>magnificient</key> + <string>magnificent</string> + <key>magolia</key> + <string>magnolia</string> + <key>mailny</key> + <string>mainly</string> + <key>maintainance</key> + <string>maintenance</string> + <key>maintainence</key> + <string>maintenance</string> + <key>maintance</key> + <string>maintenance</string> + <key>maintenence</key> + <string>maintenance</string> + <key>maintinaing</key> + <string>maintaining</string> + <key>maintioned</key> + <string>mentioned</string> + <key>majoroty</key> + <string>majority</string> + <key>maked</key> + <string>marked</string> + <key>makse</key> + <string>makes</string> + <key>maltesian</key> + <string>Maltese</string> + <key>mamal</key> + <string>mammal</string> + <key>mamalian</key> + <string>mammalian</string> + <key>managable</key> + <string>manageable</string> + <key>managment</key> + <string>management</string> + <key>maneouvre</key> + <string>manoeuvre</string> + <key>maneouvred</key> + <string>manoeuvred</string> + <key>maneouvres</key> + <string>manoeuvres</string> + <key>maneouvring</key> + <string>manoeuvring</string> + <key>manisfestations</key> + <string>manifestations</string> + <key>manoeuverability</key> + <string>maneuverability</string> + <key>manouver</key> + <string>maneuver</string> + <key>manouverability</key> + <string>maneuverability</string> + <key>manouverable</key> + <string>maneuverable</string> + <key>manouvers</key> + <string>maneuvers</string> + <key>mantained</key> + <string>maintained</string> + <key>manuever</key> + <string>maneuver</string> + <key>manuevers</key> + <string>maneuvers</string> + <key>manufacturedd</key> + <string>manufactured</string> + <key>manufature</key> + <string>manufacture</string> + <key>manufatured</key> + <string>manufactured</string> + <key>manufaturing</key> + <string>manufacturing</string> + <key>manuver</key> + <string>maneuver</string> + <key>mariage</key> + <string>marriage</string> + <key>marjority</key> + <string>majority</string> + <key>markes</key> + <string>marks</string> + <key>marketting</key> + <string>marketing</string> + <key>marmelade</key> + <string>marmalade</string> + <key>marrage</key> + <string>marriage</string> + <key>marraige</key> + <string>marriage</string> + <key>marrtyred</key> + <string>martyred</string> + <key>marryied</key> + <string>married</string> + <key>massmedia</key> + <string>mass media</string> + <key>masterbation</key> + <string>masturbation</string> + <key>mataphysical</key> + <string>metaphysical</string> + <key>materalists</key> + <string>materialist</string> + <key>mathamatics</key> + <string>mathematics</string> + <key>mathematican</key> + <string>mathematician</string> + <key>mathematicas</key> + <string>mathematics</string> + <key>matheticians</key> + <string>mathematicians</string> + <key>mathmatically</key> + <string>mathematically</string> + <key>mathmatician</key> + <string>mathematician</string> + <key>mathmaticians</key> + <string>mathematicians</string> + <key>mccarthyst</key> + <string>mccarthyist</string> + <key>mchanics</key> + <string>mechanics</string> + <key>meaninng</key> + <string>meaning</string> + <key>mear</key> + <string>wear</string> + <key>mechandise</key> + <string>merchandise</string> + <key>medacine</key> + <string>medicine</string> + <key>medeival</key> + <string>medieval</string> + <key>medevial</key> + <string>medieval</string> + <key>mediciney</key> + <string>mediciny</string> + <key>medievel</key> + <string>medieval</string> + <key>mediterainnean</key> + <string>mediterranean</string> + <key>meerkrat</key> + <string>meerkat</string> + <key>melieux</key> + <string>milieux</string> + <key>membranaphone</key> + <string>membranophone</string> + <key>memeber</key> + <string>member</string> + <key>menally</key> + <string>mentally</string> + <key>meranda</key> + <string>Miranda</string> + <key>mercentile</key> + <string>mercantile</string> + <key>messanger</key> + <string>messenger</string> + <key>messenging</key> + <string>messaging</string> + <key>metalic</key> + <string>metallic</string> + <key>metalurgic</key> + <string>metallurgic</string> + <key>metalurgical</key> + <string>metallurgical</string> + <key>metalurgy</key> + <string>metallurgy</string> + <key>metamorphysis</key> + <string>metamorphosis</string> + <key>metaphoricial</key> + <string>metaphorical</string> + <key>meterologist</key> + <string>meteorologist</string> + <key>meterology</key> + <string>meteorology</string> + <key>methaphor</key> + <string>metaphor</string> + <key>methaphors</key> + <string>metaphors</string> + <key>micoscopy</key> + <string>microscopy</string> + <key>midwifes</key> + <string>midwives</string> + <key>mileau</key> + <string>milieu</string> + <key>milennia</key> + <string>millennia</string> + <key>milennium</key> + <string>millennium</string> + <key>mileu</key> + <string>milieu</string> + <key>miliary</key> + <string>military</string> + <key>milion</key> + <string>million</string> + <key>miliraty</key> + <string>military</string> + <key>millenia</key> + <string>millennia</string> + <key>millenial</key> + <string>millennial</string> + <key>millenialism</key> + <string>millennialism</string> + <key>millenium</key> + <string>millennium</string> + <key>millepede</key> + <string>millipede</string> + <key>millioniare</key> + <string>millionaire</string> + <key>millitary</key> + <string>military</string> + <key>millon</key> + <string>million</string> + <key>miltary</key> + <string>military</string> + <key>minature</key> + <string>miniature</string> + <key>minerial</key> + <string>mineral</string> + <key>miniscule</key> + <string>minuscule</string> + <key>ministery</key> + <string>ministry</string> + <key>minstries</key> + <string>ministries</string> + <key>minstry</key> + <string>ministry</string> + <key>minumum</key> + <string>minimum</string> + <key>mirrorred</key> + <string>mirrored</string> + <key>miscelaneous</key> + <string>miscellaneous</string> + <key>miscellanious</key> + <string>miscellaneous</string> + <key>miscellanous</key> + <string>miscellaneous</string> + <key>mischeivous</key> + <string>mischievous</string> + <key>mischevious</key> + <string>mischievous</string> + <key>mischievious</key> + <string>mischievous</string> + <key>misdameanor</key> + <string>misdemeanor</string> + <key>misdameanors</key> + <string>misdemeanors</string> + <key>misdemenor</key> + <string>misdemeanor</string> + <key>misdemenors</key> + <string>misdemeanors</string> + <key>misfourtunes</key> + <string>misfortunes</string> + <key>misile</key> + <string>missile</string> + <key>mispell</key> + <string>misspell</string> + <key>mispelled</key> + <string>misspelled</string> + <key>mispelling</key> + <string>misspelling</string> + <key>missen</key> + <string>mizzen</string> + <key>missle</key> + <string>missile</string> + <key>missonary</key> + <string>missionary</string> + <key>misterious</key> + <string>mysterious</string> + <key>mistery</key> + <string>mystery</string> + <key>misteryous</key> + <string>mysterious</string> + <key>mkae</key> + <string>make</string> + <key>mkaes</key> + <string>makes</string> + <key>mkaing</key> + <string>making</string> + <key>mkea</key> + <string>make</string> + <key>moderm</key> + <string>modem</string> + <key>modle</key> + <string>model</string> + <key>moent</key> + <string>moment</string> + <key>moeny</key> + <string>money</string> + <key>mohammedans</key> + <string>muslims</string> + <key>moil</key> + <string>soil</string> + <key>moleclues</key> + <string>molecules</string> + <key>momento</key> + <string>memento</string> + <key>monestaries</key> + <string>monasteries</string> + <key>monestary</key> + <string>monastery</string> + <key>monickers</key> + <string>monikers</string> + <key>monolite</key> + <string>monolithic</string> + <key>montains</key> + <string>mountains</string> + <key>montanous</key> + <string>mountainous</string> + <key>monts</key> + <string>months</string> + <key>montypic</key> + <string>monotypic</string> + <key>moreso</key> + <string>more so</string> + <key>morgage</key> + <string>mortgage</string> + <key>morroccan</key> + <string>moroccan</string> + <key>morrocco</key> + <string>morocco</string> + <key>morroco</key> + <string>morocco</string> + <key>mortage</key> + <string>mortgage</string> + <key>mosture</key> + <string>moisture</string> + <key>motiviated</key> + <string>motivated</string> + <key>mounth</key> + <string>month</string> + <key>movei</key> + <string>movie</string> + <key>movment</key> + <string>movement</string> + <key>mroe</key> + <string>more</string> + <key>mucuous</key> + <string>mucous</string> + <key>muder</key> + <string>murder</string> + <key>mudering</key> + <string>murdering</string> + <key>muhammadan</key> + <string>muslim</string> + <key>multicultralism</key> + <string>multiculturalism</string> + <key>multipled</key> + <string>multiplied</string> + <key>multiplers</key> + <string>multipliers</string> + <key>munbers</key> + <string>numbers</string> + <key>muncipalities</key> + <string>municipalities</string> + <key>muncipality</key> + <string>municipality</string> + <key>munnicipality</key> + <string>municipality</string> + <key>muscels</key> + <string>muscles</string> + <key>muscial</key> + <string>musical</string> + <key>muscician</key> + <string>musician</string> + <key>muscicians</key> + <string>musicians</string> + <key>mutiliated</key> + <string>mutilated</string> + <key>myraid</key> + <string>myriad</string> + <key>mysef</key> + <string>myself</string> + <key>mysogynist</key> + <string>misogynist</string> + <key>mysogyny</key> + <string>misogyny</string> + <key>mysterous</key> + <string>mysterious</string> + <key>naieve</key> + <string>naive</string> + <key>naturaly</key> + <string>naturally</string> + <key>naturely</key> + <string>naturally</string> + <key>naturual</key> + <string>natural</string> + <key>naturually</key> + <string>naturally</string> + <key>neccesarily</key> + <string>necessarily</string> + <key>neccesary</key> + <string>necessary</string> + <key>neccessarily</key> + <string>necessarily</string> + <key>neccessary</key> + <string>necessary</string> + <key>neccessities</key> + <string>necessities</string> + <key>necesarily</key> + <string>necessarily</string> + <key>necesary</key> + <string>necessary</string> + <key>necessiate</key> + <string>necessitate</string> + <key>neglible</key> + <string>negligible</string> + <key>negligable</key> + <string>negligible</string> + <key>negociate</key> + <string>negotiate</string> + <key>negociation</key> + <string>negotiation</string> + <key>negociations</key> + <string>negotiations</string> + <key>negotation</key> + <string>negotiation</string> + <key>neice</key> + <string>niece</string> + <key>neigborhood</key> + <string>neighborhood</string> + <key>neigbour</key> + <string>neighbour</string> + <key>neigbourhood</key> + <string>neighbourhood</string> + <key>neolitic</key> + <string>neolithic</string> + <key>nessasarily</key> + <string>necessarily</string> + <key>nessecary</key> + <string>necessary</string> + <key>nestin</key> + <string>nesting</string> + <key>neverthless</key> + <string>nevertheless</string> + <key>newletters</key> + <string>newsletters</string> + <key>nickle</key> + <string>nickel</string> + <key>nightfa;;</key> + <string>nightfall</string> + <key>nightime</key> + <string>nighttime</string> + <key>nineth</key> + <string>ninth</string> + <key>ninteenth</key> + <string>nineteenth</string> + <key>ninties</key> + <string>1990s</string> + <key>ninty</key> + <string>ninety</string> + <key>nkow</key> + <string>know</string> + <key>nkwo</key> + <string>know</string> + <key>nmae</key> + <string>name</string> + <key>noncombatents</key> + <string>noncombatants</string> + <key>nonsence</key> + <string>nonsense</string> + <key>nontheless</key> + <string>nonetheless</string> + <key>noone</key> + <string>no one</string> + <key>norhern</key> + <string>northern</string> + <key>northen</key> + <string>northern</string> + <key>northereastern</key> + <string>northeastern</string> + <key>notabley</key> + <string>notably</string> + <key>noteable</key> + <string>notable</string> + <key>noteably</key> + <string>notably</string> + <key>noteriety</key> + <string>notoriety</string> + <key>noth</key> + <string>north</string> + <key>nothern</key> + <string>northern</string> + <key>noticable</key> + <string>noticeable</string> + <key>noticably</key> + <string>noticeably</string> + <key>noticeing</key> + <string>noticing</string> + <key>noticible</key> + <string>noticeable</string> + <key>notwhithstanding</key> + <string>notwithstanding</string> + <key>noveau</key> + <string>nouveau</string> + <key>nowdays</key> + <string>nowadays</string> + <key>nowe</key> + <string>now</string> + <key>nto</key> + <string>not</string> + <key>nucular</key> + <string>nuclear</string> + <key>nuculear</key> + <string>nuclear</string> + <key>nuisanse</key> + <string>nuisance</string> + <key>numberous</key> + <string>numerous</string> + <key>nusance</key> + <string>nuisance</string> + <key>nutritent</key> + <string>nutrient</string> + <key>nutritents</key> + <string>nutrients</string> + <key>nuturing</key> + <string>nurturing</string> + <key>obediance</key> + <string>obedience</string> + <key>obediant</key> + <string>obedient</string> + <key>obession</key> + <string>obsession</string> + <key>obssessed</key> + <string>obsessed</string> + <key>obstacal</key> + <string>obstacle</string> + <key>obstancles</key> + <string>obstacles</string> + <key>obstruced</key> + <string>obstructed</string> + <key>ocasion</key> + <string>occasion</string> + <key>ocasional</key> + <string>occasional</string> + <key>ocasionally</key> + <string>occasionally</string> + <key>ocasionaly</key> + <string>occasionally</string> + <key>ocasioned</key> + <string>occasioned</string> + <key>ocasions</key> + <string>occasions</string> + <key>ocassion</key> + <string>occasion</string> + <key>ocassional</key> + <string>occasional</string> + <key>ocassionally</key> + <string>occasionally</string> + <key>ocassionaly</key> + <string>occasionally</string> + <key>ocassioned</key> + <string>occasioned</string> + <key>ocassions</key> + <string>occasions</string> + <key>occaison</key> + <string>occasion</string> + <key>occassion</key> + <string>occasion</string> + <key>occassional</key> + <string>occasional</string> + <key>occassionally</key> + <string>occasionally</string> + <key>occassionaly</key> + <string>occasionally</string> + <key>occassioned</key> + <string>occasioned</string> + <key>occassions</key> + <string>occasions</string> + <key>occationally</key> + <string>occasionally</string> + <key>occour</key> + <string>occur</string> + <key>occurance</key> + <string>occurrence</string> + <key>occurances</key> + <string>occurrences</string> + <key>occured</key> + <string>occurred</string> + <key>occurence</key> + <string>occurrence</string> + <key>occurences</key> + <string>occurrences</string> + <key>occuring</key> + <string>occurring</string> + <key>occurr</key> + <string>occur</string> + <key>occurrance</key> + <string>occurrence</string> + <key>occurrances</key> + <string>occurrences</string> + <key>octohedra</key> + <string>octahedra</string> + <key>octohedral</key> + <string>octahedral</string> + <key>octohedron</key> + <string>octahedron</string> + <key>ocuntries</key> + <string>countries</string> + <key>ocuntry</key> + <string>country</string> + <key>ocurr</key> + <string>occur</string> + <key>ocurrance</key> + <string>occurrence</string> + <key>ocurred</key> + <string>occurred</string> + <key>ocurrence</key> + <string>occurrence</string> + <key>offcers</key> + <string>officers</string> + <key>offcially</key> + <string>officially</string> + <key>offereings</key> + <string>offerings</string> + <key>offical</key> + <string>official</string> + <key>offically</key> + <string>officially</string> + <key>officals</key> + <string>officials</string> + <key>officaly</key> + <string>officially</string> + <key>officialy</key> + <string>officially</string> + <key>offred</key> + <string>offered</string> + <key>oftenly</key> + <string>often</string> + <key>oging</key> + <string>going</string> + <key>omision</key> + <string>omission</string> + <key>omited</key> + <string>omitted</string> + <key>omiting</key> + <string>omitting</string> + <key>omlette</key> + <string>omelette</string> + <key>ommision</key> + <string>omission</string> + <key>ommited</key> + <string>omitted</string> + <key>ommiting</key> + <string>omitting</string> + <key>ommitted</key> + <string>omitted</string> + <key>ommitting</key> + <string>omitting</string> + <key>omniverous</key> + <string>omnivorous</string> + <key>omniverously</key> + <string>omnivorously</string> + <key>omre</key> + <string>more</string> + <key>onot</key> + <string>note</string> + <key>onxy</key> + <string>onyx</string> + <key>onyl</key> + <string>only</string> + <key>openess</key> + <string>openness</string> + <key>oponent</key> + <string>opponent</string> + <key>oportunity</key> + <string>opportunity</string> + <key>opose</key> + <string>oppose</string> + <key>oposite</key> + <string>opposite</string> + <key>oposition</key> + <string>opposition</string> + <key>oppenly</key> + <string>openly</string> + <key>oppinion</key> + <string>opinion</string> + <key>opponant</key> + <string>opponent</string> + <key>oppononent</key> + <string>opponent</string> + <key>oppositition</key> + <string>opposition</string> + <key>oppossed</key> + <string>opposed</string> + <key>opprotunity</key> + <string>opportunity</string> + <key>opression</key> + <string>oppression</string> + <key>opressive</key> + <string>oppressive</string> + <key>opthalmic</key> + <string>ophthalmic</string> + <key>opthalmologist</key> + <string>ophthalmologist</string> + <key>opthalmology</key> + <string>ophthalmology</string> + <key>opthamologist</key> + <string>ophthalmologist</string> + <key>optmizations</key> + <string>optimizations</string> + <key>optomism</key> + <string>optimism</string> + <key>orded</key> + <string>ordered</string> + <key>organim</key> + <string>organism</string> + <key>organistion</key> + <string>organisation</string> + <key>organiztion</key> + <string>organization</string> + <key>orgin</key> + <string>origin</string> + <key>orginal</key> + <string>original</string> + <key>orginally</key> + <string>originally</string> + <key>orginize</key> + <string>organise</string> + <key>oridinarily</key> + <string>ordinarily</string> + <key>origanaly</key> + <string>originally</string> + <key>originall</key> + <string>original</string> + <key>originaly</key> + <string>originally</string> + <key>originially</key> + <string>originally</string> + <key>originnally</key> + <string>originally</string> + <key>origional</key> + <string>original</string> + <key>orignally</key> + <string>originally</string> + <key>orignially</key> + <string>originally</string> + <key>otehr</key> + <string>other</string> + <key>oublisher</key> + <string>publisher</string> + <key>ouevre</key> + <string>oeuvre</string> + <key>oustanding</key> + <string>outstanding</string> + <key>overshaddowed</key> + <string>overshadowed</string> + <key>overthere</key> + <string>over there</string> + <key>overwelming</key> + <string>overwhelming</string> + <key>overwheliming</key> + <string>overwhelming</string> + <key>owrk</key> + <string>work</string> + <key>owudl</key> + <string>would</string> + <key>oxigen</key> + <string>oxygen</string> + <key>oximoron</key> + <string>oxymoron</string> + <key>p0enis</key> + <string>penis</string> + <key>paide</key> + <string>paid</string> + <key>paitience</key> + <string>patience</string> + <key>palce</key> + <string>place</string> + <key>paleolitic</key> + <string>paleolithic</string> + <key>paliamentarian</key> + <string>parliamentarian</string> + <key>pallete</key> + <string>palette</string> + <key>pamflet</key> + <string>pamphlet</string> + <key>pamplet</key> + <string>pamphlet</string> + <key>pantomine</key> + <string>pantomime</string> + <key>paralel</key> + <string>parallel</string> + <key>paralell</key> + <string>parallel</string> + <key>paralelly</key> + <string>parallelly</string> + <key>paralely</key> + <string>parallelly</string> + <key>parallely</key> + <string>parallelly</string> + <key>paranthesis</key> + <string>parenthesis</string> + <key>paraphenalia</key> + <string>paraphernalia</string> + <key>parellels</key> + <string>parallels</string> + <key>parituclar</key> + <string>particular</string> + <key>parliment</key> + <string>parliament</string> + <key>parrakeets</key> + <string>parakeets</string> + <key>parralel</key> + <string>parallel</string> + <key>parrallel</key> + <string>parallel</string> + <key>parrallell</key> + <string>parallel</string> + <key>parrallelly</key> + <string>parallelly</string> + <key>parrallely</key> + <string>parallelly</string> + <key>partialy</key> + <string>partially</string> + <key>particually</key> + <string>particularly</string> + <key>particualr</key> + <string>particular</string> + <key>particuarly</key> + <string>particularly</string> + <key>particularily</key> + <string>particularly</string> + <key>particulary</key> + <string>particularly</string> + <key>pary</key> + <string>party</string> + <key>pased</key> + <string>passed</string> + <key>pasengers</key> + <string>passengers</string> + <key>passerbys</key> + <string>passersby</string> + <key>pasttime</key> + <string>pastime</string> + <key>pastural</key> + <string>pastoral</string> + <key>paticular</key> + <string>particular</string> + <key>pattented</key> + <string>patented</string> + <key>pavillion</key> + <string>pavilion</string> + <key>payed</key> + <string>paid</string> + <key>pblisher</key> + <string>publisher</string> + <key>pbulisher</key> + <string>publisher</string> + <key>peacefuland</key> + <string>peaceful and</string> + <key>peageant</key> + <string>pageant</string> + <key>peculure</key> + <string>peculiar</string> + <key>pedestrain</key> + <string>pedestrian</string> + <key>peformed</key> + <string>performed</string> + <key>peice</key> + <string>piece</string> + <key>penatly</key> + <string>penalty</string> + <key>penerator</key> + <string>penetrator</string> + <key>penisula</key> + <string>peninsula</string> + <key>penisular</key> + <string>peninsular</string> + <key>penninsula</key> + <string>peninsula</string> + <key>penninsular</key> + <string>peninsular</string> + <key>pennisula</key> + <string>peninsula</string> + <key>pensinula</key> + <string>peninsula</string> + <key>peom</key> + <string>poem</string> + <key>peoms</key> + <string>poems</string> + <key>peopel</key> + <string>people</string> + <key>peotry</key> + <string>poetry</string> + <key>perade</key> + <string>parade</string> + <key>percepted</key> + <string>perceived</string> + <key>percieve</key> + <string>perceive</string> + <key>percieved</key> + <string>perceived</string> + <key>perenially</key> + <string>perennially</string> + <key>perfomance</key> + <string>performance</string> + <key>perfomers</key> + <string>performers</string> + <key>performence</key> + <string>performance</string> + <key>performes</key> + <string>performed</string> + <key>perhasp</key> + <string>perhaps</string> + <key>perheaps</key> + <string>perhaps</string> + <key>perhpas</key> + <string>perhaps</string> + <key>peripathetic</key> + <string>peripatetic</string> + <key>peristent</key> + <string>persistent</string> + <key>perjery</key> + <string>perjury</string> + <key>perjorative</key> + <string>pejorative</string> + <key>permanant</key> + <string>permanent</string> + <key>permenant</key> + <string>permanent</string> + <key>permenantly</key> + <string>permanently</string> + <key>permissable</key> + <string>permissible</string> + <key>perogative</key> + <string>prerogative</string> + <key>peronal</key> + <string>personal</string> + <key>perosnality</key> + <string>personality</string> + <key>perphas</key> + <string>perhaps</string> + <key>perpindicular</key> + <string>perpendicular</string> + <key>perseverence</key> + <string>perseverance</string> + <key>persistance</key> + <string>persistence</string> + <key>persistant</key> + <string>persistent</string> + <key>personel</key> + <string>personnel</string> + <key>personell</key> + <string>personnel</string> + <key>personnell</key> + <string>personnel</string> + <key>persuded</key> + <string>persuaded</string> + <key>persue</key> + <string>pursue</string> + <key>persued</key> + <string>pursued</string> + <key>persuing</key> + <string>pursuing</string> + <key>persuit</key> + <string>pursuit</string> + <key>persuits</key> + <string>pursuits</string> + <key>pertubation</key> + <string>perturbation</string> + <key>pertubations</key> + <string>perturbations</string> + <key>pessiary</key> + <string>pessary</string> + <key>petetion</key> + <string>petition</string> + <key>phenomenom</key> + <string>phenomenon</string> + <key>phenomenonal</key> + <string>phenomenal</string> + <key>phenomenonly</key> + <string>phenomenally</string> + <key>phenomonenon</key> + <string>phenomenon</string> + <key>phenomonon</key> + <string>phenomenon</string> + <key>phenonmena</key> + <string>phenomena</string> + <key>philisopher</key> + <string>philosopher</string> + <key>philisophical</key> + <string>philosophical</string> + <key>philisophy</key> + <string>philosophy</string> + <key>phillosophically</key> + <string>philosophically</string> + <key>philospher</key> + <string>philosopher</string> + <key>philosphies</key> + <string>philosophies</string> + <key>philosphy</key> + <string>philosophy</string> + <key>phongraph</key> + <string>phonograph</string> + <key>phylosophical</key> + <string>philosophical</string> + <key>physicaly</key> + <string>physically</string> + <key>piblisher</key> + <string>publisher</string> + <key>pich</key> + <string>pitch</string> + <key>pilgrimmage</key> + <string>pilgrimage</string> + <key>pilgrimmages</key> + <string>pilgrimages</string> + <key>pinapple</key> + <string>pineapple</string> + <key>pinnaple</key> + <string>pineapple</string> + <key>pinoneered</key> + <string>pioneered</string> + <key>plagarism</key> + <string>plagiarism</string> + <key>planation</key> + <string>plantation</string> + <key>planed</key> + <string>planned</string> + <key>plantiff</key> + <string>plaintiff</string> + <key>plateu</key> + <string>plateau</string> + <key>plausable</key> + <string>plausible</string> + <key>playright</key> + <string>playwright</string> + <key>playwrite</key> + <string>playwright</string> + <key>playwrites</key> + <string>playwrights</string> + <key>pleasent</key> + <string>pleasant</string> + <key>plebicite</key> + <string>plebiscite</string> + <key>plesant</key> + <string>pleasant</string> + <key>poenis</key> + <string>penis</string> + <key>poeoples</key> + <string>peoples</string> + <key>poety</key> + <string>poetry</string> + <key>poisin</key> + <string>poison</string> + <key>polical</key> + <string>political</string> + <key>polinator</key> + <string>pollinator</string> + <key>polinators</key> + <string>pollinators</string> + <key>politican</key> + <string>politician</string> + <key>politicans</key> + <string>politicians</string> + <key>poltical</key> + <string>political</string> + <key>polute</key> + <string>pollute</string> + <key>poluted</key> + <string>polluted</string> + <key>polutes</key> + <string>pollutes</string> + <key>poluting</key> + <string>polluting</string> + <key>polution</key> + <string>pollution</string> + <key>polyphonyic</key> + <string>polyphonic</string> + <key>polysaccaride</key> + <string>polysaccharide</string> + <key>polysaccharid</key> + <string>polysaccharide</string> + <key>pomegranite</key> + <string>pomegranate</string> + <key>pomotion</key> + <string>promotion</string> + <key>poportional</key> + <string>proportional</string> + <key>popoulation</key> + <string>population</string> + <key>popularaty</key> + <string>popularity</string> + <key>populare</key> + <string>popular</string> + <key>populer</key> + <string>popular</string> + <key>portait</key> + <string>portrait</string> + <key>portayed</key> + <string>portrayed</string> + <key>portraing</key> + <string>portraying</string> + <key>portuguease</key> + <string>portuguese</string> + <key>portugues</key> + <string>Portuguese</string> + <key>posess</key> + <string>possess</string> + <key>posessed</key> + <string>possessed</string> + <key>posesses</key> + <string>possesses</string> + <key>posessing</key> + <string>possessing</string> + <key>posession</key> + <string>possession</string> + <key>posessions</key> + <string>possessions</string> + <key>posion</key> + <string>poison</string> + <key>positon</key> + <string>position</string> + <key>possable</key> + <string>possible</string> + <key>possably</key> + <string>possibly</string> + <key>posseses</key> + <string>possesses</string> + <key>possesing</key> + <string>possessing</string> + <key>possesion</key> + <string>possession</string> + <key>possessess</key> + <string>possesses</string> + <key>possibile</key> + <string>possible</string> + <key>possibilty</key> + <string>possibility</string> + <key>possiblility</key> + <string>possibility</string> + <key>possiblilty</key> + <string>possibility</string> + <key>possiblities</key> + <string>possibilities</string> + <key>possiblity</key> + <string>possibility</string> + <key>possition</key> + <string>position</string> + <key>posthomous</key> + <string>posthumous</string> + <key>postion</key> + <string>position</string> + <key>postive</key> + <string>positive</string> + <key>potatos</key> + <string>potatoes</string> + <key>potrait</key> + <string>portrait</string> + <key>potrayed</key> + <string>portrayed</string> + <key>poulations</key> + <string>populations</string> + <key>poverful</key> + <string>powerful</string> + <key>poweful</key> + <string>powerful</string> + <key>powerfull</key> + <string>powerful</string> + <key>ppublisher</key> + <string>publisher</string> + <key>practial</key> + <string>practical</string> + <key>practially</key> + <string>practically</string> + <key>practicaly</key> + <string>practically</string> + <key>practicioner</key> + <string>practitioner</string> + <key>practicioners</key> + <string>practitioners</string> + <key>practicly</key> + <string>practically</string> + <key>practioner</key> + <string>practitioner</string> + <key>practioners</key> + <string>practitioners</string> + <key>prairy</key> + <string>prairie</string> + <key>prarie</key> + <string>prairie</string> + <key>praries</key> + <string>prairies</string> + <key>pratice</key> + <string>practice</string> + <key>preample</key> + <string>preamble</string> + <key>precedessor</key> + <string>predecessor</string> + <key>preceed</key> + <string>precede</string> + <key>preceeded</key> + <string>preceded</string> + <key>preceeding</key> + <string>preceding</string> + <key>preceeds</key> + <string>precedes</string> + <key>precentage</key> + <string>percentage</string> + <key>precice</key> + <string>precise</string> + <key>precisly</key> + <string>precisely</string> + <key>precurser</key> + <string>precursor</string> + <key>predecesors</key> + <string>predecessors</string> + <key>predicatble</key> + <string>predictable</string> + <key>predicitons</key> + <string>predictions</string> + <key>predomiantly</key> + <string>predominately</string> + <key>prefered</key> + <string>preferred</string> + <key>prefering</key> + <string>preferring</string> + <key>preferrably</key> + <string>preferably</string> + <key>pregancies</key> + <string>pregnancies</string> + <key>preiod</key> + <string>period</string> + <key>preliferation</key> + <string>proliferation</string> + <key>premeire</key> + <string>premiere</string> + <key>premeired</key> + <string>premiered</string> + <key>premillenial</key> + <string>premillennial</string> + <key>preminence</key> + <string>preeminence</string> + <key>premission</key> + <string>permission</string> + <key>preocupation</key> + <string>preoccupation</string> + <key>prepair</key> + <string>prepare</string> + <key>prepartion</key> + <string>preparation</string> + <key>prepatory</key> + <string>preparatory</string> + <key>preperation</key> + <string>preparation</string> + <key>preperations</key> + <string>preparations</string> + <key>preriod</key> + <string>period</string> + <key>presedential</key> + <string>presidential</string> + <key>presense</key> + <string>presence</string> + <key>presidenital</key> + <string>presidential</string> + <key>presidental</key> + <string>presidential</string> + <key>presitgious</key> + <string>prestigious</string> + <key>prespective</key> + <string>perspective</string> + <key>prestigeous</key> + <string>prestigious</string> + <key>prestigous</key> + <string>prestigious</string> + <key>presumabely</key> + <string>presumably</string> + <key>presumibly</key> + <string>presumably</string> + <key>pretection</key> + <string>protection</string> + <key>prevelant</key> + <string>prevalent</string> + <key>preverse</key> + <string>perverse</string> + <key>previvous</key> + <string>previous</string> + <key>pricipal</key> + <string>principal</string> + <key>priciple</key> + <string>principle</string> + <key>priestood</key> + <string>priesthood</string> + <key>primarly</key> + <string>primarily</string> + <key>primative</key> + <string>primitive</string> + <key>primatively</key> + <string>primitively</string> + <key>primatives</key> + <string>primitives</string> + <key>primordal</key> + <string>primordial</string> + <key>priveledges</key> + <string>privileges</string> + <key>privelege</key> + <string>privilege</string> + <key>priveleged</key> + <string>privileged</string> + <key>priveleges</key> + <string>privileges</string> + <key>privelige</key> + <string>privilege</string> + <key>priveliged</key> + <string>privileged</string> + <key>priveliges</key> + <string>privileges</string> + <key>privelleges</key> + <string>privileges</string> + <key>privilage</key> + <string>privilege</string> + <key>priviledge</key> + <string>privilege</string> + <key>priviledges</key> + <string>privileges</string> + <key>privledge</key> + <string>privilege</string> + <key>privte</key> + <string>private</string> + <key>probabilaty</key> + <string>probability</string> + <key>probablistic</key> + <string>probabilistic</string> + <key>probablly</key> + <string>probably</string> + <key>probalibity</key> + <string>probability</string> + <key>probaly</key> + <string>probably</string> + <key>probelm</key> + <string>problem</string> + <key>proccess</key> + <string>process</string> + <key>proccessing</key> + <string>processing</string> + <key>procede</key> + <string>proceed</string> + <key>proceded</key> + <string>proceeded</string> + <key>procedes</key> + <string>proceeds</string> + <key>procedger</key> + <string>procedure</string> + <key>proceding</key> + <string>proceeding</string> + <key>procedings</key> + <string>proceedings</string> + <key>proceedure</key> + <string>procedure</string> + <key>proces</key> + <string>process</string> + <key>processer</key> + <string>processor</string> + <key>proclaimation</key> + <string>proclamation</string> + <key>proclamed</key> + <string>proclaimed</string> + <key>proclaming</key> + <string>proclaiming</string> + <key>proclomation</key> + <string>proclamation</string> + <key>profesion</key> + <string>profession</string> + <key>profesor</key> + <string>professor</string> + <key>professer</key> + <string>professor</string> + <key>proffesed</key> + <string>professed</string> + <key>proffesion</key> + <string>profession</string> + <key>proffesional</key> + <string>professional</string> + <key>proffesor</key> + <string>professor</string> + <key>profilic</key> + <string>prolific</string> + <key>progessed</key> + <string>progressed</string> + <key>programable</key> + <string>programmable</string> + <key>progrom</key> + <string>program</string> + <key>progroms</key> + <string>programs</string> + <key>prohabition</key> + <string>prohibition</string> + <key>prologomena</key> + <string>prolegomena</string> + <key>prominance</key> + <string>prominence</string> + <key>prominant</key> + <string>prominent</string> + <key>prominantly</key> + <string>prominently</string> + <key>prominately</key> + <string>prominently</string> + <key>promiscous</key> + <string>promiscuous</string> + <key>promotted</key> + <string>promoted</string> + <key>pronomial</key> + <string>pronominal</string> + <key>pronouced</key> + <string>pronounced</string> + <key>pronounched</key> + <string>pronounced</string> + <key>pronounciation</key> + <string>pronunciation</string> + <key>proove</key> + <string>prove</string> + <key>prooved</key> + <string>proved</string> + <key>prophacy</key> + <string>prophecy</string> + <key>propietary</key> + <string>proprietary</string> + <key>propmted</key> + <string>prompted</string> + <key>propoganda</key> + <string>propaganda</string> + <key>propogate</key> + <string>propagate</string> + <key>propogates</key> + <string>propagates</string> + <key>propogation</key> + <string>propagation</string> + <key>propostion</key> + <string>proposition</string> + <key>propotions</key> + <string>proportions</string> + <key>propper</key> + <string>proper</string> + <key>propperly</key> + <string>properly</string> + <key>proprietory</key> + <string>proprietary</string> + <key>proseletyzing</key> + <string>proselytizing</string> + <key>protaganist</key> + <string>protagonist</string> + <key>protaganists</key> + <string>protagonists</string> + <key>protocal</key> + <string>protocol</string> + <key>protoganist</key> + <string>protagonist</string> + <key>protrayed</key> + <string>portrayed</string> + <key>protruberance</key> + <string>protuberance</string> + <key>protruberances</key> + <string>protuberances</string> + <key>prouncements</key> + <string>pronouncements</string> + <key>provacative</key> + <string>provocative</string> + <key>provded</key> + <string>provided</string> + <key>provicial</key> + <string>provincial</string> + <key>provinicial</key> + <string>provincial</string> + <key>provisiosn</key> + <string>provision</string> + <key>provisonal</key> + <string>provisional</string> + <key>proximty</key> + <string>proximity</string> + <key>pseudononymous</key> + <string>pseudonymous</string> + <key>pseudonyn</key> + <string>pseudonym</string> + <key>psuedo</key> + <string>pseudo</string> + <key>psycology</key> + <string>psychology</string> + <key>psyhic</key> + <string>psychic</string> + <key>pubilsher</key> + <string>publisher</string> + <key>pubisher</key> + <string>publisher</string> + <key>publiaher</key> + <string>publisher</string> + <key>publically</key> + <string>publicly</string> + <key>publicaly</key> + <string>publicly</string> + <key>publicher</key> + <string>publisher</string> + <key>publihser</key> + <string>publisher</string> + <key>publisehr</key> + <string>publisher</string> + <key>publiser</key> + <string>publisher</string> + <key>publisger</key> + <string>publisher</string> + <key>publisheed</key> + <string>published</string> + <key>publisherr</key> + <string>publisher</string> + <key>publishher</key> + <string>publisher</string> + <key>publishor</key> + <string>publisher</string> + <key>publishre</key> + <string>publisher</string> + <key>publissher</key> + <string>publisher</string> + <key>publlisher</key> + <string>publisher</string> + <key>publsiher</key> + <string>publisher</string> + <key>publusher</key> + <string>publisher</string> + <key>puchasing</key> + <string>purchasing</string> + <key>pulisher</key> + <string>publisher</string> + <key>pumkin</key> + <string>pumpkin</string> + <key>puplisher</key> + <string>publisher</string> + <key>puritannical</key> + <string>puritanical</string> + <key>purposedly</key> + <string>purposely</string> + <key>purpotedly</key> + <string>purportedly</string> + <key>pursuade</key> + <string>persuade</string> + <key>pursuaded</key> + <string>persuaded</string> + <key>pursuades</key> + <string>persuades</string> + <key>pususading</key> + <string>persuading</string> + <key>puting</key> + <string>putting</string> + <key>pwoer</key> + <string>power</string> + <key>pyscic</key> + <string>psychic</string> + <key>qtuie</key> + <string>quiet</string> + <key>quantaty</key> + <string>quantity</string> + <key>quantitiy</key> + <string>quantity</string> + <key>quarantaine</key> + <string>quarantine</string> + <key>questonable</key> + <string>questionable</string> + <key>quicklyu</key> + <string>quickly</string> + <key>quinessential</key> + <string>quintessential</string> + <key>quitted</key> + <string>quit</string> + <key>quizes</key> + <string>quizzes</string> + <key>qutie</key> + <string>quiet</string> + <key>rabinnical</key> + <string>rabbinical</string> + <key>racaus</key> + <string>raucous</string> + <key>radiactive</key> + <string>radioactive</string> + <key>radify</key> + <string>ratify</string> + <key>raelly</key> + <string>really</string> + <key>rarified</key> + <string>rarefied</string> + <key>reaccurring</key> + <string>recurring</string> + <key>reacing</key> + <string>reaching</string> + <key>reacll</key> + <string>recall</string> + <key>readmition</key> + <string>readmission</string> + <key>realitvely</key> + <string>relatively</string> + <key>realsitic</key> + <string>realistic</string> + <key>realtions</key> + <string>relations</string> + <key>realy</key> + <string>really</string> + <key>realyl</key> + <string>really</string> + <key>reasearch</key> + <string>research</string> + <key>rebiulding</key> + <string>rebuilding</string> + <key>rebllions</key> + <string>rebellions</string> + <key>rebounce</key> + <string>rebound</string> + <key>reccomend</key> + <string>recommend</string> + <key>reccomendations</key> + <string>recommendations</string> + <key>reccomended</key> + <string>recommended</string> + <key>reccomending</key> + <string>recommending</string> + <key>reccommend</key> + <string>recommend</string> + <key>reccommended</key> + <string>recommended</string> + <key>reccommending</key> + <string>recommending</string> + <key>reccuring</key> + <string>recurring</string> + <key>receeded</key> + <string>receded</string> + <key>receeding</key> + <string>receding</string> + <key>receivedfrom</key> + <string>received from</string> + <key>recepient</key> + <string>recipient</string> + <key>recepients</key> + <string>recipients</string> + <key>receving</key> + <string>receiving</string> + <key>rechargable</key> + <string>rechargeable</string> + <key>reched</key> + <string>reached</string> + <key>recide</key> + <string>reside</string> + <key>recided</key> + <string>resided</string> + <key>recident</key> + <string>resident</string> + <key>recidents</key> + <string>residents</string> + <key>reciding</key> + <string>residing</string> + <key>reciepents</key> + <string>recipients</string> + <key>reciept</key> + <string>receipt</string> + <key>recieve</key> + <string>receive</string> + <key>recieved</key> + <string>received</string> + <key>reciever</key> + <string>receiver</string> + <key>recievers</key> + <string>receivers</string> + <key>recieves</key> + <string>receives</string> + <key>recieving</key> + <string>receiving</string> + <key>recipiant</key> + <string>recipient</string> + <key>recipiants</key> + <string>recipients</string> + <key>recived</key> + <string>received</string> + <key>recivership</key> + <string>receivership</string> + <key>recogise</key> + <string>recognise</string> + <key>recogize</key> + <string>recognize</string> + <key>recomend</key> + <string>recommend</string> + <key>recomended</key> + <string>recommended</string> + <key>recomending</key> + <string>recommending</string> + <key>recomends</key> + <string>recommends</string> + <key>recommedations</key> + <string>recommendations</string> + <key>reconaissance</key> + <string>reconnaissance</string> + <key>reconcilation</key> + <string>reconciliation</string> + <key>reconized</key> + <string>recognized</string> + <key>reconnaisance</key> + <string>reconnaissance</string> + <key>reconnaissence</key> + <string>reconnaissance</string> + <key>recontructed</key> + <string>reconstructed</string> + <key>recordproducer</key> + <string>record producer</string> + <key>recquired</key> + <string>required</string> + <key>recrational</key> + <string>recreational</string> + <key>recrod</key> + <string>record</string> + <key>recuiting</key> + <string>recruiting</string> + <key>recuring</key> + <string>recurring</string> + <key>recurrance</key> + <string>recurrence</string> + <key>rediculous</key> + <string>ridiculous</string> + <key>reedeming</key> + <string>redeeming</string> + <key>reenforced</key> + <string>reinforced</string> + <key>refect</key> + <string>reflect</string> + <key>refedendum</key> + <string>referendum</string> + <key>referal</key> + <string>referral</string> + <key>referece</key> + <string>reference</string> + <key>refereces</key> + <string>references</string> + <key>refered</key> + <string>referred</string> + <key>referemce</key> + <string>reference</string> + <key>referemces</key> + <string>references</string> + <key>referencs</key> + <string>references</string> + <key>referenece</key> + <string>reference</string> + <key>refereneced</key> + <string>referenced</string> + <key>refereneces</key> + <string>references</string> + <key>referiang</key> + <string>referring</string> + <key>refering</key> + <string>referring</string> + <key>refernce</key> + <string>references</string> + <key>refernces</key> + <string>references</string> + <key>referrence</key> + <string>reference</string> + <key>referrences</key> + <string>references</string> + <key>referrs</key> + <string>refers</string> + <key>reffered</key> + <string>referred</string> + <key>refference</key> + <string>reference</string> + <key>reffering</key> + <string>referring</string> + <key>refrence</key> + <string>reference</string> + <key>refrences</key> + <string>references</string> + <key>refrers</key> + <string>refers</string> + <key>refridgeration</key> + <string>refrigeration</string> + <key>refridgerator</key> + <string>refrigerator</string> + <key>refromist</key> + <string>reformist</string> + <key>refusla</key> + <string>refusal</string> + <key>regardes</key> + <string>regards</string> + <key>regluar</key> + <string>regular</string> + <key>reguarly</key> + <string>regularly</string> + <key>regulaion</key> + <string>regulation</string> + <key>regulaotrs</key> + <string>regulators</string> + <key>regularily</key> + <string>regularly</string> + <key>rehersal</key> + <string>rehearsal</string> + <key>reicarnation</key> + <string>reincarnation</string> + <key>reigining</key> + <string>reigning</string> + <key>reknown</key> + <string>renown</string> + <key>reknowned</key> + <string>renowned</string> + <key>rela</key> + <string>real</string> + <key>relaly</key> + <string>really</string> + <key>relatiopnship</key> + <string>relationship</string> + <key>relativly</key> + <string>relatively</string> + <key>relected</key> + <string>reelected</string> + <key>releive</key> + <string>relieve</string> + <key>releived</key> + <string>relieved</string> + <key>releiver</key> + <string>reliever</string> + <key>releses</key> + <string>releases</string> + <key>relevence</key> + <string>relevance</string> + <key>relevent</key> + <string>relevant</string> + <key>reliablity</key> + <string>reliability</string> + <key>relient</key> + <string>reliant</string> + <key>religeous</key> + <string>religious</string> + <key>religous</key> + <string>religious</string> + <key>religously</key> + <string>religiously</string> + <key>relinqushment</key> + <string>relinquishment</string> + <key>relitavely</key> + <string>relatively</string> + <key>relized</key> + <string>realized</string> + <key>relpacement</key> + <string>replacement</string> + <key>remaing</key> + <string>remaining</string> + <key>remeber</key> + <string>remember</string> + <key>rememberable</key> + <string>memorable</string> + <key>rememberance</key> + <string>remembrance</string> + <key>remembrence</key> + <string>remembrance</string> + <key>remenant</key> + <string>remnant</string> + <key>remenicent</key> + <string>reminiscent</string> + <key>reminent</key> + <string>remnant</string> + <key>reminescent</key> + <string>reminiscent</string> + <key>reminscent</key> + <string>reminiscent</string> + <key>reminsicent</key> + <string>reminiscent</string> + <key>rendevous</key> + <string>rendezvous</string> + <key>rendezous</key> + <string>rendezvous</string> + <key>renedered</key> + <string>rende</string> + <key>renewl</key> + <string>renewal</string> + <key>rennovate</key> + <string>renovate</string> + <key>rennovated</key> + <string>renovated</string> + <key>rennovating</key> + <string>renovating</string> + <key>rennovation</key> + <string>renovation</string> + <key>rentors</key> + <string>renters</string> + <key>reoccurrence</key> + <string>recurrence</string> + <key>reorganision</key> + <string>reorganisation</string> + <key>repatition</key> + <string>repetition</string> + <key>repectively</key> + <string>respectively</string> + <key>repeition</key> + <string>repetition</string> + <key>repentence</key> + <string>repentance</string> + <key>repentent</key> + <string>repentant</string> + <key>repeteadly</key> + <string>repeatedly</string> + <key>repetion</key> + <string>repetition</string> + <key>repid</key> + <string>rapid</string> + <key>reponse</key> + <string>response</string> + <key>reponsible</key> + <string>responsible</string> + <key>reportadly</key> + <string>reportedly</string> + <key>represantative</key> + <string>representative</string> + <key>representive</key> + <string>representative</string> + <key>representives</key> + <string>representatives</string> + <key>reproducable</key> + <string>reproducible</string> + <key>reprtoire</key> + <string>repertoire</string> + <key>repsectively</key> + <string>respectively</string> + <key>reptition</key> + <string>repetition</string> + <key>requirment</key> + <string>requirement</string> + <key>requred</key> + <string>required</string> + <key>resaurant</key> + <string>restaurant</string> + <key>resembelance</key> + <string>resemblance</string> + <key>resembes</key> + <string>resembles</string> + <key>resemblence</key> + <string>resemblance</string> + <key>resevoir</key> + <string>reservoir</string> + <key>residental</key> + <string>residential</string> + <key>resignement</key> + <string>resignment</string> + <key>resistable</key> + <string>resistible</string> + <key>resistence</key> + <string>resistance</string> + <key>resistent</key> + <string>resistant</string> + <key>respectivly</key> + <string>respectively</string> + <key>responce</key> + <string>response</string> + <key>responibilities</key> + <string>responsibilities</string> + <key>responisble</key> + <string>responsible</string> + <key>responnsibilty</key> + <string>responsibility</string> + <key>responsability</key> + <string>responsibility</string> + <key>responsibile</key> + <string>responsible</string> + <key>responsibilites</key> + <string>responsibilities</string> + <key>responsiblities</key> + <string>responsibilities</string> + <key>responsiblity</key> + <string>responsibility</string> + <key>ressemblance</key> + <string>resemblance</string> + <key>ressemble</key> + <string>resemble</string> + <key>ressembled</key> + <string>resembled</string> + <key>ressemblence</key> + <string>resemblance</string> + <key>ressembling</key> + <string>resembling</string> + <key>resssurecting</key> + <string>resurrecting</string> + <key>ressurect</key> + <string>resurrect</string> + <key>ressurected</key> + <string>resurrected</string> + <key>ressurection</key> + <string>resurrection</string> + <key>ressurrection</key> + <string>resurrection</string> + <key>restarant</key> + <string>restaurant</string> + <key>restarants</key> + <string>restaurants</string> + <key>restaraunt</key> + <string>restaurant</string> + <key>restaraunteur</key> + <string>restaurateur</string> + <key>restaraunteurs</key> + <string>restaurateurs</string> + <key>restaraunts</key> + <string>restaurants</string> + <key>restauranteurs</key> + <string>restaurateurs</string> + <key>restauration</key> + <string>restoration</string> + <key>restauraunt</key> + <string>restaurant</string> + <key>resteraunt</key> + <string>restaurant</string> + <key>resteraunts</key> + <string>restaurants</string> + <key>resticted</key> + <string>restricted</string> + <key>restraunt</key> + <string>restraint</string> + <key>resturant</key> + <string>restaurant</string> + <key>resturants</key> + <string>restaurants</string> + <key>resturaunt</key> + <string>restaurant</string> + <key>resturaunts</key> + <string>restaurants</string> + <key>resurecting</key> + <string>resurrecting</string> + <key>retalitated</key> + <string>retaliated</string> + <key>retalitation</key> + <string>retaliation</string> + <key>retreive</key> + <string>retrieve</string> + <key>returnd</key> + <string>returned</string> + <key>revaluated</key> + <string>reevaluated</string> + <key>reveiw</key> + <string>review</string> + <key>reveral</key> + <string>reversal</string> + <key>reversable</key> + <string>reversible</string> + <key>revolutionar</key> + <string>revolutionary</string> + <key>rewitten</key> + <string>rewritten</string> + <key>rewriet</key> + <string>rewrite</string> + <key>rference</key> + <string>reference</string> + <key>rferences</key> + <string>references</string> + <key>rhymme</key> + <string>rhyme</string> + <key>rhythem</key> + <string>rhythm</string> + <key>rhythim</key> + <string>rhythm</string> + <key>rhytmic</key> + <string>rhythmic</string> + <key>rigourous</key> + <string>rigorous</string> + <key>rininging</key> + <string>ringing</string> + <key>rised</key> + <string>rose</string> + <key>rococco</key> + <string>rococo</string> + <key>rocord</key> + <string>record</string> + <key>roomate</key> + <string>roommate</string> + <key>rougly</key> + <string>roughly</string> + <key>rucuperate</key> + <string>recuperate</string> + <key>rudimentatry</key> + <string>rudimentary</string> + <key>rulle</key> + <string>rule</string> + <key>runing</key> + <string>running</string> + <key>runnung</key> + <string>running</string> + <key>russina</key> + <string>Russian</string> + <key>rwite</key> + <string>write</string> + <key>rythem</key> + <string>rhythm</string> + <key>rythim</key> + <string>rhythm</string> + <key>rythm</key> + <string>rhythm</string> + <key>rythmic</key> + <string>rhythmic</string> + <key>rythyms</key> + <string>rhythms</string> + <key>sacrafice</key> + <string>sacrifice</string> + <key>sacreligious</key> + <string>sacrilegious</string> + <key>sacrifical</key> + <string>sacrificial</string> + <key>saftey</key> + <string>safety</string> + <key>safty</key> + <string>safety</string> + <key>salery</key> + <string>salary</string> + <key>sanctionning</key> + <string>sanctioning</string> + <key>sandwhich</key> + <string>sandwich</string> + <key>santioned</key> + <string>sanctioned</string> + <key>sargant</key> + <string>sergeant</string> + <key>sargeant</key> + <string>sergeant</string> + <key>satelite</key> + <string>satellite</string> + <key>satelites</key> + <string>satellites</string> + <key>satisfactority</key> + <string>satisfactorily</string> + <key>satric</key> + <string>satiric</string> + <key>satrical</key> + <string>satirical</string> + <key>satrically</key> + <string>satirically</string> + <key>sattelite</key> + <string>satellite</string> + <key>sattelites</key> + <string>satellites</string> + <key>saught</key> + <string>sought</string> + <key>saveing</key> + <string>saving</string> + <key>saxaphone</key> + <string>saxophone</string> + <key>scaleable</key> + <string>scalable</string> + <key>scandanavia</key> + <string>Scandinavia</string> + <key>scaricity</key> + <string>scarcity</string> + <key>scavanged</key> + <string>scavenged</string> + <key>schedual</key> + <string>schedule</string> + <key>scholarhip</key> + <string>scholarship</string> + <key>scholarstic</key> + <string>scholastic</string> + <key>scientfic</key> + <string>scientific</string> + <key>scientifc</key> + <string>scientific</string> + <key>scientis</key> + <string>scientist</string> + <key>scince</key> + <string>science</string> + <key>scinece</key> + <string>science</string> + <key>scirpt</key> + <string>script</string> + <key>scoll</key> + <string>scroll</string> + <key>screenwrighter</key> + <string>screenwriter</string> + <key>scrutinity</key> + <string>scrutiny</string> + <key>scuptures</key> + <string>sculptures</string> + <key>seach</key> + <string>search</string> + <key>seached</key> + <string>searched</string> + <key>seaches</key> + <string>searches</string> + <key>secratary</key> + <string>secretary</string> + <key>secretery</key> + <string>secretary</string> + <key>sedereal</key> + <string>sidereal</string> + <key>seeked</key> + <string>sought</string> + <key>segementation</key> + <string>segmentation</string> + <key>seguoys</key> + <string>segues</string> + <key>seige</key> + <string>siege</string> + <key>seing</key> + <string>seeing</string> + <key>seinor</key> + <string>senior</string> + <key>seldomly</key> + <string>seldom</string> + <key>senarios</key> + <string>scenarios</string> + <key>senstive</key> + <string>sensitive</string> + <key>sensure</key> + <string>censure</string> + <key>seperate</key> + <string>separate</string> + <key>seperated</key> + <string>separated</string> + <key>seperately</key> + <string>separately</string> + <key>seperates</key> + <string>separates</string> + <key>seperating</key> + <string>separating</string> + <key>seperation</key> + <string>separation</string> + <key>seperatism</key> + <string>separatism</string> + <key>seperatist</key> + <string>separatist</string> + <key>sepina</key> + <string>subpoena</string> + <key>sergent</key> + <string>sergeant</string> + <key>settelement</key> + <string>settlement</string> + <key>settlment</key> + <string>settlement</string> + <key>severeal</key> + <string>several</string> + <key>severley</key> + <string>severely</string> + <key>severly</key> + <string>severely</string> + <key>sevice</key> + <string>service</string> + <key>shadasloo</key> + <string>shadaloo</string> + <key>shaddow</key> + <string>shadow</string> + <key>shadoloo</key> + <string>shadaloo</string> + <key>shamen</key> + <string>shaman</string> + <key>sheat</key> + <string>sheath</string> + <key>sheild</key> + <string>shield</string> + <key>sherif</key> + <string>sheriff</string> + <key>shineing</key> + <string>shining</string> + <key>shiped</key> + <string>shipped</string> + <key>shiping</key> + <string>shipping</string> + <key>shopkeeepers</key> + <string>shopkeepers</string> + <key>shorly</key> + <string>shortly</string> + <key>shortwhile</key> + <string>short while</string> + <key>shoudl</key> + <string>should</string> + <key>shoudln</key> + <string>shouldn't</string> + <key>shouldnt</key> + <string>shouldn't</string> + <key>shreak</key> + <string>shriek</string> + <key>shrinked</key> + <string>shrunk</string> + <key>sicne</key> + <string>since</string> + <key>sideral</key> + <string>sidereal</string> + <key>siezure</key> + <string>seizure</string> + <key>siezures</key> + <string>seizures</string> + <key>siginificant</key> + <string>significant</string> + <key>signficant</key> + <string>significant</string> + <key>signficiant</key> + <string>significant</string> + <key>signfies</key> + <string>signifies</string> + <key>signifantly</key> + <string>significantly</string> + <key>significently</key> + <string>significantly</string> + <key>signifigant</key> + <string>significant</string> + <key>signifigantly</key> + <string>significantly</string> + <key>signitories</key> + <string>signatories</string> + <key>signitory</key> + <string>signatory</string> + <key>similarily</key> + <string>similarly</string> + <key>similiar</key> + <string>similar</string> + <key>similiarity</key> + <string>similarity</string> + <key>similiarly</key> + <string>similarly</string> + <key>simmilar</key> + <string>similar</string> + <key>simpley</key> + <string>simply</string> + <key>simplier</key> + <string>simpler</string> + <key>simultanous</key> + <string>simultaneous</string> + <key>simultanously</key> + <string>simultaneously</string> + <key>sincerley</key> + <string>sincerely</string> + <key>singsog</key> + <string>singsong</string> + <key>sinse</key> + <string>since</string> + <key>skateing</key> + <string>skating</string> + <key>slaugterhouses</key> + <string>slaughterhouses</string> + <key>slighly</key> + <string>slightly</string> + <key>slowy</key> + <string>slowly</string> + <key>smae</key> + <string>same</string> + <key>smealting</key> + <string>smelting</string> + <key>smoe</key> + <string>some</string> + <key>sneeks</key> + <string>sneaks</string> + <key>snese</key> + <string>sneeze</string> + <key>socalism</key> + <string>socialism</string> + <key>socities</key> + <string>societies</string> + <key>soem</key> + <string>some</string> + <key>sofware</key> + <string>software</string> + <key>sohw</key> + <string>show</string> + <key>soilders</key> + <string>soldiers</string> + <key>solatary</key> + <string>solitary</string> + <key>soley</key> + <string>solely</string> + <key>soliders</key> + <string>soldiers</string> + <key>soliliquy</key> + <string>soliloquy</string> + <key>soluable</key> + <string>soluble</string> + <key>somene</key> + <string>someone</string> + <key>somtimes</key> + <string>sometimes</string> + <key>somwhere</key> + <string>somewhere</string> + <key>sophicated</key> + <string>sophisticated</string> + <key>sophmore</key> + <string>sophomore</string> + <key>sorceror</key> + <string>sorcerer</string> + <key>sorrounding</key> + <string>surrounding</string> + <key>sotry</key> + <string>story</string> + <key>sotyr</key> + <string>story</string> + <key>soudn</key> + <string>sound</string> + <key>soudns</key> + <string>sounds</string> + <key>sould</key> + <string>could</string> + <key>sountrack</key> + <string>soundtrack</string> + <key>sourth</key> + <string>south</string> + <key>sourthern</key> + <string>southern</string> + <key>souvenier</key> + <string>souvenir</string> + <key>souveniers</key> + <string>souvenirs</string> + <key>soveits</key> + <string>soviets</string> + <key>sovereignity</key> + <string>sovereignty</string> + <key>soverign</key> + <string>sovereign</string> + <key>soverignity</key> + <string>sovereignty</string> + <key>soverignty</key> + <string>sovereignty</string> + <key>spainish</key> + <string>Spanish</string> + <key>speach</key> + <string>speech</string> + <key>specfic</key> + <string>specific</string> + <key>speciallized</key> + <string>specialized</string> + <key>specifiying</key> + <string>specifying</string> + <key>speciman</key> + <string>specimen</string> + <key>spectauclar</key> + <string>spectacular</string> + <key>spectaulars</key> + <string>spectaculars</string> + <key>spectum</key> + <string>spectrum</string> + <key>speices</key> + <string>species</string> + <key>spendour</key> + <string>splendour</string> + <key>spermatozoan</key> + <string>spermatozoon</string> + <key>spoace</key> + <string>space</string> + <key>sponser</key> + <string>sponsor</string> + <key>sponsered</key> + <string>sponsored</string> + <key>spontanous</key> + <string>spontaneous</string> + <key>sponzored</key> + <string>sponsored</string> + <key>spoonfulls</key> + <string>spoonfuls</string> + <key>sppeches</key> + <string>speeches</string> + <key>spreaded</key> + <string>spread</string> + <key>sprech</key> + <string>speech</string> + <key>spred</key> + <string>spread</string> + <key>spriritual</key> + <string>spiritual</string> + <key>spritual</key> + <string>spiritual</string> + <key>sqaure</key> + <string>square</string> + <key>stablility</key> + <string>stability</string> + <key>stainlees</key> + <string>stainless</string> + <key>staion</key> + <string>station</string> + <key>standars</key> + <string>standards</string> + <key>stange</key> + <string>strange</string> + <key>startegic</key> + <string>strategic</string> + <key>startegies</key> + <string>strategies</string> + <key>startegy</key> + <string>strategy</string> + <key>stateman</key> + <string>statesman</string> + <key>statememts</key> + <string>statements</string> + <key>statment</key> + <string>statement</string> + <key>steriods</key> + <string>steroids</string> + <key>sterotypes</key> + <string>stereotypes</string> + <key>stilus</key> + <string>stylus</string> + <key>stingent</key> + <string>stringent</string> + <key>stiring</key> + <string>stirring</string> + <key>stirrs</key> + <string>stirs</string> + <key>stlye</key> + <string>style</string> + <key>stomache</key> + <string>stomach</string> + <key>stong</key> + <string>strong</string> + <key>stopry</key> + <string>story</string> + <key>storeis</key> + <string>stories</string> + <key>storise</key> + <string>stories</string> + <key>stornegst</key> + <string>strongest</string> + <key>stoyr</key> + <string>story</string> + <key>stpo</key> + <string>stop</string> + <key>stradegies</key> + <string>strategies</string> + <key>stradegy</key> + <string>strategy</string> + <key>strat</key> + <string>start</string> + <key>stratagically</key> + <string>strategically</string> + <key>streemlining</key> + <string>streamlining</string> + <key>stregth</key> + <string>strength</string> + <key>strenghen</key> + <string>strengthen</string> + <key>strenghened</key> + <string>strengthened</string> + <key>strenghening</key> + <string>strengthening</string> + <key>strenght</key> + <string>strength</string> + <key>strenghten</key> + <string>strengthen</string> + <key>strenghtened</key> + <string>strengthened</string> + <key>strenghtening</key> + <string>strengthening</string> + <key>strengtened</key> + <string>strengthened</string> + <key>strenous</key> + <string>strenuous</string> + <key>strictist</key> + <string>strictest</string> + <key>strikely</key> + <string>strikingly</string> + <key>strnad</key> + <string>strand</string> + <key>stroy</key> + <string>story</string> + <key>structual</key> + <string>structural</string> + <key>stubborness</key> + <string>stubbornness</string> + <key>stucture</key> + <string>structure</string> + <key>stuctured</key> + <string>structured</string> + <key>studdy</key> + <string>study</string> + <key>studing</key> + <string>studying</string> + <key>stuggling</key> + <string>struggling</string> + <key>sturcture</key> + <string>structure</string> + <key>subcatagories</key> + <string>subcategories</string> + <key>subcatagory</key> + <string>subcategory</string> + <key>subconsiously</key> + <string>subconsciously</string> + <key>subjudgation</key> + <string>subjugation</string> + <key>submachne</key> + <string>submachine</string> + <key>subpecies</key> + <string>subspecies</string> + <key>subsidary</key> + <string>subsidiary</string> + <key>subsiduary</key> + <string>subsidiary</string> + <key>subsquent</key> + <string>subsequent</string> + <key>subsquently</key> + <string>subsequently</string> + <key>substace</key> + <string>substance</string> + <key>substancial</key> + <string>substantial</string> + <key>substatial</key> + <string>substantial</string> + <key>substituded</key> + <string>substituted</string> + <key>substract</key> + <string>subtract</string> + <key>substracted</key> + <string>subtracted</string> + <key>substracting</key> + <string>subtracting</string> + <key>substraction</key> + <string>subtraction</string> + <key>substracts</key> + <string>subtracts</string> + <key>subtances</key> + <string>substances</string> + <key>subterranian</key> + <string>subterranean</string> + <key>suburburban</key> + <string>suburban</string> + <key>succceeded</key> + <string>succeeded</string> + <key>succcesses</key> + <string>successes</string> + <key>succedded</key> + <string>succeeded</string> + <key>succeded</key> + <string>succeeded</string> + <key>succeds</key> + <string>succeeds</string> + <key>succesful</key> + <string>successful</string> + <key>succesfully</key> + <string>successfully</string> + <key>succesfuly</key> + <string>successfully</string> + <key>succesion</key> + <string>succession</string> + <key>succesive</key> + <string>successive</string> + <key>successfull</key> + <string>successful</string> + <key>successully</key> + <string>successfully</string> + <key>succsess</key> + <string>success</string> + <key>succsessfull</key> + <string>successful</string> + <key>suceed</key> + <string>succeed</string> + <key>suceeded</key> + <string>succeeded</string> + <key>suceeding</key> + <string>succeeding</string> + <key>suceeds</key> + <string>succeeds</string> + <key>sucesful</key> + <string>successful</string> + <key>sucesfully</key> + <string>successfully</string> + <key>sucesfuly</key> + <string>successfully</string> + <key>sucesion</key> + <string>succession</string> + <key>sucess</key> + <string>success</string> + <key>sucesses</key> + <string>successes</string> + <key>sucessful</key> + <string>successful</string> + <key>sucessfull</key> + <string>successful</string> + <key>sucessfully</key> + <string>successfully</string> + <key>sucessfuly</key> + <string>successfully</string> + <key>sucession</key> + <string>succession</string> + <key>sucessive</key> + <string>successive</string> + <key>sucessor</key> + <string>successor</string> + <key>sucessot</key> + <string>successor</string> + <key>sucide</key> + <string>suicide</string> + <key>sucidial</key> + <string>suicidal</string> + <key>sufferage</key> + <string>suffrage</string> + <key>sufferred</key> + <string>suffered</string> + <key>sufferring</key> + <string>suffering</string> + <key>sufficent</key> + <string>sufficient</string> + <key>sufficently</key> + <string>sufficiently</string> + <key>sumary</key> + <string>summary</string> + <key>sunglases</key> + <string>sunglasses</string> + <key>suop</key> + <string>soup</string> + <key>superceeded</key> + <string>superseded</string> + <key>superintendant</key> + <string>superintendent</string> + <key>suphisticated</key> + <string>sophisticated</string> + <key>suplimented</key> + <string>supplemented</string> + <key>supose</key> + <string>suppose</string> + <key>suposed</key> + <string>supposed</string> + <key>suposedly</key> + <string>supposedly</string> + <key>suposes</key> + <string>supposes</string> + <key>suposing</key> + <string>supposing</string> + <key>supplamented</key> + <string>supplemented</string> + <key>suppliementing</key> + <string>supplementing</string> + <key>suppoed</key> + <string>supposed</string> + <key>supposingly</key> + <string>supposedly</string> + <key>suppy</key> + <string>supply</string> + <key>supress</key> + <string>suppress</string> + <key>supressed</key> + <string>suppressed</string> + <key>supresses</key> + <string>suppresses</string> + <key>supressing</key> + <string>suppressing</string> + <key>suprise</key> + <string>surprise</string> + <key>suprised</key> + <string>surprised</string> + <key>suprising</key> + <string>surprising</string> + <key>suprisingly</key> + <string>surprisingly</string> + <key>suprize</key> + <string>surprise</string> + <key>suprized</key> + <string>surprised</string> + <key>suprizing</key> + <string>surprising</string> + <key>suprizingly</key> + <string>surprisingly</string> + <key>surfce</key> + <string>surface</string> + <key>surley</key> + <string>surely</string> + <key>suround</key> + <string>surround</string> + <key>surounded</key> + <string>surrounded</string> + <key>surounding</key> + <string>surrounding</string> + <key>suroundings</key> + <string>surroundings</string> + <key>surounds</key> + <string>surrounds</string> + <key>surplanted</key> + <string>supplanted</string> + <key>surpress</key> + <string>suppress</string> + <key>surpressed</key> + <string>suppressed</string> + <key>surprize</key> + <string>surprise</string> + <key>surprized</key> + <string>surprised</string> + <key>surprizing</key> + <string>surprising</string> + <key>surprizingly</key> + <string>surprisingly</string> + <key>surrended</key> + <string>surrendered</string> + <key>surrepetitious</key> + <string>surreptitious</string> + <key>surrepetitiously</key> + <string>surreptitiously</string> + <key>surreptious</key> + <string>surreptitious</string> + <key>surreptiously</key> + <string>surreptitiously</string> + <key>surronded</key> + <string>surrounded</string> + <key>surrouded</key> + <string>surrounded</string> + <key>surrouding</key> + <string>surrounding</string> + <key>surrundering</key> + <string>surrendering</string> + <key>surveilence</key> + <string>surveillance</string> + <key>surveill</key> + <string>surveil</string> + <key>surveyer</key> + <string>surveyor</string> + <key>surviver</key> + <string>survivor</string> + <key>survivers</key> + <string>survivors</string> + <key>survivied</key> + <string>survived</string> + <key>suseptable</key> + <string>susceptible</string> + <key>suseptible</key> + <string>susceptible</string> + <key>suspention</key> + <string>suspension</string> + <key>swaer</key> + <string>swear</string> + <key>swaers</key> + <string>swears</string> + <key>swepth</key> + <string>swept</string> + <key>swiming</key> + <string>swimming</string> + <key>syas</key> + <string>says</string> + <key>symetrical</key> + <string>symmetrical</string> + <key>symetrically</key> + <string>symmetrically</string> + <key>symetry</key> + <string>symmetry</string> + <key>symettric</key> + <string>symmetric</string> + <key>symmetral</key> + <string>symmetric</string> + <key>symmetricaly</key> + <string>symmetrically</string> + <key>synagouge</key> + <string>synagogue</string> + <key>syncronization</key> + <string>synchronization</string> + <key>synonomous</key> + <string>synonymous</string> + <key>synonymns</key> + <string>synonyms</string> + <key>synphony</key> + <string>symphony</string> + <key>syphyllis</key> + <string>syphilis</string> + <key>sypmtoms</key> + <string>symptoms</string> + <key>syrap</key> + <string>syrup</string> + <key>sysmatically</key> + <string>systematically</string> + <key>sytem</key> + <string>system</string> + <key>sytle</key> + <string>style</string> + <key>tabacco</key> + <string>tobacco</string> + <key>tahn</key> + <string>than</string> + <key>taht</key> + <string>that</string> + <key>talekd</key> + <string>talked</string> + <key>targetted</key> + <string>targeted</string> + <key>targetting</key> + <string>targeting</string> + <key>tast</key> + <string>taste</string> + <key>tath</key> + <string>that</string> + <key>tattooes</key> + <string>tattoos</string> + <key>taxanomic</key> + <string>taxonomic</string> + <key>taxanomy</key> + <string>taxonomy</string> + <key>teached</key> + <string>taught</string> + <key>techician</key> + <string>technician</string> + <key>techicians</key> + <string>technicians</string> + <key>techiniques</key> + <string>techniques</string> + <key>technitian</key> + <string>technician</string> + <key>technnology</key> + <string>technology</string> + <key>technolgy</key> + <string>technology</string> + <key>teh</key> + <string>the</string> + <key>tehy</key> + <string>they</string> + <key>telelevision</key> + <string>television</string> + <key>televsion</key> + <string>television</string> + <key>telphony</key> + <string>telephony</string> + <key>temerature</key> + <string>temperature</string> + <key>tempalte</key> + <string>template</string> + <key>tempaltes</key> + <string>templates</string> + <key>temparate</key> + <string>temperate</string> + <key>temperarily</key> + <string>temporarily</string> + <key>temperment</key> + <string>temperament</string> + <key>tempertaure</key> + <string>temperature</string> + <key>temperture</key> + <string>temperature</string> + <key>temprary</key> + <string>temporary</string> + <key>tenacle</key> + <string>tentacle</string> + <key>tenacles</key> + <string>tentacles</string> + <key>tendacy</key> + <string>tendency</string> + <key>tendancies</key> + <string>tendencies</string> + <key>tendancy</key> + <string>tendency</string> + <key>tennisplayer</key> + <string>tennis player</string> + <key>tepmorarily</key> + <string>temporarily</string> + <key>terrestial</key> + <string>terrestrial</string> + <key>terriories</key> + <string>territories</string> + <key>terriory</key> + <string>territory</string> + <key>territorist</key> + <string>terrorist</string> + <key>territoy</key> + <string>territory</string> + <key>terroist</key> + <string>terrorist</string> + <key>testiclular</key> + <string>testicular</string> + <key>tghe</key> + <string>the</string> + <key>thast</key> + <string>that's</string> + <key>theather</key> + <string>theater</string> + <key>theese</key> + <string>these</string> + <key>theif</key> + <string>thief</string> + <key>theives</key> + <string>thieves</string> + <key>themselfs</key> + <string>themselves</string> + <key>themslves</key> + <string>themselves</string> + <key>ther</key> + <string>there</string> + <key>therafter</key> + <string>thereafter</string> + <key>therby</key> + <string>thereby</string> + <key>theri</key> + <string>their</string> + <key>theyre</key> + <string>they're</string> + <key>thgat</key> + <string>that</string> + <key>thge</key> + <string>the</string> + <key>thier</key> + <string>their</string> + <key>thign</key> + <string>thing</string> + <key>thigns</key> + <string>things</string> + <key>thigsn</key> + <string>things</string> + <key>thikn</key> + <string>think</string> + <key>thikning</key> + <string>thinking</string> + <key>thikns</key> + <string>thinks</string> + <key>thiunk</key> + <string>think</string> + <key>thn</key> + <string>then</string> + <key>thna</key> + <string>than</string> + <key>thne</key> + <string>then</string> + <key>thnig</key> + <string>thing</string> + <key>thnigs</key> + <string>things</string> + <key>thoughout</key> + <string>throughout</string> + <key>threatend</key> + <string>threatened</string> + <key>threatning</key> + <string>threatening</string> + <key>threee</key> + <string>three</string> + <key>threshhold</key> + <string>threshold</string> + <key>thrid</key> + <string>third</string> + <key>throrough</key> + <string>thorough</string> + <key>throughly</key> + <string>thoroughly</string> + <key>throught</key> + <string>throat</string> + <key>througout</key> + <string>throughout</string> + <key>thru</key> + <string>through</string> + <key>thsi</key> + <string>this</string> + <key>thsoe</key> + <string>those</string> + <key>thta</key> + <string>that</string> + <key>thyat</key> + <string>that</string> + <key>tiem</key> + <string>time</string> + <key>tihkn</key> + <string>think</string> + <key>tihs</key> + <string>this</string> + <key>timne</key> + <string>time</string> + <key>tiome</key> + <string>time</string> + <key>tje</key> + <string>the</string> + <key>tjhe</key> + <string>the</string> + <key>tjpanishad</key> + <string>upanishad</string> + <key>tkae</key> + <string>take</string> + <key>tkaes</key> + <string>takes</string> + <key>tkaing</key> + <string>taking</string> + <key>tlaking</key> + <string>talking</string> + <key>tobbaco</key> + <string>tobacco</string> + <key>todays</key> + <string>today's</string> + <key>todya</key> + <string>today</string> + <key>toghether</key> + <string>together</string> + <key>toke</key> + <string>took</string> + <key>tolerence</key> + <string>tolerance</string> + <key>tomatos</key> + <string>tomatoes</string> + <key>tommorow</key> + <string>tomorrow</string> + <key>tommorrow</key> + <string>tomorrow</string> + <key>tongiht</key> + <string>tonight</string> + <key>toriodal</key> + <string>toroidal</string> + <key>tormenters</key> + <string>tormentors</string> + <key>tornadoe</key> + <string>tornado</string> + <key>torpeados</key> + <string>torpedoes</string> + <key>torpedos</key> + <string>torpedoes</string> + <key>tothe</key> + <string>to the</string> + <key>toubles</key> + <string>troubles</string> + <key>tounge</key> + <string>tongue</string> + <key>tourch</key> + <string>torch</string> + <key>towords</key> + <string>towards</string> + <key>towrad</key> + <string>toward</string> + <key>tradionally</key> + <string>traditionally</string> + <key>traditionaly</key> + <string>traditionally</string> + <key>traditionnal</key> + <string>traditional</string> + <key>traditition</key> + <string>tradition</string> + <key>tradtionally</key> + <string>traditionally</string> + <key>trafficed</key> + <string>trafficked</string> + <key>trafficing</key> + <string>trafficking</string> + <key>trafic</key> + <string>traffic</string> + <key>trancendent</key> + <string>transcendent</string> + <key>trancending</key> + <string>transcending</string> + <key>tranform</key> + <string>transform</string> + <key>tranformed</key> + <string>transformed</string> + <key>transcendance</key> + <string>transcendence</string> + <key>transcendant</key> + <string>transcendent</string> + <key>transcendentational</key> + <string>transcendental</string> + <key>transcripting</key> + <string>transcribing</string> + <key>transending</key> + <string>transcending</string> + <key>transesxuals</key> + <string>transsexuals</string> + <key>transfered</key> + <string>transferred</string> + <key>transfering</key> + <string>transferring</string> + <key>transformaton</key> + <string>transformation</string> + <key>transistion</key> + <string>transition</string> + <key>translater</key> + <string>translator</string> + <key>translaters</key> + <string>translators</string> + <key>transmissable</key> + <string>transmissible</string> + <key>transporation</key> + <string>transportation</string> + <key>tremelo</key> + <string>tremolo</string> + <key>tremelos</key> + <string>tremolos</string> + <key>triguered</key> + <string>triggered</string> + <key>triology</key> + <string>trilogy</string> + <key>troling</key> + <string>trolling</string> + <key>troup</key> + <string>troupe</string> + <key>troups</key> + <string>troops</string> + <key>truely</key> + <string>truly</string> + <key>trustworthyness</key> + <string>trustworthiness</string> + <key>turnk</key> + <string>trunk</string> + <key>tust</key> + <string>trust</string> + <key>twelth</key> + <string>twelfth</string> + <key>twon</key> + <string>town</string> + <key>twpo</key> + <string>two</string> + <key>tyhat</key> + <string>that</string> + <key>tyhe</key> + <string>they</string> + <key>typcial</key> + <string>typical</string> + <key>typicaly</key> + <string>typically</string> + <key>tyranies</key> + <string>tyrannies</string> + <key>tyrany</key> + <string>tyranny</string> + <key>tyrranies</key> + <string>tyrannies</string> + <key>tyrrany</key> + <string>tyranny</string> + <key>ubiquitious</key> + <string>ubiquitous</string> + <key>ublisher</key> + <string>publisher</string> + <key>uise</key> + <string>use</string> + <key>ultimely</key> + <string>ultimately</string> + <key>unacompanied</key> + <string>unaccompanied</string> + <key>unahppy</key> + <string>unhappy</string> + <key>unanymous</key> + <string>unanimous</string> + <key>unathorised</key> + <string>unauthorised</string> + <key>unavailible</key> + <string>unavailable</string> + <key>unballance</key> + <string>unbalance</string> + <key>unbeknowst</key> + <string>unbeknownst</string> + <key>unbeleivable</key> + <string>unbelievable</string> + <key>uncertainity</key> + <string>uncertainty</string> + <key>unchallengable</key> + <string>unchallengeable</string> + <key>unchangable</key> + <string>unchangeable</string> + <key>uncompetive</key> + <string>uncompetitive</string> + <key>unconcious</key> + <string>unconscious</string> + <key>unconciousness</key> + <string>unconsciousness</string> + <key>unconfortability</key> + <string>discomfort</string> + <key>uncontitutional</key> + <string>unconstitutional</string> + <key>unconvential</key> + <string>unconventional</string> + <key>undecideable</key> + <string>undecidable</string> + <key>understoon</key> + <string>understood</string> + <key>undesireable</key> + <string>undesirable</string> + <key>undetecable</key> + <string>undetectable</string> + <key>undoubtely</key> + <string>undoubtedly</string> + <key>undreground</key> + <string>underground</string> + <key>uneccesary</key> + <string>unnecessary</string> + <key>unecessary</key> + <string>unnecessary</string> + <key>unequalities</key> + <string>inequalities</string> + <key>unforetunately</key> + <string>unfortunately</string> + <key>unforgetable</key> + <string>unforgettable</string> + <key>unforgiveable</key> + <string>unforgivable</string> + <key>unfortunatley</key> + <string>unfortunately</string> + <key>unfortunatly</key> + <string>unfortunately</string> + <key>unfourtunately</key> + <string>unfortunately</string> + <key>unihabited</key> + <string>uninhabited</string> + <key>unilateraly</key> + <string>unilaterally</string> + <key>unilatreal</key> + <string>unilateral</string> + <key>unilatreally</key> + <string>unilaterally</string> + <key>uninterruped</key> + <string>uninterrupted</string> + <key>uninterupted</key> + <string>uninterrupted</string> + <key>univeral</key> + <string>universal</string> + <key>univeristies</key> + <string>universities</string> + <key>univeristy</key> + <string>university</string> + <key>univerity</key> + <string>university</string> + <key>universtiy</key> + <string>university</string> + <key>univesities</key> + <string>universities</string> + <key>univesity</key> + <string>university</string> + <key>unkown</key> + <string>unknown</string> + <key>unlikey</key> + <string>unlikely</string> + <key>unmanouverable</key> + <string>unmaneuverable</string> + <key>unmistakeably</key> + <string>unmistakably</string> + <key>unneccesarily</key> + <string>unnecessarily</string> + <key>unneccesary</key> + <string>unnecessary</string> + <key>unneccessarily</key> + <string>unnecessarily</string> + <key>unneccessary</key> + <string>unnecessary</string> + <key>unnecesarily</key> + <string>unnecessarily</string> + <key>unnecesary</key> + <string>unnecessary</string> + <key>unoffical</key> + <string>unofficial</string> + <key>unoperational</key> + <string>nonoperational</string> + <key>unoticeable</key> + <string>unnoticeable</string> + <key>unplease</key> + <string>displease</string> + <key>unplesant</key> + <string>unpleasant</string> + <key>unprecendented</key> + <string>unprecedented</string> + <key>unprecidented</key> + <string>unprecedented</string> + <key>unrepentent</key> + <string>unrepentant</string> + <key>unrepetant</key> + <string>unrepentant</string> + <key>unrepetent</key> + <string>unrepentant</string> + <key>unsed</key> + <string>unused</string> + <key>unsubstanciated</key> + <string>unsubstantiated</string> + <key>unsuccesful</key> + <string>unsuccessful</string> + <key>unsuccesfully</key> + <string>unsuccessfully</string> + <key>unsuccessfull</key> + <string>unsuccessful</string> + <key>unsucesful</key> + <string>unsuccessful</string> + <key>unsucesfuly</key> + <string>unsuccessfully</string> + <key>unsucessful</key> + <string>unsuccessful</string> + <key>unsucessfull</key> + <string>unsuccessful</string> + <key>unsucessfully</key> + <string>unsuccessfully</string> + <key>unsuprised</key> + <string>unsurprised</string> + <key>unsuprising</key> + <string>unsurprising</string> + <key>unsuprisingly</key> + <string>unsurprisingly</string> + <key>unsuprized</key> + <string>unsurprised</string> + <key>unsuprizing</key> + <string>unsurprising</string> + <key>unsuprizingly</key> + <string>unsurprisingly</string> + <key>unsurprized</key> + <string>unsurprised</string> + <key>unsurprizing</key> + <string>unsurprising</string> + <key>unsurprizingly</key> + <string>unsurprisingly</string> + <key>untill</key> + <string>until</string> + <key>untranslateable</key> + <string>untranslatable</string> + <key>unuseable</key> + <string>unusable</string> + <key>unusuable</key> + <string>unusable</string> + <key>unviersity</key> + <string>university</string> + <key>unwarrented</key> + <string>unwarranted</string> + <key>unweildly</key> + <string>unwieldy</string> + <key>unwieldly</key> + <string>unwieldy</string> + <key>upcomming</key> + <string>upcoming</string> + <key>upgradded</key> + <string>upgraded</string> + <key>upto</key> + <string>up to</string> + <key>usally</key> + <string>usually</string> + <key>useage</key> + <string>usage</string> + <key>usefull</key> + <string>useful</string> + <key>usefuly</key> + <string>usefully</string> + <key>useing</key> + <string>using</string> + <key>usualy</key> + <string>usually</string> + <key>ususally</key> + <string>usually</string> + <key>vaccum</key> + <string>vacuum</string> + <key>vaccume</key> + <string>vacuum</string> + <key>vacinity</key> + <string>vicinity</string> + <key>vaguaries</key> + <string>vagaries</string> + <key>vaieties</key> + <string>varieties</string> + <key>vailidty</key> + <string>validity</string> + <key>valetta</key> + <string>valletta</string> + <key>valuble</key> + <string>valuable</string> + <key>valueable</key> + <string>valuable</string> + <key>varations</key> + <string>variations</string> + <key>varient</key> + <string>variant</string> + <key>variey</key> + <string>variety</string> + <key>varing</key> + <string>varying</string> + <key>varities</key> + <string>varieties</string> + <key>varity</key> + <string>variety</string> + <key>vasall</key> + <string>vassal</string> + <key>vasalls</key> + <string>vassals</string> + <key>vegatarian</key> + <string>vegetarian</string> + <key>vegitable</key> + <string>vegetable</string> + <key>vegitables</key> + <string>vegetables</string> + <key>vegtable</key> + <string>vegetable</string> + <key>vehicule</key> + <string>vehicle</string> + <key>vell</key> + <string>well</string> + <key>venemous</key> + <string>venomous</string> + <key>vengance</key> + <string>vengeance</string> + <key>vengence</key> + <string>vengeance</string> + <key>verfication</key> + <string>verification</string> + <key>verison</key> + <string>version</string> + <key>verisons</key> + <string>versions</string> + <key>vermillion</key> + <string>vermilion</string> + <key>versitilaty</key> + <string>versatility</string> + <key>versitlity</key> + <string>versatility</string> + <key>vetween</key> + <string>between</string> + <key>veyr</key> + <string>very</string> + <key>vigeur</key> + <string>vigor</string> + <key>vigilence</key> + <string>vigilance</string> + <key>vigourous</key> + <string>vigorous</string> + <key>villian</key> + <string>villain</string> + <key>villification</key> + <string>vilification</string> + <key>villify</key> + <string>vilify</string> + <key>villin</key> + <string>villain</string> + <key>vincinity</key> + <string>vicinity</string> + <key>violentce</key> + <string>violence</string> + <key>virtualy</key> + <string>virtually</string> + <key>virutal</key> + <string>virtual</string> + <key>virutally</key> + <string>virtually</string> + <key>visable</key> + <string>visible</string> + <key>visably</key> + <string>visibly</string> + <key>visting</key> + <string>visiting</string> + <key>vistors</key> + <string>visitors</string> + <key>vitories</key> + <string>victories</string> + <key>volcanoe</key> + <string>volcano</string> + <key>voleyball</key> + <string>volleyball</string> + <key>volontary</key> + <string>voluntary</string> + <key>volonteer</key> + <string>volunteer</string> + <key>volonteered</key> + <string>volunteered</string> + <key>volonteering</key> + <string>volunteering</string> + <key>volonteers</key> + <string>volunteers</string> + <key>volounteer</key> + <string>volunteer</string> + <key>volounteered</key> + <string>volunteered</string> + <key>volounteering</key> + <string>volunteering</string> + <key>volounteers</key> + <string>volunteers</string> + <key>volumne</key> + <string>volume</string> + <key>vreity</key> + <string>variety</string> + <key>vrey</key> + <string>very</string> + <key>vriety</key> + <string>variety</string> + <key>vulnerablility</key> + <string>vulnerability</string> + <key>vyer</key> + <string>very</string> + <key>vyre</key> + <string>very</string> + <key>waht</key> + <string>what</string> + <key>wanna</key> + <string>want to</string> + <key>warantee</key> + <string>warranty</string> + <key>wardobe</key> + <string>wardrobe</string> + <key>warrent</key> + <string>warrant</string> + <key>warrriors</key> + <string>warriors</string> + <key>wasnt</key> + <string>wasn't</string> + <key>wass</key> + <string>was</string> + <key>watn</key> + <string>want</string> + <key>wayword</key> + <string>wayward</string> + <key>weaponary</key> + <string>weaponry</string> + <key>weas</key> + <string>was</string> + <key>wehn</key> + <string>when</string> + <key>weild</key> + <string>wield</string> + <key>weilded</key> + <string>wielded</string> + <key>wendsay</key> + <string>Wednesday</string> + <key>wensday</key> + <string>Wednesday</string> + <key>wereabouts</key> + <string>whereabouts</string> + <key>whant</key> + <string>want</string> + <key>whants</key> + <string>wants</string> + <key>whcih</key> + <string>which</string> + <key>wheras</key> + <string>whereas</string> + <key>wherease</key> + <string>whereas</string> + <key>whereever</key> + <string>wherever</string> + <key>whic</key> + <string>which</string> + <key>whihc</key> + <string>which</string> + <key>whith</key> + <string>with</string> + <key>whlch</key> + <string>which</string> + <key>whn</key> + <string>when</string> + <key>wholey</key> + <string>wholly</string> + <key>wholy</key> + <string>holy</string> + <key>whta</key> + <string>what</string> + <key>whther</key> + <string>whether</string> + <key>wich</key> + <string>which</string> + <key>widesread</key> + <string>widespread</string> + <key>wief</key> + <string>wife</string> + <key>wierd</key> + <string>weird</string> + <key>wiew</key> + <string>view</string> + <key>wih</key> + <string>with</string> + <key>wiht</key> + <string>with</string> + <key>wille</key> + <string>will</string> + <key>willingless</key> + <string>willingness</string> + <key>wirting</key> + <string>writing</string> + <key>withdrawl</key> + <string>withdrawal</string> + <key>witheld</key> + <string>withheld</string> + <key>withh</key> + <string>with</string> + <key>withing</key> + <string>within</string> + <key>withold</key> + <string>withhold</string> + <key>witht</key> + <string>with</string> + <key>witn</key> + <string>with</string> + <key>wiull</key> + <string>will</string> + <key>wnat</key> + <string>want</string> + <key>wnated</key> + <string>wanted</string> + <key>wnats</key> + <string>wants</string> + <key>wohle</key> + <string>whole</string> + <key>wokr</key> + <string>work</string> + <key>wokring</key> + <string>working</string> + <key>wonderfull</key> + <string>wonderful</string> + <key>wont</key> + <string>won't</string> + <key>wordlwide</key> + <string>worldwide</string> + <key>workststion</key> + <string>workstation</string> + <key>worls</key> + <string>world</string> + <key>worstened</key> + <string>worsened</string> + <key>woudl</key> + <string>would</string> + <key>wresters</key> + <string>wrestlers</string> + <key>wriet</key> + <string>write</string> + <key>writen</key> + <string>written</string> + <key>wroet</key> + <string>wrote</string> + <key>wrok</key> + <string>work</string> + <key>wroking</key> + <string>working</string> + <key>wtih</key> + <string>with</string> + <key>wupport</key> + <string>support</string> + <key>xenophoby</key> + <string>xenophobia</string> + <key>yaching</key> + <string>yachting</string> + <key>yaer</key> + <string>year</string> + <key>yaerly</key> + <string>yearly</string> + <key>yaers</key> + <string>years</string> + <key>yatch</key> + <string>yacht</string> + <key>yearm</key> + <string>year</string> + <key>yeasr</key> + <string>years</string> + <key>yeild</key> + <string>yield</string> + <key>yeilding</key> + <string>yielding</string> + <key>yera</key> + <string>year</string> + <key>yeras</key> + <string>years</string> + <key>yersa</key> + <string>years</string> + <key>yotube</key> + <string>YouTube</string> + <key>youre</key> + <string>you're</string> + <key>youseff</key> + <string>yousef</string> + <key>youself</key> + <string>yourself</string> + <key>ytou</key> + <string>you</string> + <key>yuo</key> + <string>you</string> + <key>zeebra</key> + <string>zebra</string> + </map> + </map> + </array> +</llsd> diff --git a/indra/newview/app_settings/cmd_line.xml b/indra/newview/app_settings/cmd_line.xml index 15434f2b8f..be79f91919 100644 --- a/indra/newview/app_settings/cmd_line.xml +++ b/indra/newview/app_settings/cmd_line.xml @@ -1,45 +1,101 @@ <?xml version="1.0"?> <llsd> <map> - <key>help</key> + <!-- Please insert new keys in alphabetical order. --> + <key>analyzeperformance</key> <map> <key>desc</key> - <string>display this help message</string> + <string>When used in conjunction with logperformance, analyzes result of log against baseline.</string> + <key>map-to</key> + <string>AnalyzePerformance</string> + </map> - <key>short</key> - <string>h</string> + <key>autologin</key> + <map> + <key>desc</key> + <string>log in as last saved user</string> + <key>map-to</key> + <string>AutoLogin</string> </map> - <key>port</key> + <key>channel</key> <map> <key>count</key> <integer>1</integer> - <key>map-to</key> - <string>UserConnectionPort</string> + <!-- Special case. Not mapped to a setting. --> </map> - <key>drop</key> + <key>console</key> <map> <key>count</key> <integer>1</integer> <key>map-to</key> - <string>PacketDropPercentage</string> + <string>ShowConsoleWindow</string> </map> - <key>inbw</key> + <key>cooperative</key> <map> + <key>desc</key> + <string>Yield some idle time to local host.</string> <key>count</key> <integer>1</integer> <key>map-to</key> - <string>InBandwidth</string> + <string>YieldTime</string> </map> - <key>outbw</key> + <key>crashonstartup</key> + <map> + <key>desc</key> + <string>Crashes on startup. For QA use.</string> + <key>map-to</key> + <string>CrashOnStartup</string> + </map> + + <key>debugsession</key> + <map> + <key>desc</key> + <string>Run as if RenderDebugGL is TRUE, but log errors until end of session.</string> + <key>map-to</key> + <string>DebugSession</string> + </map> + + <key>debugviews</key> + <map> + <key>map-to</key> + <string>DebugViews</string> + </map> + + <key>disablecrashlogger</key> + <map> + <key>desc</key> + <string>Disables the crash logger and lets the OS handle crashes</string> + <key>map-to</key> + <string>DisableCrashLogger</string> + </map> + + <key>drop</key> <map> <key>count</key> <integer>1</integer> <key>map-to</key> - <string>OutBandwidth</string> + <string>PacketDropPercentage</string> + </map> + + <key>god</key> + <map> + <key>desc</key> + <string>Log in a god if you have god access.</string> + <key>map-to</key> + <string>ConnectAsGod</string> + </map> + + <key>graphicslevel</key> + <map> + <key>desc</key> + <string>Set the detail level. +0 - low, 1 - medium, 2 - high, 3 - ultra</string> + <key>count</key> + <integer>1</integer> </map> <key>grid</key> @@ -52,16 +108,13 @@ <string>CmdLineGridChoice</string> </map> - <key>loginuri</key> + <key>help</key> <map> <key>desc</key> - <string>login server and CGI script to use</string> - <key>count</key> - <integer>1</integer> - <key>compose</key> - <boolean>true</boolean> - <key>map-to</key> - <string>CmdLineLoginURI</string> + <string>display this help message</string> + + <key>short</key> + <string>h</string> </map> <key>helperuri</key> @@ -74,44 +127,73 @@ <string>CmdLineHelperURI</string> </map> - <key>debugviews</key> + <key>ignorepixeldepth</key> <map> + <key>desc</key> + <string>Ignore pixel depth settings.</string> <key>map-to</key> - <string>DebugViews</string> + <string>IgnorePixelDepth</string> </map> - <key>skin</key> + <key>inbw</key> + <map> + <key>count</key> + <integer>1</integer> + <key>map-to</key> + <string>InBandwidth</string> + </map> + + <key>leap</key> <map> <key>desc</key> - <string>ui/branding skin folder to use</string> + <string>command line to run an LLSD Event API Plugin</string> <key>count</key> <integer>1</integer> + <!-- you can specify multiple such plugins --> + <key>compose</key> + <boolean>true</boolean> <key>map-to</key> - <string>SkinFolder</string> + <string>LeapCommand</string> </map> - <key>autologin</key> + <key>logfile</key> + <map> + <key>count</key> + <integer>1</integer> + <key>map-to</key> + <string>UserLogFile</string> + </map> + + <key>login</key> <map> <key>desc</key> - <string>log in as last saved user</string> + <string>3 tokens: first, last and password</string> + <key>count</key> + <integer>3</integer> <key>map-to</key> - <string>AutoLogin</string> + <string>UserLoginInfo</string> </map> - <key>quitafter</key> + <key>loginpage</key> <map> + <key>desc</key> + <string>Login authentication page to use.</string> <key>count</key> <integer>1</integer> <key>map-to</key> - <string>QuitAfterSeconds</string> + <string>LoginPage</string> </map> - <key>logperformance</key> + <key>loginuri</key> <map> <key>desc</key> - <string>Log performance metrics for benchmarking</string> + <string>login server and CGI script to use</string> + <key>count</key> + <integer>1</integer> + <key>compose</key> + <boolean>true</boolean> <key>map-to</key> - <string>LogPerformance</string> + <string>CmdLineLoginURI</string> </map> <key>logmetrics</key> @@ -123,29 +205,35 @@ <key>map-to</key> <string>LogMetrics</string> </map> - - <key>analyzeperformance</key> + + <key>logperformance</key> <map> <key>desc</key> - <string>When used in conjunction with logperformance, analyzes result of log against baseline.</string> + <string>Log performance metrics for benchmarking</string> <key>map-to</key> - <string>AnalyzePerformance</string> + <string>LogPerformance</string> </map> - <key>debugsession</key> + <key>multiple</key> <map> <key>desc</key> - <string>Run as if RenderDebugGL is TRUE, but log errors until end of session.</string> + <string>Allow multiple viewers.</string> <key>map-to</key> - <string>DebugSession</string> + <string>AllowMultipleViewers</string> </map> - <key>replaysession</key> + <key>noaudio</key> + <map> + <key>map-to</key> + <string>NoAudio</string> + </map> + + <key>noinvlib</key> <map> <key>desc</key> - <string>After login, replay last recorded session and quit.</string> + <string>Do not request the inventory library.</string> <key>map-to</key> - <string>ReplaySession</string> + <string>NoInventoryLibrary</string> </map> <key>nonotifications</key> @@ -156,22 +244,10 @@ <string>IgnoreAllNotifications</string> </map> - <key>rotate</key> - <map> - <key>map-to</key> - <string>RotateRight</string> - </map> - - <key>noaudio</key> - <map> - <key>map-to</key> - <string>NoAudio</string> - </map> - - <key>nosound</key> + <key>nopreload</key> <map> <key>map-to</key> - <string>NoAudio</string> + <string>NoPreload</string> </map> <key>noprobe</key> @@ -186,151 +262,134 @@ <string>NoQuickTime</string> </map> - <key>nopreload</key> + <key>nosound</key> <map> <key>map-to</key> - <string>NoPreload</string> + <string>NoAudio</string> </map> - <key>purge</key> + <key>no-verify-ssl-cert</key> <map> - <key>desc</key> - <string>Delete files in the cache.</string> <key>map-to</key> - <string>PurgeCacheOnNextStartup</string> + <string>NoVerifySSLCert</string> </map> - <key>noinvlib</key> + <key>novoice</key> <map> <key>desc</key> - <string>Do not request the inventory library.</string> + <string>Disable voice.</string> <key>map-to</key> - <string>NoInventoryLibrary</string> + <string>CmdLineDisableVoice</string> </map> - <key>logfile</key> + <key>outbw</key> <map> <key>count</key> <integer>1</integer> <key>map-to</key> - <string>UserLogFile</string> + <string>OutBandwidth</string> </map> - <key>graphicslevel</key> + <key>port</key> <map> - <key>desc</key> - <string>Set the detail level. -0 - low, 1 - medium, 2 - high, 3 - ultra</string> <key>count</key> <integer>1</integer> + <key>map-to</key> + <string>UserConnectionPort</string> </map> - <key>setdefault</key> + <key>purge</key> <map> <key>desc</key> - <string>specify the value of a particular configuration variable which can be overridden by settings.xml.</string> - <key>count</key> - <integer>2</integer> - <!-- Special case. Mapped to settings procedurally. --> + <string>Delete files in the cache.</string> + <key>map-to</key> + <string>PurgeCacheOnNextStartup</string> </map> - <key>set</key> + <key>qa</key> <map> <key>desc</key> - <string>specify the value of a particular configuration variable that overrides all other settings.</string> - <key>count</key> - <integer>2</integer> - <key>compose</key> - <boolean>true</boolean> - <!-- Special case. Mapped to settings procedurally. --> + <string>Activated debugging menu in Advanced Settings.</string> + <key>map-to</key> + <string>QAMode</string> </map> - <key>settings</key> + <key>quitafter</key> <map> - <key>desc</key> - <string>Specify the filename of a configuration file.</string> <key>count</key> <integer>1</integer> - <!-- Special case. Mapped to settings procedurally. --> + <key>map-to</key> + <string>QuitAfterSeconds</string> </map> - - <key>sessionsettings</key> + + <key>replaysession</key> <map> <key>desc</key> - <string>Specify the filename of a configuration file that contains temporary per-session configuration overrides.</string> - <key>count</key> - <integer>1</integer> - <!-- Special case. Mapped to settings procedurally. --> + <string>After login, replay last recorded session and quit.</string> + <key>map-to</key> + <string>ReplaySession</string> </map> - <key>usersessionsettings</key> - <map> - <key>desc</key> - <string>Specify the filename of a configuration file that contains temporary per-session configuration user overrides.</string> - <key>count</key> - <integer>1</integer> - <!-- Special case. Mapped to settings procedurally. --> - </map> - - <key>login</key> + <key>rotate</key> <map> - <key>desc</key> - <string>3 tokens: first, last and password</string> - <key>count</key> - <integer>3</integer> <key>map-to</key> - <string>UserLoginInfo</string> + <string>RotateRight</string> </map> - <key>god</key> + <key>safe</key> <map> <key>desc</key> - <string>Log in a god if you have god access.</string> + <string>Reset preferences, run in safe mode.</string> <key>map-to</key> - <string>ConnectAsGod</string> + <string>SafeMode</string> </map> - <key>console</key> + <key>sessionsettings</key> <map> + <key>desc</key> + <string>Specify the filename of a configuration file that contains temporary per-session configuration overrides.</string> <key>count</key> <integer>1</integer> - <key>map-to</key> - <string>ShowConsoleWindow</string> + <!-- Special case. Mapped to settings procedurally. --> </map> - <key>safe</key> + <key>set</key> <map> <key>desc</key> - <string>Reset preferences, run in safe mode.</string> - <key>map-to</key> - <string>SafeMode</string> + <string>specify the value of a particular configuration variable that overrides all other settings.</string> + <key>count</key> + <integer>2</integer> + <key>compose</key> + <boolean>true</boolean> + <!-- Special case. Mapped to settings procedurally. --> </map> - <key>multiple</key> + <key>setdefault</key> <map> <key>desc</key> - <string>Allow multiple viewers.</string> - <key>map-to</key> - <string>AllowMultipleViewers</string> + <string>specify the value of a particular configuration variable which can be overridden by settings.xml.</string> + <key>count</key> + <integer>2</integer> + <!-- Special case. Mapped to settings procedurally. --> </map> - <key>novoice</key> + <key>settings</key> <map> <key>desc</key> - <string>Disable voice.</string> - <key>map-to</key> - <string>CmdLineDisableVoice</string> + <string>Specify the filename of a configuration file.</string> + <key>count</key> + <integer>1</integer> + <!-- Special case. Mapped to settings procedurally. --> </map> - <key>url</key> + <key>skin</key> <map> <key>desc</key> - <string>Startup location</string> + <string>ui/branding skin folder to use</string> <key>count</key> <integer>1</integer> - <key>last_option</key> - <boolean>true</boolean> - <!-- Special case. Not mapped to a setting. --> + <key>map-to</key> + <string>SkinFolder</string> </map> <key>slurl</key> @@ -346,69 +405,24 @@ <!-- Special case. Not mapped to a setting. --> </map> - <key>ignorepixeldepth</key> - <map> - <key>desc</key> - <string>Ignore pixel depth settings.</string> - <key>map-to</key> - <string>IgnorePixelDepth</string> - </map> - - <key>cooperative</key> + <key>url</key> <map> <key>desc</key> - <string>Yield some idle time to local host.</string> - <key>count</key> - <integer>1</integer> - <key>map-to</key> - <string>YieldTime</string> - </map> - - <key>no-verify-ssl-cert</key> - <map> - <key>map-to</key> - <string>NoVerifySSLCert</string> - </map> - - <key>channel</key> - <map> + <string>Startup location</string> <key>count</key> <integer>1</integer> + <key>last_option</key> + <boolean>true</boolean> <!-- Special case. Not mapped to a setting. --> </map> - <key>loginpage</key> + <key>usersessionsettings</key> <map> <key>desc</key> - <string>Login authentication page to use.</string> + <string>Specify the filename of a configuration file that contains temporary per-session configuration user overrides.</string> <key>count</key> <integer>1</integer> - <key>map-to</key> - <string>LoginPage</string> - </map> - - <key>qa</key> - <map> - <key>desc</key> - <string>Activated debugging menu in Advanced Settings.</string> - <key>map-to</key> - <string>QAMode</string> - </map> - - <key>crashonstartup</key> - <map> - <key>desc</key> - <string>Crashes on startup. For QA use.</string> - <key>map-to</key> - <string>CrashOnStartup</string> - </map> - - <key>disablecrashlogger</key> - <map> - <key>desc</key> - <string>Disables the crash logger and lets the OS handle crashes</string> - <key>map-to</key> - <string>DisableCrashLogger</string> + <!-- Special case. Mapped to settings procedurally. --> </map> </map> </llsd> diff --git a/indra/newview/app_settings/logcontrol.xml b/indra/newview/app_settings/logcontrol.xml index a76eb3cd37..64122bbb6c 100644 --- a/indra/newview/app_settings/logcontrol.xml +++ b/indra/newview/app_settings/logcontrol.xml @@ -20,7 +20,7 @@ <key>tags</key> <array> <string>AppInit</string> - <string>Capabilities</string> + <string>Capabilities</string> <string>SystemInfo</string> <string>TextureCache</string> <string>AppCache</string> @@ -42,8 +42,10 @@ </array> <key>tags</key> <array> - <!-- sample entry for debugging a specific item --> -<!-- <string>Voice</string> --> + <!-- sample entry for debugging specific items + <string>Avatar</string> + <string>Voice</string> + --> </array> </map> </array> diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index da3ff2d1ee..325cb1f583 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -170,7 +170,7 @@ <key>Value</key> <integer>1</integer> </map> - <key>ApplyTextureImmediately</key> + <key>TextureLivePreview</key> <map> <key>Comment</key> <string>Preview selections in texture picker immediately</string> @@ -357,17 +357,17 @@ <key>Value</key> <integer>1</integer> </map> - <key>AuditTexture</key> - <map> - <key>Comment</key> - <string>Enable texture auditting.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>0</integer> - </map> + <key>AutoReplace</key> + <map> + <key>Comment</key> + <string>Replaces keywords with a configured word or phrase</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> <key>AutoAcceptNewInventory</key> <map> <key>Comment</key> @@ -1958,7 +1958,7 @@ <key>Type</key> <string>Boolean</string> <key>Value</key> - <integer>0</integer> + <integer>1</integer> </map> <key>DebugBeaconLineWidth</key> <map> @@ -4326,6 +4326,17 @@ <key>Value</key> <integer>0</integer> </map> + <key>InventoryInboxToggleState</key> + <map> + <key>Comment</key> + <string>Stores the open/closed state of inventory Received items panel</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> <key>InventoryLinking</key> <map> <key>Comment</key> @@ -4623,6 +4634,17 @@ <key>Value</key> <integer>0</integer> </map> + <key>LeapCommand</key> + <map> + <key>Comment</key> + <string>Zero or more command lines to run LLSD Event API Plugin programs.</string> + <key>Persist</key> + <integer>0</integer> + <key>Type</key> + <string>LLSD</string> + <key>Value</key> + <array /> + </map> <key>LSLFindCaseInsensitivity</key> <map> <key>Comment</key> @@ -6378,17 +6400,6 @@ <key>Value</key> <integer>0</integer> </map> - <key>NumpadControl</key> - <map> - <key>Comment</key> - <string>How numpad keys control your avatar. 0 = Like the normal arrow keys, 1 = Numpad moves avatar when numlock is off, 2 = Numpad moves avatar regardless of numlock (use this if you have no numlock)</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>0</integer> - </map> <key>ObjectCacheEnabled</key> <map> <key>Comment</key> @@ -7186,7 +7197,7 @@ <key>QAModeEventHostPort</key> <map> <key>Comment</key> - <string>Port on which lleventhost should listen</string> + <string>DEPRECATED: Port on which lleventhost should listen</string> <key>Persist</key> <integer>0</integer> <key>Type</key> @@ -7205,6 +7216,17 @@ <key>Value</key> <integer>-1</integer> </map> + <key>QAModeMetrics</key> + <map> + <key>Comment</key> + <string>"Enables QA features (logging, faster cycling) for metrics collector"</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> <key>QuietSnapshotsToDisk</key> <map> <key>Comment</key> @@ -7285,7 +7307,7 @@ <key>WebContentWindowLimit</key> <map> <key>Comment</key> - <string>Maximum number of web brower windows that can be open at once in the Web content floater (0 for no limit)</string> + <string>Maximum number of web browser windows that can be open at once in the Web content floater (0 for no limit)</string> <key>Persist</key> <integer>1</integer> <key>Type</key> @@ -7653,6 +7675,17 @@ <key>Value</key> <integer>1</integer> </map> + <key>RenderCompressTextures</key> + <map> + <key>Comment</key> + <string>Enable texture compression on OpenGL 3.0 and later implementations (EXPERIMENTAL, requires restart)</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> <key>RenderPerformanceTest</key> <map> <key>Comment</key> @@ -8093,6 +8126,18 @@ <real>0</real> </map> + <key>RenderDepthPrePass</key> + <map> + <key>Comment</key> + <string>EXPERIMENTAL: Prime the depth buffer with simple prim geometry before rendering with textures.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>RenderDepthOfField</key> <map> <key>Comment</key> @@ -9145,28 +9190,19 @@ <key>Value</key> <integer>0</integer> </map> - <key>RenderUseShaderLOD</key> - <map> - <key>Comment</key> - <string>Whether we want to have different shaders for LOD</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>1</integer> - </map> - <key>RenderUseShaderNearParticles</key> - <map> - <key>Comment</key> - <string>Whether we want to use shaders on near particles</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>0</integer> - </map> + + <key>RenderAutoHideSurfaceAreaLimit</key> + <map> + <key>Comment</key> + <string>Maximum surface area of a set of proximal objects inworld before automatically hiding geometry to prevent system overload.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>RenderVBOEnable</key> <map> <key>Comment</key> @@ -9181,7 +9217,7 @@ <key>RenderUseVAO</key> <map> <key>Comment</key> - <string>Use GL Vertex Array Objects</string> + <string>[EXPERIMENTAL] Use GL Vertex Array Objects</string> <key>Persist</key> <integer>1</integer> <key>Type</key> @@ -9189,7 +9225,19 @@ <key>Value</key> <integer>0</integer> </map> - <key>RenderVBOMappingDisable</key> + <key>RenderUseTransformFeedback</key> + <map> + <key>Comment</key> + <string>[EXPERIMENTAL] Use transform feedback shaders for LoD updates</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + + <key>RenderVBOMappingDisable</key> <map> <key>Comment</key> <string>Disable VBO glMapBufferARB</string> @@ -10697,6 +10745,39 @@ <key>Value</key> <real>20.0</real> </map> + <key>TexelPixelRatio</key> + <map> + <key>Comment</key> + <string>texel pixel ratio = texel / pixel</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>1.0</real> + </map> + <key>TextureCameraMotionThreshold</key> + <map> + <key>Comment</key> + <string>If the overall motion is lower than this value, textures will be loaded faster</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>0.2</real> + </map> + <key>TextureCameraMotionBoost</key> + <map> + <key>Comment</key> + <string>Progressive discard level decrement when the camera is still</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>S32</string> + <key>Value</key> + <integer>3</integer> + </map> <key>TextureDecodeDisabled</key> <map> <key>Comment</key> @@ -10730,6 +10811,17 @@ <key>Value</key> <integer>0</integer> </map> + <key>TextureFetchDebuggerEnabled</key> + <map> + <key>Comment</key> + <string>Enable the texture fetching debugger if set</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> <key>TextureLoadFullRes</key> <map> <key>Comment</key> @@ -10752,6 +10844,17 @@ <key>Value</key> <integer>0</integer> </map> + <key>TextureNewByteRange</key> + <map> + <key>Comment</key> + <string>Use the new more accurate byte range computation for j2c discard levels</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> <key>TexturePickerShowFolders</key> <map> <key>Comment</key> @@ -10774,6 +10877,17 @@ <key>Value</key> <integer>2</integer> </map> + <key>TextureReverseByteRange</key> + <map> + <key>Comment</key> + <string>Minimal percent of the optimal byte range allowed to render a given discard level</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>S32</string> + <key>Value</key> + <integer>50</integer> + </map> <key>ThrottleBandwidthKBPS</key> <map> <key>Comment</key> @@ -10817,7 +10931,8 @@ <string>F32</string> <key>Value</key> <real>0.1</real> - </map> <key>ToolTipFadeTime</key> + </map> + <key>ToolTipFadeTime</key> <map> <key>Comment</key> <string>Seconds over which tooltip fades away</string> @@ -12181,6 +12296,17 @@ <key>Value</key> <integer>1</integer> </map> + <key>RenderSynchronousOcclusion</key> + <map> + <key>Comment</key> + <string>Don't let occlusion queries get more than one frame behind (block until they complete).</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> <key>RenderDelayVBUpdate</key> <map> <key>Comment</key> @@ -12214,6 +12340,28 @@ <key>Value</key> <real>10.0</real> </map> + <key>SpellCheck</key> + <map> + <key>Comment</key> + <string>Enable spellchecking on line and text editors</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>SpellCheckDictionary</key> + <map> + <key>Comment</key> + <string>Current primary and secondary dictionaries used for spell checking</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>String</string> + <key>Value</key> + <string>English (United States),Second Life Glossary</string> + </map> <key>UseNewWalkRun</key> <map> <key>Comment</key> diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaNonIndexedNoColorF.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaNonIndexedNoColorF.glsl index cb87b754b4..1113a9845b 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/alphaNonIndexedNoColorF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/alphaNonIndexedNoColorF.glsl @@ -31,6 +31,8 @@ out vec4 frag_color; #define frag_color gl_FragColor #endif +uniform float minimum_alpha; + uniform sampler2DRect depthMap; uniform sampler2D diffuseMap; @@ -70,9 +72,15 @@ void main() vec4 diff= texture2D(diffuseMap,vary_texcoord0.xy); + if (diff.a < minimum_alpha) + { + discard; + } + vec4 col = vec4(vary_ambient + vary_directional.rgb, 1.0); vec4 color = diff * col; + color.rgb = atmosLighting(color.rgb); color.rgb = scaleSoftClip(color.rgb); diff --git a/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl index 75de47614c..bff87cb6aa 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl @@ -55,8 +55,6 @@ uniform float far_clip; uniform vec3 proj_origin; //origin of projection to be used for angular attenuation uniform float sun_wash; -uniform int proj_shadow_idx; -uniform float shadow_fade; uniform vec3 center; uniform vec3 color; @@ -143,7 +141,8 @@ void main() discard; } - vec3 norm = texture2DRect(normalMap, frag.xy).xyz*2.0-1.0; + vec3 norm = texture2DRect(normalMap, frag.xy).xyz; + norm = vec3((norm.xy-0.5)*2.0, norm.z); norm = normalize(norm); float l_dist = -dot(lv, proj_n); diff --git a/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl index 19800a8b8e..f671d5b750 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl @@ -42,12 +42,13 @@ uniform sampler2DRect depthMap; uniform vec3 env_mat[3]; uniform float sun_wash; -uniform vec3 center; uniform vec3 color; uniform float falloff; uniform float size; VARYING vec4 vary_fragcoord; +VARYING vec3 trans_center; + uniform vec2 screen_res; uniform mat4 inv_proj; @@ -74,7 +75,7 @@ void main() frag.xy *= screen_res; vec3 pos = getPosition(frag.xy).xyz; - vec3 lv = center.xyz-pos; + vec3 lv = trans_center.xyz-pos; float dist2 = dot(lv,lv); dist2 /= size; if (dist2 > 1.0) diff --git a/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl b/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl index cb14e6d4e8..9491421236 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl @@ -24,16 +24,22 @@ */ uniform mat4 modelview_projection_matrix; +uniform mat4 modelview_matrix; ATTRIBUTE vec3 position; +uniform vec3 center; +uniform float size; + VARYING vec4 vary_fragcoord; +VARYING vec3 trans_center; void main() { //transform vertex - vec4 pos = modelview_projection_matrix * vec4(position.xyz, 1.0); + vec3 p = position*sqrt(size)+center; + vec4 pos = modelview_projection_matrix * vec4(p.xyz, 1.0); vary_fragcoord = pos; - + trans_center = (modelview_matrix*vec4(center.xyz, 1.0)).xyz; gl_Position = pos; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskF.glsl index cf8cf8364a..bced4a5577 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskF.glsl @@ -29,11 +29,11 @@ out vec4 frag_color; #define frag_color gl_FragColor #endif -uniform float minimum_alpha; - uniform sampler2D diffuseMap; -VARYING vec4 post_pos; +VARYING float pos_zd2; +VARYING float pos_w; +VARYING float target_pos_x; VARYING vec4 vertex_color; VARYING vec2 vary_texcoord0; @@ -41,12 +41,20 @@ void main() { float alpha = diffuseLookup(vary_texcoord0.xy).a * vertex_color.a; - if (alpha < minimum_alpha) + if (alpha < 0.05) // treat as totally transparent { discard; } + if (alpha < 0.88) // treat as semi-transparent + { + if (fract(0.5*floor(target_pos_x / pos_w )) < 0.25) + { + discard; + } + } + frag_color = vec4(1,1,1,1); - gl_FragDepth = max(post_pos.z/post_pos.w*0.5+0.5, 0.0); + gl_FragDepth = max(pos_zd2/pos_w+0.5, 0.0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskV.glsl b/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskV.glsl index 7d3b06c56e..c1f2d90712 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskV.glsl @@ -25,12 +25,15 @@ uniform mat4 texture_matrix0; uniform mat4 modelview_projection_matrix; +uniform float shadow_target_width; ATTRIBUTE vec3 position; ATTRIBUTE vec4 diffuse_color; ATTRIBUTE vec2 texcoord0; -VARYING vec4 post_pos; +VARYING float pos_zd2; +VARYING float pos_w; +VARYING float target_pos_x; VARYING vec4 vertex_color; VARYING vec2 vary_texcoord0; @@ -39,8 +42,11 @@ void passTextureIndex(); void main() { //transform vertex - vec4 pos = modelview_projection_matrix*vec4(position.xyz, 1.0); - post_pos = pos; + vec4 pre_pos = vec4(position.xyz, 1.0); + vec4 pos = modelview_projection_matrix * pre_pos; + target_pos_x = 0.5 * (shadow_target_width - 1.0) * pos.x; + pos_w = pos.w; + pos_zd2 = pos.z * 0.5; gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w); diff --git a/indra/newview/app_settings/shaders/class1/deferred/shadowCubeV.glsl b/indra/newview/app_settings/shaders/class1/deferred/shadowCubeV.glsl new file mode 100644 index 0000000000..6195e2f1ec --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/shadowCubeV.glsl @@ -0,0 +1,44 @@ +/** + * @file shadowCubeV.glsl + * + * $LicenseInfo:firstyear=2011&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2007, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +uniform mat4 modelview_projection_matrix; + +ATTRIBUTE vec3 position; + +VARYING vec4 post_pos; + +uniform vec3 box_center; +uniform vec3 box_size; + +void main() +{ + //transform vertex + vec3 p = position*box_size+box_center; + vec4 pos = modelview_projection_matrix*vec4(p.xyz, 1.0); + + post_pos = pos; + + gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w); +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl index 7ed8ed3370..cca63872de 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl @@ -24,18 +24,21 @@ */ -#extension GL_ARB_texture_rectangle : enable - #ifdef DEFINE_GL_FRAGCOLOR out vec4 frag_color; #else #define frag_color gl_FragColor #endif +//class 1 -- no shadows + +#extension GL_ARB_texture_rectangle : enable + uniform sampler2DRect diffuseRect; uniform sampler2DRect specularRect; uniform sampler2DRect depthMap; uniform sampler2DRect normalMap; +uniform samplerCube environmentMap; uniform sampler2D noiseMap; uniform sampler2D projectionMap; @@ -46,6 +49,7 @@ uniform vec3 proj_n; uniform float proj_focus; //distance from plane to begin blurring uniform float proj_lod; //(number of mips in proj map) uniform float proj_range; //range between near clip and far clip plane of projection +uniform float proj_ambient_lod; uniform float proj_ambiance; uniform float near_clip; uniform float far_clip; @@ -53,19 +57,66 @@ uniform float far_clip; uniform vec3 proj_origin; //origin of projection to be used for angular attenuation uniform float sun_wash; -uniform vec3 center; uniform vec3 color; uniform float falloff; uniform float size; VARYING vec4 vary_fragcoord; +VARYING vec3 trans_center; + uniform vec2 screen_res; uniform mat4 inv_proj; +vec4 texture2DLodSpecular(sampler2D projectionMap, vec2 tc, float lod) +{ + vec4 ret = texture2DLod(projectionMap, tc, lod); + + vec2 dist = tc-vec2(0.5); + + float det = max(1.0-lod/(proj_lod*0.5), 0.0); + + float d = dot(dist,dist); + + ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0)+det, 1.0); + + return ret; +} + +vec4 texture2DLodDiffuse(sampler2D projectionMap, vec2 tc, float lod) +{ + vec4 ret = texture2DLod(projectionMap, tc, lod); + + vec2 dist = vec2(0.5) - abs(tc-vec2(0.5)); + + float det = min(lod/(proj_lod*0.5), 1.0); + + float d = min(dist.x, dist.y); + + float edge = 0.25*det; + + ret *= clamp(d/edge, 0.0, 1.0); + + return ret; +} + +vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod) +{ + vec4 ret = texture2DLod(projectionMap, tc, lod); + + vec2 dist = tc-vec2(0.5); + + float d = dot(dist,dist); + + ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0), 1.0); + + return ret; +} + + vec4 getPosition(vec2 pos_screen) { - float depth = texture2DRect(depthMap, pos_screen.xy).a; + float depth = texture2DRect(depthMap, pos_screen.xy).r; vec2 sc = pos_screen.xy*2.0; sc /= screen_res; sc -= vec2(1.0,1.0); @@ -84,16 +135,16 @@ void main() frag.xy *= screen_res; vec3 pos = getPosition(frag.xy).xyz; - vec3 lv = center.xyz-pos.xyz; + vec3 lv = trans_center.xyz-pos.xyz; float dist2 = dot(lv,lv); dist2 /= size; if (dist2 > 1.0) { discard; } - + vec3 norm = texture2DRect(normalMap, frag.xy).xyz; - norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm + norm = vec3((norm.xy-0.5)*2.0, norm.z); norm = normalize(norm); float l_dist = -dot(lv, proj_n); @@ -107,7 +158,11 @@ void main() proj_tc.xyz /= proj_tc.w; float fa = falloff+1.0; - float dist_atten = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0); + float dist_atten = min(1.0-(dist2-1.0*(1.0-fa))/fa, 1.0); + if (dist_atten <= 0.0) + { + discard; + } lv = proj_origin-pos.xyz; lv = normalize(lv); @@ -125,32 +180,32 @@ void main() proj_tc.y > 0.0) { float lit = 0.0; + float amb_da = proj_ambiance; + if (da > 0.0) { float diff = clamp((l_dist-proj_focus)/proj_range, 0.0, 1.0); float lod = diff * proj_lod; - vec4 plcol = texture2DLod(projectionMap, proj_tc.xy, lod); + vec4 plcol = texture2DLodDiffuse(projectionMap, proj_tc.xy, lod); vec3 lcol = color.rgb * plcol.rgb * plcol.a; lit = da * dist_atten * noise; col = lcol*lit*diff_tex; + amb_da += (da*0.5)*proj_ambiance; } - float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0); - float lod = diff * proj_lod; - vec4 amb_plcol = texture2DLod(projectionMap, proj_tc.xy, lod); - //float amb_da = mix(proj_ambiance, proj_ambiance*max(-da, 0.0), max(da, 0.0)); - float amb_da = proj_ambiance; - + //float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0); + vec4 amb_plcol = texture2DLodAmbient(projectionMap, proj_tc.xy, proj_lod); + amb_da += (da*da*0.5+0.5)*proj_ambiance; - + amb_da *= dist_atten * noise; - + amb_da = min(amb_da, 1.0-lit); - + col += amb_da*color.rgb*diff_tex.rgb*amb_plcol.rgb*amb_plcol.a; } @@ -168,18 +223,22 @@ void main() { vec3 pfinal = pos + ref * dot(pdelta, proj_n)/ds; - vec3 stc = (proj_mat * vec4(pfinal.xyz, 1.0)).xyz; + vec4 stc = (proj_mat * vec4(pfinal.xyz, 1.0)); if (stc.z > 0.0) { - stc.xy /= stc.z+proj_near; - + stc.xy /= stc.w; + + float fatten = clamp(spec.a*spec.a+spec.a*0.5, 0.25, 1.0); + + stc.xy = (stc.xy - vec2(0.5)) * fatten + vec2(0.5); + if (stc.x < 1.0 && stc.y < 1.0 && stc.x > 0.0 && stc.y > 0.0) { - vec4 scol = texture2DLod(projectionMap, stc.xy, proj_lod-spec.a*proj_lod); + vec4 scol = texture2DLodSpecular(projectionMap, stc.xy, proj_lod-spec.a*proj_lod); col += dist_atten*scol.rgb*color.rgb*scol.a*spec.rgb; } } diff --git a/indra/newview/app_settings/shaders/class1/interface/clipF.glsl b/indra/newview/app_settings/shaders/class1/interface/clipF.glsl new file mode 100644 index 0000000000..ac2bc8703b --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/interface/clipF.glsl @@ -0,0 +1,46 @@ +/** + * @file debugF.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifdef DEFINE_GL_FRAGCOLOR +out vec4 frag_color; +#else +#define frag_color gl_FragColor +#endif + +uniform vec4 color; +uniform vec4 clip_plane; + +VARYING vec3 vary_position; + + +void main() +{ + if (dot(vary_position,clip_plane.xyz)+clip_plane.w < 0.0) + { + discard; + } + + frag_color = color; +} diff --git a/indra/newview/app_settings/shaders/class1/interface/clipV.glsl b/indra/newview/app_settings/shaders/class1/interface/clipV.glsl new file mode 100644 index 0000000000..e376b25a71 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/interface/clipV.glsl @@ -0,0 +1,38 @@ +/** + * @file debugV.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +uniform mat4 modelview_projection_matrix; +uniform mat4 modelview_matrix; + +ATTRIBUTE vec3 position; + +VARYING vec3 vary_position; + +void main() +{ + vary_position = (modelview_matrix*vec4(position.xyz,1.0)).xyz; + gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); +} + diff --git a/indra/newview/app_settings/shaders/class1/interface/occlusionCubeV.glsl b/indra/newview/app_settings/shaders/class1/interface/occlusionCubeV.glsl new file mode 100644 index 0000000000..5c479d27a9 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/interface/occlusionCubeV.glsl @@ -0,0 +1,38 @@ +/** + * @file occlusionCubeV.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2007, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +uniform mat4 modelview_projection_matrix; + +ATTRIBUTE vec3 position; + +uniform vec3 box_center; +uniform vec3 box_size; + +void main() +{ + vec3 p = position*box_size+box_center; + gl_Position = modelview_projection_matrix * vec4(p.xyz, 1.0); +} + diff --git a/indra/newview/app_settings/shaders/class1/objects/indexedTextureV.glsl b/indra/newview/app_settings/shaders/class1/objects/indexedTextureV.glsl index 7c0699d72f..ca29bf3143 100644 --- a/indra/newview/app_settings/shaders/class1/objects/indexedTextureV.glsl +++ b/indra/newview/app_settings/shaders/class1/objects/indexedTextureV.glsl @@ -23,9 +23,9 @@ * $/LicenseInfo$ */ -ATTRIBUTE ivec4 texture_index; +ATTRIBUTE int texture_index; -VARYING_FLAT ivec4 vary_texture_index; +VARYING_FLAT int vary_texture_index; void passTextureIndex() { diff --git a/indra/newview/app_settings/shaders/class1/transform/binormalV.glsl b/indra/newview/app_settings/shaders/class1/transform/binormalV.glsl new file mode 100644 index 0000000000..44f1aa34a0 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/transform/binormalV.glsl @@ -0,0 +1,36 @@ +/** + * @file binormalV.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2007, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +uniform mat3 normal_matrix; + +ATTRIBUTE vec3 binormal; + +VARYING vec4 binormal_out; + +void main() +{ + binormal_out = vec4(normal_matrix * binormal, 0.0); +} + diff --git a/indra/newview/app_settings/shaders/class1/transform/colorV.glsl b/indra/newview/app_settings/shaders/class1/transform/colorV.glsl new file mode 100644 index 0000000000..59c4a7d895 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/transform/colorV.glsl @@ -0,0 +1,36 @@ +/** + * @file colorV.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2007, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +uniform int color_in; + +ATTRIBUTE vec3 position; + +VARYING int color_out; + +void main() +{ + color_out = color_in; +} + diff --git a/indra/newview/app_settings/shaders/class1/transform/normalV.glsl b/indra/newview/app_settings/shaders/class1/transform/normalV.glsl new file mode 100644 index 0000000000..a213aa0ae8 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/transform/normalV.glsl @@ -0,0 +1,36 @@ +/** + * @file normalV.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2007, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +uniform mat3 normal_matrix; + +ATTRIBUTE vec3 normal; + +VARYING vec4 normal_out; + +void main() +{ + normal_out = vec4(normalize(normal_matrix * normal), 0.0); +} + diff --git a/indra/newview/app_settings/shaders/class1/transform/positionV.glsl b/indra/newview/app_settings/shaders/class1/transform/positionV.glsl new file mode 100644 index 0000000000..01eed18de4 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/transform/positionV.glsl @@ -0,0 +1,40 @@ +/** + * @file positionV.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2007, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +uniform mat4 modelview_matrix; + +uniform int texture_index_in; + +ATTRIBUTE vec3 position; + +VARYING vec3 position_out; +VARYING int texture_index_out; + +void main() +{ + texture_index_out = texture_index_in; + position_out = (modelview_matrix*vec4(position, 1.0)).xyz; +} + diff --git a/indra/newview/app_settings/shaders/class1/transform/texcoordV.glsl b/indra/newview/app_settings/shaders/class1/transform/texcoordV.glsl new file mode 100644 index 0000000000..0e074f3cec --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/transform/texcoordV.glsl @@ -0,0 +1,35 @@ +/** + * @file texcoordV.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2007, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + + +ATTRIBUTE vec2 texcoord0; + +VARYING vec2 texcoord_out; + +void main() +{ + texcoord_out = texcoord0; +} + diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl index 08f6ec63fe..8db4cb58cf 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl @@ -58,20 +58,22 @@ uniform float shadow_bias; uniform mat4 inv_proj; -float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc, float scl) +float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc) { stc.xyz /= stc.w; stc.z += shadow_bias; + + stc.x = floor(stc.x + fract(stc.y*12345)); // add some chaotic jitter to X sample pos according to Y to disguise the snapping going on here float cs = shadow2DRect(shadowMap, stc.xyz).x; float shadow = cs; - shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(scl, scl, 0.0)).x, cs); - shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(scl, -scl, 0.0)).x, cs); - shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-scl, scl, 0.0)).x, cs); - shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-scl, -scl, 0.0)).x, cs); - - return shadow/5.0; + shadow += shadow2DRect(shadowMap, stc.xyz+vec3(2.0, 1.5, 0.0)).x; + shadow += shadow2DRect(shadowMap, stc.xyz+vec3(1.0, -1.5, 0.0)).x; + shadow += shadow2DRect(shadowMap, stc.xyz+vec3(-1.0, 1.5, 0.0)).x; + shadow += shadow2DRect(shadowMap, stc.xyz+vec3(-2.0, -1.5, 0.0)).x; + + return shadow*0.2; } @@ -101,7 +103,7 @@ void main() float w = 1.0; w -= max(spos.z-far_split.z, 0.0)/transition_domain.z; - shadow += pcfShadow(shadowMap3, lpos, 0.25)*w; + shadow += pcfShadow(shadowMap3, lpos)*w; weight += w; shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0); } @@ -114,7 +116,7 @@ void main() float w = 1.0; w -= max(spos.z-far_split.y, 0.0)/transition_domain.y; w -= max(near_split.z-spos.z, 0.0)/transition_domain.z; - shadow += pcfShadow(shadowMap2, lpos, 0.75)*w; + shadow += pcfShadow(shadowMap2, lpos)*w; weight += w; } @@ -126,7 +128,7 @@ void main() float w = 1.0; w -= max(spos.z-far_split.x, 0.0)/transition_domain.x; w -= max(near_split.y-spos.z, 0.0)/transition_domain.y; - shadow += pcfShadow(shadowMap1, lpos, 0.75)*w; + shadow += pcfShadow(shadowMap1, lpos)*w; weight += w; } @@ -138,7 +140,7 @@ void main() float w = 1.0; w -= max(near_split.x-spos.z, 0.0)/transition_domain.x; - shadow += pcfShadow(shadowMap0, lpos, 1.0)*w; + shadow += pcfShadow(shadowMap0, lpos)*w; weight += w; } diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaNonIndexedF.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaNonIndexedF.glsl index aae6a070e2..33958a5010 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/alphaNonIndexedF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/alphaNonIndexedF.glsl @@ -71,20 +71,22 @@ vec4 getPosition(vec2 pos_screen) return pos; } -float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc, float scl) +float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc) { stc.xyz /= stc.w; stc.z += shadow_bias; + + stc.x = floor(stc.x + fract(stc.y*12345)); // add some chaotic jitter to X sample pos according to Y to disguise the snapping going on here float cs = shadow2DRect(shadowMap, stc.xyz).x; float shadow = cs; - shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(scl, scl, 0.0)).x, cs); - shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(scl, -scl, 0.0)).x, cs); - shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-scl, scl, 0.0)).x, cs); - shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-scl, -scl, 0.0)).x, cs); - - return shadow/5.0; + shadow += shadow2DRect(shadowMap, stc.xyz+vec3(2.0, 1.5, 0.0)).x; + shadow += shadow2DRect(shadowMap, stc.xyz+vec3(1.0, -1.5, 0.0)).x; + shadow += shadow2DRect(shadowMap, stc.xyz+vec3(-1.0, 1.5, 0.0)).x; + shadow += shadow2DRect(shadowMap, stc.xyz+vec3(-2.0, -1.5, 0.0)).x; + + return shadow*0.2; } @@ -114,7 +116,7 @@ void main() float w = 1.0; w -= max(spos.z-far_split.z, 0.0)/transition_domain.z; - shadow += pcfShadow(shadowMap3, lpos, 0.25)*w; + shadow += pcfShadow(shadowMap3, lpos)*w; weight += w; shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0); } @@ -127,7 +129,7 @@ void main() float w = 1.0; w -= max(spos.z-far_split.y, 0.0)/transition_domain.y; w -= max(near_split.z-spos.z, 0.0)/transition_domain.z; - shadow += pcfShadow(shadowMap2, lpos, 0.75)*w; + shadow += pcfShadow(shadowMap2, lpos)*w; weight += w; } @@ -139,7 +141,7 @@ void main() float w = 1.0; w -= max(spos.z-far_split.x, 0.0)/transition_domain.x; w -= max(near_split.y-spos.z, 0.0)/transition_domain.y; - shadow += pcfShadow(shadowMap1, lpos, 0.75)*w; + shadow += pcfShadow(shadowMap1, lpos)*w; weight += w; } @@ -151,7 +153,7 @@ void main() float w = 1.0; w -= max(near_split.x-spos.z, 0.0)/transition_domain.x; - shadow += pcfShadow(shadowMap0, lpos, 1.0)*w; + shadow += pcfShadow(shadowMap0, lpos)*w; weight += w; } diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaNonIndexedNoColorF.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaNonIndexedNoColorF.glsl index 931577359e..2093fc37dc 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/alphaNonIndexedNoColorF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/alphaNonIndexedNoColorF.glsl @@ -31,6 +31,8 @@ out vec4 frag_color; #define frag_color gl_FragColor #endif +uniform float minimum_alpha; + uniform sampler2DRectShadow shadowMap0; uniform sampler2DRectShadow shadowMap1; uniform sampler2DRectShadow shadowMap2; @@ -70,20 +72,22 @@ vec4 getPosition(vec2 pos_screen) return pos; } -float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc, float scl) +float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc) { stc.xyz /= stc.w; stc.z += shadow_bias; + + stc.x = floor(stc.x + fract(stc.y*12345)); // add some chaotic jitter to X sample pos according to Y to disguise the snapping going on here float cs = shadow2DRect(shadowMap, stc.xyz).x; float shadow = cs; - shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(scl, scl, 0.0)).x, cs); - shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(scl, -scl, 0.0)).x, cs); - shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-scl, scl, 0.0)).x, cs); - shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-scl, -scl, 0.0)).x, cs); - - return shadow/5.0; + shadow += shadow2DRect(shadowMap, stc.xyz+vec3(2.0, 1.5, 0.0)).x; + shadow += shadow2DRect(shadowMap, stc.xyz+vec3(1.0, -1.5, 0.0)).x; + shadow += shadow2DRect(shadowMap, stc.xyz+vec3(-1.0, 1.5, 0.0)).x; + shadow += shadow2DRect(shadowMap, stc.xyz+vec3(-2.0, -1.5, 0.0)).x; + + return shadow*0.2; } @@ -95,6 +99,13 @@ void main() float shadow = 0.0; vec4 pos = vec4(vary_position, 1.0); + vec4 diff = texture2D(diffuseMap,vary_texcoord0.xy); + + if (diff.a < minimum_alpha) + { + discard; + } + vec4 spos = pos; if (spos.z > -shadow_clip.w) @@ -113,7 +124,7 @@ void main() float w = 1.0; w -= max(spos.z-far_split.z, 0.0)/transition_domain.z; - shadow += pcfShadow(shadowMap3, lpos, 0.25)*w; + shadow += pcfShadow(shadowMap3, lpos)*w; weight += w; shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0); } @@ -126,7 +137,7 @@ void main() float w = 1.0; w -= max(spos.z-far_split.y, 0.0)/transition_domain.y; w -= max(near_split.z-spos.z, 0.0)/transition_domain.z; - shadow += pcfShadow(shadowMap2, lpos, 0.75)*w; + shadow += pcfShadow(shadowMap2, lpos)*w; weight += w; } @@ -138,7 +149,7 @@ void main() float w = 1.0; w -= max(spos.z-far_split.x, 0.0)/transition_domain.x; w -= max(near_split.y-spos.z, 0.0)/transition_domain.y; - shadow += pcfShadow(shadowMap1, lpos, 0.75)*w; + shadow += pcfShadow(shadowMap1, lpos)*w; weight += w; } @@ -150,7 +161,7 @@ void main() float w = 1.0; w -= max(near_split.x-spos.z, 0.0)/transition_domain.x; - shadow += pcfShadow(shadowMap0, lpos, 1.0)*w; + shadow += pcfShadow(shadowMap0, lpos)*w; weight += w; } @@ -162,8 +173,6 @@ void main() shadow = 1.0; } - vec4 diff = texture2D(diffuseMap,vary_texcoord0.xy); - vec4 col = vec4(vary_ambient + vary_directional.rgb*shadow, 1.0); vec4 color = diff * col; diff --git a/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl index 99a277fbfc..ab077d9e02 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl @@ -31,8 +31,6 @@ out vec4 frag_color; #define frag_color gl_FragColor #endif -VARYING vec4 vertex_color; - uniform sampler2DRect diffuseRect; uniform sampler2DRect specularRect; uniform sampler2DRect depthMap; @@ -49,6 +47,7 @@ uniform vec3 proj_n; uniform float proj_focus; //distance from plane to begin blurring uniform float proj_lod; //(number of mips in proj map) uniform float proj_range; //range between near clip and far clip plane of projection +uniform float proj_ambient_lod; uniform float proj_ambiance; uniform float near_clip; uniform float far_clip; @@ -58,16 +57,65 @@ uniform float sun_wash; uniform int proj_shadow_idx; uniform float shadow_fade; -VARYING vec4 vary_light; +uniform float size; +uniform vec3 color; +uniform float falloff; +VARYING vec3 trans_center; VARYING vec4 vary_fragcoord; uniform vec2 screen_res; uniform mat4 inv_proj; +vec4 texture2DLodSpecular(sampler2D projectionMap, vec2 tc, float lod) +{ + vec4 ret = texture2DLod(projectionMap, tc, lod); + + vec2 dist = tc-vec2(0.5); + + float det = max(1.0-lod/(proj_lod*0.5), 0.0); + + float d = dot(dist,dist); + + ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0)+det, 1.0); + + return ret; +} + +vec4 texture2DLodDiffuse(sampler2D projectionMap, vec2 tc, float lod) +{ + vec4 ret = texture2DLod(projectionMap, tc, lod); + + vec2 dist = vec2(0.5) - abs(tc-vec2(0.5)); + + float det = min(lod/(proj_lod*0.5), 1.0); + + float d = min(dist.x, dist.y); + + float edge = 0.25*det; + + ret *= clamp(d/edge, 0.0, 1.0); + + return ret; +} + +vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod) +{ + vec4 ret = texture2DLod(projectionMap, tc, lod); + + vec2 dist = tc-vec2(0.5); + + float d = dot(dist,dist); + + ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0), 1.0); + + return ret; +} + + vec4 getPosition(vec2 pos_screen) { - float depth = texture2DRect(depthMap, pos_screen.xy).a; + float depth = texture2DRect(depthMap, pos_screen.xy).r; vec2 sc = pos_screen.xy*2.0; sc /= screen_res; sc -= vec2(1.0,1.0); @@ -85,6 +133,15 @@ void main() frag.xyz = frag.xyz*0.5+0.5; frag.xy *= screen_res; + vec3 pos = getPosition(frag.xy).xyz; + vec3 lv = trans_center.xyz-pos.xyz; + float dist2 = dot(lv,lv); + dist2 /= size; + if (dist2 > 1.0) + { + discard; + } + float shadow = 1.0; if (proj_shadow_idx >= 0) @@ -96,15 +153,6 @@ void main() shadow = min(sh[proj_shadow_idx]+shadow_fade, 1.0); } - vec3 pos = getPosition(frag.xy).xyz; - vec3 lv = vary_light.xyz-pos.xyz; - float dist2 = dot(lv,lv); - dist2 /= vary_light.w; - if (dist2 > 1.0) - { - discard; - } - vec3 norm = texture2DRect(normalMap, frag.xy).xyz; norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm @@ -119,8 +167,12 @@ void main() proj_tc.xyz /= proj_tc.w; - float fa = vertex_color.a+1.0; - float dist_atten = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0); + float fa = falloff+1.0; + float dist_atten = min(1.0-(dist2-1.0*(1.0-fa))/fa, 1.0); + if (dist_atten <= 0.0) + { + discard; + } lv = proj_origin-pos.xyz; lv = normalize(lv); @@ -138,37 +190,33 @@ void main() proj_tc.y > 0.0) { float lit = 0.0; + float amb_da = proj_ambiance; + if (da > 0.0) { float diff = clamp((l_dist-proj_focus)/proj_range, 0.0, 1.0); float lod = diff * proj_lod; - vec4 plcol = texture2DLod(projectionMap, proj_tc.xy, lod); + vec4 plcol = texture2DLodDiffuse(projectionMap, proj_tc.xy, lod); - vec3 lcol = vertex_color.rgb * plcol.rgb * plcol.a; + vec3 lcol = color.rgb * plcol.rgb * plcol.a; lit = da * dist_atten * noise; col = lcol*lit*diff_tex*shadow; - } - - float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0); - float lod = diff * proj_lod; - vec4 amb_plcol = texture2DLod(projectionMap, proj_tc.xy, lod); - //float amb_da = mix(proj_ambiance, proj_ambiance*max(-da, 0.0), max(da, 0.0)); - float amb_da = proj_ambiance; - if (da > 0.0) - { amb_da += (da*0.5)*(1.0-shadow)*proj_ambiance; } + //float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0); + vec4 amb_plcol = texture2DLodAmbient(projectionMap, proj_tc.xy, proj_lod); + amb_da += (da*da*0.5+0.5)*proj_ambiance; - + amb_da *= dist_atten * noise; - + amb_da = min(amb_da, 1.0-lit); - - col += amb_da*vertex_color.rgb*diff_tex.rgb*amb_plcol.rgb*amb_plcol.a; + + col += amb_da*color.rgb*diff_tex.rgb*amb_plcol.rgb*amb_plcol.a; } @@ -185,19 +233,23 @@ void main() { vec3 pfinal = pos + ref * dot(pdelta, proj_n)/ds; - vec3 stc = (proj_mat * vec4(pfinal.xyz, 1.0)).xyz; + vec4 stc = (proj_mat * vec4(pfinal.xyz, 1.0)); if (stc.z > 0.0) { - stc.xy /= stc.z+proj_near; - + stc.xy /= stc.w; + + float fatten = clamp(spec.a*spec.a+spec.a*0.5, 0.25, 1.0); + + stc.xy = (stc.xy - vec2(0.5)) * fatten + vec2(0.5); + if (stc.x < 1.0 && stc.y < 1.0 && stc.x > 0.0 && stc.y > 0.0) { - vec4 scol = texture2DLod(projectionMap, stc.xy, proj_lod-spec.a*proj_lod); - col += dist_atten*scol.rgb*vertex_color.rgb*scol.a*spec.rgb*shadow; + vec4 scol = texture2DLodSpecular(projectionMap, stc.xy, proj_lod-spec.a*proj_lod); + col += dist_atten*scol.rgb*color.rgb*scol.a*spec.rgb*shadow; } } } diff --git a/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl index 8c4ccf9cb3..db3d760359 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl @@ -78,42 +78,42 @@ vec4 getPosition(vec2 pos_screen) return pos; } -float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc, float scl) +float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc, float scl, vec2 pos_screen) { stc.xyz /= stc.w; stc.z += shadow_bias*scl; - + + stc.x = floor(stc.x + fract(pos_screen.y*0.666666666)); // add some jitter to X sample pos according to Y to disguise the snapping going on here + float cs = shadow2DRect(shadowMap, stc.xyz).x; float shadow = cs; - shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(1.5, 1.5, 0.0)).x, cs); - shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(1.5, -1.5, 0.0)).x, cs); - shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-1.5, 1.5, 0.0)).x, cs); - shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-1.5, -1.5, 0.0)).x, cs); + shadow += shadow2DRect(shadowMap, stc.xyz+vec3(2.0, 1.5, 0.0)).x; + shadow += shadow2DRect(shadowMap, stc.xyz+vec3(1.0, -1.5, 0.0)).x; + shadow += shadow2DRect(shadowMap, stc.xyz+vec3(-2.0, 1.5, 0.0)).x; + shadow += shadow2DRect(shadowMap, stc.xyz+vec3(-1.0, -1.5, 0.0)).x; - return shadow/5.0; - - //return shadow; + return shadow*0.2; } -float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl) +float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_screen) { stc.xyz /= stc.w; stc.z += spot_shadow_bias*scl; + stc.x = floor(proj_shadow_res.x * stc.x + fract(pos_screen.y*0.666666666)) / proj_shadow_res.x; // snap float cs = shadow2D(shadowMap, stc.xyz).x; float shadow = cs; - vec2 off = 1.5/proj_shadow_res; + vec2 off = 1.0/proj_shadow_res; + off.y *= 1.5; - shadow += max(shadow2D(shadowMap, stc.xyz+vec3(off.x, off.y, 0.0)).x, cs); - shadow += max(shadow2D(shadowMap, stc.xyz+vec3(off.x, -off.y, 0.0)).x, cs); - shadow += max(shadow2D(shadowMap, stc.xyz+vec3(-off.x, off.y, 0.0)).x, cs); - shadow += max(shadow2D(shadowMap, stc.xyz+vec3(-off.x, -off.y, 0.0)).x, cs); - - return shadow/5.0; - - //return shadow; + shadow += shadow2D(shadowMap, stc.xyz+vec3(off.x*2.0, off.y, 0.0)).x; + shadow += shadow2D(shadowMap, stc.xyz+vec3(off.x, -off.y, 0.0)).x; + shadow += shadow2D(shadowMap, stc.xyz+vec3(-off.x, off.y, 0.0)).x; + shadow += shadow2D(shadowMap, stc.xyz+vec3(-off.x*2.0, -off.y, 0.0)).x; + + return shadow*0.2; } void main() @@ -166,7 +166,7 @@ void main() float w = 1.0; w -= max(spos.z-far_split.z, 0.0)/transition_domain.z; - shadow += pcfShadow(shadowMap3, lpos, 0.25)*w; + shadow += pcfShadow(shadowMap3, lpos, 0.25, pos_screen)*w; weight += w; shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0); } @@ -179,7 +179,7 @@ void main() float w = 1.0; w -= max(spos.z-far_split.y, 0.0)/transition_domain.y; w -= max(near_split.z-spos.z, 0.0)/transition_domain.z; - shadow += pcfShadow(shadowMap2, lpos, 0.75)*w; + shadow += pcfShadow(shadowMap2, lpos, 0.5, pos_screen)*w; weight += w; } @@ -191,7 +191,7 @@ void main() float w = 1.0; w -= max(spos.z-far_split.x, 0.0)/transition_domain.x; w -= max(near_split.y-spos.z, 0.0)/transition_domain.y; - shadow += pcfShadow(shadowMap1, lpos, 0.75)*w; + shadow += pcfShadow(shadowMap1, lpos, 0.75, pos_screen)*w; weight += w; } @@ -203,7 +203,7 @@ void main() float w = 1.0; w -= max(near_split.x-spos.z, 0.0)/transition_domain.x; - shadow += pcfShadow(shadowMap0, lpos, 1.0)*w; + shadow += pcfShadow(shadowMap0, lpos, 1.0, pos_screen)*w; weight += w; } @@ -237,11 +237,11 @@ void main() //spotlight shadow 1 vec4 lpos = shadow_matrix[4]*spos; - frag_color[2] = pcfShadow(shadowMap4, lpos, 0.8); + frag_color[2] = pcfShadow(shadowMap4, lpos, 0.8, pos_screen); //spotlight shadow 2 lpos = shadow_matrix[5]*spos; - frag_color[3] = pcfShadow(shadowMap5, lpos, 0.8); + frag_color[3] = pcfShadow(shadowMap5, lpos, 0.8, pos_screen); //frag_color.rgb = pos.xyz; //frag_color.b = shadow; diff --git a/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl index 02075a7687..dfe108eb01 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl @@ -90,7 +90,7 @@ vec2 getKern(int i) kern[5] = vec2(-0.7071, -0.7071) * 0.750*0.750; kern[6] = vec2(-0.7071, 0.7071) * 0.875*0.875; kern[7] = vec2(0.7071, -0.7071) * 1.000*1.000; - + return kern[i]; } @@ -139,42 +139,42 @@ float calcAmbientOcclusion(vec4 pos, vec3 norm) return min(ret, 1.0); } -float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc, float scl) +float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc, float scl, vec2 pos_screen) { stc.xyz /= stc.w; stc.z += shadow_bias*scl; + + stc.x = floor(stc.x + fract(pos_screen.y*0.666666666)); float cs = shadow2DRect(shadowMap, stc.xyz).x; float shadow = cs; - - shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(1.5, 1.5, 0.0)).x, cs); - shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(1.5, -1.5, 0.0)).x, cs); - shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-1.5, 1.5, 0.0)).x, cs); - shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-1.5, -1.5, 0.0)).x, cs); - - return shadow/5.0; - //return shadow; + shadow += shadow2DRect(shadowMap, stc.xyz+vec3(2.0, 1.5, 0.0)).x; + shadow += shadow2DRect(shadowMap, stc.xyz+vec3(1.0, -1.5, 0.0)).x; + shadow += shadow2DRect(shadowMap, stc.xyz+vec3(-1.0, 1.5, 0.0)).x; + shadow += shadow2DRect(shadowMap, stc.xyz+vec3(-2.0, -1.5, 0.0)).x; + + return shadow*0.2; } -float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl) +float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_screen) { stc.xyz /= stc.w; stc.z += spot_shadow_bias*scl; + stc.x = floor(proj_shadow_res.x * stc.x + fract(pos_screen.y*0.666666666)) / proj_shadow_res.x; // snap float cs = shadow2D(shadowMap, stc.xyz).x; float shadow = cs; - vec2 off = 1.5/proj_shadow_res; + vec2 off = 1.0/proj_shadow_res; + off.y *= 1.5; - shadow += max(shadow2D(shadowMap, stc.xyz+vec3(off.x, off.y, 0.0)).x, cs); - shadow += max(shadow2D(shadowMap, stc.xyz+vec3(off.x, -off.y, 0.0)).x, cs); - shadow += max(shadow2D(shadowMap, stc.xyz+vec3(-off.x, off.y, 0.0)).x, cs); - shadow += max(shadow2D(shadowMap, stc.xyz+vec3(-off.x, -off.y, 0.0)).x, cs); - - return shadow/5.0; - - //return shadow; + shadow += shadow2D(shadowMap, stc.xyz+vec3(off.x*2.0, off.y, 0.0)).x; + shadow += shadow2D(shadowMap, stc.xyz+vec3(off.x, -off.y, 0.0)).x; + shadow += shadow2D(shadowMap, stc.xyz+vec3(-off.x, off.y, 0.0)).x; + shadow += shadow2D(shadowMap, stc.xyz+vec3(-off.x*2.0, -off.y, 0.0)).x; + + return shadow*0.2; } void main() @@ -227,7 +227,7 @@ void main() float w = 1.0; w -= max(spos.z-far_split.z, 0.0)/transition_domain.z; - shadow += pcfShadow(shadowMap3, lpos, 0.25)*w; + shadow += pcfShadow(shadowMap3, lpos, 0.25, pos_screen)*w; weight += w; shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0); } @@ -240,7 +240,7 @@ void main() float w = 1.0; w -= max(spos.z-far_split.y, 0.0)/transition_domain.y; w -= max(near_split.z-spos.z, 0.0)/transition_domain.z; - shadow += pcfShadow(shadowMap2, lpos, 0.75)*w; + shadow += pcfShadow(shadowMap2, lpos, 0.5, pos_screen)*w; weight += w; } @@ -252,7 +252,7 @@ void main() float w = 1.0; w -= max(spos.z-far_split.x, 0.0)/transition_domain.x; w -= max(near_split.y-spos.z, 0.0)/transition_domain.y; - shadow += pcfShadow(shadowMap1, lpos, 0.75)*w; + shadow += pcfShadow(shadowMap1, lpos, 0.75, pos_screen)*w; weight += w; } @@ -264,7 +264,7 @@ void main() float w = 1.0; w -= max(near_split.x-spos.z, 0.0)/transition_domain.x; - shadow += pcfShadow(shadowMap0, lpos, 1.0)*w; + shadow += pcfShadow(shadowMap0, lpos, 1.0, pos_screen)*w; weight += w; } @@ -298,11 +298,11 @@ void main() //spotlight shadow 1 vec4 lpos = shadow_matrix[4]*spos; - frag_color[2] = pcfShadow(shadowMap4, lpos, 0.8); + frag_color[2] = pcfShadow(shadowMap4, lpos, 0.8, pos_screen); //spotlight shadow 2 lpos = shadow_matrix[5]*spos; - frag_color[3] = pcfShadow(shadowMap5, lpos, 0.8); + frag_color[3] = pcfShadow(shadowMap5, lpos, 0.8, pos_screen); //frag_color.rgb = pos.xyz; //frag_color.b = shadow; diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt index 76bb2b0976..eeb632acaf 100644 --- a/indra/newview/featuretable.txt +++ b/indra/newview/featuretable.txt @@ -61,6 +61,7 @@ WLSkyDetail 1 128 Disregard128DefaultDrawDistance 1 1 Disregard96DefaultDrawDistance 1 1 RenderTextureMemoryMultiple 1 1.0 +RenderCompressTextures 1 1 RenderShaderLightingMaxLevel 1 3 RenderDeferred 1 1 RenderDeferredSSAO 1 1 @@ -72,6 +73,38 @@ RenderMaxTextureIndex 1 16 // +// Low Graphics Settings (fixed function) +// +list LowFixedFunction +RenderAnisotropic 1 0 +RenderAvatarCloth 1 0 +RenderAvatarLODFactor 1 0 +RenderAvatarPhysicsLODFactor 1 0 +RenderAvatarMaxVisible 1 3 +RenderAvatarVP 1 0 +RenderFarClip 1 64 +RenderFlexTimeFactor 1 0 +RenderGlowResolutionPow 1 8 +RenderMaxPartCount 1 0 +RenderObjectBump 1 0 +RenderLocalLights 1 0 +RenderReflectionDetail 1 0 +RenderTerrainDetail 1 0 +RenderTerrainLODFactor 1 1 +RenderTransparentWater 1 0 +RenderTreeLODFactor 1 0 +RenderUseImpostors 1 1 +RenderVolumeLODFactor 1 1.125 +VertexShaderEnable 1 0 +WindLightUseAtmosShaders 1 0 +WLSkyDetail 1 48 +RenderDeferred 1 0 +RenderDeferredSSAO 1 0 +RenderShadowDetail 1 0 +RenderFSAASamples 1 0 + + +// // Low Graphics Settings // list Low @@ -94,7 +127,7 @@ RenderTransparentWater 1 0 RenderTreeLODFactor 1 0 RenderUseImpostors 1 1 RenderVolumeLODFactor 1 1.125 -VertexShaderEnable 1 0 +VertexShaderEnable 1 1 WindLightUseAtmosShaders 1 0 WLSkyDetail 1 48 RenderDeferred 1 0 @@ -223,6 +256,12 @@ list Class3 RenderVBOEnable 1 1 // +// VRAM > 512MB +// +list VRAMGT512 +RenderCompressTextures 1 0 + +// // No Pixel Shaders available // list NoPixelShaders @@ -302,6 +341,7 @@ RenderMaxTextureIndex 1 1 list Intel RenderAnisotropic 1 0 RenderVBOEnable 1 0 +RenderFSAASamples 1 0 list GeForce2 RenderAnisotropic 1 0 @@ -480,6 +520,7 @@ Disregard128DefaultDrawDistance 1 0 list ATIOldDriver RenderAvatarVP 0 0 RenderAvatarCloth 0 0 +RenderVBOEnable 1 0 // ATI cards generally perform better when not using VBOs for streaming data diff --git a/indra/newview/featuretable_linux.txt b/indra/newview/featuretable_linux.txt index 5e217e000a..3a0e7e3697 100644 --- a/indra/newview/featuretable_linux.txt +++ b/indra/newview/featuretable_linux.txt @@ -61,6 +61,7 @@ WLSkyDetail 1 128 Disregard128DefaultDrawDistance 1 1 Disregard96DefaultDrawDistance 1 1 RenderTextureMemoryMultiple 1 1.0 +RenderCompressTextures 1 1 RenderShaderLightingMaxLevel 1 3 RenderDeferred 1 1 RenderDeferredSSAO 1 1 @@ -69,6 +70,37 @@ RenderFSAASamples 1 16 RenderMaxTextureIndex 1 16 // +// Low Graphics Settings (fixed function) +// +list LowFixedFunction +RenderAnisotropic 1 0 +RenderAvatarCloth 1 0 +RenderAvatarLODFactor 1 0 +RenderAvatarPhysicsLODFactor 1 0 +RenderAvatarMaxVisible 1 3 +RenderAvatarVP 1 0 +RenderFarClip 1 64 +RenderFlexTimeFactor 1 0 +RenderGlowResolutionPow 1 8 +RenderLocalLights 1 0 +RenderMaxPartCount 1 0 +RenderObjectBump 1 0 +RenderReflectionDetail 1 0 +RenderTerrainDetail 1 0 +RenderTerrainLODFactor 1 1 +RenderTransparentWater 1 0 +RenderTreeLODFactor 1 0 +RenderUseImpostors 1 1 +RenderVolumeLODFactor 1 0.5 +VertexShaderEnable 1 1 +WindLightUseAtmosShaders 1 0 +WLSkyDetail 1 48 +RenderDeferred 1 0 +RenderDeferredSSAO 1 0 +RenderShadowDetail 1 0 +RenderFSAASamples 1 0 + +// // Low Graphics Settings // list Low @@ -220,6 +252,12 @@ list Class3 RenderVBOEnable 1 1 // +// VRAM > 512MB +// +list VRAMGT512 +RenderCompressTextures 1 0 + +// // No Pixel Shaders available // list NoPixelShaders @@ -291,10 +329,15 @@ RenderObjectBump 0 0 list OpenGLPre15 RenderVBOEnable 1 0 +list OpenGLPre30 +RenderDeferred 0 0 +RenderMaxTextureIndex 1 1 + list Intel RenderAnisotropic 1 0 // Avoid some Intel crashes on Linux RenderCubeMap 0 0 +RenderFSAASamples 1 0 list GeForce2 RenderAnisotropic 1 0 diff --git a/indra/newview/featuretable_mac.txt b/indra/newview/featuretable_mac.txt index 915a012a39..96362ff4bb 100644 --- a/indra/newview/featuretable_mac.txt +++ b/indra/newview/featuretable_mac.txt @@ -61,6 +61,7 @@ WLSkyDetail 1 128 Disregard128DefaultDrawDistance 1 1 Disregard96DefaultDrawDistance 1 1 RenderTextureMemoryMultiple 1 0.5 +RenderCompressTextures 1 1 RenderShaderLightingMaxLevel 1 3 RenderDeferred 1 1 RenderDeferredSSAO 1 1 @@ -71,6 +72,37 @@ RenderFSAASamples 1 16 RenderMaxTextureIndex 1 16 // +// Low Graphics Settings (fixed function) +// +list LowFixedFunction +RenderAnisotropic 1 0 +RenderAvatarCloth 1 0 +RenderAvatarLODFactor 1 0 +RenderAvatarPhysicsLODFactor 1 0 +RenderAvatarMaxVisible 1 3 +RenderAvatarVP 1 0 +RenderFarClip 1 64 +RenderFlexTimeFactor 1 0 +RenderGlowResolutionPow 1 8 +RenderLocalLights 1 0 +RenderMaxPartCount 1 0 +RenderObjectBump 1 0 +RenderReflectionDetail 1 0 +RenderTerrainDetail 1 0 +RenderTerrainLODFactor 1 1 +RenderTransparentWater 1 0 +RenderTreeLODFactor 1 0 +RenderUseImpostors 1 1 +RenderVolumeLODFactor 1 0.5 +VertexShaderEnable 1 0 +WindLightUseAtmosShaders 1 0 +WLSkyDetail 1 48 +RenderDeferred 1 0 +RenderDeferredSSAO 1 0 +RenderShadowDetail 1 0 +RenderFSAASamples 1 0 + +// // Low Graphics Settings // list Low @@ -93,7 +125,7 @@ RenderTransparentWater 1 0 RenderTreeLODFactor 1 0 RenderUseImpostors 1 1 RenderVolumeLODFactor 1 0.5 -VertexShaderEnable 1 0 +VertexShaderEnable 1 1 WindLightUseAtmosShaders 1 0 WLSkyDetail 1 48 RenderDeferred 1 0 @@ -248,6 +280,12 @@ RenderDeferredSSAO 0 0 RenderShadowDetail 0 0 // +// VRAM > 512MB +// +list VRAMGT512 +RenderCompressTextures 1 0 + +// // "Default" setups for safe, low, medium, high // list safe @@ -286,6 +324,7 @@ RenderObjectBump 0 0 list OpenGLPre15 RenderVBOEnable 1 0 + list TexUnit8orLess RenderDeferredSSAO 0 0 @@ -295,6 +334,7 @@ RenderDeferredSSAO 1 0 list Intel RenderAnisotropic 1 0 RenderLocalLights 1 0 +RenderFSAASamples 1 0 list GeForce2 RenderAnisotropic 1 0 diff --git a/indra/newview/featuretable_xp.txt b/indra/newview/featuretable_xp.txt index ae2cf910f2..a945f7a693 100644 --- a/indra/newview/featuretable_xp.txt +++ b/indra/newview/featuretable_xp.txt @@ -61,6 +61,7 @@ WLSkyDetail 1 128 Disregard128DefaultDrawDistance 1 1 Disregard96DefaultDrawDistance 1 1 RenderTextureMemoryMultiple 1 1.0 +RenderCompressTextures 1 1 RenderShaderLightingMaxLevel 1 3 RenderDeferred 1 0 RenderDeferredSSAO 1 0 @@ -71,6 +72,37 @@ RenderFSAASamples 1 16 RenderMaxTextureIndex 1 16 // +// Low Graphics Settings (fixed function) +// +list LowFixedFunction +RenderAnisotropic 1 0 +RenderAvatarCloth 1 0 +RenderAvatarLODFactor 1 0 +RenderAvatarPhysicsLODFactor 1 0 +RenderAvatarMaxVisible 1 3 +RenderAvatarVP 1 0 +RenderFarClip 1 64 +RenderFlexTimeFactor 1 0 +RenderGlowResolutionPow 1 8 +RenderLocalLights 1 0 +RenderMaxPartCount 1 0 +RenderObjectBump 1 0 +RenderReflectionDetail 1 0 +RenderTerrainDetail 1 0 +RenderTerrainLODFactor 1 1 +RenderTransparentWater 1 0 +RenderTreeLODFactor 1 0 +RenderUseImpostors 1 1 +RenderVolumeLODFactor 1 0.5 +VertexShaderEnable 1 0 +WindLightUseAtmosShaders 1 0 +WLSkyDetail 1 48 +RenderDeferred 1 0 +RenderDeferredSSAO 1 0 +RenderShadowDetail 1 0 +RenderFSAASamples 1 0 + +// // Low Graphics Settings // list Low @@ -93,7 +125,7 @@ RenderTransparentWater 1 0 RenderTreeLODFactor 1 0 RenderUseImpostors 1 1 RenderVolumeLODFactor 1 0.5 -VertexShaderEnable 1 0 +VertexShaderEnable 1 1 WindLightUseAtmosShaders 1 0 WLSkyDetail 1 48 RenderDeferred 1 0 @@ -222,6 +254,12 @@ list Class3 RenderVBOEnable 1 1 // +// VRAM > 512MB +// +list VRAMGT512 +RenderCompressTextures 1 0 + +// // No Pixel Shaders available // list NoPixelShaders @@ -299,6 +337,7 @@ RenderMaxTextureIndex 1 1 list Intel RenderAnisotropic 1 0 RenderVBOEnable 1 0 +RenderFSAASamples 1 0 list GeForce2 RenderAnisotropic 1 0 @@ -478,6 +517,7 @@ Disregard128DefaultDrawDistance 1 0 list ATIOldDriver RenderAvatarVP 0 0 RenderAvatarCloth 0 0 +RenderVBOEnable 1 0 // ATI cards generally perform better when not using VBOs for streaming data diff --git a/indra/newview/gpu_table.txt b/indra/newview/gpu_table.txt index 198e702459..777d54a5c3 100644 --- a/indra/newview/gpu_table.txt +++ b/indra/newview/gpu_table.txt @@ -205,6 +205,7 @@ ATI Radeon X800 .*ATI.*Radeon ?X8.* 2 1 ATI Radeon X900 .*ATI.*Radeon ?X9.* 2 1 ATI Radeon Xpress .*ATI.*Radeon Xpress.* 0 1 ATI Rage 128 .*ATI.*Rage 128.* 0 1 +ATI R300 (9700) .*R300.* 1 1 ATI R350 (9800) .*R350.* 1 1 ATI R580 (X1900) .*R580.* 3 1 ATI RC410 (Xpress 200) .*RC410.* 0 0 diff --git a/indra/newview/linux_tools/wrapper.sh b/indra/newview/linux_tools/wrapper.sh index 283a28a0aa..20936c6460 100755 --- a/indra/newview/linux_tools/wrapper.sh +++ b/indra/newview/linux_tools/wrapper.sh @@ -110,22 +110,34 @@ export SAVED_LD_LIBRARY_PATH="${LD_LIBRARY_PATH}" # fi #fi -export SL_ENV='LD_LIBRARY_PATH="`pwd`"/lib:"${LD_LIBRARY_PATH}"' -export SL_CMD='$LL_WRAPPER bin/do-not-directly-run-secondlife-bin' -export SL_OPT="`cat etc/gridargs.dat` $@" - -# Run the program -eval ${SL_ENV} ${SL_CMD} ${SL_OPT} || LL_RUN_ERR=runerr +export LD_LIBRARY_PATH="$PWD/lib:${LD_LIBRARY_PATH}" + +# Have to deal specially with gridargs.dat; typical contents look like: +# --channel "Second Life Developer" --settings settings_developer.xml +# Simply embedding $(<etc/gridargs.dat) into a command line treats each of +# Second, Life and Developer as separate args -- no good. We need bash to +# process quotes using eval. +# First read it without scanning, then scan that string. Break quoted words +# into a bash array. Note that if gridargs.dat is empty, or contains only +# whitespace, the resulting gridargs array will be empty -- zero entries -- +# therefore "${gridargs[@]}" entirely vanishes from the command line below, +# just as we want. +eval gridargs=("$(<etc/gridargs.dat)") + +# Run the program. +# Don't quote $LL_WRAPPER because, if empty, it should simply vanish from the +# command line. But DO quote "$@": preserve separate args as individually +# quoted. Similar remarks about the contents of gridargs. +$LL_WRAPPER bin/do-not-directly-run-secondlife-bin "${gridargs[@]}" "$@" +LL_RUN_ERR=$? # Handle any resulting errors -if [ -n "$LL_RUN_ERR" ]; then - LL_RUN_ERR_MSG="" - if [ "$LL_RUN_ERR" = "runerr" ]; then - # generic error running the binary - echo '*** Bad shutdown. ***' - if [ "`uname -m`" = "x86_64" ]; then - echo - cat << EOFMARKER +if [ $LL_RUN_ERR -ne 0 ]; then + # generic error running the binary + echo '*** Bad shutdown ($LL_RUN_ERR). ***' + if [ "$(uname -m)" = "x86_64" ]; then + echo + cat << EOFMARKER You are running the Second Life Viewer on a x86_64 platform. The most common problems when launching the Viewer (particularly 'bin/do-not-directly-run-secondlife-bin: not found' and 'error while @@ -134,10 +146,8 @@ distribution's 32-bit compatibility packages. For example, on Ubuntu and other Debian-based Linuxes you might run: $ sudo apt-get install ia32-libs ia32-libs-gtk ia32-libs-kde ia32-libs-sdl EOFMARKER - fi fi fi - echo echo '*******************************************************' diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 0db03289d8..8960ca7569 100755 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -81,6 +81,7 @@ #include "llviewermenu.h" #include "llviewerobjectlist.h" #include "llviewerparcelmgr.h" +#include "llviewerregion.h" #include "llviewerstats.h" #include "llviewerwindow.h" #include "llvoavatarself.h" @@ -112,6 +113,105 @@ const F32 MAX_FIDGET_TIME = 20.f; // seconds // The agent instance. LLAgent gAgent; +class LLTeleportRequest +{ +public: + enum EStatus + { + kPending, + kStarted, + kFailed, + kRestartPending + }; + + LLTeleportRequest(); + virtual ~LLTeleportRequest(); + + EStatus getStatus() const {return mStatus;}; + void setStatus(EStatus pStatus) {mStatus = pStatus;}; + + virtual bool canRestartTeleport(); + + virtual void startTeleport() = 0; + virtual void restartTeleport(); + +protected: + +private: + EStatus mStatus; +}; + +class LLTeleportRequestViaLandmark : public LLTeleportRequest +{ +public: + LLTeleportRequestViaLandmark(const LLUUID &pLandmarkId); + virtual ~LLTeleportRequestViaLandmark(); + + virtual bool canRestartTeleport(); + + virtual void startTeleport(); + virtual void restartTeleport(); + +protected: + inline const LLUUID &getLandmarkId() const {return mLandmarkId;}; + +private: + LLUUID mLandmarkId; +}; + +class LLTeleportRequestViaLure : public LLTeleportRequestViaLandmark +{ +public: + LLTeleportRequestViaLure(const LLUUID &pLureId, BOOL pIsLureGodLike); + virtual ~LLTeleportRequestViaLure(); + + virtual bool canRestartTeleport(); + + virtual void startTeleport(); + +protected: + inline BOOL isLureGodLike() const {return mIsLureGodLike;}; + +private: + BOOL mIsLureGodLike; +}; + +class LLTeleportRequestViaLocation : public LLTeleportRequest +{ +public: + LLTeleportRequestViaLocation(const LLVector3d &pPosGlobal); + virtual ~LLTeleportRequestViaLocation(); + + virtual bool canRestartTeleport(); + + virtual void startTeleport(); + virtual void restartTeleport(); + +protected: + inline const LLVector3d &getPosGlobal() const {return mPosGlobal;}; + +private: + LLVector3d mPosGlobal; +}; + + +class LLTeleportRequestViaLocationLookAt : public LLTeleportRequestViaLocation +{ +public: + LLTeleportRequestViaLocationLookAt(const LLVector3d &pPosGlobal); + virtual ~LLTeleportRequestViaLocationLookAt(); + + virtual bool canRestartTeleport(); + + virtual void startTeleport(); + virtual void restartTeleport(); + +protected: + +private: + +}; + //-------------------------------------------------------------------- // Statics // @@ -245,6 +345,17 @@ LLAgent::LLAgent() : mAgentAccess(new LLAgentAccess(gSavedSettings)), mCanEditParcel(false), mTeleportSourceSLURL(new LLSLURL), + mTeleportRequest(), + mTeleportFinishedSlot(), + mTeleportFailedSlot(), + mIsMaturityRatingChangingDuringTeleport(false), + mMaturityRatingChange(0U), + mIsDoSendMaturityPreferenceToServer(false), + mMaturityPreferenceRequestId(0U), + mMaturityPreferenceResponseId(0U), + mMaturityPreferenceNumRetries(0U), + mLastKnownRequestMaturity(SIM_ACCESS_MIN), + mLastKnownResponseMaturity(SIM_ACCESS_MIN), mTeleportState( TELEPORT_NONE ), mRegionp(NULL), @@ -330,9 +441,21 @@ void LLAgent::init() gSavedSettings.getControl("PreferredMaturity")->getValidateSignal()->connect(boost::bind(&LLAgent::validateMaturity, this, _2)); gSavedSettings.getControl("PreferredMaturity")->getSignal()->connect(boost::bind(&LLAgent::handleMaturity, this, _2)); + mLastKnownResponseMaturity = static_cast<U8>(gSavedSettings.getU32("PreferredMaturity")); + mLastKnownRequestMaturity = mLastKnownResponseMaturity; + mIsDoSendMaturityPreferenceToServer = true; LLViewerParcelMgr::getInstance()->addAgentParcelChangedCallback(boost::bind(&LLAgent::parcelChangedCallback)); + if (!mTeleportFinishedSlot.connected()) + { + mTeleportFinishedSlot = LLViewerParcelMgr::getInstance()->setTeleportFinishedCallback(boost::bind(&LLAgent::handleTeleportFinished, this)); + } + if (!mTeleportFailedSlot.connected()) + { + mTeleportFailedSlot = LLViewerParcelMgr::getInstance()->setTeleportFailedCallback(boost::bind(&LLAgent::handleTeleportFailed, this)); + } + mInitialized = TRUE; } @@ -342,6 +465,14 @@ void LLAgent::init() void LLAgent::cleanup() { mRegionp = NULL; + if (mTeleportFinishedSlot.connected()) + { + mTeleportFinishedSlot.disconnect(); + } + if (mTeleportFailedSlot.connected()) + { + mTeleportFailedSlot.disconnect(); + } } //----------------------------------------------------------------------------- @@ -2371,49 +2502,278 @@ bool LLAgent::isAdult() const return mAgentAccess->isAdult(); } -void LLAgent::setTeen(bool teen) -{ - mAgentAccess->setTeen(teen); -} - //static int LLAgent::convertTextToMaturity(char text) { return LLAgentAccess::convertTextToMaturity(text); } -bool LLAgent::sendMaturityPreferenceToServer(int preferredMaturity) +class LLMaturityPreferencesResponder : public LLHTTPClient::Responder { - if (!getRegion()) - return false; +public: + LLMaturityPreferencesResponder(LLAgent *pAgent, U8 pPreferredMaturity, U8 pPreviousMaturity); + virtual ~LLMaturityPreferencesResponder(); + + virtual void result(const LLSD &pContent); + virtual void error(U32 pStatus, const std::string& pReason); + +protected: + +private: + U8 parseMaturityFromServerResponse(const LLSD &pContent); + + LLAgent *mAgent; + U8 mPreferredMaturity; + U8 mPreviousMaturity; +}; + +LLMaturityPreferencesResponder::LLMaturityPreferencesResponder(LLAgent *pAgent, U8 pPreferredMaturity, U8 pPreviousMaturity) + : LLHTTPClient::Responder(), + mAgent(pAgent), + mPreferredMaturity(pPreferredMaturity), + mPreviousMaturity(pPreviousMaturity) +{ +} + +LLMaturityPreferencesResponder::~LLMaturityPreferencesResponder() +{ +} + +void LLMaturityPreferencesResponder::result(const LLSD &pContent) +{ + U8 actualMaturity = parseMaturityFromServerResponse(pContent); + + if (actualMaturity != mPreferredMaturity) + { + llwarns << "while attempting to change maturity preference from '" << LLViewerRegion::accessToString(mPreviousMaturity) + << "' to '" << LLViewerRegion::accessToString(mPreferredMaturity) << "', the server responded with '" + << LLViewerRegion::accessToString(actualMaturity) << "' [value:" << static_cast<U32>(actualMaturity) << ", llsd:" + << pContent << "]" << llendl; + } + mAgent->handlePreferredMaturityResult(actualMaturity); +} + +void LLMaturityPreferencesResponder::error(U32 pStatus, const std::string& pReason) +{ + llwarns << "while attempting to change maturity preference from '" << LLViewerRegion::accessToString(mPreviousMaturity) + << "' to '" << LLViewerRegion::accessToString(mPreferredMaturity) << "', we got an error because '" + << pReason << "' [status:" << pStatus << "]" << llendl; + mAgent->handlePreferredMaturityError(); +} + +U8 LLMaturityPreferencesResponder::parseMaturityFromServerResponse(const LLSD &pContent) +{ + // stinson 05/24/2012 Pathfinding regions have re-defined the response behavior. In the old server code, + // if you attempted to change the preferred maturity to the same value, the response content would be an + // undefined LLSD block. In the new server code with pathfinding, the response content should always be + // defined. Thus, the check for isUndefined() can be replaced with an assert after pathfinding is merged + // into server trunk and fully deployed. + U8 maturity = SIM_ACCESS_MIN; + if (pContent.isUndefined()) + { + maturity = mPreferredMaturity; + } + else + { + llassert(!pContent.isUndefined()); + llassert(pContent.isMap()); - // Update agent access preference on the server - std::string url = getRegion()->getCapability("UpdateAgentInformation"); - if (!url.empty()) + if (!pContent.isUndefined() && pContent.isMap()) + { + // stinson 05/24/2012 Pathfinding regions have re-defined the response syntax. The if statement catches + // the new syntax, and the else statement catches the old syntax. After pathfinding is merged into + // server trunk and fully deployed, we can remove the else statement. + if (pContent.has("access_prefs")) + { + llassert(pContent.has("access_prefs")); + llassert(pContent.get("access_prefs").isMap()); + llassert(pContent.get("access_prefs").has("max")); + llassert(pContent.get("access_prefs").get("max").isString()); + if (pContent.get("access_prefs").isMap() && pContent.get("access_prefs").has("max") && + pContent.get("access_prefs").get("max").isString()) + { + LLSD::String actualPreference = pContent.get("access_prefs").get("max").asString(); + LLStringUtil::trim(actualPreference); + maturity = LLViewerRegion::shortStringToAccess(actualPreference); + } + } + else if (pContent.has("max")) + { + llassert(pContent.get("max").isString()); + if (pContent.get("max").isString()) + { + LLSD::String actualPreference = pContent.get("max").asString(); + LLStringUtil::trim(actualPreference); + maturity = LLViewerRegion::shortStringToAccess(actualPreference); + } + } + } + } + + return maturity; +} + +void LLAgent::handlePreferredMaturityResult(U8 pServerMaturity) +{ + // Update the number of responses received + ++mMaturityPreferenceResponseId; + llassert(mMaturityPreferenceResponseId <= mMaturityPreferenceRequestId); + + // Update the last known server maturity response + mLastKnownResponseMaturity = pServerMaturity; + + // Ignore all responses if we know there are more unanswered requests that are expected + if (mMaturityPreferenceResponseId == mMaturityPreferenceRequestId) { - // Set new access preference - LLSD access_prefs = LLSD::emptyMap(); - if (preferredMaturity == SIM_ACCESS_PG) + // If we received a response that matches the last known request, then we are good + if (mLastKnownRequestMaturity == mLastKnownResponseMaturity) { - access_prefs["max"] = "PG"; + mMaturityPreferenceNumRetries = 0; + reportPreferredMaturitySuccess(); + llassert(static_cast<U8>(gSavedSettings.getU32("PreferredMaturity")) == mLastKnownResponseMaturity); } - else if (preferredMaturity == SIM_ACCESS_MATURE) + // Else, the viewer is out of sync with the server, so let's try to re-sync with the + // server by re-sending our last known request. Cap the re-tries at 3 just to be safe. + else if (++mMaturityPreferenceNumRetries <= 3) { - access_prefs["max"] = "M"; + llinfos << "Retrying attempt #" << mMaturityPreferenceNumRetries << " to set viewer preferred maturity to '" + << LLViewerRegion::accessToString(mLastKnownRequestMaturity) << "'" << llendl; + sendMaturityPreferenceToServer(mLastKnownRequestMaturity); } - if (preferredMaturity == SIM_ACCESS_ADULT) + // Else, the viewer is style out of sync with the server after 3 retries, so inform the user + else { - access_prefs["max"] = "A"; + mMaturityPreferenceNumRetries = 0; + reportPreferredMaturityError(); + } + } +} + +void LLAgent::handlePreferredMaturityError() +{ + // Update the number of responses received + ++mMaturityPreferenceResponseId; + llassert(mMaturityPreferenceResponseId <= mMaturityPreferenceRequestId); + + // Ignore all responses if we know there are more unanswered requests that are expected + if (mMaturityPreferenceResponseId == mMaturityPreferenceRequestId) + { + mMaturityPreferenceNumRetries = 0; + + // If we received a response that matches the last known request, then we are synced with + // the server, but not quite sure why we are + if (mLastKnownRequestMaturity == mLastKnownResponseMaturity) + { + llwarns << "Got an error but maturity preference '" << LLViewerRegion::accessToString(mLastKnownRequestMaturity) + << "' seems to be in sync with the server" << llendl; + reportPreferredMaturitySuccess(); + } + // Else, the more likely case is that the last request does not match the last response, + // so inform the user + else + { + reportPreferredMaturityError(); + } + } +} + +void LLAgent::reportPreferredMaturitySuccess() +{ + // If there is a pending teleport request waiting for the maturity preference to be synced with + // the server, let's start the pending request + if (hasPendingTeleportRequest()) + { + startTeleportRequest(); + } +} + +void LLAgent::reportPreferredMaturityError() +{ + // If there is a pending teleport request waiting for the maturity preference to be synced with + // the server, we were unable to successfully sync with the server on maturity preference, so let's + // just raise the screen. + mIsMaturityRatingChangingDuringTeleport = false; + if (hasPendingTeleportRequest()) + { + setTeleportState(LLAgent::TELEPORT_NONE); + } + + // Get the last known maturity request from the user activity + std::string preferredMaturity = LLViewerRegion::accessToString(mLastKnownRequestMaturity); + LLStringUtil::toLower(preferredMaturity); + + // Get the last known maturity response from the server + std::string actualMaturity = LLViewerRegion::accessToString(mLastKnownResponseMaturity); + LLStringUtil::toLower(actualMaturity); + + // Notify the user + LLSD args = LLSD::emptyMap(); + args["PREFERRED_MATURITY"] = preferredMaturity; + args["ACTUAL_MATURITY"] = actualMaturity; + LLNotificationsUtil::add("MaturityChangeError", args); + + // Check the saved settings to ensure that we are consistent. If we are not consistent, update + // the viewer, but do not send anything to server + U8 localMaturity = static_cast<U8>(gSavedSettings.getU32("PreferredMaturity")); + if (localMaturity != mLastKnownResponseMaturity) + { + bool tmpIsDoSendMaturityPreferenceToServer = mIsDoSendMaturityPreferenceToServer; + mIsDoSendMaturityPreferenceToServer = false; + llinfos << "Setting viewer preferred maturity to '" << LLViewerRegion::accessToString(mLastKnownResponseMaturity) << "'" << llendl; + gSavedSettings.setU32("PreferredMaturity", static_cast<U32>(mLastKnownResponseMaturity)); + mIsDoSendMaturityPreferenceToServer = tmpIsDoSendMaturityPreferenceToServer; + } +} + +bool LLAgent::isMaturityPreferenceSyncedWithServer() const +{ + return (mMaturityPreferenceRequestId == mMaturityPreferenceResponseId); +} + +void LLAgent::sendMaturityPreferenceToServer(U8 pPreferredMaturity) +{ + // Only send maturity preference to the server if enabled + if (mIsDoSendMaturityPreferenceToServer) + { + // Increment the number of requests. The handlers manage a separate count of responses. + ++mMaturityPreferenceRequestId; + + // Update the last know maturity request + mLastKnownRequestMaturity = pPreferredMaturity; + + // Create a response handler + LLHTTPClient::ResponderPtr responderPtr = LLHTTPClient::ResponderPtr(new LLMaturityPreferencesResponder(this, pPreferredMaturity, mLastKnownResponseMaturity)); + + // If we don't have a region, report it as an error + if (getRegion() == NULL) + { + responderPtr->error(0U, "region is not defined"); + } + else + { + // Find the capability to send maturity preference + std::string url = getRegion()->getCapability("UpdateAgentInformation"); + + // If the capability is not defined, report it as an error + if (url.empty()) + { + responderPtr->error(0U, "capability 'UpdateAgentInformation' is not defined for region"); + } + else + { + // Set new access preference + LLSD access_prefs = LLSD::emptyMap(); + access_prefs["max"] = LLViewerRegion::accessToShortString(pPreferredMaturity); + + LLSD body = LLSD::emptyMap(); + body["access_prefs"] = access_prefs; + llinfos << "Sending viewer preferred maturity to '" << LLViewerRegion::accessToString(pPreferredMaturity) + << "' via capability to: " << url << llendl; + LLSD headers; + LLHTTPClient::post(url, body, responderPtr, headers, 30.0f); + } } - - LLSD body = LLSD::emptyMap(); - body["access_prefs"] = access_prefs; - llinfos << "Sending access prefs update to " << (access_prefs["max"].asString()) << " via capability to: " - << url << llendl; - LLHTTPClient::post(url, body, new LLHTTPClient::Responder()); // Ignore response - return true; } - return false; } BOOL LLAgent::getAdminOverride() const @@ -2436,11 +2796,6 @@ void LLAgent::setGodLevel(U8 god_level) mAgentAccess->setGodLevel(god_level); } -void LLAgent::setAOTransition() -{ - mAgentAccess->setTransition(); -} - const LLAgentAccess& LLAgent::getAgentAccess() { return *mAgentAccess; @@ -2451,9 +2806,9 @@ bool LLAgent::validateMaturity(const LLSD& newvalue) return mAgentAccess->canSetMaturity(newvalue.asInteger()); } -void LLAgent::handleMaturity(const LLSD& newvalue) +void LLAgent::handleMaturity(const LLSD &pNewValue) { - sendMaturityPreferenceToServer(newvalue.asInteger()); + sendMaturityPreferenceToServer(static_cast<U8>(pNewValue.asInteger())); } //---------------------------------------------------------------------------- @@ -3253,6 +3608,10 @@ void LLAgent::processControlRelease(LLMessageSystem *msg, void **) void LLAgent::processAgentCachedTextureResponse(LLMessageSystem *mesgsys, void **user_data) { gAgentQueryManager.mNumPendingQueries--; + if (gAgentQueryManager.mNumPendingQueries == 0) + { + selfStopPhase("fetch_texture_cache_entries"); + } if (!isAgentAvatarValid() || gAgentAvatarp->isDead()) { @@ -3302,13 +3661,12 @@ void LLAgent::processAgentCachedTextureResponse(LLMessageSystem *mesgsys, void * else { // no cache of this bake. request upload. - gAgentAvatarp->requestLayerSetUpload(baked_index); + gAgentAvatarp->invalidateComposite(gAgentAvatarp->getLayerSet(baked_index),TRUE); } } } } } - llinfos << "Received cached texture response for " << num_results << " textures." << llendl; gAgentAvatarp->outputRezTiming("Fetched agent wearables textures from cache. Will now load them"); @@ -3385,7 +3743,7 @@ void LLAgent::clearVisualParams(void *data) // protected bool LLAgent::teleportCore(bool is_local) { - if(TELEPORT_NONE != mTeleportState) + if ((TELEPORT_NONE != mTeleportState) && (mTeleportState != TELEPORT_PENDING)) { llwarns << "Attempt to teleport when already teleporting." << llendl; return false; @@ -3463,6 +3821,102 @@ bool LLAgent::teleportCore(bool is_local) return true; } +bool LLAgent::hasRestartableFailedTeleportRequest() +{ + return ((mTeleportRequest != NULL) && (mTeleportRequest->getStatus() == LLTeleportRequest::kFailed) && + mTeleportRequest->canRestartTeleport()); +} + +void LLAgent::restartFailedTeleportRequest() +{ + if (hasRestartableFailedTeleportRequest()) + { + mTeleportRequest->setStatus(LLTeleportRequest::kRestartPending); + startTeleportRequest(); + } +} + +void LLAgent::clearTeleportRequest() +{ + mTeleportRequest.reset(); +} + +void LLAgent::setMaturityRatingChangeDuringTeleport(U8 pMaturityRatingChange) +{ + mIsMaturityRatingChangingDuringTeleport = true; + mMaturityRatingChange = pMaturityRatingChange; +} + +bool LLAgent::hasPendingTeleportRequest() +{ + return ((mTeleportRequest != NULL) && + ((mTeleportRequest->getStatus() == LLTeleportRequest::kPending) || + (mTeleportRequest->getStatus() == LLTeleportRequest::kRestartPending))); +} + +void LLAgent::startTeleportRequest() +{ + if (hasPendingTeleportRequest()) + { + if (!isMaturityPreferenceSyncedWithServer()) + { + gTeleportDisplay = TRUE; + setTeleportState(TELEPORT_PENDING); + } + else + { + switch (mTeleportRequest->getStatus()) + { + case LLTeleportRequest::kPending : + mTeleportRequest->setStatus(LLTeleportRequest::kStarted); + mTeleportRequest->startTeleport(); + break; + case LLTeleportRequest::kRestartPending : + llassert(mTeleportRequest->canRestartTeleport()); + mTeleportRequest->setStatus(LLTeleportRequest::kStarted); + mTeleportRequest->restartTeleport(); + break; + default : + llassert(0); + break; + } + } + } +} + +void LLAgent::handleTeleportFinished() +{ + clearTeleportRequest(); + if (mIsMaturityRatingChangingDuringTeleport) + { + // notify user that the maturity preference has been changed + std::string maturityRating = LLViewerRegion::accessToString(mMaturityRatingChange); + LLStringUtil::toLower(maturityRating); + LLSD args; + args["RATING"] = maturityRating; + LLNotificationsUtil::add("PreferredMaturityChanged", args); + mIsMaturityRatingChangingDuringTeleport = false; + } +} + +void LLAgent::handleTeleportFailed() +{ + if (mTeleportRequest != NULL) + { + mTeleportRequest->setStatus(LLTeleportRequest::kFailed); + } + if (mIsMaturityRatingChangingDuringTeleport) + { + // notify user that the maturity preference has been changed + std::string maturityRating = LLViewerRegion::accessToString(mMaturityRatingChange); + LLStringUtil::toLower(maturityRating); + LLSD args; + args["RATING"] = maturityRating; + LLNotificationsUtil::add("PreferredMaturityChanged", args); + mIsMaturityRatingChangingDuringTeleport = false; + } +} + void LLAgent::teleportRequest( const U64& region_handle, const LLVector3& pos_local, @@ -3495,6 +3949,12 @@ void LLAgent::teleportRequest( // Landmark ID = LLUUID::null means teleport home void LLAgent::teleportViaLandmark(const LLUUID& landmark_asset_id) { + mTeleportRequest = LLTeleportRequestPtr(new LLTeleportRequestViaLandmark(landmark_asset_id)); + startTeleportRequest(); +} + +void LLAgent::doTeleportViaLandmark(const LLUUID& landmark_asset_id) +{ LLViewerRegion *regionp = getRegion(); if(regionp && teleportCore()) { @@ -3510,6 +3970,12 @@ void LLAgent::teleportViaLandmark(const LLUUID& landmark_asset_id) void LLAgent::teleportViaLure(const LLUUID& lure_id, BOOL godlike) { + mTeleportRequest = LLTeleportRequestPtr(new LLTeleportRequestViaLure(lure_id, godlike)); + startTeleportRequest(); +} + +void LLAgent::doTeleportViaLure(const LLUUID& lure_id, BOOL godlike) +{ LLViewerRegion* regionp = getRegion(); if(regionp && teleportCore()) { @@ -3541,24 +4007,33 @@ void LLAgent::teleportViaLure(const LLUUID& lure_id, BOOL godlike) // James Cook, July 28, 2005 void LLAgent::teleportCancel() { - LLViewerRegion* regionp = getRegion(); - if(regionp) + if (!hasPendingTeleportRequest()) { - // send the message - LLMessageSystem* msg = gMessageSystem; - msg->newMessage("TeleportCancel"); - msg->nextBlockFast(_PREHASH_Info); - msg->addUUIDFast(_PREHASH_AgentID, getID()); - msg->addUUIDFast(_PREHASH_SessionID, getSessionID()); - sendReliableMessage(); - } - gTeleportDisplay = FALSE; + LLViewerRegion* regionp = getRegion(); + if(regionp) + { + // send the message + LLMessageSystem* msg = gMessageSystem; + msg->newMessage("TeleportCancel"); + msg->nextBlockFast(_PREHASH_Info); + msg->addUUIDFast(_PREHASH_AgentID, getID()); + msg->addUUIDFast(_PREHASH_SessionID, getSessionID()); + sendReliableMessage(); + } + } + clearTeleportRequest(); gAgent.setTeleportState( LLAgent::TELEPORT_NONE ); } void LLAgent::teleportViaLocation(const LLVector3d& pos_global) { + mTeleportRequest = LLTeleportRequestPtr(new LLTeleportRequestViaLocation(pos_global)); + startTeleportRequest(); +} + +void LLAgent::doTeleportViaLocation(const LLVector3d& pos_global) +{ LLViewerRegion* regionp = getRegion(); U64 handle = to_region_handle(pos_global); LLSimInfo* info = LLWorldMap::getInstance()->simInfoFromHandle(handle); @@ -3601,6 +4076,12 @@ void LLAgent::teleportViaLocation(const LLVector3d& pos_global) // Teleport to global position, but keep facing in the same direction void LLAgent::teleportViaLocationLookAt(const LLVector3d& pos_global) { + mTeleportRequest = LLTeleportRequestPtr(new LLTeleportRequestViaLocationLookAt(pos_global)); + startTeleportRequest(); +} + +void LLAgent::doTeleportViaLocationLookAt(const LLVector3d& pos_global) +{ mbTeleportKeepsLookAt = true; gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE); // detach camera form avatar, so it keeps direction U64 region_handle = to_region_handle(pos_global); @@ -3775,7 +4256,15 @@ void LLAgent::sendAgentSetAppearance() return; } - llinfos << "TAT: Sent AgentSetAppearance: " << gAgentAvatarp->getBakedStatusForPrintout() << llendl; + if (!gAgentWearables.changeInProgress()) + { + // Change is fully resolved, can close some open phases. + gAgentAvatarp->getPhases().stopPhase("process_initial_wearables_update"); + gAgentAvatarp->getPhases().stopPhase("wear_inventory_category"); + } + + gAgentAvatarp->sendAppearanceChangeMetrics(); + LL_INFOS("Avatar") << gAgentAvatarp->avString() << "TAT: Sent AgentSetAppearance: " << gAgentAvatarp->getBakedStatusForPrintout() << LL_ENDL; //dumpAvatarTEs( "sendAgentSetAppearance()" ); LLMessageSystem* msg = gMessageSystem; @@ -3822,14 +4311,14 @@ void LLAgent::sendAgentSetAppearance() // only update cache entries if we have all our baked textures if (textures_current) { - llinfos << "TAT: Sending cached texture data" << llendl; + LL_INFOS("Avatar") << gAgentAvatarp->avString() << "TAT: Sending cached texture data" << LL_ENDL; for (U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++) { BOOL generate_valid_hash = TRUE; if (isAgentAvatarValid() && !gAgentAvatarp->isBakedTextureFinal((LLVOAvatarDefines::EBakedTextureIndex)baked_index)) { generate_valid_hash = FALSE; - llinfos << "Not caching baked texture upload for " << (U32)baked_index << " due to being uploaded at low resolution." << llendl; + LL_DEBUGS("Avatar") << gAgentAvatarp->avString() << "Not caching baked texture upload for " << (U32)baked_index << " due to being uploaded at low resolution." << LL_ENDL; } const LLUUID hash = gAgentWearables.computeBakedTextureHash((EBakedTextureIndex) baked_index, generate_valid_hash); @@ -4034,5 +4523,149 @@ LLAgentQueryManager::~LLAgentQueryManager() { } -// EOF +//----------------------------------------------------------------------------- +// LLTeleportRequest +//----------------------------------------------------------------------------- + +LLTeleportRequest::LLTeleportRequest() + : mStatus(kPending) +{ +} +LLTeleportRequest::~LLTeleportRequest() +{ +} + +bool LLTeleportRequest::canRestartTeleport() +{ + return false; +} + +void LLTeleportRequest::restartTeleport() +{ + llassert(0); +} + +//----------------------------------------------------------------------------- +// LLTeleportRequestViaLandmark +//----------------------------------------------------------------------------- + +LLTeleportRequestViaLandmark::LLTeleportRequestViaLandmark(const LLUUID &pLandmarkId) + : LLTeleportRequest(), + mLandmarkId(pLandmarkId) +{ +} + +LLTeleportRequestViaLandmark::~LLTeleportRequestViaLandmark() +{ +} + +bool LLTeleportRequestViaLandmark::canRestartTeleport() +{ + return true; +} + +void LLTeleportRequestViaLandmark::startTeleport() +{ + gAgent.doTeleportViaLandmark(getLandmarkId()); +} + +void LLTeleportRequestViaLandmark::restartTeleport() +{ + gAgent.doTeleportViaLandmark(getLandmarkId()); +} + +//----------------------------------------------------------------------------- +// LLTeleportRequestViaLure +//----------------------------------------------------------------------------- + +LLTeleportRequestViaLure::LLTeleportRequestViaLure(const LLUUID &pLureId, BOOL pIsLureGodLike) + : LLTeleportRequestViaLandmark(pLureId), + mIsLureGodLike(pIsLureGodLike) +{ +} + +LLTeleportRequestViaLure::~LLTeleportRequestViaLure() +{ +} + +bool LLTeleportRequestViaLure::canRestartTeleport() +{ + // stinson 05/17/2012 : cannot restart a teleport via lure because of server-side restrictions + // The current scenario is as follows: + // 1. User A initializes a request for User B to teleport via lure + // 2. User B accepts the teleport via lure request + // 3. The server sees the init request from User A and the accept request from User B and matches them up + // 4. The server then removes the paired requests up from the "queue" + // 5. The server then fails User B's teleport for reason of maturity level (for example) + // 6. User B's viewer prompts user to increase their maturity level profile value. + // 7. User B confirms and accepts increase in maturity level + // 8. User B's viewer then attempts to teleport via lure again + // 9. This request will time-out on the viewer-side because User A's initial request has been removed from the "queue" in step 4 + + return false; +} + +void LLTeleportRequestViaLure::startTeleport() +{ + gAgent.doTeleportViaLure(getLandmarkId(), isLureGodLike()); +} + +//----------------------------------------------------------------------------- +// LLTeleportRequestViaLocation +//----------------------------------------------------------------------------- + +LLTeleportRequestViaLocation::LLTeleportRequestViaLocation(const LLVector3d &pPosGlobal) + : LLTeleportRequest(), + mPosGlobal(pPosGlobal) +{ +} + +LLTeleportRequestViaLocation::~LLTeleportRequestViaLocation() +{ +} + +bool LLTeleportRequestViaLocation::canRestartTeleport() +{ + return true; +} + +void LLTeleportRequestViaLocation::startTeleport() +{ + gAgent.doTeleportViaLocation(getPosGlobal()); +} + +void LLTeleportRequestViaLocation::restartTeleport() +{ + gAgent.doTeleportViaLocation(getPosGlobal()); +} + +//----------------------------------------------------------------------------- +// LLTeleportRequestViaLocationLookAt +//----------------------------------------------------------------------------- + +LLTeleportRequestViaLocationLookAt::LLTeleportRequestViaLocationLookAt(const LLVector3d &pPosGlobal) + : LLTeleportRequestViaLocation(pPosGlobal) +{ +} + +LLTeleportRequestViaLocationLookAt::~LLTeleportRequestViaLocationLookAt() +{ +} + +bool LLTeleportRequestViaLocationLookAt::canRestartTeleport() +{ + return true; +} + +void LLTeleportRequestViaLocationLookAt::startTeleport() +{ + gAgent.doTeleportViaLocationLookAt(getPosGlobal()); +} + +void LLTeleportRequestViaLocationLookAt::restartTeleport() +{ + gAgent.doTeleportViaLocationLookAt(getPosGlobal()); +} + +// EOF diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h index 740770bbdf..a505d5bbae 100644 --- a/indra/newview/llagent.h +++ b/indra/newview/llagent.h @@ -35,6 +35,8 @@ #include "llcoordframe.h" // for mFrameAgent #include "llvoavatardefines.h" +#include <boost/function.hpp> +#include <boost/shared_ptr.hpp> #include <boost/signals2.hpp> extern const BOOL ANIMATE; @@ -56,6 +58,9 @@ class LLAgentAccess; class LLSLURL; class LLPauseRequestHandle; class LLUIColor; +class LLTeleportRequest; + +typedef boost::shared_ptr<LLTeleportRequest> LLTeleportRequestPtr; //-------------------------------------------------------------------- // Types @@ -539,7 +544,8 @@ public: TELEPORT_MOVING = 3, // Viewer has received destination location from source simulator TELEPORT_START_ARRIVAL = 4, // Transition to ARRIVING. Viewer has received avatar update, etc., from destination simulator TELEPORT_ARRIVING = 5, // Make the user wait while content "pre-caches" - TELEPORT_LOCAL = 6 // Teleporting in-sim without showing the progress screen + TELEPORT_LOCAL = 6, // Teleporting in-sim without showing the progress screen + TELEPORT_PENDING = 7 }; public: @@ -556,9 +562,6 @@ private: // Teleport Actions //-------------------------------------------------------------------- public: - void teleportRequest(const U64& region_handle, - const LLVector3& pos_local, // Go to a named location home - bool look_at_from_camera = false); void teleportViaLandmark(const LLUUID& landmark_id); // Teleport to a landmark void teleportHome() { teleportViaLandmark(LLUUID::null); } // Go home void teleportViaLure(const LLUUID& lure_id, BOOL godlike); // To an invited location @@ -572,6 +575,44 @@ protected: //-------------------------------------------------------------------- // Teleport State //-------------------------------------------------------------------- + +public: + bool hasRestartableFailedTeleportRequest(); + void restartFailedTeleportRequest(); + void clearTeleportRequest(); + void setMaturityRatingChangeDuringTeleport(U8 pMaturityRatingChange); + +private: + friend class LLTeleportRequest; + friend class LLTeleportRequestViaLandmark; + friend class LLTeleportRequestViaLure; + friend class LLTeleportRequestViaLocation; + friend class LLTeleportRequestViaLocationLookAt; + + LLTeleportRequestPtr mTeleportRequest; + boost::signals2::connection mTeleportFinishedSlot; + boost::signals2::connection mTeleportFailedSlot; + + bool mIsMaturityRatingChangingDuringTeleport; + U8 mMaturityRatingChange; + + bool hasPendingTeleportRequest(); + void startTeleportRequest(); + + void teleportRequest(const U64& region_handle, + const LLVector3& pos_local, // Go to a named location home + bool look_at_from_camera = false); + void doTeleportViaLandmark(const LLUUID& landmark_id); // Teleport to a landmark + void doTeleportViaLure(const LLUUID& lure_id, BOOL godlike); // To an invited location + void doTeleportViaLocation(const LLVector3d& pos_global); // To a global location - this will probably need to be deprecated + void doTeleportViaLocationLookAt(const LLVector3d& pos_global);// To a global location, preserving camera rotation + + void handleTeleportFinished(); + void handleTeleportFailed(); + + //-------------------------------------------------------------------- + // Teleport State + //-------------------------------------------------------------------- public: ETeleportState getTeleportState() const { return mTeleportState; } void setTeleportState(ETeleportState state); @@ -614,8 +655,6 @@ public: const LLAgentAccess& getAgentAccess(); BOOL canManageEstate() const; BOOL getAdminOverride() const; - // ! BACKWARDS COMPATIBILITY ! This function can go away after the AO transition (see llstartup.cpp). - void setAOTransition(); private: LLAgentAccess * mAgentAccess; @@ -650,13 +689,28 @@ public: bool isTeen() const; bool isMature() const; bool isAdult() const; - void setTeen(bool teen); void setMaturity(char text); - static int convertTextToMaturity(char text); - bool sendMaturityPreferenceToServer(int preferredMaturity); // ! "U8" instead of "int"? + static int convertTextToMaturity(char text); + +private: + bool mIsDoSendMaturityPreferenceToServer; + unsigned int mMaturityPreferenceRequestId; + unsigned int mMaturityPreferenceResponseId; + unsigned int mMaturityPreferenceNumRetries; + U8 mLastKnownRequestMaturity; + U8 mLastKnownResponseMaturity; + + bool isMaturityPreferenceSyncedWithServer() const; + void sendMaturityPreferenceToServer(U8 pPreferredMaturity); + + friend class LLMaturityPreferencesResponder; + void handlePreferredMaturityResult(U8 pServerMaturity); + void handlePreferredMaturityError(); + void reportPreferredMaturitySuccess(); + void reportPreferredMaturityError(); // Maturity callbacks for PreferredMaturity control variable - void handleMaturity(const LLSD& newvalue); + void handleMaturity(const LLSD &pNewValue); bool validateMaturity(const LLSD& newvalue); diff --git a/indra/newview/llagentaccess.cpp b/indra/newview/llagentaccess.cpp index 08a33ab04a..c4ee321e04 100644 --- a/indra/newview/llagentaccess.cpp +++ b/indra/newview/llagentaccess.cpp @@ -33,8 +33,7 @@ LLAgentAccess::LLAgentAccess(LLControlGroup& savedSettings) : mSavedSettings(savedSettings), mAccess(SIM_ACCESS_PG), mAdminOverride(false), - mGodLevel(GOD_NOT), - mAOTransition(false) + mGodLevel(GOD_NOT) { } @@ -133,18 +132,6 @@ bool LLAgentAccess::isAdult() const return mAccess >= SIM_ACCESS_ADULT; } -void LLAgentAccess::setTeen(bool teen) -{ - if (teen) - { - mAccess = SIM_ACCESS_PG; - } - else - { - mAccess = SIM_ACCESS_MATURE; - } -} - //static int LLAgentAccess::convertTextToMaturity(char text) { @@ -182,16 +169,6 @@ void LLAgentAccess::setMaturity(char text) mSavedSettings.setU32("PreferredMaturity", preferred_access); } -void LLAgentAccess::setTransition() -{ - mAOTransition = true; -} - -bool LLAgentAccess::isInTransition() const -{ - return mAOTransition; -} - bool LLAgentAccess::canSetMaturity(S32 maturity) { if (isGodlike()) // Gods can always set their Maturity level diff --git a/indra/newview/llagentaccess.h b/indra/newview/llagentaccess.h index 2e98e4eea1..4e851b0aa0 100644 --- a/indra/newview/llagentaccess.h +++ b/indra/newview/llagentaccess.h @@ -59,13 +59,10 @@ public: bool isMature() const; bool isAdult() const; - void setTeen(bool teen); void setMaturity(char text); static int convertTextToMaturity(char text); - void setTransition(); // sets the transition bit, which defaults to false - bool isInTransition() const; bool canSetMaturity(S32 maturity); private: @@ -73,13 +70,6 @@ private: U8 mGodLevel; bool mAdminOverride; - // this should be deleted after the 60-day AO transition. - // It should be safe to remove it in Viewer 2009 - // It's set by a special short-term flag in login.cgi - // called ao_transition. When that's gone, this can go, along with - // all of the code that depends on it. - bool mAOTransition; - LLControlGroup& mSavedSettings; }; diff --git a/indra/newview/llagentlistener.cpp b/indra/newview/llagentlistener.cpp index a8d2222c03..a4c0b056ac 100644 --- a/indra/newview/llagentlistener.cpp +++ b/indra/newview/llagentlistener.cpp @@ -126,6 +126,17 @@ LLAgentListener::LLAgentListener(LLAgent &agent) "[\"obj_uuid\"]: id of object to look at, use this or [\"position\"] to indicate the target\n" "[\"position\"]: region position {x, y, z} where to find closest object or avatar to look at", &LLAgentListener::lookAt); + add("getGroups", + "Send information about the agent's groups on [\"reply\"]:\n" + "[\"groups\"]: array of group information\n" + "[\"id\"]: group id\n" + "[\"name\"]: group name\n" + "[\"insignia\"]: group insignia texture id\n" + "[\"notices\"]: boolean indicating if this user accepts notices from this group\n" + "[\"display\"]: boolean indicating if this group is listed in the user's profile\n" + "[\"contrib\"]: user's land contribution to this group\n", + &LLAgentListener::getGroups, + LLSDMap("reply", LLSD())); } void LLAgentListener::requestTeleport(LLSD const & event_data) const diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index dd02a74a38..e441f21f90 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -955,6 +955,8 @@ void LLAgentWearables::processAgentInitialWearablesUpdate(LLMessageSystem* mesgs if (isAgentAvatarValid()) { + //gAgentAvatarp->clearPhases(); // reset phase timers for outfit loading. + gAgentAvatarp->getPhases().startPhase("process_initial_wearables_update"); gAgentAvatarp->outputRezTiming("Received initial wearables update"); } @@ -1448,7 +1450,16 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it { gAgentAvatarp->setCompositeUpdatesEnabled(TRUE); gAgentAvatarp->updateVisualParams(); - gAgentAvatarp->invalidateAll(); + + // If we have not yet declouded, we may want to use + // baked texture UUIDs sent from the first objectUpdate message + // don't overwrite these. If we have already declouded, we've saved + // these ids as the last known good textures and can invalidate without + // re-clouding. + if (!gAgentAvatarp->getIsCloud()) + { + gAgentAvatarp->invalidateAll(); + } } // Start rendering & update the server @@ -1630,10 +1641,11 @@ void LLAgentWearables::queryWearableCache() { if (isAgentAvatarValid()) { + selfStartPhase("fetch_texture_cache_entries"); gAgentAvatarp->outputRezTiming("Fetching textures from cache"); } - llinfos << "Requesting texture cache entry for " << num_queries << " baked textures" << llendl; + LL_INFOS("Avatar") << gAgentAvatarp->avString() << "Requesting texture cache entry for " << num_queries << " baked textures" << LL_ENDL; gMessageSystem->sendReliable(gAgent.getRegion()->getHost()); gAgentQueryManager.mNumPendingQueries++; gAgentQueryManager.mWearablesCacheQueryID++; @@ -2081,6 +2093,11 @@ boost::signals2::connection LLAgentWearables::addLoadedCallback(loaded_callback_ return mLoadedSignal.connect(cb); } +bool LLAgentWearables::changeInProgress() const +{ + return mCOFChangeInProgress; +} + void LLAgentWearables::notifyLoadingStarted() { mCOFChangeInProgress = true; diff --git a/indra/newview/llagentwearables.h b/indra/newview/llagentwearables.h index 01cae3ffd8..5932be21c6 100644 --- a/indra/newview/llagentwearables.h +++ b/indra/newview/llagentwearables.h @@ -233,6 +233,7 @@ public: typedef boost::signals2::signal<void()> loaded_signal_t; boost::signals2::connection addLoadedCallback(loaded_callback_t cb); + bool changeInProgress() const; void notifyLoadingStarted(); void notifyLoadingFinished(); diff --git a/indra/newview/llagentwearablesfetch.cpp b/indra/newview/llagentwearablesfetch.cpp index 8cba54347e..e2417cdddb 100644 --- a/indra/newview/llagentwearablesfetch.cpp +++ b/indra/newview/llagentwearablesfetch.cpp @@ -89,6 +89,7 @@ LLInitialWearablesFetch::LLInitialWearablesFetch(const LLUUID& cof_id) : { if (isAgentAvatarValid()) { + gAgentAvatarp->getPhases().startPhase("initial_wearables_fetch"); gAgentAvatarp->outputRezTiming("Initial wearables fetch started"); } } @@ -107,6 +108,7 @@ void LLInitialWearablesFetch::done() doOnIdleOneTime(boost::bind(&LLInitialWearablesFetch::processContents,this)); if (isAgentAvatarValid()) { + gAgentAvatarp->getPhases().stopPhase("initial_wearables_fetch"); gAgentAvatarp->outputRezTiming("Initial wearables fetch done"); } } diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 33f5373d7e..6d67e098a6 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -50,6 +50,11 @@ #include "llviewerregion.h" #include "llwearablelist.h" +std::string self_av_string() +{ + return gAgentAvatarp->avString(); +} + // RAII thingy to guarantee that a variable gets reset when the Setter // goes out of scope. More general utility would be handy - TODO: // check boost. @@ -156,6 +161,10 @@ public: { mCatID = cat_id; mAppend = append; + + LL_INFOS("Avatar") << self_av_string() << "starting" << LL_ENDL; + + selfStartPhase("wear_inventory_category_callback"); } void fire(const LLUUID& item_id) { @@ -167,13 +176,16 @@ public: * after the last item has fired the event and dereferenced it -- if all * the events actually fire! */ + LL_DEBUGS("Avatar") << self_av_string() << " fired on copied item, id " << item_id << LL_ENDL; } protected: ~LLWearInventoryCategoryCallback() { - llinfos << "done all inventory callbacks" << llendl; + LL_INFOS("Avatar") << self_av_string() << "done all inventory callbacks" << LL_ENDL; + selfStopPhase("wear_inventory_category_callback"); + // Is the destructor called by ordinary dereference, or because the app's shutting down? // If the inventory callback manager goes away, we're shutting down, no longer want the callback. if( LLInventoryCallbackManager::is_instantiated() ) @@ -182,7 +194,7 @@ protected: } else { - llwarns << "Dropping unhandled LLWearInventoryCategoryCallback" << llendl; + llwarns << self_av_string() << "Dropping unhandled LLWearInventoryCategoryCallback" << llendl; } } @@ -212,14 +224,18 @@ LLUpdateAppearanceOnDestroy::LLUpdateAppearanceOnDestroy(bool update_base_outfit mFireCount(0), mUpdateBaseOrder(update_base_outfit_ordering) { + selfStartPhase("update_appearance_on_destroy"); } LLUpdateAppearanceOnDestroy::~LLUpdateAppearanceOnDestroy() { - llinfos << "done update appearance on destroy" << llendl; - if (!LLApp::isExiting()) { + // speculative fix for MAINT-1150 + LL_INFOS("Avatar") << self_av_string() << "done update appearance on destroy" << LL_ENDL; + + selfStopPhase("update_appearance_on_destroy"); + LLAppearanceMgr::instance().updateAppearanceFromCOF(mUpdateBaseOrder); } } @@ -229,7 +245,7 @@ void LLUpdateAppearanceOnDestroy::fire(const LLUUID& inv_item) LLViewerInventoryItem* item = (LLViewerInventoryItem*)gInventory.getItem(inv_item); const std::string item_name = item ? item->getName() : "ITEM NOT FOUND"; #ifndef LL_RELEASE_FOR_DOWNLOAD - llinfos << "callback fired [ name:" << item_name << " UUID:" << inv_item << " count:" << mFireCount << " ] " << llendl; + LL_DEBUGS("Avatar") << self_av_string() << "callback fired [ name:" << item_name << " UUID:" << inv_item << " count:" << mFireCount << " ] " << LL_ENDL; #endif mFireCount++; } @@ -339,11 +355,16 @@ LLWearableHoldingPattern::LLWearableHoldingPattern(): } sActiveHoldingPatterns.insert(this); + selfStartPhase("holding_pattern"); } LLWearableHoldingPattern::~LLWearableHoldingPattern() { sActiveHoldingPatterns.erase(this); + if (isMostRecent()) + { + selfStopPhase("holding_pattern"); + } } bool LLWearableHoldingPattern::isMostRecent() @@ -390,9 +411,10 @@ void LLWearableHoldingPattern::checkMissingWearables() { if (!isMostRecent()) { - llwarns << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl; + // runway why don't we actually skip here? + llwarns << self_av_string() << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl; } - + std::vector<S32> found_by_type(LLWearableType::WT_COUNT,0); std::vector<S32> requested_by_type(LLWearableType::WT_COUNT,0); for (found_list_t::iterator it = getFoundList().begin(); it != getFoundList().end(); ++it) @@ -408,7 +430,7 @@ void LLWearableHoldingPattern::checkMissingWearables() { if (requested_by_type[type] > found_by_type[type]) { - llwarns << "got fewer wearables than requested, type " << type << ": requested " << requested_by_type[type] << ", found " << found_by_type[type] << llendl; + llwarns << self_av_string() << "got fewer wearables than requested, type " << type << ": requested " << requested_by_type[type] << ", found " << found_by_type[type] << llendl; } if (found_by_type[type] > 0) continue; @@ -425,11 +447,13 @@ void LLWearableHoldingPattern::checkMissingWearables() mTypesToRecover.insert(type); mTypesToLink.insert(type); recoverMissingWearable((LLWearableType::EType)type); - llwarns << "need to replace " << type << llendl; + llwarns << self_av_string() << "need to replace " << type << llendl; } } resetTime(60.0F); + + selfStartPhase("get_missing_wearables"); if (!pollMissingWearables()) { doOnIdleRepeating(boost::bind(&LLWearableHoldingPattern::pollMissingWearables,this)); @@ -445,13 +469,14 @@ void LLWearableHoldingPattern::onAllComplete() if (!isMostRecent()) { - llwarns << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl; + // runway need to skip here? + llwarns << self_av_string() << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl; } // Activate all gestures in this folder if (mGestItems.count() > 0) { - llinfos << "Activating " << mGestItems.count() << " gestures" << llendl; + LL_DEBUGS("Avatar") << self_av_string() << "Activating " << mGestItems.count() << " gestures" << LL_ENDL; LLGestureMgr::instance().activateGestures(mGestItems); @@ -468,13 +493,13 @@ void LLWearableHoldingPattern::onAllComplete() } // Update wearables. - llinfos << "Updating agent wearables with " << mResolved << " wearable items " << llendl; + LL_INFOS("Avatar") << self_av_string() << "Updating agent wearables with " << mResolved << " wearable items " << LL_ENDL; LLAppearanceMgr::instance().updateAgentWearables(this, false); // Update attachments to match those requested. if (isAgentAvatarValid()) { - llinfos << "Updating " << mObjItems.count() << " attachments" << llendl; + LL_DEBUGS("Avatar") << self_av_string() << "Updating " << mObjItems.count() << " attachments" << LL_ENDL; LLAgentWearables::userUpdateAttachments(mObjItems); } @@ -492,9 +517,12 @@ void LLWearableHoldingPattern::onAllComplete() void LLWearableHoldingPattern::onFetchCompletion() { + selfStopPhase("get_wearables"); + if (!isMostRecent()) { - llwarns << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl; + // runway skip here? + llwarns << self_av_string() << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl; } checkMissingWearables(); @@ -505,7 +533,8 @@ bool LLWearableHoldingPattern::pollFetchCompletion() { if (!isMostRecent()) { - llwarns << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl; + // runway skip here? + llwarns << self_av_string() << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl; } bool completed = isFetchCompleted(); @@ -514,14 +543,14 @@ bool LLWearableHoldingPattern::pollFetchCompletion() if (done) { - llinfos << "polling, done status: " << completed << " timed out " << timed_out - << " elapsed " << mWaitTime.getElapsedTimeF32() << llendl; + LL_INFOS("Avatar") << self_av_string() << "polling, done status: " << completed << " timed out " << timed_out + << " elapsed " << mWaitTime.getElapsedTimeF32() << LL_ENDL; mFired = true; if (timed_out) { - llwarns << "Exceeded max wait time for wearables, updating appearance based on what has arrived" << llendl; + llwarns << self_av_string() << "Exceeded max wait time for wearables, updating appearance based on what has arrived" << llendl; } onFetchCompletion(); @@ -543,6 +572,7 @@ public: if (!mHolder->isMostRecent()) { llwarns << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl; + // runway skip here? } llinfos << "Recovered item link for type " << mType << llendl; @@ -569,12 +599,12 @@ public: } else { - llwarns << "inventory item not found for recovered wearable" << llendl; + llwarns << self_av_string() << "inventory item not found for recovered wearable" << llendl; } } else { - llwarns << "inventory link not found for recovered wearable" << llendl; + llwarns << self_av_string() << "inventory link not found for recovered wearable" << llendl; } } private: @@ -596,10 +626,11 @@ public: { if (!mHolder->isMostRecent()) { - llwarns << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl; + // runway skip here? + llwarns << self_av_string() << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl; } - llinfos << "Recovered item for type " << mType << llendl; + LL_DEBUGS("Avatar") << self_av_string() << "Recovered item for type " << mType << LL_ENDL; LLViewerInventoryItem *itemp = gInventory.getItem(item_id); mWearable->setItemID(item_id); LLPointer<LLInventoryCallback> cb = new RecoveredItemLinkCB(mType,mWearable,mHolder); @@ -626,7 +657,8 @@ void LLWearableHoldingPattern::recoverMissingWearable(LLWearableType::EType type { if (!isMostRecent()) { - llwarns << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl; + // runway skip here? + llwarns << self_av_string() << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl; } // Try to recover by replacing missing wearable with a new one. @@ -665,7 +697,7 @@ void LLWearableHoldingPattern::clearCOFLinksForMissingWearables() if ((data.mWearableType < LLWearableType::WT_COUNT) && (!data.mWearable)) { // Wearable link that was never resolved; remove links to it from COF - llinfos << "removing link for unresolved item " << data.mItemID.asString() << llendl; + LL_INFOS("Avatar") << self_av_string() << "removing link for unresolved item " << data.mItemID.asString() << LL_ENDL; LLAppearanceMgr::instance().removeCOFItemLinks(data.mItemID,false); } } @@ -675,7 +707,8 @@ bool LLWearableHoldingPattern::pollMissingWearables() { if (!isMostRecent()) { - llwarns << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl; + // runway skip here? + llwarns << self_av_string() << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl; } bool timed_out = isTimedOut(); @@ -684,15 +717,17 @@ bool LLWearableHoldingPattern::pollMissingWearables() if (!done) { - llinfos << "polling missing wearables, waiting for items " << mTypesToRecover.size() + LL_INFOS("Avatar") << self_av_string() << "polling missing wearables, waiting for items " << mTypesToRecover.size() << " links " << mTypesToLink.size() << " wearables, timed out " << timed_out << " elapsed " << mWaitTime.getElapsedTimeF32() - << " done " << done << llendl; + << " done " << done << LL_ENDL; } if (done) { + selfStopPhase("get_missing_wearables"); + gAgentAvatarp->debugWearablesLoaded(); // BAP - if we don't call clearCOFLinksForMissingWearables() @@ -722,14 +757,14 @@ void LLWearableHoldingPattern::handleLateArrivals() } if (!isMostRecent()) { - llwarns << "Late arrivals not handled - outfit change no longer valid" << llendl; + llwarns << self_av_string() << "Late arrivals not handled - outfit change no longer valid" << llendl; } if (!mIsAllComplete) { - llwarns << "Late arrivals not handled - in middle of missing wearables processing" << llendl; + llwarns << self_av_string() << "Late arrivals not handled - in middle of missing wearables processing" << llendl; } - llinfos << "Need to handle " << mLateArrivals.size() << " late arriving wearables" << llendl; + LL_INFOS("Avatar") << self_av_string() << "Need to handle " << mLateArrivals.size() << " late arriving wearables" << LL_ENDL; // Update mFoundList using late-arriving wearables. std::set<LLWearableType::EType> replaced_types; @@ -805,19 +840,19 @@ void LLWearableHoldingPattern::onWearableAssetFetch(LLWearable *wearable) { if (!isMostRecent()) { - llwarns << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl; + llwarns << self_av_string() << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl; } mResolved += 1; // just counting callbacks, not successes. - llinfos << "resolved " << mResolved << "/" << getFoundList().size() << llendl; + LL_DEBUGS("Avatar") << self_av_string() << "resolved " << mResolved << "/" << getFoundList().size() << LL_ENDL; if (!wearable) { - llwarns << "no wearable found" << llendl; + llwarns << self_av_string() << "no wearable found" << llendl; } if (mFired) { - llwarns << "called after holder fired" << llendl; + llwarns << self_av_string() << "called after holder fired" << llendl; if (wearable) { mLateArrivals.insert(wearable); @@ -843,7 +878,7 @@ void LLWearableHoldingPattern::onWearableAssetFetch(LLWearable *wearable) // Failing this means inventory or asset server are corrupted in a way we don't handle. if ((data.mWearableType >= LLWearableType::WT_COUNT) || (wearable->getType() != data.mWearableType)) { - llwarns << "recovered wearable but type invalid. inventory wearable type: " << data.mWearableType << " asset wearable type: " << wearable->getType() << llendl; + llwarns << self_av_string() << "recovered wearable but type invalid. inventory wearable type: " << data.mWearableType << " asset wearable type: " << wearable->getType() << llendl; break; } @@ -1391,8 +1426,8 @@ void LLAppearanceMgr::filterWearableItems( // Create links to all listed items. void LLAppearanceMgr::linkAll(const LLUUID& cat_uuid, - LLInventoryModel::item_array_t& items, - LLPointer<LLInventoryCallback> cb) + LLInventoryModel::item_array_t& items, + LLPointer<LLInventoryCallback> cb) { for (S32 i=0; i<items.count(); i++) { @@ -1408,7 +1443,7 @@ void LLAppearanceMgr::linkAll(const LLUUID& cat_uuid, const LLViewerInventoryCategory *cat = gInventory.getCategory(cat_uuid); const std::string cat_name = cat ? cat->getName() : "CAT NOT FOUND"; #ifndef LL_RELEASE_FOR_DOWNLOAD - llinfos << "Linking Item [ name:" << item->getName() << " UUID:" << item->getUUID() << " ] to Category [ name:" << cat_name << " UUID:" << cat_uuid << " ] " << llendl; + LL_DEBUGS("Avatar") << self_av_string() << "Linking Item [ name:" << item->getName() << " UUID:" << item->getUUID() << " ] to Category [ name:" << cat_name << " UUID:" << cat_uuid << " ] " << LL_ENDL; #endif } } @@ -1416,7 +1451,7 @@ void LLAppearanceMgr::linkAll(const LLUUID& cat_uuid, void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append) { LLViewerInventoryCategory *pcat = gInventory.getCategory(category); - llinfos << "starting, cat " << (pcat ? pcat->getName() : "[UNKNOWN]") << llendl; + LL_INFOS("Avatar") << self_av_string() << "starting, cat '" << (pcat ? pcat->getName() : "[UNKNOWN]") << "'" << LL_ENDL; const LLUUID cof = getCOF(); @@ -1478,26 +1513,26 @@ void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append) gInventory.notifyObservers(); // Create links to new COF contents. - llinfos << "creating LLUpdateAppearanceOnDestroy" << llendl; + LL_DEBUGS("Avatar") << self_av_string() << "creating LLUpdateAppearanceOnDestroy" << LL_ENDL; LLPointer<LLInventoryCallback> link_waiter = new LLUpdateAppearanceOnDestroy(!append); #ifndef LL_RELEASE_FOR_DOWNLOAD - llinfos << "Linking body items" << llendl; + LL_DEBUGS("Avatar") << self_av_string() << "Linking body items" << LL_ENDL; #endif linkAll(cof, body_items, link_waiter); #ifndef LL_RELEASE_FOR_DOWNLOAD - llinfos << "Linking wear items" << llendl; + LL_DEBUGS("Avatar") << self_av_string() << "Linking wear items" << LL_ENDL; #endif linkAll(cof, wear_items, link_waiter); #ifndef LL_RELEASE_FOR_DOWNLOAD - llinfos << "Linking obj items" << llendl; + LL_DEBUGS("Avatar") << self_av_string() << "Linking obj items" << LL_ENDL; #endif linkAll(cof, obj_items, link_waiter); #ifndef LL_RELEASE_FOR_DOWNLOAD - llinfos << "Linking gesture items" << llendl; + LL_DEBUGS("Avatar") << self_av_string() << "Linking gesture items" << LL_ENDL; #endif linkAll(cof, gest_items, link_waiter); @@ -1506,7 +1541,7 @@ void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append) { createBaseOutfitLink(category, link_waiter); } - llinfos << "waiting for LLUpdateAppearanceOnDestroy" << llendl; + LL_DEBUGS("Avatar") << self_av_string() << "waiting for LLUpdateAppearanceOnDestroy" << LL_ENDL; } void LLAppearanceMgr::updatePanelOutfitName(const std::string& name) @@ -1663,7 +1698,7 @@ void LLAppearanceMgr::enforceItemRestrictions() ++it) { LLViewerInventoryItem *item = *it; - llinfos << "purging duplicate or excess item " << item->getName() << llendl; + LL_DEBUGS("Avatar") << self_av_string() << "purging duplicate or excess item " << item->getName() << LL_ENDL; gInventory.purgeObject(item->getUUID()); } gInventory.notifyObservers(); @@ -1678,9 +1713,11 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool update_base_outfit_ordering) return; } + LLVOAvatar::ScopedPhaseSetter(gAgentAvatarp,"update_appearance_from_cof"); + BoolSetter setIsInUpdateAppearanceFromCOF(mIsInUpdateAppearanceFromCOF); - llinfos << "starting" << llendl; + LL_INFOS("Avatar") << self_av_string() << "starting" << LL_ENDL; //checking integrity of the COF in terms of ordering of wearables, //checking and updating links' descriptions of wearables in the COF (before analyzed for "dirty" state) @@ -1772,12 +1809,14 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool update_base_outfit_ordering) } } + selfStartPhase("get_wearables"); + for (LLWearableHoldingPattern::found_list_t::iterator it = holder->getFoundList().begin(); it != holder->getFoundList().end(); ++it) { LLFoundData& found = *it; - lldebugs << "waiting for onWearableAssetFetch callback, asset " << found.mAssetID.asString() << llendl; + lldebugs << self_av_string() << "waiting for onWearableAssetFetch callback, asset " << found.mAssetID.asString() << llendl; // Fetch the wearables about to be worn. LLWearableList::instance().getAsset(found.mAssetID, @@ -1849,11 +1888,15 @@ void LLAppearanceMgr::wearInventoryCategory(LLInventoryCategory* category, bool { if(!category) return; + selfClearPhases(); + selfStartPhase("wear_inventory_category"); + gAgentWearables.notifyLoadingStarted(); - llinfos << "wearInventoryCategory( " << category->getName() - << " )" << llendl; + LL_INFOS("Avatar") << self_av_string() << "wearInventoryCategory( " << category->getName() + << " )" << LL_ENDL; + selfStartPhase("wear_inventory_category_fetch"); callAfterCategoryFetch(category->getUUID(),boost::bind(&LLAppearanceMgr::wearCategoryFinal, &LLAppearanceMgr::instance(), category->getUUID(), copy, append)); @@ -1861,7 +1904,9 @@ void LLAppearanceMgr::wearInventoryCategory(LLInventoryCategory* category, bool void LLAppearanceMgr::wearCategoryFinal(LLUUID& cat_id, bool copy_items, bool append) { - llinfos << "starting" << llendl; + LL_INFOS("Avatar") << self_av_string() << "starting" << LL_ENDL; + + selfStopPhase("wear_inventory_category_fetch"); // We now have an outfit ready to be copied to agent inventory. Do // it, and wear that outfit normally. @@ -1944,8 +1989,8 @@ void LLAppearanceMgr::wearInventoryCategoryOnAvatar( LLInventoryCategory* catego // wearables being dirty. if(!category) return; - llinfos << "wearInventoryCategoryOnAvatar( " << category->getName() - << " )" << llendl; + LL_INFOS("Avatar") << self_av_string() << "wearInventoryCategoryOnAvatar '" << category->getName() + << "'" << LL_ENDL; if (gAgentCamera.cameraCustomizeAvatar()) { @@ -1958,7 +2003,7 @@ void LLAppearanceMgr::wearInventoryCategoryOnAvatar( LLInventoryCategory* catego void LLAppearanceMgr::wearOutfitByName(const std::string& name) { - llinfos << "Wearing category " << name << llendl; + LL_INFOS("Avatar") << self_av_string() << "Wearing category " << name << LL_ENDL; //inc_busy_count(); LLInventoryModel::cat_array_t cat_array; @@ -2281,7 +2326,7 @@ const std::string OTHER_GESTURES_FOLDER = "Other Gestures"; void LLAppearanceMgr::copyLibraryGestures() { - llinfos << "Copying library gestures" << llendl; + LL_INFOS("Avatar") << self_av_string() << "Copying library gestures" << LL_ENDL; // Copy gestures LLUUID lib_gesture_cat_id = @@ -2337,11 +2382,11 @@ void LLAppearanceMgr::copyLibraryGestures() LLUUID cat_id = findDescendentCategoryIDByName(lib_gesture_cat_id,folder_name); if (cat_id.isNull()) { - llwarns << "failed to find gesture folder for " << folder_name << llendl; + llwarns << self_av_string() << "failed to find gesture folder for " << folder_name << llendl; } else { - llinfos << "initiating fetch and copy for " << folder_name << " cat_id " << cat_id << llendl; + LL_DEBUGS("Avatar") << self_av_string() << "initiating fetch and copy for " << folder_name << " cat_id " << cat_id << LL_ENDL; callAfterCategoryFetch(cat_id, boost::bind(&LLAppearanceMgr::shallowCopyCategory, &LLAppearanceMgr::instance(), @@ -2355,7 +2400,7 @@ void LLAppearanceMgr::autopopulateOutfits() // If this is the very first time the user has logged into viewer2+ (from a legacy viewer, or new account) // then auto-populate outfits from the library into the My Outfits folder. - llinfos << "avatar fully visible" << llendl; + LL_INFOS("Avatar") << self_av_string() << "avatar fully visible" << LL_ENDL; static bool check_populate_my_outfits = true; if (check_populate_my_outfits && @@ -2731,7 +2776,7 @@ void LLAppearanceMgr::dumpCat(const LLUUID& cat_id, const std::string& msg) } void LLAppearanceMgr::dumpItemArray(const LLInventoryModel::item_array_t& items, - const std::string& msg) + const std::string& msg) { for (S32 i=0; i<items.count(); i++) { @@ -2742,9 +2787,8 @@ void LLAppearanceMgr::dumpItemArray(const LLInventoryModel::item_array_t& items, { asset_id = linked_item->getAssetUUID(); } - llinfos << msg << " " << i <<" " << (item ? item->getName() : "(nullitem)") << " " << asset_id.asString() << llendl; + LL_DEBUGS("Avatar") << self_av_string() << msg << " " << i <<" " << (item ? item->getName() : "(nullitem)") << " " << asset_id.asString() << LL_ENDL; } - llinfos << llendl; } LLAppearanceMgr::LLAppearanceMgr(): diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 1174d108d2..efa24796e5 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -93,6 +93,8 @@ #include "llsecondlifeurls.h" #include "llupdaterservice.h" #include "llcallfloater.h" +#include "llfloatertexturefetchdebugger.h" +#include "llspellcheck.h" // Linden library includes #include "llavatarnamecache.h" @@ -111,9 +113,12 @@ #include "llnotifications.h" #include "llnotificationsutil.h" +#include "llleap.h" + // Third party library includes #include <boost/bind.hpp> #include <boost/foreach.hpp> +#include <boost/algorithm/string.hpp> @@ -124,7 +129,6 @@ #endif #include "llapr.h" -#include "apr_dso.h" #include <boost/lexical_cast.hpp> #include "llviewerkeyboard.h" @@ -161,6 +165,7 @@ #include "llcontainerview.h" #include "lltooltip.h" +#include "llsdutil.h" #include "llsdserialize.h" #include "llworld.h" @@ -528,6 +533,7 @@ static void settings_to_globals() LLRender::sGLCoreProfile = gSavedSettings.getBOOL("RenderGLCoreProfile"); LLImageGL::sGlobalUseAnisotropic = gSavedSettings.getBOOL("RenderAnisotropic"); + LLImageGL::sCompressTextures = gSavedSettings.getBOOL("RenderCompressTextures"); LLVOVolume::sLODFactor = gSavedSettings.getF32("RenderVolumeLODFactor"); LLVOVolume::sDistanceFactor = 1.f-LLVOVolume::sLODFactor * 0.1f; LLVolumeImplFlexible::sUpdateFactor = gSavedSettings.getF32("RenderFlexTimeFactor"); @@ -545,7 +551,7 @@ static void settings_to_globals() gAgentPilot.setNumRuns(gSavedSettings.getS32("StatsNumRuns")); gAgentPilot.setQuitAfterRuns(gSavedSettings.getBOOL("StatsQuitAfterRuns")); gAgent.setHideGroupTitle(gSavedSettings.getBOOL("RenderHideGroupTitle")); - + gDebugWindowProc = gSavedSettings.getBOOL("DebugWindowProc"); gShowObjectUpdates = gSavedSettings.getBOOL("ShowObjectUpdates"); LLWorldMapView::sMapScale = gSavedSettings.getF32("MapScale"); @@ -560,7 +566,6 @@ static void settings_modify() LLVOSurfacePatch::sLODFactor *= LLVOSurfacePatch::sLODFactor; //square lod factor to get exponential range of [1,4] gDebugGL = gSavedSettings.getBOOL("RenderDebugGL") || gDebugSession; gDebugPipeline = gSavedSettings.getBOOL("RenderDebugPipeline"); - gAuditTexture = gSavedSettings.getBOOL("AuditTexture"); } class LLFastTimerLogThread : public LLThread @@ -622,6 +627,7 @@ LLAppViewer::LLAppViewer() : mPurgeOnExit(false), mSecondInstance(false), mSavedFinalSnapshot(false), + mSavePerAccountSettings(false), // don't save settings on logout unless login succeeded. mForceGraphicsDetail(false), mQuitRequested(false), mLogoutRequestSent(false), @@ -731,12 +737,12 @@ bool LLAppViewer::init() { // Viewer metrics initialization - static LLCachedControl<bool> metrics_submode(gSavedSettings, - "QAModeMetrics", - false, - "Enables QA features (logging, faster cycling) for metrics collector"); + //static LLCachedControl<bool> metrics_submode(gSavedSettings, + // "QAModeMetrics", + // false, + // "Enables QA features (logging, faster cycling) for metrics collector"); - if (metrics_submode) + if (gSavedSettings.getBOOL("QAModeMetrics")) { app_metrics_qa_mode = true; app_metrics_interval = METRICS_INTERVAL_QA; @@ -1014,6 +1020,15 @@ bool LLAppViewer::init() } } +#if LL_WINDOWS + if (gGLManager.mIsIntel && + LLFeatureManager::getInstance()->getGPUClass() > 0 && + gGLManager.mGLVersion <= 3.f) + { + LLNotificationsUtil::add("IntelOldDriver"); + } +#endif + // save the graphics card gDebugInfo["GraphicsCard"] = LLFeatureManager::getInstance()->getGPUString(); @@ -1038,11 +1053,38 @@ bool LLAppViewer::init() gGLActive = FALSE; + + // Iterate over --leap command-line options. But this is a bit tricky: if + // there's only one, it won't be an array at all. + LLSD LeapCommand(gSavedSettings.getLLSD("LeapCommand")); + LL_DEBUGS("InitInfo") << "LeapCommand: " << LeapCommand << LL_ENDL; + if (LeapCommand.isDefined() && ! LeapCommand.isArray()) + { + // If LeapCommand is actually a scalar value, make an array of it. + // Have to do it in two steps because LeapCommand.append(LeapCommand) + // trashes content! :-P + LLSD item(LeapCommand); + LeapCommand.append(item); + } + BOOST_FOREACH(const std::string& leap, llsd::inArray(LeapCommand)) + { + LL_INFOS("InitInfo") << "processing --leap \"" << leap << '"' << LL_ENDL; + // We don't have any better description of this plugin than the + // user-specified command line. Passing "" causes LLLeap to derive a + // description from the command line itself. + // Suppress LLLeap::Error exception: trust LLLeap's own logging. We + // don't consider any one --leap command mission-critical, so if one + // fails, log it, shrug and carry on. + LLLeap::create("", leap, false); // exception=false + } + if (gSavedSettings.getBOOL("QAMode") && gSavedSettings.getS32("QAModeEventHostPort") > 0) { - loadEventHostModule(gSavedSettings.getS32("QAModeEventHostPort")); + LL_WARNS("InitInfo") << "QAModeEventHostPort DEPRECATED: " + << "lleventhost no longer supported as a dynamic library" + << LL_ENDL; } - + LLViewerMedia::initClass(); LL_INFOS("InitInfo") << "Viewer media initialized." << LL_ENDL ; @@ -1123,6 +1165,8 @@ void LLAppViewer::checkMemory() static LLFastTimer::DeclareTimer FTM_MESSAGES("System Messages"); static LLFastTimer::DeclareTimer FTM_SLEEP("Sleep"); +static LLFastTimer::DeclareTimer FTM_YIELD("Yield"); + static LLFastTimer::DeclareTimer FTM_TEXTURE_CACHE("Texture Cache"); static LLFastTimer::DeclareTimer FTM_DECODE("Image Decode"); static LLFastTimer::DeclareTimer FTM_VFS("VFS Thread"); @@ -1219,7 +1263,7 @@ bool LLAppViewer::mainLoop() if(mem_leak_instance) { mem_leak_instance->idle() ; - } + } // canonical per-frame event mainloop.post(newFrame); @@ -1308,6 +1352,7 @@ bool LLAppViewer::mainLoop() // yield some time to the os based on command line option if(mYieldTime >= 0) { + LLFastTimer t(FTM_YIELD); ms_sleep(mYieldTime); } @@ -1340,13 +1385,11 @@ bool LLAppViewer::mainLoop() ms_sleep(500); } - static const F64 FRAME_SLOW_THRESHOLD = 0.5; //2 frames per seconds const F64 max_idle_time = llmin(.005*10.0*gFrameTimeSeconds, 0.005); // 5 ms a second idleTimer.reset(); - bool is_slow = (frameTimer.getElapsedTimeF64() > FRAME_SLOW_THRESHOLD) ; S32 total_work_pending = 0; S32 total_io_pending = 0; - while(!is_slow)//do not unpause threads if the frame rates are very low. + while(1) { S32 work_pending = 0; S32 io_pending = 0; @@ -1406,6 +1449,17 @@ bool LLAppViewer::mainLoop() LLLFSThread::sLocal->pause(); } + //texture fetching debugger + if(LLTextureFetchDebugger::isEnabled()) + { + LLFloaterTextureFetchDebugger* tex_fetch_debugger_instance = + LLFloaterReg::findTypedInstance<LLFloaterTextureFetchDebugger>("tex_fetch_debugger"); + if(tex_fetch_debugger_instance) + { + tex_fetch_debugger_instance->idle() ; + } + } + if ((LLStartUp::getStartupState() >= STATE_CLEANUP) && (frameTimer.getElapsedTimeF64() > FRAME_STALL_THRESHOLD)) { @@ -1511,21 +1565,27 @@ bool LLAppViewer::cleanup() if (! isError()) { std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, ""); - logdir += gDirUtilp->getDirDelimiter(); gDirUtilp->deleteFilesInDir(logdir, "*-*-*-*-*.dmp"); } - // *TODO - generalize this and move DSO wrangling to a helper class -brad - std::set<struct apr_dso_handle_t *>::const_iterator i; - for(i = mPlugins.begin(); i != mPlugins.end(); ++i) { - int (*ll_plugin_stop_func)(void) = NULL; - apr_status_t rv = apr_dso_sym((apr_dso_handle_sym_t*)&ll_plugin_stop_func, *i, "ll_plugin_stop"); - ll_plugin_stop_func(); - - rv = apr_dso_unload(*i); - } - mPlugins.clear(); + // Kill off LLLeap objects. We can find them all because LLLeap is derived + // from LLInstanceTracker. But collect instances first: LLInstanceTracker + // specifically forbids adding/deleting instances while iterating. + std::vector<LLLeap*> leaps; + leaps.reserve(LLLeap::instanceCount()); + for (LLLeap::instance_iter li(LLLeap::beginInstances()), lend(LLLeap::endInstances()); + li != lend; ++li) + { + leaps.push_back(&*li); + } + // Okay, now trash them all. We don't have to NULL or erase the entry + // in 'leaps' because the whole vector is going away momentarily. + BOOST_FOREACH(LLLeap* leap, leaps) + { + delete leap; + } + } // destroy 'leaps' //flag all elements as needing to be destroyed immediately // to ensure shutdown order @@ -1742,6 +1802,13 @@ bool LLAppViewer::cleanup() { llinfos << "Not saving per-account settings; don't know the account name yet." << llendl; } + // Only save per account settings if the previous login succeeded, otherwise + // we might end up with a cleared out settings file in case a previous login + // failed after loading per account settings. + else if (!mSavePerAccountSettings) + { + llinfos << "Not saving per-account settings; last login was not successful." << llendl; + } else { gSavedPerAccountSettings.saveToFile(gSavedSettings.getString("PerAccountSettingsFile"), TRUE); @@ -1760,8 +1827,7 @@ bool LLAppViewer::cleanup() if (mPurgeOnExit) { llinfos << "Purging all cache files on exit" << llendflush; - std::string mask = gDirUtilp->getDirDelimiter() + "*.*"; - gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE,""),mask); + gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE,""), "*.*"); } removeMarkerFile(); // Any crashes from here on we'll just have to ignore @@ -1951,7 +2017,7 @@ bool LLAppViewer::initThreads() static const bool enable_threads = true; #endif - LLImage::initClass(); + LLImage::initClass(gSavedSettings.getBOOL("TextureNewByteRange"),gSavedSettings.getS32("TextureReverseByteRange")); LLVFSThread::initClass(enable_threads && false); LLLFSThread::initClass(enable_threads && false); @@ -2497,6 +2563,19 @@ bool LLAppViewer::initConfiguration() //gDirUtilp->setSkinFolder("default"); } + if (gSavedSettings.getBOOL("SpellCheck")) + { + std::list<std::string> dict_list; + std::string dict_setting = gSavedSettings.getString("SpellCheckDictionary"); + boost::split(dict_list, dict_setting, boost::is_any_of(std::string(","))); + if (!dict_list.empty()) + { + LLSpellChecker::setUseSpellCheck(dict_list.front()); + dict_list.pop_front(); + LLSpellChecker::instance().setSecondaryDictionaries(dict_list); + } + } + mYieldTime = gSavedSettings.getS32("YieldTime"); // Read skin/branding settings if specified. @@ -2995,8 +3074,7 @@ void LLAppViewer::cleanupSavedSettings() void LLAppViewer::removeCacheFiles(const std::string& file_mask) { - std::string mask = gDirUtilp->getDirDelimiter() + file_mask; - gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ""), mask); + gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ""), file_mask); } void LLAppViewer::writeSystemInfo() @@ -3855,8 +3933,7 @@ void LLAppViewer::purgeCache() LL_INFOS("AppCache") << "Purging Cache and Texture Cache..." << LL_ENDL; LLAppViewer::getTextureCache()->purgeCache(LL_PATH_CACHE); LLVOCache::getInstance()->removeCache(LL_PATH_CACHE); - std::string mask = "*.*"; - gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ""), mask); + gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ""), "*.*"); } std::string LLAppViewer::getSecondLifeTitle() const @@ -4201,6 +4278,7 @@ void LLAppViewer::idle() // The 5-second interval is nice for this purpose. If the object debug // bit moves or is disabled, please give this a suitable home. LLViewerAssetStatsFF::record_fps_main(gFPSClamped); + LLViewerAssetStatsFF::record_avatar_stats(); } } @@ -4248,7 +4326,8 @@ void LLAppViewer::idle() static LLTimer report_interval; // *TODO: Add configuration controls for this - if (report_interval.getElapsedTimeF32() >= app_metrics_interval) + F32 seconds = report_interval.getElapsedTimeF32(); + if (seconds >= app_metrics_interval) { metricsSend(! gDisconnected); report_interval.reset(); @@ -4956,87 +5035,10 @@ void LLAppViewer::handleLoginComplete() mOnLoginCompleted(); writeDebugInfo(); -} - -// *TODO - generalize this and move DSO wrangling to a helper class -brad -void LLAppViewer::loadEventHostModule(S32 listen_port) -{ - std::string dso_name = -#if LL_WINDOWS - "lleventhost.dll"; -#elif LL_DARWIN - "liblleventhost.dylib"; -#else - "liblleventhost.so"; -#endif - - std::string dso_path = gDirUtilp->findFile(dso_name, - gDirUtilp->getAppRODataDir(), - gDirUtilp->getExecutableDir()); - - if(dso_path == "") - { - llerrs << "QAModeEventHost requested but module \"" << dso_name << "\" not found!" << llendl; - return; - } - - LL_INFOS("eventhost") << "Found lleventhost at '" << dso_path << "'" << LL_ENDL; -#if ! defined(LL_WINDOWS) - { - std::string outfile("/tmp/lleventhost.file.out"); - std::string command("file '" + dso_path + "' > '" + outfile + "' 2>&1"); - int rc = system(command.c_str()); - if (rc != 0) - { - LL_WARNS("eventhost") << command << " ==> " << rc << ':' << LL_ENDL; - } - else - { - LL_INFOS("eventhost") << command << ':' << LL_ENDL; - } - { - std::ifstream reader(outfile.c_str()); - std::string line; - while (std::getline(reader, line)) - { - size_t len = line.length(); - if (len && line[len-1] == '\n') - line.erase(len-1); - LL_INFOS("eventhost") << line << LL_ENDL; - } - } - remove(outfile.c_str()); - } -#endif // LL_WINDOWS - - apr_dso_handle_t * eventhost_dso_handle = NULL; - apr_pool_t * eventhost_dso_memory_pool = NULL; - - //attempt to load the shared library - apr_pool_create(&eventhost_dso_memory_pool, NULL); - apr_status_t rv = apr_dso_load(&eventhost_dso_handle, - dso_path.c_str(), - eventhost_dso_memory_pool); - llassert_always(! ll_apr_warn_status(rv, eventhost_dso_handle)); - llassert_always(eventhost_dso_handle != NULL); - - int (*ll_plugin_start_func)(LLSD const &) = NULL; - rv = apr_dso_sym((apr_dso_handle_sym_t*)&ll_plugin_start_func, eventhost_dso_handle, "ll_plugin_start"); - - llassert_always(! ll_apr_warn_status(rv, eventhost_dso_handle)); - llassert_always(ll_plugin_start_func != NULL); - - LLSD args; - args["listen_port"] = listen_port; - - int status = ll_plugin_start_func(args); - - if(status != 0) - { - llerrs << "problem loading eventhost plugin, status: " << status << llendl; - } - mPlugins.insert(eventhost_dso_handle); + // we logged in successfully, so save settings on logout + llinfos << "Login successful, per account settings will be saved on log out." << llendl; + mSavePerAccountSettings=true; } void LLAppViewer::launchUpdater() diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index 71a7868191..ae3c795d1e 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -41,8 +41,6 @@ class LLTextureFetch; class LLWatchdogTimeout; class LLUpdaterService; -struct apr_dso_handle_t; - class LLAppViewer : public LLApp { public: @@ -220,8 +218,6 @@ private: void sendLogoutRequest(); void disconnectViewer(); - - void loadEventHostModule(S32 listen_port); // *FIX: the app viewer class should be some sort of singleton, no? // Perhaps its child class is the singleton and this should be an abstract base. @@ -251,6 +247,7 @@ private: bool mPurgeOnExit; bool mSavedFinalSnapshot; + bool mSavePerAccountSettings; // only save per account settings if login succeeded bool mForceGraphicsDetail; @@ -270,8 +267,6 @@ private: LLAllocator mAlloc; - std::set<struct apr_dso_handle_t*> mPlugins; - LLFrameTimer mMemCheckTimer; boost::scoped_ptr<LLUpdaterService> mUpdater; diff --git a/indra/newview/llautoreplace.cpp b/indra/newview/llautoreplace.cpp new file mode 100644 index 0000000000..0f1ce2bcd0 --- /dev/null +++ b/indra/newview/llautoreplace.cpp @@ -0,0 +1,771 @@ +/** + * @file llautoreplace.cpp + * @brief Auto Replace Manager + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" +#include "llautoreplace.h" +#include "llsdserialize.h" +#include "llboost.h" +#include "llcontrol.h" +#include "llviewercontrol.h" +#include "llnotificationsutil.h" + +LLAutoReplace* LLAutoReplace::sInstance; + +const char* LLAutoReplace::SETTINGS_FILE_NAME = "autoreplace.xml"; + +LLAutoReplace::LLAutoReplace() +{ +} + +LLAutoReplace::~LLAutoReplace() +{ + sInstance = NULL; +} + +void LLAutoReplace::autoreplaceCallback(LLUIString& inputText, S32& cursorPos) +{ + static LLCachedControl<bool> perform_autoreplace(gSavedSettings, "AutoReplace"); + if(perform_autoreplace) + { + S32 wordEnd = cursorPos-1; + LLWString text = inputText.getWString(); + + bool atSpace = (text[wordEnd] == ' '); + bool haveWord = (LLWStringUtil::isPartOfWord(text[wordEnd])); + + if (atSpace || haveWord) + { + if (atSpace && wordEnd > 0) + { + // find out if this space immediately follows a word + wordEnd--; + haveWord = (LLWStringUtil::isPartOfWord(text[wordEnd])); + } + if (haveWord) + { + // wordEnd points to the end of a word, now find the start of the word + std::string word; + S32 wordStart = wordEnd; + for ( S32 backOne = wordStart - 1; + backOne >= 0 && LLWStringUtil::isPartOfWord(text[backOne]); + backOne-- + ) + { + wordStart--; // walk wordStart back to the beginning of the word + } + LL_DEBUGS("AutoReplace")<<"wordStart: "<<wordStart<<" wordEnd: "<<wordEnd<<LL_ENDL; + std::string strText = std::string(text.begin(), text.end()); + std::string lastWord = strText.substr(wordStart, wordEnd-wordStart+1); + std::string replacementWord( mSettings.replaceWord( lastWord ) ); + + if ( replacementWord != lastWord ) + { + // The last word is one for which we have a replacement + if (atSpace) + { + // replace the last word in the input + LLWString strNew = utf8str_to_wstring(replacementWord); + LLWString strOld = utf8str_to_wstring(lastWord); + int size_change = strNew.size() - strOld.size(); + + text.replace(wordStart,lastWord.length(),strNew); + inputText = wstring_to_utf8str(text); + cursorPos+=size_change; + } + } + } + } + } +} + +LLAutoReplace* LLAutoReplace::getInstance() +{ + if(!sInstance) + { + sInstance = new LLAutoReplace(); + sInstance->loadFromSettings(); + } + return sInstance; +} + +std::string LLAutoReplace::getUserSettingsFileName() +{ + std::string path=gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, ""); + + if (!path.empty()) + { + path = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, SETTINGS_FILE_NAME); + } + return path; +} + +std::string LLAutoReplace::getAppSettingsFileName() +{ + std::string path=gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, ""); + + if (!path.empty()) + { + path = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, SETTINGS_FILE_NAME); + } + else + { + LL_ERRS("AutoReplace") << "Failed to get app settings directory name" << LL_ENDL; + } + return path; +} + +LLAutoReplaceSettings LLAutoReplace::getSettings() +{ + return mSettings; +} + +void LLAutoReplace::setSettings(const LLAutoReplaceSettings& newSettings) +{ + mSettings.set(newSettings); + /// Make the newSettings active and write them to user storage + saveToUserSettings(); +} + +void LLAutoReplace::loadFromSettings() +{ + std::string filename=getUserSettingsFileName(); + if (filename.empty()) + { + LL_INFOS("AutoReplace") << "no valid user settings directory." << LL_ENDL; + } + if(gDirUtilp->fileExists(filename)) + { + LLSD userSettings; + llifstream file; + file.open(filename.c_str()); + if (file.is_open()) + { + LLSDSerialize::fromXML(userSettings, file); + } + file.close(); + if ( mSettings.setFromLLSD(userSettings) ) + { + LL_INFOS("AutoReplace") << "settings loaded from '" << filename << "'" << LL_ENDL; + } + else + { + LL_WARNS("AutoReplace") << "invalid settings found in '" << filename << "'" << LL_ENDL; + } + } + else // no user settings found, try application settings + { + std::string defaultName = getAppSettingsFileName(); + LL_INFOS("AutoReplace") << " user settings file '" << filename << "' not found"<< LL_ENDL; + + bool gotSettings = false; + if(gDirUtilp->fileExists(defaultName)) + { + LLSD appDefault; + llifstream file; + file.open(defaultName.c_str()); + if (file.is_open()) + { + LLSDSerialize::fromXMLDocument(appDefault, file); + } + file.close(); + + if ( mSettings.setFromLLSD(appDefault) ) + { + LL_INFOS("AutoReplace") << "settings loaded from '" << defaultName.c_str() << "'" << LL_ENDL; + gotSettings = true; + } + else + { + LL_WARNS("AutoReplace") << "invalid settings found in '" << defaultName.c_str() << "'" << LL_ENDL; + } + } + + if ( ! gotSettings ) + { + if (mSettings.setFromLLSD(mSettings.getExampleLLSD())) + { + LL_WARNS("AutoReplace") << "no settings found; loaded example." << LL_ENDL; + } + else + { + LL_WARNS("AutoReplace") << "no settings found and example invalid!" << LL_ENDL; + } + } + } +} + +void LLAutoReplace::saveToUserSettings() +{ + std::string filename=getUserSettingsFileName(); + llofstream file; + file.open(filename.c_str()); + LLSDSerialize::toPrettyXML(mSettings.getAsLLSD(), file); + file.close(); + LL_INFOS("AutoReplace") << "settings saved to '" << filename << "'" << LL_ENDL; +} + +// ================================================================ +// LLAutoReplaceSettings +// ================================================================ + +const std::string LLAutoReplaceSettings::AUTOREPLACE_LIST_NAME = "name"; ///< key for looking up list names +const std::string LLAutoReplaceSettings::AUTOREPLACE_LIST_REPLACEMENTS = "replacements"; ///< key for looking up replacement map + +LLAutoReplaceSettings::LLAutoReplaceSettings() +{ +} + +LLAutoReplaceSettings::LLAutoReplaceSettings(const LLAutoReplaceSettings& settings) +{ + // copy all values through fundamental type intermediates for thread safety + mLists = LLSD::emptyArray(); + + for ( LLSD::array_const_iterator list = settings.mLists.beginArray(), listEnd = settings.mLists.endArray(); + list != listEnd; + list++ + ) + { + if ( (*list).isMap() ) // can fail due to LLSD-30: ignore it + { + LLSD listMap = LLSD::emptyMap(); + std::string listName = (*list)[AUTOREPLACE_LIST_NAME]; + listMap[AUTOREPLACE_LIST_NAME] = listName; + listMap[AUTOREPLACE_LIST_REPLACEMENTS] = LLSD::emptyMap(); + + for ( LLSD::map_const_iterator + entry = (*list)[AUTOREPLACE_LIST_REPLACEMENTS].beginMap(), + entriesEnd = (*list)[AUTOREPLACE_LIST_REPLACEMENTS].endMap(); + entry != entriesEnd; + entry++ + ) + { + std::string keyword = entry->first; + std::string replacement = entry->second.asString(); + listMap[AUTOREPLACE_LIST_REPLACEMENTS].insert(keyword, LLSD(replacement)); + } + + mLists.append(listMap); + } + } +} + +void LLAutoReplaceSettings::set(const LLAutoReplaceSettings& newSettings) +{ + mLists = newSettings.mLists; +} + +bool LLAutoReplaceSettings::setFromLLSD(const LLSD& settingsFromLLSD) +{ + bool settingsValid = true; + + if ( settingsFromLLSD.isArray() ) + { + for ( LLSD::array_const_iterator + list = settingsFromLLSD.beginArray(), + listEnd = settingsFromLLSD.endArray(); + settingsValid && list != listEnd; + list++ + ) + { + if ( (*list).isDefined() ) // can be undef due to LLSD-30: ignore it + { + settingsValid = listIsValid(*list); + } + } + } + else + { + settingsValid = false; + LL_WARNS("AutoReplace") << "settings are not an array" << LL_ENDL; + } + + if ( settingsValid ) + { + mLists = settingsFromLLSD; + } + else + { + LL_WARNS("AutoReplace") << "invalid settings discarded; using hard coded example" << LL_ENDL; + } + + return settingsValid; +} + +bool LLAutoReplaceSettings::listNameMatches( const LLSD& list, const std::string name ) +{ + return list.isMap() + && list.has(AUTOREPLACE_LIST_NAME) + && list[AUTOREPLACE_LIST_NAME].asString() == name; +} + +const LLSD* LLAutoReplaceSettings::getListEntries(std::string listName) +{ + const LLSD* returnedEntries = NULL; + for( LLSD::array_const_iterator list = mLists.beginArray(), endList = mLists.endArray(); + returnedEntries == NULL && list != endList; + list++ + ) + { + const LLSD& thisList = *list; + if ( listNameMatches(thisList, listName) ) + { + returnedEntries = &thisList[AUTOREPLACE_LIST_REPLACEMENTS]; + } + } + return returnedEntries; +} + +std::string LLAutoReplaceSettings::replacementFor(std::string keyword, std::string listName) +{ + std::string replacement; + bool foundList = false; + for( LLSD::array_const_iterator list = mLists.beginArray(), endList = mLists.endArray(); + ! foundList && list != endList; + list++ + ) + { + const LLSD& thisList = *list; + if ( listNameMatches(thisList, listName) ) + { + foundList = true; // whether there is a replacement or not, we're done + if ( thisList.isMap() + && thisList.has(AUTOREPLACE_LIST_REPLACEMENTS) + && thisList[AUTOREPLACE_LIST_REPLACEMENTS].has(keyword) + ) + { + replacement = thisList[AUTOREPLACE_LIST_REPLACEMENTS][keyword].asString(); + LL_DEBUGS("AutoReplace")<<"'"<<keyword<<"' -> '"<<replacement<<"'"<<LL_ENDL; + } + } + if (!foundList) + { + LL_WARNS("AutoReplace")<<"failed to find list '"<<listName<<"'"<<LL_ENDL; + } + } + if (replacement.empty()) + { + LL_WARNS("AutoReplace")<<"failed to find '"<<keyword<<"'"<<LL_ENDL; + } + return replacement; +} + +LLSD LLAutoReplaceSettings::getListNames() +{ + LL_DEBUGS("AutoReplace")<<"====="<<LL_ENDL; + LLSD toReturn = LLSD::emptyArray(); + S32 counter=0; + for( LLSD::array_const_iterator list = mLists.beginArray(), endList = mLists.endArray(); + list != endList; + list++ + ) + { + const LLSD& thisList = *list; + if ( thisList.isMap() ) + { + if ( thisList.has(AUTOREPLACE_LIST_NAME) ) + { + std::string name = thisList[AUTOREPLACE_LIST_NAME].asString(); + LL_DEBUGS("AutoReplace")<<counter<<" '"<<name<<"'"<<LL_ENDL; + toReturn.append(LLSD(name)); + } + else + { + LL_ERRS("AutoReplace") <<counter<<" ! MISSING "<<AUTOREPLACE_LIST_NAME<< LL_ENDL; + } + } + else + { + LL_WARNS("AutoReplace")<<counter<<" ! not a map: "<<LLSD::typeString(thisList.type())<< LL_ENDL; + } + counter++; + } + LL_DEBUGS("AutoReplace")<<"^^^^^^"<<LL_ENDL; + return toReturn; +} + +bool LLAutoReplaceSettings::listIsValid(const LLSD& list) +{ + bool listValid = true; + if ( ! list.isMap() ) + { + listValid = false; + LL_WARNS("AutoReplace") << "list is not a map" << LL_ENDL; + } + else if ( ! list.has(AUTOREPLACE_LIST_NAME) + || ! list[AUTOREPLACE_LIST_NAME].isString() + || list[AUTOREPLACE_LIST_NAME].asString().empty() + ) + { + listValid = false; + LL_WARNS("AutoReplace") + << "list found without " << AUTOREPLACE_LIST_NAME + << " (or it is empty)" + << LL_ENDL; + } + else if ( ! list.has(AUTOREPLACE_LIST_REPLACEMENTS) || ! list[AUTOREPLACE_LIST_REPLACEMENTS].isMap() ) + { + listValid = false; + LL_WARNS("AutoReplace") << "list '" << list[AUTOREPLACE_LIST_NAME].asString() << "' without " << AUTOREPLACE_LIST_REPLACEMENTS << LL_ENDL; + } + else + { + for ( LLSD::map_const_iterator + entry = list[AUTOREPLACE_LIST_REPLACEMENTS].beginMap(), + entriesEnd = list[AUTOREPLACE_LIST_REPLACEMENTS].endMap(); + listValid && entry != entriesEnd; + entry++ + ) + { + if ( ! entry->second.isString() ) + { + listValid = false; + LL_WARNS("AutoReplace") + << "non-string replacement value found in list '" + << list[AUTOREPLACE_LIST_NAME].asString() << "'" + << LL_ENDL; + } + } + } + + return listValid; +} + +const LLSD* LLAutoReplaceSettings::exportList(std::string listName) +{ + const LLSD* exportedList = NULL; + for ( LLSD::array_const_iterator list = mLists.beginArray(), listEnd = mLists.endArray(); + exportedList == NULL && list != listEnd; + list++ + ) + { + if ( listNameMatches(*list, listName) ) + { + const LLSD& namedList = (*list); + exportedList = &namedList; + } + } + return exportedList; +} + +bool LLAutoReplaceSettings::listNameIsUnique(const LLSD& newList) +{ + bool nameIsUnique = true; + // this must always be called with a valid list, so it is safe to assume it has a name + std::string newListName = newList[AUTOREPLACE_LIST_NAME].asString(); + for ( LLSD::array_const_iterator list = mLists.beginArray(), listEnd = mLists.endArray(); + nameIsUnique && list != listEnd; + list++ + ) + { + if ( listNameMatches(*list, newListName) ) + { + LL_WARNS("AutoReplace")<<"duplicate list name '"<<newListName<<"'"<<LL_ENDL; + nameIsUnique = false; + } + } + return nameIsUnique; +} + +/* static */ +void LLAutoReplaceSettings::createEmptyList(LLSD& emptyList) +{ + emptyList = LLSD::emptyMap(); + emptyList[AUTOREPLACE_LIST_NAME] = "Empty"; + emptyList[AUTOREPLACE_LIST_REPLACEMENTS] = LLSD::emptyMap(); +} + +/* static */ +void LLAutoReplaceSettings::setListName(LLSD& list, const std::string& newName) +{ + list[AUTOREPLACE_LIST_NAME] = newName; +} + +/* static */ +std::string LLAutoReplaceSettings::getListName(LLSD& list) +{ + std::string name; + if ( list.isMap() && list.has(AUTOREPLACE_LIST_NAME) && list[AUTOREPLACE_LIST_NAME].isString() ) + { + name = list[AUTOREPLACE_LIST_NAME].asString(); + } + return name; +} + +LLAutoReplaceSettings::AddListResult LLAutoReplaceSettings::addList(const LLSD& newList) +{ + AddListResult result; + if ( listIsValid( newList ) ) + { + if ( listNameIsUnique( newList ) ) + { + mLists.append(newList); + result = AddListOk; + } + else + { + LL_WARNS("AutoReplace") << "attempt to add duplicate name" << LL_ENDL; + result = AddListDuplicateName; + } + } + else + { + LL_WARNS("AutoReplace") << "attempt to add invalid list" << LL_ENDL; + result = AddListInvalidList; + } + return result; +} + +bool LLAutoReplaceSettings::removeReplacementList(std::string listName) +{ + bool found = false; + for( S32 index = 0; !found && mLists[index].isDefined(); index++ ) + { + if( listNameMatches(mLists.get(index), listName) ) + { + LL_DEBUGS("AutoReplace")<<"list '"<<listName<<"'"<<LL_ENDL; + mLists.erase(index); + found = true; + } + } + return found; +} + +/// Move the named list up in the priority order +bool LLAutoReplaceSettings::increaseListPriority(std::string listName) +{ + LL_DEBUGS("AutoReplace")<<listName<<LL_ENDL; + bool found = false; + S32 search_index, previous_index; + LLSD targetList; + // The following is working around the fact that LLSD arrays containing maps also seem to have undefined entries... see LLSD-30 + previous_index = -1; + for ( search_index = 0, targetList = mLists[0]; + !found && search_index < mLists.size(); + search_index += 1, targetList = mLists[search_index] + ) + { + if ( targetList.isMap() ) + { + if ( listNameMatches( targetList, listName) ) + { + LL_DEBUGS("AutoReplace")<<"found at "<<search_index<<", previous is "<<previous_index<<LL_ENDL; + found = true; + if (previous_index >= 0) + { + LL_DEBUGS("AutoReplace") << "erase "<<search_index<<LL_ENDL; + mLists.erase(search_index); + LL_DEBUGS("AutoReplace") << "insert at "<<previous_index<<LL_ENDL; + mLists.insert(previous_index, targetList); + } + else + { + LL_WARNS("AutoReplace") << "attempted to move top list up" << LL_ENDL; + } + } + else + { + previous_index = search_index; + } + } + else + { + LL_DEBUGS("AutoReplace") << search_index<<" is "<<LLSD::typeString(targetList.type())<<LL_ENDL; + } + } + return found; +} + +/// Move the named list down in the priority order +bool LLAutoReplaceSettings::decreaseListPriority(std::string listName) +{ + LL_DEBUGS("AutoReplace")<<listName<<LL_ENDL; + S32 found_index = -1; + S32 search_index; + for ( search_index = 0; + found_index == -1 && search_index < mLists.size(); + search_index++ + ) + { + if ( listNameMatches( mLists[search_index], listName) ) + { + LL_DEBUGS("AutoReplace")<<"found at index "<<search_index<<LL_ENDL; + found_index = search_index; + } + } + if (found_index != -1) + { + S32 next_index; + for ( next_index = found_index+1; + next_index < mLists.size() && ! mLists[next_index].isMap(); + next_index++ + ) + { + // skipping over any undefined slots (see LLSD-30) + LL_WARNS("AutoReplace")<<next_index<<" ! not a map: "<<LLSD::typeString(mLists[next_index].type())<< LL_ENDL; + } + if ( next_index < mLists.size() ) + { + LLSD next_list = mLists[next_index]; + LL_DEBUGS("AutoReplace") << "erase "<<next_index<<LL_ENDL; + mLists.erase(next_index); + LL_DEBUGS("AutoReplace") << "insert at "<<found_index<<LL_ENDL; + mLists.insert(found_index, next_list); + } + else + { + LL_WARNS("AutoReplace") << "attempted to move bottom list down" << LL_ENDL; + } + } + else + { + LL_WARNS("AutoReplace") << "not found" << LL_ENDL; + } + return (found_index != -1); +} + + +std::string LLAutoReplaceSettings::replaceWord(const std::string currentWord) +{ + std::string returnedWord = currentWord; // in case no replacement is found + static LLCachedControl<bool> autoreplace_enabled(gSavedSettings, "AutoReplace"); + if ( autoreplace_enabled ) + { + LL_DEBUGS("AutoReplace")<<"checking '"<<currentWord<<"'"<< LL_ENDL; + //loop through lists in order + bool found = false; + for( LLSD::array_const_iterator list = mLists.beginArray(), endLists = mLists.endArray(); + ! found && list != endLists; + list++ + ) + { + const LLSD& checkList = *list; + const LLSD& replacements = checkList[AUTOREPLACE_LIST_REPLACEMENTS]; + + if ( replacements.has(currentWord) ) + { + found = true; + LL_DEBUGS("AutoReplace") + << " found in list '" << checkList[AUTOREPLACE_LIST_NAME].asString() + << " => '" << replacements[currentWord].asString() << "'" + << LL_ENDL; + returnedWord = replacements[currentWord].asString(); + } + } + } + return returnedWord; +} + +bool LLAutoReplaceSettings::addEntryToList(LLWString keyword, LLWString replacement, std::string listName) +{ + bool added = false; + + if ( ! keyword.empty() && ! replacement.empty() ) + { + bool isOneWord = true; + for (S32 character = 0; isOneWord && character < keyword.size(); character++ ) + { + if ( ! LLWStringUtil::isPartOfWord(keyword[character]) ) + { + LL_WARNS("AutoReplace") << "keyword '" << wstring_to_utf8str(keyword) << "' not a single word (len "<<keyword.size()<<" '"<<character<<"')" << LL_ENDL; + isOneWord = false; + } + } + + if ( isOneWord ) + { + bool listFound = false; + for( LLSD::array_iterator list = mLists.beginArray(), endLists = mLists.endArray(); + ! listFound && list != endLists; + list++ + ) + { + if ( listNameMatches(*list, listName) ) + { + listFound = true; + (*list)[AUTOREPLACE_LIST_REPLACEMENTS][wstring_to_utf8str(keyword)]=wstring_to_utf8str(replacement); + } + } + if (listFound) + { + added = true; + } + else + { + LL_WARNS("AutoReplace") << "list '" << listName << "' not found" << LL_ENDL; + } + } + } + + return added; +} + +bool LLAutoReplaceSettings::removeEntryFromList(std::string keyword, std::string listName) +{ + bool found = false; + for( LLSD::array_iterator list = mLists.beginArray(), endLists = mLists.endArray(); + ! found && list != endLists; + list++ + ) + { + if ( listNameMatches(*list, listName) ) + { + found = true; + (*list)[AUTOREPLACE_LIST_REPLACEMENTS].erase(keyword); + } + } + if (!found) + { + LL_WARNS("AutoReplace") << "list '" << listName << "' not found" << LL_ENDL; + } + return found; +} + +LLSD LLAutoReplaceSettings::getExampleLLSD() +{ + LL_DEBUGS("AutoReplace")<<LL_ENDL; + LLSD example = LLSD::emptyArray(); + + example[0] = LLSD::emptyMap(); + example[0][AUTOREPLACE_LIST_NAME] = "Example List 1"; + example[0][AUTOREPLACE_LIST_REPLACEMENTS] = LLSD::emptyMap(); + example[0][AUTOREPLACE_LIST_REPLACEMENTS]["keyword1"] = "replacement string 1"; + example[0][AUTOREPLACE_LIST_REPLACEMENTS]["keyword2"] = "replacement string 2"; + + example[1] = LLSD::emptyMap(); + example[1][AUTOREPLACE_LIST_NAME] = "Example List 2"; + example[1][AUTOREPLACE_LIST_REPLACEMENTS] = LLSD::emptyMap(); + example[1][AUTOREPLACE_LIST_REPLACEMENTS]["mistake1"] = "correction 1"; + example[1][AUTOREPLACE_LIST_REPLACEMENTS]["mistake2"] = "correction 2"; + + return example; +} + +const LLSD& LLAutoReplaceSettings::getAsLLSD() +{ + return mLists; +} + +LLAutoReplaceSettings::~LLAutoReplaceSettings() +{ +} diff --git a/indra/newview/llautoreplace.h b/indra/newview/llautoreplace.h new file mode 100644 index 0000000000..30b1fd2c65 --- /dev/null +++ b/indra/newview/llautoreplace.h @@ -0,0 +1,228 @@ +/** + * @file llautoreplace.h + * @brief Auto Replace Manager + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#ifndef LLAUTOREPLACE_H +#define LLAUTOREPLACE_H + +#include "lllineeditor.h" + +class LLAutoReplace; + +/** The configuration data for the LLAutoReplace object + * + * This is a separate class so that the LLFloaterAutoReplaceSettings + * can have a copy of the configuration to manipulate before committing + * the changes back to the LLAutoReplace singleton that provides the + * autoreplace callback. + */ +class LLAutoReplaceSettings +{ + public: + LLAutoReplaceSettings(); + ~LLAutoReplaceSettings(); + + /// Constructor for creating a tempory copy of the current settings + LLAutoReplaceSettings(const LLAutoReplaceSettings& settings); + + /// Replace the current settings with new ones and save them to the user settings file + void set(const LLAutoReplaceSettings& newSettings); + + /// Load the current settings read from an LLSD file + bool setFromLLSD(const LLSD& settingsFromLLSD); + ///< @returns whether or not the settingsFromLLSD were valid + + // ================================================================ + ///@{ @name List Operations + // ================================================================ + + /// @returns the configured list names as an LLSD Array of strings + LLSD getListNames(); + + /// Status values returned from the addList method + typedef enum + { + AddListOk, + AddListDuplicateName, + AddListInvalidList, + } AddListResult; + + /// Inserts a new list at the end of the priority order + AddListResult addList(const LLSD& newList); + + /// Removes the named list, @returns false if not found + bool removeReplacementList(std::string listName); + + /// Move the named list up in the priority order + bool increaseListPriority(std::string listName); + ///< @returns false if the list is not found + + /// Move the named list down in the priority order + bool decreaseListPriority(std::string listName); + ///< @returns false if the list is not found + + /// Get a copy of just one list (for saving to an export file) + const LLSD* exportList(std::string listName); + /// @returns an LLSD map + + /// Checks for required elements, and that each has the correct type. + bool listIsValid(const LLSD& listSettings); + + /// Checks for required elements, and that each has the correct type. + bool listNameIs(const LLSD& listSettings); + + /// Checks to see if a new lists name conflicts with one in the settings + bool listNameIsUnique(const LLSD& newList); + /// @note must be called with LLSD that has passed listIsValid + + /// Initializes emptyList to an empty list named 'Empty' + static void createEmptyList(LLSD& emptyList); + + /// Resets the name of a list to a new value + static void setListName(LLSD& list, const std::string& newName); + + /// Gets the name of a list + static std::string getListName(LLSD& list); + + ///@} + // ================================================================ + ///@{ @name Replacement Entry Operations + // ================================================================ + + /// Get the replacements specified by a given list + const LLSD* getListEntries(std::string listName); + ///< @returns an LLSD Map of keyword -> replacement test pairs + + /// Get the replacement for the keyword from the specified list + std::string replacementFor(std::string keyword, std::string listName); + + /// Adds a keywword/replacement pair to the named list + bool addEntryToList(LLWString keyword, LLWString replacement, std::string listName); + + /// Removes the keywword and its replacement from the named list + bool removeEntryFromList(std::string keyword, std::string listName); + + /** + * Look for currentWord in the lists in order, returning any substitution found + * If no configured substitution is found, returns currentWord + */ + std::string replaceWord(const std::string currentWord /**< word to search for */ ); + + /// Provides a hard-coded example of settings + LLSD getExampleLLSD(); + + /// Get the actual settings as LLSD + const LLSD& getAsLLSD(); + ///< @note for use only in AutoReplace::saveToUserSettings + + private: + /// Efficiently and safely compare list names + bool listNameMatches( const LLSD& list, const std::string name ); + + /// The actual llsd data structure + LLSD mLists; + + static const std::string AUTOREPLACE_LIST_NAME; ///< key for looking up list names + static const std::string AUTOREPLACE_LIST_REPLACEMENTS; ///< key for looking up replacement map + + /**< + * LLSD structure of the lists + * - The configuration is an array (mLists), + * - Each entry in the array is a replacement list + * - Each replacement list is a map with three keys: + * @verbatim + * "name" String the name of the list + * "replacements" Map keyword -> replacement pairs + * + * <llsd> + * <array> + * <map> + * <key>name</key> <string>List 1</string> + * <key>data</key> + * <map> + * <key>keyword1</key> <string>replacement1</string> + * <key>keyword2</key> <string>replacement2</string> + * </map> + * </map> + * <map> + * <key>name</key> <string>List 2</string> + * <key>data</key> + * <map> + * <key>keyword1</key> <string>replacement1</string> + * <key>keyword2</key> <string>replacement2</string> + * </map> + * </map> + * </array> + * </llsd> + * @endverbatim + */ +}; + +/** Provides a facility to auto-replace text dynamically as it is entered. + * + * When the end of a word is detected (defined as any punctuation character, + * or any whitespace except newline or return), the preceding word is used + * as a lookup key in an ordered list of maps. If a match is found in any + * map, the keyword is replaced by the associated value from the map. + * + * See the autoreplaceCallback method for how to add autoreplace functionality + * to a text entry tool. + */ +class LLAutoReplace : public LLSingleton<LLAutoReplace> +{ + public: + LLAutoReplace(); + ~LLAutoReplace(); + + /// @return a pointer to the active instance + static LLAutoReplace* getInstance(); + + /// Callback that provides the hook for use in text entry methods + void autoreplaceCallback(LLUIString& inputText, S32& cursorPos); + + /// Get a copy of the current settings + LLAutoReplaceSettings getSettings(); + + /// Commit new settings after making changes + void setSettings(const LLAutoReplaceSettings& settings); + + private: + friend class LLSingleton<LLAutoReplace>; + static LLAutoReplace* sInstance; ///< the active settings instance + + LLAutoReplaceSettings mSettings; ///< configuration information + + /// Read settings from persistent storage + void loadFromSettings(); + + /// Make the newSettings active and write them to user storage + void saveToUserSettings(); + + /// Compute the user settings file name + std::string getUserSettingsFileName(); + + /// Compute the (read-ony) application settings file name + std::string getAppSettingsFileName(); + + /// basename for the settings files + static const char* SETTINGS_FILE_NAME; +}; + +#endif /* LLAUTOREPLACE_H */ diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index 6babdc1f44..93e8b9ca40 100755 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -577,7 +577,7 @@ namespace action_give_inventory } S32 count = LLShareInfo::instance().mAvatarNames.size(); - bool shared = false; + bool shared = count && !inventory_selected_uuids.empty(); // iterate through avatars for(S32 i = 0; i < count; ++i) @@ -599,8 +599,10 @@ namespace action_give_inventory LLViewerInventoryCategory* inv_cat = gInventory.getCategory(*it); if (inv_cat) { - LLGiveInventory::doGiveInventoryCategory(avatar_uuid, inv_cat, session_id); - shared = true; + if (!LLGiveInventory::doGiveInventoryCategory(avatar_uuid, inv_cat, session_id, "ItemsShared")) + { + shared = false; + } break; } LLViewerInventoryItem* inv_item = gInventory.getItem(*it); @@ -615,8 +617,10 @@ namespace action_give_inventory } else { - LLGiveInventory::doGiveInventoryItem(avatar_uuid, inv_item, session_id); - shared = true; + if (!LLGiveInventory::doGiveInventoryItem(avatar_uuid, inv_item, session_id)) + { + shared = false; + } } } if (noncopy_items.beginArray() != noncopy_items.endArray()) @@ -626,8 +630,10 @@ namespace action_give_inventory LLSD payload; payload["agent_id"] = avatar_uuid; payload["items"] = noncopy_items; + payload["success_notification"] = "ItemsShared"; LLNotificationsUtil::add("CannotCopyWarning", substitutions, payload, &LLGiveInventory::handleCopyProtectedItem); + shared = false; break; } } diff --git a/indra/newview/llavatarpropertiesprocessor.cpp b/indra/newview/llavatarpropertiesprocessor.cpp index b1cd83a1fb..706bc42ea0 100644 --- a/indra/newview/llavatarpropertiesprocessor.cpp +++ b/indra/newview/llavatarpropertiesprocessor.cpp @@ -33,6 +33,7 @@ #include "llagentpicksinfo.h" #include "lldateutil.h" #include "llviewergenericmessage.h" +#include "llstartup.h" // Linden library includes #include "llavatarconstants.h" // AVATAR_TRANSACTED, etc. @@ -113,6 +114,14 @@ void LLAvatarPropertiesProcessor::sendGenericRequest(const LLUUID& avatar_id, EA void LLAvatarPropertiesProcessor::sendAvatarPropertiesRequest(const LLUUID& avatar_id) { + // this is the startup state when send_complete_agent_movement() message is sent. + // Before this, the AvatarPropertiesRequest message + // won't work so don't bother trying + if (LLStartUp::getStartupState() <= STATE_AGENT_SEND) + { + return; + } + if (isPendingRequest(avatar_id, APT_PROPERTIES)) { // waiting for a response, don't re-request diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index 80be753d9e..e3d57ab7ae 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -496,7 +496,7 @@ protected: void showInfoCtrl() { - if (mAvatarID.isNull() || mFrom.empty() || SYSTEM_FROM == mFrom) return; + if (mAvatarID.isNull() || mFrom.empty() || CHAT_SOURCE_SYSTEM == mSourceType) return; if (!sInfoCtrl) { @@ -690,8 +690,11 @@ void LLChatHistory::clear() mLastFromID = LLUUID::null; } +static LLFastTimer::DeclareTimer FTM_APPEND_MESSAGE("Append Chat Message"); + void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LLStyle::Params& input_append_params) { + LLFastTimer _(FTM_APPEND_MESSAGE); bool use_plain_text_chat_history = args["use_plain_text_chat_history"].asBoolean(); bool square_brackets = false; // square brackets necessary for a system messages @@ -739,7 +742,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL LLViewerChat::getChatColor(chat,txt_color); LLFontGL* fontp = LLViewerChat::getChatFont(); std::string font_name = LLFontGL::nameFromFont(fontp); - std::string font_size = LLFontGL::sizeFromFont(fontp); + std::string font_size = LLFontGL::sizeFromFont(fontp); LLStyle::Params body_message_params; body_message_params.color(txt_color); @@ -889,7 +892,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL else { view = getHeader(chat, name_params, args); - if (mEditor->getText().size() == 0) + if (mEditor->getLength() == 0) p.top_pad = 0; else p.top_pad = mTopHeaderPad; @@ -970,7 +973,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL if (square_brackets) { message += "]"; - } + } mEditor->appendText(message, prependNewLineState, body_message_params); prependNewLineState = false; diff --git a/indra/newview/llcommandlineparser.cpp b/indra/newview/llcommandlineparser.cpp index 65c61c4a8b..17d403bbe1 100644 --- a/indra/newview/llcommandlineparser.cpp +++ b/indra/newview/llcommandlineparser.cpp @@ -342,6 +342,15 @@ bool LLCommandLineParser::parseCommandLine(int argc, char **argv) return parseAndStoreResults(clp); } +// TODO: +// - Break out this funky parsing logic into separate method +// - Unit-test it with tests like LLStringUtil::getTokens() (the command-line +// overload that supports quoted tokens) +// - Unless this logic offers significant semantic benefits, replace it with +// LLStringUtil::getTokens(). This would fix a known bug: you cannot --set a +// string-valued variable to the empty string, because empty strings are +// eliminated below. + bool LLCommandLineParser::parseCommandLineString(const std::string& str) { // Split the string content into tokens diff --git a/indra/newview/lldebugview.cpp b/indra/newview/lldebugview.cpp index 7d3170cb76..29b1d23d7d 100644 --- a/indra/newview/lldebugview.cpp +++ b/indra/newview/lldebugview.cpp @@ -68,8 +68,6 @@ LLDebugView::~LLDebugView() gDebugView = NULL; gTextureView = NULL; gSceneView = NULL; - gTextureSizeView = NULL; - gTextureCategoryView = NULL; } void LLDebugView::init() @@ -117,35 +115,11 @@ void LLDebugView::init() LLTextureView::Params tvp; tvp.name("gTextureView"); tvp.rect(r); - tvp.follows.flags(FOLLOWS_BOTTOM|FOLLOWS_LEFT); + tvp.follows.flags(FOLLOWS_TOP|FOLLOWS_LEFT); tvp.visible(false); gTextureView = LLUICtrlFactory::create<LLTextureView>(tvp); addChild(gTextureView); //gTextureView->reshape(r.getWidth(), r.getHeight(), TRUE); - - - if(gAuditTexture) - { - r.set(150, rect.getHeight() - 50, 900 + LLImageGL::sTextureLoadedCounter.size() * 30, 100); - LLTextureSizeView::Params tsv ; - tsv.name("gTextureSizeView"); - tsv.rect(r); - tsv.follows.flags(FOLLOWS_BOTTOM|FOLLOWS_LEFT); - tsv.visible(false); - gTextureSizeView = LLUICtrlFactory::create<LLTextureSizeView>(tsv); - addChild(gTextureSizeView); - gTextureSizeView->setType(LLTextureSizeView::TEXTURE_MEM_OVER_SIZE) ; - - r.set(150, rect.getHeight() - 50, 900 + LLViewerTexture::getTotalNumOfCategories() * 30, 100); - LLTextureSizeView::Params tcv ; - tcv.name("gTextureCategoryView"); - tcv.rect(r); - tcv.follows.flags(FOLLOWS_BOTTOM|FOLLOWS_LEFT); - tcv.visible(false); - gTextureCategoryView = LLUICtrlFactory::create<LLTextureSizeView>(tcv); - gTextureCategoryView->setType(LLTextureSizeView::TEXTURE_MEM_OVER_CATEGORY); - addChild(gTextureCategoryView); - } } void LLDebugView::draw() diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp index 21b21c152a..108ec92f6d 100644 --- a/indra/newview/lldrawable.cpp +++ b/indra/newview/lldrawable.cpp @@ -450,7 +450,7 @@ void LLDrawable::makeStatic(BOOL warning_enabled) { if (isState(ACTIVE)) { - clearState(ACTIVE); + clearState(ACTIVE | ANIMATED_CHILD); if (mParent.notNull() && mParent->isActive() && warning_enabled) { @@ -538,9 +538,9 @@ F32 LLDrawable::updateXform(BOOL undamped) target_rot = new_rot; target_scale = new_scale; } - else + else if (mVObjp->getAngularVelocity().isExactlyZero()) { - // snap to final position + // snap to final position (only if no target omega is applied) dist_squared = 0.0f; if (getVOVolume() && !isRoot()) { //child prim snapping to some position, needs a rebuild @@ -549,15 +549,25 @@ F32 LLDrawable::updateXform(BOOL undamped) } } - if ((mCurrentScale != target_scale) || - (!isRoot() && - (dist_squared >= MIN_INTERPOLATE_DISTANCE_SQUARED || - !mVObjp->getAngularVelocity().isExactlyZero() || - target_pos != mXform.getPosition() || - target_rot != mXform.getRotation()))) - { //child prim moving or scale change requires immediate rebuild + LLVector3 vec = mCurrentScale-target_scale; + + if (vec*vec > MIN_INTERPOLATE_DISTANCE_SQUARED) + { //scale change requires immediate rebuild + mCurrentScale = target_scale; gPipeline.markRebuild(this, LLDrawable::REBUILD_POSITION, TRUE); } + else if (!isRoot() && + (!mVObjp->getAngularVelocity().isExactlyZero() || + dist_squared > 0.f)) + { //child prim moving relative to parent, tag as needing to be rendered atomically and rebuild + dist_squared = 1.f; //keep this object on the move list + if (!isState(LLDrawable::ANIMATED_CHILD)) + { + setState(LLDrawable::ANIMATED_CHILD); + gPipeline.markRebuild(this, LLDrawable::REBUILD_ALL, TRUE); + mVObjp->dirtySpatialGroup(); + } + } else if (!getVOVolume() && !isAvatar()) { movePartition(); @@ -568,9 +578,7 @@ F32 LLDrawable::updateXform(BOOL undamped) mXform.setRotation(target_rot); mXform.setScale(LLVector3(1,1,1)); //no scale in drawable transforms (IT'S A RULE!) mXform.updateMatrix(); - - mCurrentScale = target_scale; - + if (mSpatialBridge) { gPipeline.markMoved(mSpatialBridge, FALSE); @@ -596,7 +604,11 @@ void LLDrawable::moveUpdatePipeline(BOOL moved) // Update the face centers. for (S32 i = 0; i < getNumFaces(); i++) { - getFace(i)->updateCenterAgent(); + LLFace* face = getFace(i); + if (face) + { + face->updateCenterAgent(); + } } } @@ -651,7 +663,6 @@ BOOL LLDrawable::updateMoveUndamped() } mVObjp->clearChanged(LLXform::MOVED); - return TRUE; } @@ -727,7 +738,8 @@ void LLDrawable::updateDistance(LLCamera& camera, bool force_update) for (S32 i = 0; i < getNumFaces(); i++) { LLFace* facep = getFace(i); - if (force_update || facep->getPoolType() == LLDrawPool::POOL_ALPHA) + if (facep && + (force_update || facep->getPoolType() == LLDrawPool::POOL_ALPHA)) { LLVector4a box; box.setSub(facep->mExtents[1], facep->mExtents[0]); @@ -771,18 +783,6 @@ void LLDrawable::updateTexture() if (getVOVolume()) { - /*if (isActive()) - { - if (isRoot()) - { - mQuietCount = 0; - } - else - { - getParent()->mQuietCount = 0; - } - }*/ - gPipeline.markRebuild(this, LLDrawable::REBUILD_MATERIAL, TRUE); } } @@ -826,13 +826,16 @@ void LLDrawable::shiftPos(const LLVector4a &shift_vector) for (S32 i = 0; i < getNumFaces(); i++) { LLFace *facep = getFace(i); - facep->mCenterAgent += LLVector3(shift_vector.getF32ptr()); - facep->mExtents[0].add(shift_vector); - facep->mExtents[1].add(shift_vector); - - if (!volume && facep->hasGeometry()) + if (facep) { - facep->clearVertexBuffer(); + facep->mCenterAgent += LLVector3(shift_vector.getF32ptr()); + facep->mExtents[0].add(shift_vector); + facep->mExtents[1].add(shift_vector); + + if (!volume && facep->hasGeometry()) + { + facep->clearVertexBuffer(); + } } } @@ -954,7 +957,10 @@ void LLDrawable::setSpatialGroup(LLSpatialGroup *groupp) for (S32 i = 0; i < getNumFaces(); ++i) { LLFace* facep = getFace(i); - facep->clearVertexBuffer(); + if (facep) + { + facep->clearVertexBuffer(); + } } } @@ -1529,10 +1535,10 @@ BOOL LLDrawable::isAnimating() const return TRUE; } - if (!isRoot() && !mVObjp->getAngularVelocity().isExactlyZero()) - { + /*if (!isRoot() && !mVObjp->getAngularVelocity().isExactlyZero()) + { //target omega return TRUE; - } + }*/ return FALSE; } diff --git a/indra/newview/lldrawable.h b/indra/newview/lldrawable.h index e268640a21..e2064b79f8 100644 --- a/indra/newview/lldrawable.h +++ b/indra/newview/lldrawable.h @@ -277,6 +277,7 @@ public: HAS_ALPHA = 0x04000000, RIGGED = 0x08000000, PARTITION_MOVE = 0x10000000, + ANIMATED_CHILD = 0x20000000, } EDrawableFlags; private: //aligned members @@ -333,12 +334,14 @@ inline LLFace* LLDrawable::getFace(const S32 i) const if ((U32) i >= mFaces.size()) { - llerrs << "Invalid face index." << llendl; + llwarns << "Invalid face index." << llendl; + return NULL; } if (!mFaces[i]) { - llerrs << "Null face found." << llendl; + llwarns << "Null face found." << llendl; + return NULL; } return mFaces[i]; diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp index 5b62dbc560..5f2a982ed3 100644 --- a/indra/newview/lldrawpoolalpha.cpp +++ b/indra/newview/lldrawpoolalpha.cpp @@ -405,6 +405,12 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask) { LLDrawInfo& params = **k; + if ((params.mVertexBuffer->getTypeMask() & mask) != mask) + { //FIXME! + llwarns << "Missing required components, skipping render batch." << llendl; + continue; + } + LLRenderPass::applyModelMatrix(params); diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index 0103373fd2..ace3a20bbb 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -261,7 +261,9 @@ void LLDrawPoolAvatar::beginPostDeferredAlpha() sRenderingSkinned = TRUE; gPipeline.bindDeferredShader(*sVertexProgram); - + + sVertexProgram->setMinimumAlpha(0.2f); + sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); } diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp index b58efe62ab..6f71e6ebc8 100644 --- a/indra/newview/lldrawpoolbump.cpp +++ b/indra/newview/lldrawpoolbump.cpp @@ -1341,8 +1341,7 @@ void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerTexture *src_vi, LLI // immediately assign bump to a global smart pointer in case some local smart pointer // accidentally releases it. LLPointer<LLViewerTexture> bump = LLViewerTextureManager::getLocalTexture( TRUE ); - - + if (!LLPipeline::sRenderDeferred) { LLFastTimer t(FTM_BUMP_SOURCE_CREATE); @@ -1351,6 +1350,10 @@ void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerTexture *src_vi, LLI } else { //convert to normal map + + //disable compression on normal maps to prevent errors below + bump->getGLTexture()->setAllowCompression(false); + { LLFastTimer t(FTM_BUMP_SOURCE_CREATE); bump->setExplicitFormat(GL_RGBA8, GL_ALPHA); diff --git a/indra/newview/lldynamictexture.cpp b/indra/newview/lldynamictexture.cpp index a93b2b71de..bf8338e5f2 100644 --- a/indra/newview/lldynamictexture.cpp +++ b/indra/newview/lldynamictexture.cpp @@ -216,12 +216,14 @@ BOOL LLViewerDynamicTexture::updateAllInstances() return TRUE; } +#if 0 //THIS CAUSES MAINT-1092 bool use_fbo = gGLManager.mHasFramebufferObject && gPipeline.mWaterDis.isComplete(); if (use_fbo) { gPipeline.mWaterDis.bindTarget(); } +#endif LLGLSLShader::bindNoShader(); LLVertexBuffer::unbind(); @@ -256,10 +258,12 @@ BOOL LLViewerDynamicTexture::updateAllInstances() } } +#if 0 if (use_fbo) { gPipeline.mWaterDis.flush(); } +#endif return ret; } diff --git a/indra/newview/llexternaleditor.cpp b/indra/newview/llexternaleditor.cpp index ed1d7e860a..9480e54809 100644 --- a/indra/newview/llexternaleditor.cpp +++ b/indra/newview/llexternaleditor.cpp @@ -29,6 +29,9 @@ #include "lltrans.h" #include "llui.h" +#include "llprocess.h" +#include "llsdutil.h" +#include <boost/foreach.hpp> // static const std::string LLExternalEditor::sFilenameMarker = "%s"; @@ -45,19 +48,8 @@ LLExternalEditor::EErrorCode LLExternalEditor::setCommand(const std::string& env return EC_NOT_SPECIFIED; } - // Add the filename marker if missing. - if (cmd.find(sFilenameMarker) == std::string::npos) - { - cmd += " \"" + sFilenameMarker + "\""; - llinfos << "Adding the filename marker (" << sFilenameMarker << ")" << llendl; - } - string_vec_t tokens; - if (tokenize(tokens, cmd) < 2) // 2 = bin + at least one arg (%s) - { - llwarns << "Error parsing editor command" << llendl; - return EC_PARSE_ERROR; - } + tokenize(tokens, cmd); // Check executable for existence. std::string bin_path = tokens[0]; @@ -68,51 +60,48 @@ LLExternalEditor::EErrorCode LLExternalEditor::setCommand(const std::string& env } // Save command. - mProcess.setExecutable(bin_path); - mArgs.clear(); + mProcessParams = LLProcess::Params(); + mProcessParams.executable = bin_path; for (size_t i = 1; i < tokens.size(); ++i) { - if (i > 1) mArgs += " "; - mArgs += "\"" + tokens[i] + "\""; + mProcessParams.args.add(tokens[i]); } - llinfos << "Setting command [" << bin_path << " " << mArgs << "]" << llendl; + + // Add the filename marker if missing. + if (cmd.find(sFilenameMarker) == std::string::npos) + { + mProcessParams.args.add(sFilenameMarker); + llinfos << "Adding the filename marker (" << sFilenameMarker << ")" << llendl; + } + + llinfos << "Setting command [" << mProcessParams << "]" << llendl; return EC_SUCCESS; } LLExternalEditor::EErrorCode LLExternalEditor::run(const std::string& file_path) { - std::string args = mArgs; - if (mProcess.getExecutable().empty() || args.empty()) + if (std::string(mProcessParams.executable).empty() || mProcessParams.args.empty()) { llwarns << "Editor command not set" << llendl; return EC_NOT_SPECIFIED; } - // Substitute the filename marker in the command with the actual passed file name. - LLStringUtil::replaceString(args, sFilenameMarker, file_path); - - // Split command into separate tokens. - string_vec_t tokens; - tokenize(tokens, args); + // Copy params block so we can replace sFilenameMarker + LLProcess::Params params; + params.executable = mProcessParams.executable; - // Set process arguments taken from the command. - mProcess.clearArguments(); - for (string_vec_t::const_iterator arg_it = tokens.begin(); arg_it != tokens.end(); ++arg_it) - { - mProcess.addArgument(*arg_it); - } - - // Run the editor. - llinfos << "Running editor command [" << mProcess.getExecutable() + " " + args << "]" << llendl; - int result = mProcess.launch(); - if (result == 0) + // Substitute the filename marker in the command with the actual passed file name. + BOOST_FOREACH(const std::string& arg, mProcessParams.args) { - // Prevent killing the process in destructor (will add it to the zombies list). - mProcess.orphan(); + std::string fixed(arg); + LLStringUtil::replaceString(fixed, sFilenameMarker, file_path); + params.args.add(fixed); } - return result == 0 ? EC_SUCCESS : EC_FAILED_TO_RUN; + // Run the editor. Prevent killing the process in destructor. + params.autokill = false; + return LLProcess::create(params) ? EC_SUCCESS : EC_FAILED_TO_RUN; } // static @@ -130,6 +119,12 @@ std::string LLExternalEditor::getErrorMessage(EErrorCode code) return LLTrans::getString("Unknown"); } +// TODO: +// - Unit-test this with tests like LLStringUtil::getTokens() (the +// command-line overload that supports quoted tokens) +// - Unless there are significant semantic differences, eliminate this method +// and use LLStringUtil::getTokens() instead. + // static size_t LLExternalEditor::tokenize(string_vec_t& tokens, const std::string& str) { diff --git a/indra/newview/llexternaleditor.h b/indra/newview/llexternaleditor.h index ef5db56c6e..fd2c25020c 100644 --- a/indra/newview/llexternaleditor.h +++ b/indra/newview/llexternaleditor.h @@ -27,7 +27,7 @@ #ifndef LL_LLEXTERNALEDITOR_H #define LL_LLEXTERNALEDITOR_H -#include <llprocesslauncher.h> +#include "llprocess.h" /** * Usage: @@ -97,9 +97,7 @@ private: */ static const std::string sSetting; - - std::string mArgs; - LLProcessLauncher mProcess; + LLProcess::Params mProcessParams; }; #endif // LL_LLEXTERNALEDITOR_H diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index 4108d69e82..373b1930f5 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -44,11 +44,14 @@ #include "llsky.h" #include "llviewercamera.h" #include "llviewertexturelist.h" +#include "llvopartgroup.h" #include "llvosky.h" #include "llvovolume.h" #include "pipeline.h" #include "llviewerregion.h" #include "llviewerwindow.h" +#include "llviewershadermgr.h" + #define LL_MAX_INDICES_COUNT 1000000 @@ -56,7 +59,6 @@ BOOL LLFace::sSafeRenderSelect = TRUE; // FALSE #define DOTVEC(a,b) (a.mV[0]*b.mV[0] + a.mV[1]*b.mV[1] + a.mV[2]*b.mV[2]) - /* For each vertex, given: B - binormal @@ -161,7 +163,15 @@ void LLFace::init(LLDrawable* drawablep, LLViewerObject* objp) mGeomCount = 0; mGeomIndex = 0; mIndicesCount = 0; - mIndicesIndex = 0; + if (drawablep->getRenderType() == LLPipeline::RENDER_TYPE_PARTICLES || + drawablep->getRenderType() == LLPipeline::RENDER_TYPE_HUD_PARTICLES) + { //indicate to LLParticlePartition that this particle is uninitialized + mIndicesIndex = 0xFFFFFFFF; + } + else + { + mIndicesIndex = 0; + } mIndexInTex = 0; mTexture = NULL; mTEOffset = -1; @@ -177,12 +187,6 @@ void LLFace::init(LLDrawable* drawablep, LLViewerObject* objp) mFaceColor = LLColor4(1,0,0,1); - mLastVertexBuffer = mVertexBuffer; - mLastGeomCount = mGeomCount; - mLastGeomIndex = mGeomIndex; - mLastIndicesCount = mIndicesCount; - mLastIndicesIndex = mIndicesIndex; - mImportanceToCamera = 0.f ; mBoundingSphereRadius = 0.0f ; @@ -203,6 +207,15 @@ void LLFace::destroy() mTexture->removeFace(this) ; } + if (mDrawablep.notNull() && + (mDrawablep->getRenderType() == LLPipeline::RENDER_TYPE_PARTICLES || + mDrawablep->getRenderType() == LLPipeline::RENDER_TYPE_HUD_PARTICLES) && + mIndicesIndex != 0xFFFFFFFF) + { + LLVOPartGroup::freeVBSlot(getGeomIndex()/4); + mIndicesIndex = 0xFFFFFFFF; + } + if (mDrawPoolp) { if (this->isState(LLFace::RIGGED) && mDrawPoolp->getType() == LLDrawPool::POOL_AVATAR) @@ -313,7 +326,20 @@ void LLFace::setTexture(LLViewerTexture* tex) void LLFace::dirtyTexture() { - gPipeline.markTextured(getDrawable()); + LLDrawable* drawablep = getDrawable(); + + if (mVObjp.notNull() && mVObjp->getVolume() && + mTexture.notNull() && mTexture->getComponents() == 4) + { //dirty texture on an alpha object should be treated as an LoD update + LLVOVolume* vobj = drawablep->getVOVolume(); + if (vobj) + { + vobj->mLODChanged = TRUE; + } + gPipeline.markRebuild(drawablep, LLDrawable::REBUILD_VOLUME, FALSE); + } + + gPipeline.markTextured(drawablep); } void LLFace::switchTexture(LLViewerTexture* new_texture) @@ -372,7 +398,6 @@ void LLFace::setSize(S32 num_vertices, S32 num_indices, bool align) mGeomCount = num_vertices; mIndicesCount = num_indices; mVertexBuffer = NULL; - mLastVertexBuffer = NULL; } llassert(verify()); @@ -765,12 +790,6 @@ BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f, LLMatrix4a mat_normal; mat_normal.loadu(mat_normal_in); - //if (mDrawablep->isState(LLDrawable::REBUILD_VOLUME)) - //{ //vertex buffer no longer valid - // mVertexBuffer = NULL; - // mLastVertexBuffer = NULL; - //} - //VECTORIZE THIS LLVector4a min,max; @@ -1032,30 +1051,13 @@ bool LLFace::calcAlignedPlanarTE(const LLFace* align_to, LLVector2* res_st_offs void LLFace::updateRebuildFlags() { - if (!mDrawablep->isState(LLDrawable::REBUILD_VOLUME)) - { - BOOL moved = TRUE; - if (mLastVertexBuffer == mVertexBuffer && - !mVertexBuffer->isEmpty()) - { //this face really doesn't need to be regenerated, try real hard not to do so - if (mLastGeomCount == mGeomCount && - mLastGeomIndex == mGeomIndex && - mLastIndicesCount == mIndicesCount && - mLastIndicesIndex == mIndicesIndex) - { //data is in same location in vertex buffer - moved = FALSE; - } - } - mLastMoveTime = gFrameTimeSeconds; - - if (moved) - { - mDrawablep->setState(LLDrawable::REBUILD_VOLUME); - } + if (mDrawablep->isState(LLDrawable::REBUILD_VOLUME)) + { //this rebuild is zero overhead (direct consequence of some change that affects this face) + mLastUpdateTime = gFrameTimeSeconds; } else - { - mLastUpdateTime = gFrameTimeSeconds; + { //this rebuild is overhead (side effect of some change that does not affect this face) + mLastMoveTime = gFrameTimeSeconds; } } @@ -1094,6 +1096,73 @@ bool LLFace::canRenderAsMask() } +static LLFastTimer::DeclareTimer FTM_FACE_GEOM_VOLUME("Volume VB Cache"); + +//static +void LLFace::cacheFaceInVRAM(const LLVolumeFace& vf) +{ + LLFastTimer t(FTM_FACE_GEOM_VOLUME); + U32 mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | + LLVertexBuffer::MAP_BINORMAL | LLVertexBuffer::MAP_NORMAL; + + if (vf.mWeights) + { + mask |= LLVertexBuffer::MAP_WEIGHT4; + } + + LLVertexBuffer* buff = new LLVertexBuffer(mask, GL_STATIC_DRAW_ARB); + vf.mVertexBuffer = buff; + + buff->allocateBuffer(vf.mNumVertices, 0, true); + + LLStrider<LLVector4a> f_vert; + LLStrider<LLVector3> f_binorm; + LLStrider<LLVector3> f_norm; + LLStrider<LLVector2> f_tc; + + buff->getBinormalStrider(f_binorm); + buff->getVertexStrider(f_vert); + buff->getNormalStrider(f_norm); + buff->getTexCoord0Strider(f_tc); + + for (U32 i = 0; i < vf.mNumVertices; ++i) + { + *f_vert++ = vf.mPositions[i]; + (*f_binorm++).set(vf.mBinormals[i].getF32ptr()); + *f_tc++ = vf.mTexCoords[i]; + (*f_norm++).set(vf.mNormals[i].getF32ptr()); + } + + if (vf.mWeights) + { + LLStrider<LLVector4> f_wght; + buff->getWeight4Strider(f_wght); + for (U32 i = 0; i < vf.mNumVertices; ++i) + { + (*f_wght++).set(vf.mWeights[i].getF32ptr()); + } + } + + buff->flush(); +} + +//helper function for pushing primitives for transform shaders and cleaning up +//uninitialized data on the tail, plus tracking number of expected primitives +void push_for_transform(LLVertexBuffer* buff, U32 source_count, U32 dest_count) +{ + if (source_count > 0 && dest_count >= source_count) //protect against possible U32 wrapping + { + //push source primitives + buff->drawArrays(LLRender::POINTS, 0, source_count); + U32 tail = dest_count-source_count; + for (U32 i = 0; i < tail; ++i) + { //copy last source primitive into each element in tail + buff->drawArrays(LLRender::POINTS, source_count-1, 1); + } + gPipeline.mTransformFeedbackPrimitives += dest_count; + } +} + static LLFastTimer::DeclareTimer FTM_FACE_GET_GEOM("Face Geom"); static LLFastTimer::DeclareTimer FTM_FACE_GEOM_POSITION("Position"); static LLFastTimer::DeclareTimer FTM_FACE_GEOM_NORMAL("Normal"); @@ -1111,7 +1180,6 @@ static LLFastTimer::DeclareTimer FTM_FACE_TEX_DEFAULT("Default"); static LLFastTimer::DeclareTimer FTM_FACE_TEX_QUICK("Quick"); static LLFastTimer::DeclareTimer FTM_FACE_TEX_QUICK_NO_XFORM("No Xform"); static LLFastTimer::DeclareTimer FTM_FACE_TEX_QUICK_XFORM("Xform"); - static LLFastTimer::DeclareTimer FTM_FACE_TEX_QUICK_PLANAR("Quick Planar"); BOOL LLFace::getGeometryVolume(const LLVolume& volume, @@ -1144,9 +1212,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, << " VF Num Indices: " << num_indices << " Indices Index: " << mIndicesIndex << " VB Num Indices: " << mVertexBuffer->getNumIndices() << llendl; - llwarns << "Last Indices Count: " << mLastIndicesCount - << " Last Indices Index: " << mLastIndicesIndex - << " Face Index: " << f + llwarns << " Face Index: " << f << " Pool Type: " << mPoolType << llendl; return FALSE; } @@ -1284,17 +1350,10 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, LLMatrix4a mat_normal; mat_normal.loadu(mat_norm_in); - //if it's not fullbright and has no normals, bake sunlight based on face normal - //bool bake_sunlight = !getTextureEntry()->getFullbright() && - // !mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_NORMAL); - F32 r = 0, os = 0, ot = 0, ms = 0, mt = 0, cos_ang = 0, sin_ang = 0; - + bool do_xform = false; if (rebuild_tcoord) { - LLFastTimer t(FTM_FACE_GEOM_TEXTURE); - bool do_xform; - if (tep) { r = tep->getRotation(); @@ -1323,599 +1382,756 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, { do_xform = false; } + } + + static LLCachedControl<bool> use_transform_feedback(gSavedSettings, "RenderUseTransformFeedback"); + +#ifdef GL_TRANSFORM_FEEDBACK_BUFFER + if (use_transform_feedback && + gTransformPositionProgram.mProgramObject && //transform shaders are loaded + mVertexBuffer->useVBOs() && //target buffer is in VRAM + !rebuild_weights && //TODO: add support for weights + !volume.isUnique()) //source volume is NOT flexi + { //use transform feedback to pack vertex buffer + + LLVertexBuffer* buff = (LLVertexBuffer*) vf.mVertexBuffer.get(); + + if (vf.mVertexBuffer.isNull() || buff->getNumVerts() != vf.mNumVertices) + { + mVObjp->getVolume()->genBinormals(f); + LLFace::cacheFaceInVRAM(vf); + buff = (LLVertexBuffer*) vf.mVertexBuffer.get(); + } + + LLGLSLShader* cur_shader = LLGLSLShader::sCurBoundShaderPtr; + + gGL.pushMatrix(); + gGL.loadMatrix((GLfloat*) mat_vert_in.mMatrix); + + if (rebuild_pos) + { + LLFastTimer t(FTM_FACE_GEOM_POSITION); + gTransformPositionProgram.bind(); + + mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_VERTEX, mGeomIndex, mGeomCount); + + U8 index = mTextureIndex < 255 ? mTextureIndex : 0; + + S32 val = 0; + U8* vp = (U8*) &val; + vp[0] = index; + vp[1] = 0; + vp[2] = 0; + vp[3] = 0; + + gTransformPositionProgram.uniform1i("texture_index_in", val); + glBeginTransformFeedback(GL_POINTS); + buff->setBuffer(LLVertexBuffer::MAP_VERTEX); + + push_for_transform(buff, vf.mNumVertices, mGeomCount); + + glEndTransformFeedback(); + } + + if (rebuild_color) + { + LLFastTimer t(FTM_FACE_GEOM_COLOR); + gTransformColorProgram.bind(); + + mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_COLOR, mGeomIndex, mGeomCount); + + S32 val = *((S32*) color.mV); + + gTransformColorProgram.uniform1i("color_in", val); + glBeginTransformFeedback(GL_POINTS); + buff->setBuffer(LLVertexBuffer::MAP_VERTEX); + push_for_transform(buff, vf.mNumVertices, mGeomCount); + glEndTransformFeedback(); + } + + if (rebuild_emissive) + { + LLFastTimer t(FTM_FACE_GEOM_EMISSIVE); + gTransformColorProgram.bind(); + + mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_EMISSIVE, mGeomIndex, mGeomCount); + + U8 glow = (U8) llclamp((S32) (getTextureEntry()->getGlow()*255), 0, 255); + + S32 glow32 = glow | + (glow << 8) | + (glow << 16) | + (glow << 24); + + gTransformColorProgram.uniform1i("color_in", glow32); + glBeginTransformFeedback(GL_POINTS); + buff->setBuffer(LLVertexBuffer::MAP_VERTEX); + push_for_transform(buff, vf.mNumVertices, mGeomCount); + glEndTransformFeedback(); + } + + if (rebuild_normal) + { + LLFastTimer t(FTM_FACE_GEOM_NORMAL); + gTransformNormalProgram.bind(); + + mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_NORMAL, mGeomIndex, mGeomCount); - //bump setup - LLVector4a binormal_dir( -sin_ang, cos_ang, 0.f ); - LLVector4a bump_s_primary_light_ray(0.f, 0.f, 0.f); - LLVector4a bump_t_primary_light_ray(0.f, 0.f, 0.f); + glBeginTransformFeedback(GL_POINTS); + buff->setBuffer(LLVertexBuffer::MAP_NORMAL); + push_for_transform(buff, vf.mNumVertices, mGeomCount); + glEndTransformFeedback(); + } - LLQuaternion bump_quat; - if (mDrawablep->isActive()) + if (rebuild_binormal) { - bump_quat = LLQuaternion(mDrawablep->getRenderMatrix()); + LLFastTimer t(FTM_FACE_GEOM_BINORMAL); + gTransformBinormalProgram.bind(); + + mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_BINORMAL, mGeomIndex, mGeomCount); + + glBeginTransformFeedback(GL_POINTS); + buff->setBuffer(LLVertexBuffer::MAP_BINORMAL); + push_for_transform(buff, vf.mNumVertices, mGeomCount); + glEndTransformFeedback(); } - - if (bump_code) + + if (rebuild_tcoord) { - mVObjp->getVolume()->genBinormals(f); - F32 offset_multiple; - switch( bump_code ) - { - case BE_NO_BUMP: - offset_multiple = 0.f; - break; - case BE_BRIGHTNESS: - case BE_DARKNESS: - if( mTexture.notNull() && mTexture->hasGLTexture()) - { - // Offset by approximately one texel - S32 cur_discard = mTexture->getDiscardLevel(); - S32 max_size = llmax( mTexture->getWidth(), mTexture->getHeight() ); - max_size <<= cur_discard; - const F32 ARTIFICIAL_OFFSET = 2.f; - offset_multiple = ARTIFICIAL_OFFSET / (F32)max_size; - } - else - { - offset_multiple = 1.f/256; - } - break; + LLFastTimer t(FTM_FACE_GEOM_TEXTURE); + gTransformTexCoordProgram.bind(); + + mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_TEXCOORD0, mGeomIndex, mGeomCount); + + glBeginTransformFeedback(GL_POINTS); + buff->setBuffer(LLVertexBuffer::MAP_TEXCOORD0); + push_for_transform(buff, vf.mNumVertices, mGeomCount); + glEndTransformFeedback(); - default: // Standard bumpmap textures. Assumed to be 256x256 - offset_multiple = 1.f / 256; - break; - } + bool do_bump = bump_code && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD1); - F32 s_scale = 1.f; - F32 t_scale = 1.f; - if( tep ) + if (do_bump) { - tep->getScale( &s_scale, &t_scale ); - } - // Use the nudged south when coming from above sun angle, such - // that emboss mapping always shows up on the upward faces of cubes when - // it's noon (since a lot of builders build with the sun forced to noon). - LLVector3 sun_ray = gSky.mVOSkyp->mBumpSunDir; - LLVector3 moon_ray = gSky.getMoonDirection(); - LLVector3& primary_light_ray = (sun_ray.mV[VZ] > 0) ? sun_ray : moon_ray; - - bump_s_primary_light_ray.load3((offset_multiple * s_scale * primary_light_ray).mV); - bump_t_primary_light_ray.load3((offset_multiple * t_scale * primary_light_ray).mV); + mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_TEXCOORD1, mGeomIndex, mGeomCount); + glBeginTransformFeedback(GL_POINTS); + buff->setBuffer(LLVertexBuffer::MAP_TEXCOORD0); + push_for_transform(buff, vf.mNumVertices, mGeomCount); + glEndTransformFeedback(); + } } - U8 texgen = getTextureEntry()->getTexGen(); - if (rebuild_tcoord && texgen != LLTextureEntry::TEX_GEN_DEFAULT) - { //planar texgen needs binormals - mVObjp->getVolume()->genBinormals(f); + glBindBufferARB(GL_TRANSFORM_FEEDBACK_BUFFER, 0); + + gGL.popMatrix(); + + if (cur_shader) + { + cur_shader->bind(); } + } + else +#endif + { + //if it's not fullbright and has no normals, bake sunlight based on face normal + //bool bake_sunlight = !getTextureEntry()->getFullbright() && + // !mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_NORMAL); - U8 tex_mode = 0; - - if (isState(TEXTURE_ANIM)) + if (rebuild_tcoord) { - LLVOVolume* vobj = (LLVOVolume*) (LLViewerObject*) mVObjp; - tex_mode = vobj->mTexAnimMode; + LLFastTimer t(FTM_FACE_GEOM_TEXTURE); + + //bump setup + LLVector4a binormal_dir( -sin_ang, cos_ang, 0.f ); + LLVector4a bump_s_primary_light_ray(0.f, 0.f, 0.f); + LLVector4a bump_t_primary_light_ray(0.f, 0.f, 0.f); - if (!tex_mode) + LLQuaternion bump_quat; + if (mDrawablep->isActive()) { - clearState(TEXTURE_ANIM); + bump_quat = LLQuaternion(mDrawablep->getRenderMatrix()); } - else + + if (bump_code) { - os = ot = 0.f; - r = 0.f; - cos_ang = 1.f; - sin_ang = 0.f; - ms = mt = 1.f; + mVObjp->getVolume()->genBinormals(f); + F32 offset_multiple; + switch( bump_code ) + { + case BE_NO_BUMP: + offset_multiple = 0.f; + break; + case BE_BRIGHTNESS: + case BE_DARKNESS: + if( mTexture.notNull() && mTexture->hasGLTexture()) + { + // Offset by approximately one texel + S32 cur_discard = mTexture->getDiscardLevel(); + S32 max_size = llmax( mTexture->getWidth(), mTexture->getHeight() ); + max_size <<= cur_discard; + const F32 ARTIFICIAL_OFFSET = 2.f; + offset_multiple = ARTIFICIAL_OFFSET / (F32)max_size; + } + else + { + offset_multiple = 1.f/256; + } + break; - do_xform = false; + default: // Standard bumpmap textures. Assumed to be 256x256 + offset_multiple = 1.f / 256; + break; + } + + F32 s_scale = 1.f; + F32 t_scale = 1.f; + if( tep ) + { + tep->getScale( &s_scale, &t_scale ); + } + // Use the nudged south when coming from above sun angle, such + // that emboss mapping always shows up on the upward faces of cubes when + // it's noon (since a lot of builders build with the sun forced to noon). + LLVector3 sun_ray = gSky.mVOSkyp->mBumpSunDir; + LLVector3 moon_ray = gSky.getMoonDirection(); + LLVector3& primary_light_ray = (sun_ray.mV[VZ] > 0) ? sun_ray : moon_ray; + + bump_s_primary_light_ray.load3((offset_multiple * s_scale * primary_light_ray).mV); + bump_t_primary_light_ray.load3((offset_multiple * t_scale * primary_light_ray).mV); } - if (getVirtualSize() >= MIN_TEX_ANIM_SIZE) - { //don't override texture transform during tc bake - tex_mode = 0; + U8 texgen = getTextureEntry()->getTexGen(); + if (rebuild_tcoord && texgen != LLTextureEntry::TEX_GEN_DEFAULT) + { //planar texgen needs binormals + mVObjp->getVolume()->genBinormals(f); } - } - LLVector4a scalea; - scalea.load3(scale.mV); + U8 tex_mode = 0; + + if (isState(TEXTURE_ANIM)) + { + LLVOVolume* vobj = (LLVOVolume*) (LLViewerObject*) mVObjp; + tex_mode = vobj->mTexAnimMode; + + if (!tex_mode) + { + clearState(TEXTURE_ANIM); + } + else + { + os = ot = 0.f; + r = 0.f; + cos_ang = 1.f; + sin_ang = 0.f; + ms = mt = 1.f; - bool do_bump = bump_code && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD1); - bool do_tex_mat = tex_mode && mTextureMatrix; + do_xform = false; + } - if (!in_atlas && !do_bump) - { //not in atlas or not bump mapped, might be able to do a cheap update - mVertexBuffer->getTexCoord0Strider(tex_coords, mGeomIndex, mGeomCount); + if (getVirtualSize() >= MIN_TEX_ANIM_SIZE) + { //don't override texture transform during tc bake + tex_mode = 0; + } + } - if (texgen != LLTextureEntry::TEX_GEN_PLANAR) - { - LLFastTimer t(FTM_FACE_TEX_QUICK); - if (!do_tex_mat) + LLVector4a scalea; + scalea.load3(scale.mV); + + bool do_bump = bump_code && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD1); + bool do_tex_mat = tex_mode && mTextureMatrix; + + if (!in_atlas && !do_bump) + { //not in atlas or not bump mapped, might be able to do a cheap update + mVertexBuffer->getTexCoord0Strider(tex_coords, mGeomIndex, mGeomCount); + + if (texgen != LLTextureEntry::TEX_GEN_PLANAR) { - if (!do_xform) + LLFastTimer t(FTM_FACE_TEX_QUICK); + if (!do_tex_mat) { - LLFastTimer t(FTM_FACE_TEX_QUICK_NO_XFORM); - LLVector4a::memcpyNonAliased16((F32*) tex_coords.get(), (F32*) vf.mTexCoords, num_vertices*2*sizeof(F32)); - } - else - { - LLFastTimer t(FTM_FACE_TEX_QUICK_XFORM); - F32* dst = (F32*) tex_coords.get(); - LLVector4a* src = (LLVector4a*) vf.mTexCoords; + if (!do_xform) + { + LLFastTimer t(FTM_FACE_TEX_QUICK_NO_XFORM); + LLVector4a::memcpyNonAliased16((F32*) tex_coords.get(), (F32*) vf.mTexCoords, num_vertices*2*sizeof(F32)); + } + else + { + LLFastTimer t(FTM_FACE_TEX_QUICK_XFORM); + F32* dst = (F32*) tex_coords.get(); + LLVector4a* src = (LLVector4a*) vf.mTexCoords; - LLVector4a trans; - trans.splat(-0.5f); + LLVector4a trans; + trans.splat(-0.5f); - LLVector4a rot0; - rot0.set(cos_ang, -sin_ang, cos_ang, -sin_ang); + LLVector4a rot0; + rot0.set(cos_ang, -sin_ang, cos_ang, -sin_ang); - LLVector4a rot1; - rot1.set(sin_ang, cos_ang, sin_ang, cos_ang); + LLVector4a rot1; + rot1.set(sin_ang, cos_ang, sin_ang, cos_ang); - LLVector4a scale; - scale.set(ms, mt, ms, mt); + LLVector4a scale; + scale.set(ms, mt, ms, mt); - LLVector4a offset; - offset.set(os+0.5f, ot+0.5f, os+0.5f, ot+0.5f); + LLVector4a offset; + offset.set(os+0.5f, ot+0.5f, os+0.5f, ot+0.5f); - LLVector4Logical mask; - mask.clear(); - mask.setElement<2>(); - mask.setElement<3>(); + LLVector4Logical mask; + mask.clear(); + mask.setElement<2>(); + mask.setElement<3>(); - U32 count = num_vertices/2 + num_vertices%2; + U32 count = num_vertices/2 + num_vertices%2; - for (S32 i = 0; i < count; i++) + for (S32 i = 0; i < count; i++) + { + LLVector4a res = *src++; + xform4a(res, trans, mask, rot0, rot1, offset, scale); + res.store4a(dst); + dst += 4; + } + } + } + else + { //do tex mat, no texgen, no atlas, no bump + for (S32 i = 0; i < num_vertices; i++) { - LLVector4a res = *src++; - xform4a(res, trans, mask, rot0, rot1, offset, scale); - res.store4a(dst); - dst += 4; + LLVector2 tc(vf.mTexCoords[i]); + //LLVector4a& norm = vf.mNormals[i]; + //LLVector4a& center = *(vf.mCenter); + + LLVector3 tmp(tc.mV[0], tc.mV[1], 0.f); + tmp = tmp * *mTextureMatrix; + tc.mV[0] = tmp.mV[0]; + tc.mV[1] = tmp.mV[1]; + *tex_coords++ = tc; } } } else - { //do tex mat, no texgen, no atlas, no bump - for (S32 i = 0; i < num_vertices; i++) - { - LLVector2 tc(vf.mTexCoords[i]); - //LLVector4a& norm = vf.mNormals[i]; - //LLVector4a& center = *(vf.mCenter); - - LLVector3 tmp(tc.mV[0], tc.mV[1], 0.f); - tmp = tmp * *mTextureMatrix; - tc.mV[0] = tmp.mV[0]; - tc.mV[1] = tmp.mV[1]; - *tex_coords++ = tc; - } - } - } - else - { //no bump, no atlas, tex gen planar - LLFastTimer t(FTM_FACE_TEX_QUICK_PLANAR); - if (do_tex_mat) - { - for (S32 i = 0; i < num_vertices; i++) - { - LLVector2 tc(vf.mTexCoords[i]); - LLVector4a& norm = vf.mNormals[i]; - LLVector4a& center = *(vf.mCenter); - LLVector4a vec = vf.mPositions[i]; - vec.mul(scalea); - planarProjection(tc, norm, center, vec); + { //no bump, no atlas, tex gen planar + LLFastTimer t(FTM_FACE_TEX_QUICK_PLANAR); + if (do_tex_mat) + { + for (S32 i = 0; i < num_vertices; i++) + { + LLVector2 tc(vf.mTexCoords[i]); + LLVector4a& norm = vf.mNormals[i]; + LLVector4a& center = *(vf.mCenter); + LLVector4a vec = vf.mPositions[i]; + vec.mul(scalea); + planarProjection(tc, norm, center, vec); - LLVector3 tmp(tc.mV[0], tc.mV[1], 0.f); - tmp = tmp * *mTextureMatrix; - tc.mV[0] = tmp.mV[0]; - tc.mV[1] = tmp.mV[1]; + LLVector3 tmp(tc.mV[0], tc.mV[1], 0.f); + tmp = tmp * *mTextureMatrix; + tc.mV[0] = tmp.mV[0]; + tc.mV[1] = tmp.mV[1]; - *tex_coords++ = tc; + *tex_coords++ = tc; + } } - } - else - { - for (S32 i = 0; i < num_vertices; i++) - { - LLVector2 tc(vf.mTexCoords[i]); - LLVector4a& norm = vf.mNormals[i]; - LLVector4a& center = *(vf.mCenter); - LLVector4a vec = vf.mPositions[i]; - vec.mul(scalea); - planarProjection(tc, norm, center, vec); + else + { + for (S32 i = 0; i < num_vertices; i++) + { + LLVector2 tc(vf.mTexCoords[i]); + LLVector4a& norm = vf.mNormals[i]; + LLVector4a& center = *(vf.mCenter); + LLVector4a vec = vf.mPositions[i]; + vec.mul(scalea); + planarProjection(tc, norm, center, vec); - xform(tc, cos_ang, sin_ang, os, ot, ms, mt); + xform(tc, cos_ang, sin_ang, os, ot, ms, mt); - *tex_coords++ = tc; + *tex_coords++ = tc; + } } } - } - if (map_range) - { - mVertexBuffer->flush(); + if (map_range) + { + mVertexBuffer->flush(); + } } - } - else - { //either bump mapped or in atlas, just do the whole expensive loop - LLFastTimer t(FTM_FACE_TEX_DEFAULT); - mVertexBuffer->getTexCoord0Strider(tex_coords, mGeomIndex, mGeomCount, map_range); + else + { //either bump mapped or in atlas, just do the whole expensive loop + LLFastTimer t(FTM_FACE_TEX_DEFAULT); + mVertexBuffer->getTexCoord0Strider(tex_coords, mGeomIndex, mGeomCount, map_range); - std::vector<LLVector2> bump_tc; + std::vector<LLVector2> bump_tc; - for (S32 i = 0; i < num_vertices; i++) - { - LLVector2 tc(vf.mTexCoords[i]); + for (S32 i = 0; i < num_vertices; i++) + { + LLVector2 tc(vf.mTexCoords[i]); - LLVector4a& norm = vf.mNormals[i]; + LLVector4a& norm = vf.mNormals[i]; - LLVector4a& center = *(vf.mCenter); + LLVector4a& center = *(vf.mCenter); - if (texgen != LLTextureEntry::TEX_GEN_DEFAULT) - { - LLVector4a vec = vf.mPositions[i]; + if (texgen != LLTextureEntry::TEX_GEN_DEFAULT) + { + LLVector4a vec = vf.mPositions[i]; - vec.mul(scalea); + vec.mul(scalea); - switch (texgen) + switch (texgen) + { + case LLTextureEntry::TEX_GEN_PLANAR: + planarProjection(tc, norm, center, vec); + break; + case LLTextureEntry::TEX_GEN_SPHERICAL: + sphericalProjection(tc, norm, center, vec); + break; + case LLTextureEntry::TEX_GEN_CYLINDRICAL: + cylindricalProjection(tc, norm, center, vec); + break; + default: + break; + } + } + + if (tex_mode && mTextureMatrix) { - case LLTextureEntry::TEX_GEN_PLANAR: - planarProjection(tc, norm, center, vec); + LLVector3 tmp(tc.mV[0], tc.mV[1], 0.f); + tmp = tmp * *mTextureMatrix; + tc.mV[0] = tmp.mV[0]; + tc.mV[1] = tmp.mV[1]; + } + else + { + xform(tc, cos_ang, sin_ang, os, ot, ms, mt); + } + + if(in_atlas) + { + // + //manually calculate tex-coord per vertex for varying address modes. + //should be removed if shader can handle this. + // + + S32 int_part = 0 ; + switch(mTexture->getAddressMode()) + { + case LLTexUnit::TAM_CLAMP: + if(tc.mV[0] < 0.f) + { + tc.mV[0] = 0.f ; + } + else if(tc.mV[0] > 1.f) + { + tc.mV[0] = 1.f; + } + + if(tc.mV[1] < 0.f) + { + tc.mV[1] = 0.f ; + } + else if(tc.mV[1] > 1.f) + { + tc.mV[1] = 1.f; + } break; - case LLTextureEntry::TEX_GEN_SPHERICAL: - sphericalProjection(tc, norm, center, vec); + case LLTexUnit::TAM_MIRROR: + if(tc.mV[0] < 0.f) + { + tc.mV[0] = -tc.mV[0] ; + } + int_part = (S32)tc.mV[0] ; + if(int_part & 1) //odd number + { + tc.mV[0] = int_part + 1 - tc.mV[0] ; + } + else //even number + { + tc.mV[0] -= int_part ; + } + + if(tc.mV[1] < 0.f) + { + tc.mV[1] = -tc.mV[1] ; + } + int_part = (S32)tc.mV[1] ; + if(int_part & 1) //odd number + { + tc.mV[1] = int_part + 1 - tc.mV[1] ; + } + else //even number + { + tc.mV[1] -= int_part ; + } break; - case LLTextureEntry::TEX_GEN_CYLINDRICAL: - cylindricalProjection(tc, norm, center, vec); + case LLTexUnit::TAM_WRAP: + if(tc.mV[0] > 1.f) + tc.mV[0] -= (S32)(tc.mV[0] - 0.00001f) ; + else if(tc.mV[0] < -1.f) + tc.mV[0] -= (S32)(tc.mV[0] + 0.00001f) ; + + if(tc.mV[1] > 1.f) + tc.mV[1] -= (S32)(tc.mV[1] - 0.00001f) ; + else if(tc.mV[1] < -1.f) + tc.mV[1] -= (S32)(tc.mV[1] + 0.00001f) ; + + if(tc.mV[0] < 0.f) + { + tc.mV[0] = 1.0f + tc.mV[0] ; + } + if(tc.mV[1] < 0.f) + { + tc.mV[1] = 1.0f + tc.mV[1] ; + } break; default: break; - } - } + } + + tc.mV[0] = tcoord_xoffset + tcoord_xscale * tc.mV[0] ; + tc.mV[1] = tcoord_yoffset + tcoord_yscale * tc.mV[1] ; + } + - if (tex_mode && mTextureMatrix) - { - LLVector3 tmp(tc.mV[0], tc.mV[1], 0.f); - tmp = tmp * *mTextureMatrix; - tc.mV[0] = tmp.mV[0]; - tc.mV[1] = tmp.mV[1]; + *tex_coords++ = tc; + if (do_bump) + { + bump_tc.push_back(tc); + } } - else + + if (map_range) { - xform(tc, cos_ang, sin_ang, os, ot, ms, mt); + mVertexBuffer->flush(); } - if(in_atlas) + if (do_bump) { - // - //manually calculate tex-coord per vertex for varying address modes. - //should be removed if shader can handle this. - // - - S32 int_part = 0 ; - switch(mTexture->getAddressMode()) + mVertexBuffer->getTexCoord1Strider(tex_coords2, mGeomIndex, mGeomCount, map_range); + + for (S32 i = 0; i < num_vertices; i++) { - case LLTexUnit::TAM_CLAMP: - if(tc.mV[0] < 0.f) - { - tc.mV[0] = 0.f ; - } - else if(tc.mV[0] > 1.f) - { - tc.mV[0] = 1.f; - } - - if(tc.mV[1] < 0.f) - { - tc.mV[1] = 0.f ; - } - else if(tc.mV[1] > 1.f) - { - tc.mV[1] = 1.f; - } - break; - case LLTexUnit::TAM_MIRROR: - if(tc.mV[0] < 0.f) - { - tc.mV[0] = -tc.mV[0] ; - } - int_part = (S32)tc.mV[0] ; - if(int_part & 1) //odd number - { - tc.mV[0] = int_part + 1 - tc.mV[0] ; - } - else //even number + LLVector4a tangent; + tangent.setCross3(vf.mBinormals[i], vf.mNormals[i]); + + LLMatrix4a tangent_to_object; + tangent_to_object.setRows(tangent, vf.mBinormals[i], vf.mNormals[i]); + LLVector4a t; + tangent_to_object.rotate(binormal_dir, t); + LLVector4a binormal; + mat_normal.rotate(t, binormal); + + //VECTORIZE THIS + if (mDrawablep->isActive()) { - tc.mV[0] -= int_part ; + LLVector3 t; + t.set(binormal.getF32ptr()); + t *= bump_quat; + binormal.load3(t.mV); } - if(tc.mV[1] < 0.f) - { - tc.mV[1] = -tc.mV[1] ; - } - int_part = (S32)tc.mV[1] ; - if(int_part & 1) //odd number - { - tc.mV[1] = int_part + 1 - tc.mV[1] ; - } - else //even number - { - tc.mV[1] -= int_part ; - } - break; - case LLTexUnit::TAM_WRAP: - if(tc.mV[0] > 1.f) - tc.mV[0] -= (S32)(tc.mV[0] - 0.00001f) ; - else if(tc.mV[0] < -1.f) - tc.mV[0] -= (S32)(tc.mV[0] + 0.00001f) ; - - if(tc.mV[1] > 1.f) - tc.mV[1] -= (S32)(tc.mV[1] - 0.00001f) ; - else if(tc.mV[1] < -1.f) - tc.mV[1] -= (S32)(tc.mV[1] + 0.00001f) ; - - if(tc.mV[0] < 0.f) - { - tc.mV[0] = 1.0f + tc.mV[0] ; - } - if(tc.mV[1] < 0.f) - { - tc.mV[1] = 1.0f + tc.mV[1] ; - } - break; - default: - break; + binormal.normalize3fast(); + LLVector2 tc = bump_tc[i]; + tc += LLVector2( bump_s_primary_light_ray.dot3(tangent).getF32(), bump_t_primary_light_ray.dot3(binormal).getF32() ); + + *tex_coords2++ = tc; } - - tc.mV[0] = tcoord_xoffset + tcoord_xscale * tc.mV[0] ; - tc.mV[1] = tcoord_yoffset + tcoord_yscale * tc.mV[1] ; - } - - *tex_coords++ = tc; - if (do_bump) - { - bump_tc.push_back(tc); - } - } - - if (map_range) - { - mVertexBuffer->flush(); - } - - if (do_bump) - { - mVertexBuffer->getTexCoord1Strider(tex_coords2, mGeomIndex, mGeomCount, map_range); - - for (S32 i = 0; i < num_vertices; i++) - { - LLVector4a tangent; - tangent.setCross3(vf.mBinormals[i], vf.mNormals[i]); - - LLMatrix4a tangent_to_object; - tangent_to_object.setRows(tangent, vf.mBinormals[i], vf.mNormals[i]); - LLVector4a t; - tangent_to_object.rotate(binormal_dir, t); - LLVector4a binormal; - mat_normal.rotate(t, binormal); - - //VECTORIZE THIS - if (mDrawablep->isActive()) + if (map_range) { - LLVector3 t; - t.set(binormal.getF32ptr()); - t *= bump_quat; - binormal.load3(t.mV); + mVertexBuffer->flush(); } - - binormal.normalize3fast(); - LLVector2 tc = bump_tc[i]; - tc += LLVector2( bump_s_primary_light_ray.dot3(tangent).getF32(), bump_t_primary_light_ray.dot3(binormal).getF32() ); - - *tex_coords2++ = tc; - } - - if (map_range) - { - mVertexBuffer->flush(); } } } - } - if (rebuild_pos) - { - LLFastTimer t(FTM_FACE_GEOM_POSITION); - llassert(num_vertices > 0); + if (rebuild_pos) + { + LLFastTimer t(FTM_FACE_GEOM_POSITION); + llassert(num_vertices > 0); - mVertexBuffer->getVertexStrider(vert, mGeomIndex, mGeomCount, map_range); + mVertexBuffer->getVertexStrider(vert, mGeomIndex, mGeomCount, map_range); - LLMatrix4a mat_vert; - mat_vert.loadu(mat_vert_in); + LLMatrix4a mat_vert; + mat_vert.loadu(mat_vert_in); - LLVector4a* src = vf.mPositions; - volatile F32* dst = (volatile F32*) vert.get(); + LLVector4a* src = vf.mPositions; + volatile F32* dst = (volatile F32*) vert.get(); - volatile F32* end = dst+num_vertices*4; - LLVector4a res; + volatile F32* end = dst+num_vertices*4; + LLVector4a res; - LLVector4a texIdx; + LLVector4a texIdx; - U8 index = mTextureIndex < 255 ? mTextureIndex : 0; + S32 index = mTextureIndex < 255 ? mTextureIndex : 0; - F32 val = 0.f; - U8* vp = (U8*) &val; - vp[0] = index; - vp[1] = 0; - vp[2] = 0; - vp[3] = 0; - - llassert(index <= LLGLSLShader::sIndexedTextureChannels-1); + F32 val = 0.f; + S32* vp = (S32*) &val; + *vp = index; + + llassert(index <= LLGLSLShader::sIndexedTextureChannels-1); - LLVector4Logical mask; - mask.clear(); - mask.setElement<3>(); + LLVector4Logical mask; + mask.clear(); + mask.setElement<3>(); - texIdx.set(0,0,0,val); + texIdx.set(0,0,0,val); - { - LLFastTimer t(FTM_FACE_POSITION_STORE); - LLVector4a tmp; - - do - { - mat_vert.affineTransform(*src++, res); - tmp.setSelectWithMask(mask, texIdx, res); - tmp.store4a((F32*) dst); - dst += 4; + { + LLFastTimer t(FTM_FACE_POSITION_STORE); + LLVector4a tmp; + + do + { + mat_vert.affineTransform(*src++, res); + tmp.setSelectWithMask(mask, texIdx, res); + tmp.store4a((F32*) dst); + dst += 4; + } + while(dst < end); } - while(dst < end); - } - { - LLFastTimer t(FTM_FACE_POSITION_PAD); - S32 aligned_pad_vertices = mGeomCount - num_vertices; - res.set(res[0], res[1], res[2], 0.f); + { + LLFastTimer t(FTM_FACE_POSITION_PAD); + S32 aligned_pad_vertices = mGeomCount - num_vertices; + res.set(res[0], res[1], res[2], 0.f); - while (aligned_pad_vertices > 0) + while (aligned_pad_vertices > 0) + { + --aligned_pad_vertices; + res.store4a((F32*) dst); + dst += 4; + } + } + + if (map_range) { - --aligned_pad_vertices; - res.store4a((F32*) dst); - dst += 4; + mVertexBuffer->flush(); } } - if (map_range) - { - mVertexBuffer->flush(); - } - } - if (rebuild_normal) - { - LLFastTimer t(FTM_FACE_GEOM_NORMAL); - mVertexBuffer->getNormalStrider(norm, mGeomIndex, mGeomCount, map_range); - F32* normals = (F32*) norm.get(); + if (rebuild_normal) + { + LLFastTimer t(FTM_FACE_GEOM_NORMAL); + mVertexBuffer->getNormalStrider(norm, mGeomIndex, mGeomCount, map_range); + F32* normals = (F32*) norm.get(); - for (S32 i = 0; i < num_vertices; i++) - { - LLVector4a normal; - mat_normal.rotate(vf.mNormals[i], normal); - normal.normalize3fast(); - normal.store4a(normals); - normals += 4; - } + for (S32 i = 0; i < num_vertices; i++) + { + LLVector4a normal; + mat_normal.rotate(vf.mNormals[i], normal); + normal.normalize3fast(); + normal.store4a(normals); + normals += 4; + } - if (map_range) - { - mVertexBuffer->flush(); + if (map_range) + { + mVertexBuffer->flush(); + } } - } - if (rebuild_binormal) - { - LLFastTimer t(FTM_FACE_GEOM_BINORMAL); - mVertexBuffer->getBinormalStrider(binorm, mGeomIndex, mGeomCount, map_range); - F32* binormals = (F32*) binorm.get(); + if (rebuild_binormal) + { + LLFastTimer t(FTM_FACE_GEOM_BINORMAL); + mVertexBuffer->getBinormalStrider(binorm, mGeomIndex, mGeomCount, map_range); + F32* binormals = (F32*) binorm.get(); - for (S32 i = 0; i < num_vertices; i++) - { - LLVector4a binormal; - mat_normal.rotate(vf.mBinormals[i], binormal); - binormal.normalize3fast(); - binormal.store4a(binormals); - binormals += 4; - } + for (S32 i = 0; i < num_vertices; i++) + { + LLVector4a binormal; + mat_normal.rotate(vf.mBinormals[i], binormal); + binormal.normalize3fast(); + binormal.store4a(binormals); + binormals += 4; + } - if (map_range) - { - mVertexBuffer->flush(); + if (map_range) + { + mVertexBuffer->flush(); + } } - } - if (rebuild_weights && vf.mWeights) - { - LLFastTimer t(FTM_FACE_GEOM_WEIGHTS); - mVertexBuffer->getWeight4Strider(wght, mGeomIndex, mGeomCount, map_range); - F32* weights = (F32*) wght.get(); - LLVector4a::memcpyNonAliased16(weights, (F32*) vf.mWeights, num_vertices*4*sizeof(F32)); - if (map_range) + if (rebuild_weights && vf.mWeights) { - mVertexBuffer->flush(); + LLFastTimer t(FTM_FACE_GEOM_WEIGHTS); + mVertexBuffer->getWeight4Strider(wght, mGeomIndex, mGeomCount, map_range); + F32* weights = (F32*) wght.get(); + LLVector4a::memcpyNonAliased16(weights, (F32*) vf.mWeights, num_vertices*4*sizeof(F32)); + if (map_range) + { + mVertexBuffer->flush(); + } } - } - if (rebuild_color && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_COLOR) ) - { - LLFastTimer t(FTM_FACE_GEOM_COLOR); - mVertexBuffer->getColorStrider(colors, mGeomIndex, mGeomCount, map_range); + if (rebuild_color && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_COLOR) ) + { + LLFastTimer t(FTM_FACE_GEOM_COLOR); + mVertexBuffer->getColorStrider(colors, mGeomIndex, mGeomCount, map_range); - LLVector4a src; + LLVector4a src; - U32 vec[4]; - vec[0] = vec[1] = vec[2] = vec[3] = color.mAll; + U32 vec[4]; + vec[0] = vec[1] = vec[2] = vec[3] = color.mAll; - src.loadua((F32*) vec); + src.loadua((F32*) vec); - F32* dst = (F32*) colors.get(); - S32 num_vecs = num_vertices/4; - if (num_vertices%4 > 0) - { - ++num_vecs; - } + F32* dst = (F32*) colors.get(); + S32 num_vecs = num_vertices/4; + if (num_vertices%4 > 0) + { + ++num_vecs; + } - for (S32 i = 0; i < num_vecs; i++) - { - src.store4a(dst); - dst += 4; - } + for (S32 i = 0; i < num_vecs; i++) + { + src.store4a(dst); + dst += 4; + } - if (map_range) - { - mVertexBuffer->flush(); + if (map_range) + { + mVertexBuffer->flush(); + } } - } - if (rebuild_emissive) - { - LLFastTimer t(FTM_FACE_GEOM_EMISSIVE); - LLStrider<LLColor4U> emissive; - mVertexBuffer->getEmissiveStrider(emissive, mGeomIndex, mGeomCount, map_range); + if (rebuild_emissive) + { + LLFastTimer t(FTM_FACE_GEOM_EMISSIVE); + LLStrider<LLColor4U> emissive; + mVertexBuffer->getEmissiveStrider(emissive, mGeomIndex, mGeomCount, map_range); - U8 glow = (U8) llclamp((S32) (getTextureEntry()->getGlow()*255), 0, 255); + U8 glow = (U8) llclamp((S32) (getTextureEntry()->getGlow()*255), 0, 255); - LLVector4a src; + LLVector4a src; - U32 glow32 = glow | - (glow << 8) | - (glow << 16) | - (glow << 24); + U32 glow32 = glow | + (glow << 8) | + (glow << 16) | + (glow << 24); - U32 vec[4]; - vec[0] = vec[1] = vec[2] = vec[3] = glow32; + U32 vec[4]; + vec[0] = vec[1] = vec[2] = vec[3] = glow32; - src.loadua((F32*) vec); + src.loadua((F32*) vec); - F32* dst = (F32*) emissive.get(); - S32 num_vecs = num_vertices/4; - if (num_vertices%4 > 0) - { - ++num_vecs; - } + F32* dst = (F32*) emissive.get(); + S32 num_vecs = num_vertices/4; + if (num_vertices%4 > 0) + { + ++num_vecs; + } - for (S32 i = 0; i < num_vecs; i++) - { - src.store4a(dst); - dst += 4; - } + for (S32 i = 0; i < num_vecs; i++) + { + src.store4a(dst); + dst += 4; + } - if (map_range) - { - mVertexBuffer->flush(); + if (map_range) + { + mVertexBuffer->flush(); + } } } + if (rebuild_tcoord) { mTexExtents[0].setVec(0,0); @@ -1932,12 +2148,6 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, } - mLastVertexBuffer = mVertexBuffer; - mLastGeomCount = mGeomCount; - mLastGeomIndex = mGeomIndex; - mLastIndicesCount = mIndicesCount; - mLastIndicesIndex = mIndicesIndex; - return TRUE; } @@ -2516,7 +2726,6 @@ void LLFace::setVertexBuffer(LLVertexBuffer* buffer) void LLFace::clearVertexBuffer() { mVertexBuffer = NULL; - mLastVertexBuffer = NULL; } //static diff --git a/indra/newview/llface.h b/indra/newview/llface.h index 82e4ab61b7..76ea5c853a 100644 --- a/indra/newview/llface.h +++ b/indra/newview/llface.h @@ -83,6 +83,8 @@ public: static void initClass(); + static void cacheFaceInVRAM(const LLVolumeFace& vf); + public: LLFace(LLDrawable* drawablep, LLViewerObject* objp) { init(drawablep, objp); } ~LLFace() { destroy(); } @@ -222,7 +224,7 @@ public: //vertex buffer tracking void setVertexBuffer(LLVertexBuffer* buffer); - void clearVertexBuffer(); //sets mVertexBuffer and mLastVertexBuffer to NULL + void clearVertexBuffer(); //sets mVertexBuffer to NULL LLVertexBuffer* getVertexBuffer() const { return mVertexBuffer; } U32 getRiggedVertexBufferDataMask() const; S32 getRiggedIndex(U32 type) const; @@ -255,8 +257,7 @@ public: private: LLPointer<LLVertexBuffer> mVertexBuffer; - LLPointer<LLVertexBuffer> mLastVertexBuffer; - + U32 mState; LLFacePool* mDrawPoolp; U32 mPoolType; @@ -269,12 +270,6 @@ private: U32 mIndicesIndex; // index into draw pool for indices (yeah, I know!) S32 mIndexInTex ; - //previous rebuild's geometry info - U16 mLastGeomCount; - U16 mLastGeomIndex; - U32 mLastIndicesCount; - U32 mLastIndicesIndex; - LLXformMatrix* mXform; LLPointer<LLViewerTexture> mTexture; LLPointer<LLDrawable> mDrawablep; diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp index 4a96de942d..c68577db75 100644 --- a/indra/newview/llfavoritesbar.cpp +++ b/indra/newview/llfavoritesbar.cpp @@ -1196,7 +1196,7 @@ void LLFavoritesBarCtrl::doToSelected(const LLSD& userdata) } else if (action == "paste") { - pastFromClipboard(); + pasteFromClipboard(); } else if (action == "delete") { @@ -1244,7 +1244,7 @@ BOOL LLFavoritesBarCtrl::isClipboardPasteable() const return TRUE; } -void LLFavoritesBarCtrl::pastFromClipboard() const +void LLFavoritesBarCtrl::pasteFromClipboard() const { LLInventoryModel* model = &gInventory; if(model && isClipboardPasteable()) diff --git a/indra/newview/llfavoritesbar.h b/indra/newview/llfavoritesbar.h index 60e02b661e..e000adc4aa 100644 --- a/indra/newview/llfavoritesbar.h +++ b/indra/newview/llfavoritesbar.h @@ -91,7 +91,7 @@ protected: bool enableSelected(const LLSD& userdata); void doToSelected(const LLSD& userdata); BOOL isClipboardPasteable() const; - void pastFromClipboard() const; + void pasteFromClipboard() const; void showDropDownMenu(); diff --git a/indra/newview/llfeaturemanager.cpp b/indra/newview/llfeaturemanager.cpp index 08f9d26705..393f8b9d46 100644 --- a/indra/newview/llfeaturemanager.cpp +++ b/indra/newview/llfeaturemanager.cpp @@ -670,7 +670,14 @@ void LLFeatureManager::setGraphicsLevel(S32 level, bool skipFeatures) switch (level) { case 0: - maskFeatures("Low"); + if (gGLManager.mGLVersion < 3.f || gGLManager.mIsIntel) + { //only use fixed function by default if GL version < 3.0 or this is an intel graphics chip + maskFeatures("LowFixedFunction"); + } + else + { //same as low, but with "Basic Shaders" enabled + maskFeatures("Low"); + } break; case 1: maskFeatures("Mid"); @@ -690,6 +697,7 @@ void LLFeatureManager::setGraphicsLevel(S32 level, bool skipFeatures) LLViewerShaderMgr::sSkipReload = false; LLViewerShaderMgr::instance()->setShaders(); + gPipeline.refreshCachedSettings(); } void LLFeatureManager::applyBaseMasks() @@ -779,6 +787,10 @@ void LLFeatureManager::applyBaseMasks() { maskFeatures("MapBufferRange"); } + if (gGLManager.mVRAM > 512) + { + maskFeatures("VRAMGT512"); + } // now mask by gpu string // Replaces ' ' with '_' in mGPUString to deal with inability for parser to handle spaces diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp index 8986a694f9..4bf5b26b3b 100644 --- a/indra/newview/llfilepicker.cpp +++ b/indra/newview/llfilepicker.cpp @@ -59,6 +59,7 @@ LLFilePicker LLFilePicker::sInstance; #define RAW_FILTER L"RAW files (*.raw)\0*.raw\0" #define MODEL_FILTER L"Model files (*.dae)\0*.dae\0" #define SCRIPT_FILTER L"Script files (*.lsl)\0*.lsl\0" +#define DICTIONARY_FILTER L"Dictionary files (*.dic; *.xcu)\0*.dic;*.xcu\0" #endif // @@ -218,6 +219,10 @@ BOOL LLFilePicker::setupFilter(ELoadFilter filter) mOFN.lpstrFilter = SCRIPT_FILTER \ L"\0"; break; + case FFLOAD_DICTIONARY: + mOFN.lpstrFilter = DICTIONARY_FILTER \ + L"\0"; + break; default: res = FALSE; break; @@ -643,6 +648,16 @@ Boolean LLFilePicker::navOpenFilterProc(AEDesc *theItem, void *info, void *callB result = false; } } + else if (filter == FFLOAD_DICTIONARY) + { + if (fileInfo.filetype != 'DIC ' && + fileInfo.filetype != 'XCU ' && + (fileInfo.extension && (CFStringCompare(fileInfo.extension, CFSTR("dic"), kCFCompareCaseInsensitive) != kCFCompareEqualTo) && + fileInfo.extension && (CFStringCompare(fileInfo.extension, CFSTR("xcu"), kCFCompareCaseInsensitive) != kCFCompareEqualTo))) + { + result = false; + } + } if (fileInfo.extension) { @@ -1235,6 +1250,12 @@ static std::string add_script_filter_to_gtkchooser(GtkWindow *picker) LLTrans::getString("script_files") + " (*.lsl)"); } +static std::string add_dictionary_filter_to_gtkchooser(GtkWindow *picker) +{ + return add_simple_mime_filter_to_gtkchooser(picker, "text/plain", + LLTrans::getString("dictionary_files") + " (*.dic; *.xcu)"); +} + BOOL LLFilePicker::getSaveFile( ESaveFilter filter, const std::string& filename ) { BOOL rtn = FALSE; @@ -1371,6 +1392,9 @@ BOOL LLFilePicker::getOpenFile( ELoadFilter filter, bool blocking ) case FFLOAD_SCRIPT: filtername = add_script_filter_to_gtkchooser(picker); break; + case FFLOAD_DICTIONARY: + filtername = add_dictionary_filter_to_gtkchooser(picker); + break; default:; break; } diff --git a/indra/newview/llfilepicker.h b/indra/newview/llfilepicker.h index a4d5d68ff5..55c665b9c7 100644 --- a/indra/newview/llfilepicker.h +++ b/indra/newview/llfilepicker.h @@ -85,6 +85,7 @@ public: FFLOAD_MODEL = 9, FFLOAD_COLLADA = 10, FFLOAD_SCRIPT = 11, + FFLOAD_DICTIONARY = 12 }; enum ESaveFilter diff --git a/indra/newview/llflexibleobject.cpp b/indra/newview/llflexibleobject.cpp index 32a533570a..11edb60712 100644 --- a/indra/newview/llflexibleobject.cpp +++ b/indra/newview/llflexibleobject.cpp @@ -368,7 +368,7 @@ void LLVolumeImplFlexible::doFlexibleUpdate() LLPath *path = &volume->getPath(); if ((mSimulateRes == 0 || !mInitialized) && mVO->mDrawable->isVisible()) { - mVO->markForUpdate(TRUE); + //mVO->markForUpdate(TRUE); if (!doIdleUpdate(gAgent, *LLWorld::getInstance(), 0.0)) { return; // we did not get updated or initialized, proceeding without can be dangerous @@ -729,7 +729,11 @@ BOOL LLVolumeImplFlexible::doUpdateGeometry(LLDrawable *drawable) else if (!mUpdated || rotated) { volume->mDrawable->setState(LLDrawable::REBUILD_POSITION); - volume->dirtyMesh(); + LLSpatialGroup* group = volume->mDrawable->getSpatialGroup(); + if (group) + { + group->dirtyMesh(); + } volume->genBBoxes(isVolumeGlobal()); } @@ -814,15 +818,17 @@ LLQuaternion LLVolumeImplFlexible::getEndRotation() }//------------------------------------------------------------------ -void LLVolumeImplFlexible::updateRelativeXform() +void LLVolumeImplFlexible::updateRelativeXform(bool force_identity) { LLQuaternion delta_rot; LLVector3 delta_pos, delta_scale; LLVOVolume* vo = (LLVOVolume*) mVO; + bool use_identity = vo->mDrawable->isSpatialRoot() || force_identity; + //matrix from local space to parent relative/global space - delta_rot = vo->mDrawable->isSpatialRoot() ? LLQuaternion() : vo->mDrawable->getRotation(); - delta_pos = vo->mDrawable->isSpatialRoot() ? LLVector3(0,0,0) : vo->mDrawable->getPosition(); + delta_rot = use_identity ? LLQuaternion() : vo->mDrawable->getRotation(); + delta_pos = use_identity ? LLVector3(0,0,0) : vo->mDrawable->getPosition(); delta_scale = LLVector3(1,1,1); // Vertex transform (4x4) diff --git a/indra/newview/llflexibleobject.h b/indra/newview/llflexibleobject.h index fef43d464d..371d6a0773 100644 --- a/indra/newview/llflexibleobject.h +++ b/indra/newview/llflexibleobject.h @@ -89,7 +89,7 @@ class LLVolumeImplFlexible : public LLVolumeInterface bool isVolumeGlobal() const { return true; } bool isActive() const { return true; } const LLMatrix4& getWorldMatrix(LLXformMatrix* xform) const; - void updateRelativeXform(); + void updateRelativeXform(bool force_identity); void doFlexibleUpdate(); // Called to update the simulation void doFlexibleRebuild(); // Called to rebuild the geometry void preRebuild(); diff --git a/indra/newview/llfloaterautoreplacesettings.cpp b/indra/newview/llfloaterautoreplacesettings.cpp new file mode 100644 index 0000000000..7d1bcba978 --- /dev/null +++ b/indra/newview/llfloaterautoreplacesettings.cpp @@ -0,0 +1,641 @@ +/** + * @file llfloaterautoreplacesettings.cpp + * @brief Auto Replace List floater + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llfloaterautoreplacesettings.h" + +#include "llagentdata.h" +#include "llcommandhandler.h" +#include "llfloater.h" +#include "lluictrlfactory.h" +#include "llagent.h" +#include "llpanel.h" +#include "llbutton.h" +#include "llcolorswatch.h" +#include "llcombobox.h" +#include "llview.h" +#include "llhttpclient.h" +#include "llbufferstream.h" +#include "llcheckboxctrl.h" +#include "llviewercontrol.h" + +#include "llui.h" +#include "llcontrol.h" +#include "llscrollingpanellist.h" +#include "llautoreplace.h" +#include "llfilepicker.h" +#include "llfile.h" +#include "llsdserialize.h" +#include "llsdutil.h" + +#include "llchat.h" +#include "llinventorymodel.h" +#include "llhost.h" +#include "llassetstorage.h" +#include "roles_constants.h" +#include "llviewertexteditor.h" +#include <boost/tokenizer.hpp> + +#include <iosfwd> +#include "llfloaterreg.h" +#include "llinspecttoast.h" +#include "llnotificationhandler.h" +#include "llnotificationmanager.h" +#include "llnotificationsutil.h" + + +LLFloaterAutoReplaceSettings::LLFloaterAutoReplaceSettings(const LLSD& key) + : LLFloater(key) + , mSelectedListName("") + , mListNames(NULL) + , mReplacementsList(NULL) + , mKeyword(NULL) + , mPreviousKeyword("") + , mReplacement(NULL) +{ +} + +void LLFloaterAutoReplaceSettings::onClose(bool app_quitting) +{ + cleanUp(); +} + +BOOL LLFloaterAutoReplaceSettings::postBuild(void) +{ + // get copies of the current settings that we will operate on + mEnabled = gSavedSettings.getBOOL("AutoReplace"); + LL_DEBUGS("AutoReplace") << ( mEnabled ? "enabled" : "disabled") << LL_ENDL; + + mSettings = LLAutoReplace::getInstance()->getSettings(); + + // global checkbox for whether or not autoreplace is active + LLUICtrl* enabledCheckbox = getChild<LLUICtrl>("autoreplace_enable"); + enabledCheckbox->setCommitCallback(boost::bind(&LLFloaterAutoReplaceSettings::onAutoReplaceToggled, this)); + enabledCheckbox->setValue(LLSD(mEnabled)); + + // top row list creation and deletion + getChild<LLUICtrl>("autoreplace_import_list")->setCommitCallback(boost::bind(&LLFloaterAutoReplaceSettings::onImportList,this)); + getChild<LLUICtrl>("autoreplace_export_list")->setCommitCallback(boost::bind(&LLFloaterAutoReplaceSettings::onExportList,this)); + getChild<LLUICtrl>("autoreplace_new_list")->setCommitCallback( boost::bind(&LLFloaterAutoReplaceSettings::onNewList,this)); + getChild<LLUICtrl>("autoreplace_delete_list")->setCommitCallback(boost::bind(&LLFloaterAutoReplaceSettings::onDeleteList,this)); + + // the list of keyword->replacement lists + mListNames = getChild<LLScrollListCtrl>("autoreplace_list_name"); + mListNames->setCommitCallback(boost::bind(&LLFloaterAutoReplaceSettings::onSelectList, this)); + mListNames->setCommitOnSelectionChange(true); + + // list ordering + getChild<LLUICtrl>("autoreplace_list_up")->setCommitCallback( boost::bind(&LLFloaterAutoReplaceSettings::onListUp,this)); + getChild<LLUICtrl>("autoreplace_list_down")->setCommitCallback(boost::bind(&LLFloaterAutoReplaceSettings::onListDown,this)); + + // keyword->replacement entry add / delete + getChild<LLUICtrl>("autoreplace_add_entry")->setCommitCallback( boost::bind(&LLFloaterAutoReplaceSettings::onAddEntry,this)); + getChild<LLUICtrl>("autoreplace_delete_entry")->setCommitCallback(boost::bind(&LLFloaterAutoReplaceSettings::onDeleteEntry,this)); + + // entry edits + mKeyword = getChild<LLLineEditor>("autoreplace_keyword"); + mReplacement = getChild<LLLineEditor>("autoreplace_replacement"); + getChild<LLUICtrl>("autoreplace_save_entry")->setCommitCallback(boost::bind(&LLFloaterAutoReplaceSettings::onSaveEntry, this)); + + // dialog termination ( Save Changes / Cancel ) + getChild<LLUICtrl>("autoreplace_save_changes")->setCommitCallback(boost::bind(&LLFloaterAutoReplaceSettings::onSaveChanges, this)); + getChild<LLUICtrl>("autoreplace_cancel")->setCommitCallback(boost::bind(&LLFloaterAutoReplaceSettings::onCancel, this)); + + // the list of keyword->replacement pairs + mReplacementsList = getChild<LLScrollListCtrl>("autoreplace_list_replacements"); + mReplacementsList->setCommitCallback(boost::bind(&LLFloaterAutoReplaceSettings::onSelectEntry, this)); + mReplacementsList->setCommitOnSelectionChange(true); + + center(); + + mSelectedListName.clear(); + updateListNames(); + updateListNamesControls(); + updateReplacementsList(); + + return true; +} + + +void LLFloaterAutoReplaceSettings::updateListNames() +{ + mListNames->deleteAllItems(); // start from scratch + + LLSD listNames = mSettings.getListNames(); // Array of Strings + + for ( LLSD::array_const_iterator entry = listNames.beginArray(), end = listNames.endArray(); + entry != end; + ++entry + ) + { + const std::string& listName = entry->asString(); + mListNames->addSimpleElement(listName); + } + + if (!mSelectedListName.empty()) + { + mListNames->setSelectedByValue( LLSD(mSelectedListName), true ); + } +} + +void LLFloaterAutoReplaceSettings::updateListNamesControls() +{ + if ( mSelectedListName.empty() ) + { + // There is no selected list + + // Disable all controls that operate on the selected list + getChild<LLButton>("autoreplace_export_list")->setEnabled(false); + getChild<LLButton>("autoreplace_delete_list")->setEnabled(false); + getChild<LLButton>("autoreplace_list_up")->setEnabled(false); + getChild<LLButton>("autoreplace_list_down")->setEnabled(false); + + mReplacementsList->deleteAllItems(); + } + else + { + // Enable the controls that operate on the selected list + getChild<LLButton>("autoreplace_export_list")->setEnabled(true); + getChild<LLButton>("autoreplace_delete_list")->setEnabled(true); + getChild<LLButton>("autoreplace_list_up")->setEnabled(!selectedListIsFirst()); + getChild<LLButton>("autoreplace_list_down")->setEnabled(!selectedListIsLast()); + } +} + +void LLFloaterAutoReplaceSettings::onSelectList() +{ + std::string previousSelectedListName = mSelectedListName; + // only one selection allowed + LLSD selected = mListNames->getSelectedValue(); + if (selected.isDefined()) + { + mSelectedListName = selected.asString(); + LL_DEBUGS("AutoReplace")<<"selected list '"<<mSelectedListName<<"'"<<LL_ENDL; + } + else + { + mSelectedListName.clear(); + LL_DEBUGS("AutoReplace")<<"unselected"<<LL_ENDL; + } + + updateListNamesControls(); + + if ( previousSelectedListName != mSelectedListName ) + { + updateReplacementsList(); + } +} + +void LLFloaterAutoReplaceSettings::onSelectEntry() +{ + LLSD selectedRow = mReplacementsList->getSelectedValue(); + if (selectedRow.isDefined()) + { + mPreviousKeyword = selectedRow.asString(); + LL_DEBUGS("AutoReplace")<<"selected entry '"<<mPreviousKeyword<<"'"<<LL_ENDL; + mKeyword->setValue(selectedRow); + std::string replacement = mSettings.replacementFor(mPreviousKeyword, mSelectedListName ); + mReplacement->setValue(replacement); + enableReplacementEntry(); + mReplacement->setFocus(true); + } + else + { + // no entry selection, so the entry panel should be off + disableReplacementEntry(); + LL_DEBUGS("AutoReplace")<<"no row selected"<<LL_ENDL; + } +} + +void LLFloaterAutoReplaceSettings::updateReplacementsList() +{ + // start from scratch, since this should only be called when the list changes + mReplacementsList->deleteAllItems(); + + if ( mSelectedListName.empty() ) + { + mReplacementsList->setEnabled(false); + getChild<LLButton>("autoreplace_add_entry")->setEnabled(false); + disableReplacementEntry(); + } + else + { + // Populate the keyword->replacement list from the selected list + const LLSD* mappings = mSettings.getListEntries(mSelectedListName); + for ( LLSD::map_const_iterator entry = mappings->beginMap(), end = mappings->endMap(); + entry != end; + entry++ + ) + { + LLSD row; + row["id"] = entry->first; + row["columns"][0]["column"] = "keyword"; + row["columns"][0]["value"] = entry->first; + row["columns"][1]["column"] = "replacement"; + row["columns"][1]["value"] = entry->second; + + mReplacementsList->addElement(row, ADD_BOTTOM); + } + + mReplacementsList->deselectAllItems(false /* don't call commit */); + mReplacementsList->setEnabled(true); + + getChild<LLButton>("autoreplace_add_entry")->setEnabled(true); + disableReplacementEntry(); + } +} + +void LLFloaterAutoReplaceSettings::enableReplacementEntry() +{ + LL_DEBUGS("AutoReplace")<<LL_ENDL; + mKeyword->setEnabled(true); + mReplacement->setEnabled(true); + getChild<LLButton>("autoreplace_save_entry")->setEnabled(true); + getChild<LLButton>("autoreplace_delete_entry")->setEnabled(true); +} + +void LLFloaterAutoReplaceSettings::disableReplacementEntry() +{ + LL_DEBUGS("AutoReplace")<<LL_ENDL; + mPreviousKeyword.clear(); + mKeyword->clear(); + mKeyword->setEnabled(false); + mReplacement->clear(); + mReplacement->setEnabled(false); + getChild<LLButton>("autoreplace_save_entry")->setEnabled(false); + getChild<LLButton>("autoreplace_delete_entry")->setEnabled(false); +} + +// called when the global settings checkbox is changed +void LLFloaterAutoReplaceSettings::onAutoReplaceToggled() +{ + // set our local copy of the flag, copied to the global preference in onOk + mEnabled = childGetValue("autoreplace_enable").asBoolean(); + LL_DEBUGS("AutoReplace")<< "autoreplace_enable " << ( mEnabled ? "on" : "off" ) << LL_ENDL; +} + +// called when the List Up button is pressed +void LLFloaterAutoReplaceSettings::onListUp() +{ + S32 selectedRow = mListNames->getFirstSelectedIndex(); + LLSD selectedName = mListNames->getSelectedValue().asString(); + + if ( mSettings.increaseListPriority(selectedName) ) + { + updateListNames(); + updateListNamesControls(); + } + else + { + LL_WARNS("AutoReplace") + << "invalid row ("<<selectedRow<<") selected '"<<selectedName<<"'" + <<LL_ENDL; + } +} + +// called when the List Down button is pressed +void LLFloaterAutoReplaceSettings::onListDown() +{ + S32 selectedRow = mListNames->getFirstSelectedIndex(); + std::string selectedName = mListNames->getSelectedValue().asString(); + + if ( mSettings.decreaseListPriority(selectedName) ) + { + updateListNames(); + updateListNamesControls(); + } + else + { + LL_WARNS("AutoReplace") + << "invalid row ("<<selectedRow<<") selected '"<<selectedName<<"'" + <<LL_ENDL; + } +} + +// called when the Delete Entry button is pressed +void LLFloaterAutoReplaceSettings::onDeleteEntry() +{ + LLSD selectedRow = mReplacementsList->getSelectedValue(); + if (selectedRow.isDefined()) + { + std::string keyword = selectedRow.asString(); + mReplacementsList->deleteSelectedItems(); // delete from the control + mSettings.removeEntryFromList(keyword, mSelectedListName); // delete from the local settings copy + disableReplacementEntry(); // no selection active, so turn off the buttons + } +} + +// called when the Import List button is pressed +void LLFloaterAutoReplaceSettings::onImportList() +{ + LLFilePicker& picker = LLFilePicker::instance(); + if( picker.getOpenFile( LLFilePicker::FFLOAD_XML) ) + { + llifstream file; + file.open(picker.getFirstFile().c_str()); + LLSD newList; + if (file.is_open()) + { + LLSDSerialize::fromXMLDocument(newList, file); + } + file.close(); + + switch ( mSettings.addList(newList) ) + { + case LLAutoReplaceSettings::AddListOk: + mSelectedListName = LLAutoReplaceSettings::getListName(newList); + + updateListNames(); + updateListNamesControls(); + updateReplacementsList(); + break; + + case LLAutoReplaceSettings::AddListDuplicateName: + { + std::string newName = LLAutoReplaceSettings::getListName(newList); + LL_WARNS("AutoReplace")<<"name '"<<newName<<"' is in use; prompting for new name"<<LL_ENDL; + LLSD newPayload; + newPayload["list"] = newList; + LLSD args; + args["DUPNAME"] = newName; + + LLNotificationsUtil::add("RenameAutoReplaceList", args, newPayload, + boost::bind(&LLFloaterAutoReplaceSettings::callbackListNameConflict, this, _1, _2)); + } + break; + + case LLAutoReplaceSettings::AddListInvalidList: + LLNotificationsUtil::add("InvalidAutoReplaceList"); + LL_WARNS("AutoReplace") << "imported list was invalid" << LL_ENDL; + + mSelectedListName.clear(); + updateListNames(); + updateListNamesControls(); + updateReplacementsList(); + break; + + default: + LL_ERRS("AutoReplace") << "invalid AddListResult" << LL_ENDL; + + } + + } + else + { + LL_DEBUGS("AutoReplace") << "file selection failed for import list" << LL_ENDL; + } +} + +void LLFloaterAutoReplaceSettings::onNewList() +{ + LLSD payload; + LLSD emptyList; + LLAutoReplaceSettings::createEmptyList(emptyList); + payload["list"] = emptyList; + LLSD args; + + LLNotificationsUtil::add("AddAutoReplaceList", args, payload, + boost::bind(&LLFloaterAutoReplaceSettings::callbackNewListName, this, _1, _2)); +} + +bool LLFloaterAutoReplaceSettings::callbackNewListName(const LLSD& notification, const LLSD& response) +{ + LL_DEBUGS("AutoReplace")<<"called"<<LL_ENDL; + + LLSD newList = notification["payload"]["list"]; + + if ( response.has("listname") && response["listname"].isString() ) + { + std::string newName = response["listname"].asString(); + LLAutoReplaceSettings::setListName(newList, newName); + + switch ( mSettings.addList(newList) ) + { + case LLAutoReplaceSettings::AddListOk: + LL_INFOS("AutoReplace") << "added new list '"<<newName<<"'"<<LL_ENDL; + mSelectedListName = newName; + updateListNames(); + updateListNamesControls(); + updateReplacementsList(); + break; + + case LLAutoReplaceSettings::AddListDuplicateName: + { + LL_WARNS("AutoReplace")<<"name '"<<newName<<"' is in use; prompting for new name"<<LL_ENDL; + LLSD newPayload; + newPayload["list"] = notification["payload"]["list"]; + LLSD args; + args["DUPNAME"] = newName; + + LLNotificationsUtil::add("RenameAutoReplaceList", args, newPayload, + boost::bind(&LLFloaterAutoReplaceSettings::callbackListNameConflict, this, _1, _2)); + } + break; + + case LLAutoReplaceSettings::AddListInvalidList: + LLNotificationsUtil::add("InvalidAutoReplaceList"); + + mSelectedListName.clear(); + updateListNames(); + updateListNamesControls(); + updateReplacementsList(); + break; + + default: + LL_ERRS("AutoReplace") << "invalid AddListResult" << LL_ENDL; + } + } + else + { + LL_ERRS("AutoReplace") << "adding notification response" << LL_ENDL; + } + return false; +} + +// callback for the RenameAutoReplaceList notification +bool LLFloaterAutoReplaceSettings::callbackListNameConflict(const LLSD& notification, const LLSD& response) +{ + LLSD newList = notification["payload"]["list"]; + + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + switch ( option ) + { + case 0: + // Replace current list + LL_INFOS("AutoReplace")<<"option 'replace current list' selected"<<LL_ENDL; + + break; + + case 1: + // Use New Name + LL_INFOS("AutoReplace")<<"option 'use new name' selected"<<LL_ENDL; + callbackNewListName(notification, response); + break; + + default: + LL_ERRS("AutoReplace")<<"invalid selected option "<<option<<LL_ENDL; + } + + return false; +} + +void LLFloaterAutoReplaceSettings::onDeleteList() +{ + std::string listName= mListNames->getFirstSelected()->getColumn(0)->getValue().asString(); + mSettings.removeReplacementList(listName); // remove from the copy of settings + mReplacementsList->deleteSelectedItems(); // remove from the scrolling list + + mSelectedListName.clear(); + updateListNames(); + updateListNamesControls(); + updateReplacementsList(); +} + +void LLFloaterAutoReplaceSettings::onExportList() +{ + std::string listName=mListNames->getFirstSelected()->getColumn(0)->getValue().asString(); + const LLSD* list = mSettings.exportList(listName); + std::string listFileName = listName + ".xml"; + LLFilePicker& picker = LLFilePicker::instance(); + if( picker.getSaveFile( LLFilePicker::FFSAVE_XML, listFileName) ) + { + llofstream file; + file.open(picker.getFirstFile().c_str()); + LLSDSerialize::toPrettyXML(*list, file); + file.close(); + } +} + +void LLFloaterAutoReplaceSettings::onAddEntry() +{ + mPreviousKeyword.clear(); + mReplacementsList->deselectAllItems(false /* don't call commit */); + mKeyword->clear(); + mReplacement->clear(); + enableReplacementEntry(); + mKeyword->setFocus(true); +} + +void LLFloaterAutoReplaceSettings::onSaveEntry() +{ + LL_DEBUGS("AutoReplace")<<"called"<<LL_ENDL; + + if ( ! mPreviousKeyword.empty() ) + { + // delete any existing value for the key that was editted + LL_INFOS("AutoReplace") + << "list '" << mSelectedListName << "' " + << "removed '" << mPreviousKeyword + << "'" << LL_ENDL; + mSettings.removeEntryFromList( mPreviousKeyword, mSelectedListName ); + } + + LLWString keyword = mKeyword->getWText(); + LLWString replacement = mReplacement->getWText(); + if ( mSettings.addEntryToList(keyword, replacement, mSelectedListName) ) + { + // insert the new keyword->replacement pair + LL_INFOS("AutoReplace") + << "list '" << mSelectedListName << "' " + << "added '" << wstring_to_utf8str(keyword) + << "' -> '" << wstring_to_utf8str(replacement) + << "'" << LL_ENDL; + + updateReplacementsList(); + } + else + { + LLNotificationsUtil::add("InvalidAutoReplaceEntry"); + LL_WARNS("AutoReplace")<<"invalid entry " + << "keyword '" << wstring_to_utf8str(keyword) + << "' replacement '" << wstring_to_utf8str(replacement) + << "'" << LL_ENDL; + } +} + +void LLFloaterAutoReplaceSettings::onCancel() +{ + cleanUp(); + closeFloater(false /* not quitting */); +} + +void LLFloaterAutoReplaceSettings::onSaveChanges() +{ + // put our local copy of the settings into the active copy + LLAutoReplace::getInstance()->setSettings( mSettings ); + // save our local copy of the global feature enable/disable value + gSavedSettings.setBOOL("AutoReplace", mEnabled); + cleanUp(); + closeFloater(false /* not quitting */); +} + +void LLFloaterAutoReplaceSettings::cleanUp() +{ + +} + +bool LLFloaterAutoReplaceSettings::selectedListIsFirst() +{ + bool isFirst = false; + + if (!mSelectedListName.empty()) + { + LLSD lists = mSettings.getListNames(); // an Array of Strings + LLSD first = lists.get(0); + if ( first.isString() && first.asString() == mSelectedListName ) + { + isFirst = true; + } + } + return isFirst; +} + +bool LLFloaterAutoReplaceSettings::selectedListIsLast() +{ + bool isLast = false; + + if (!mSelectedListName.empty()) + { + LLSD last; + LLSD lists = mSettings.getListNames(); // an Array of Strings + for ( LLSD::array_const_iterator list = lists.beginArray(), listEnd = lists.endArray(); + list != listEnd; + list++ + ) + { + last = *list; + } + if ( last.isString() && last.asString() == mSelectedListName ) + { + isLast = true; + } + } + return isLast; +} + +/* TBD +mOldText = getChild<LLLineEditor>("autoreplace_old_text"); +mNewText = getChild<LLLineEditor>("autoreplace_new_text"); +*/ diff --git a/indra/newview/llfloaterautoreplacesettings.h b/indra/newview/llfloaterautoreplacesettings.h new file mode 100644 index 0000000000..629aea3e3c --- /dev/null +++ b/indra/newview/llfloaterautoreplacesettings.h @@ -0,0 +1,117 @@ +/** + * @file llfloaterautoreplacesettings.h + * @brief Auto Replace List floater + * @copyright Copyright (c) 2011 LordGregGreg Back + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * $/LicenseInfo$ + */ + +#ifndef LLFLOATERAUTOREPLACESETTINGS_H +#define LLFLOATERAUTOREPLACESETTINGS_H + +#include "llfloater.h" +#include "llmediactrl.h" +#include "llscrolllistctrl.h" +#include "lllineeditor.h" + +#include "llviewerinventory.h" +#include <boost/bind.hpp> +#include "llautoreplace.h" + +class LLFloaterAutoReplaceSettings : public LLFloater +{ +public: + LLFloaterAutoReplaceSettings(const LLSD& key); + + /*virtual*/ BOOL postBuild(); + /*virtual*/ void onClose(bool app_quitting); + + void setData(void * data); + +private: + + /** @{ @name Local Copies of Settings + * These are populated in the postBuild method with the values + * current when the floater is instantiated, and then either + * discarded when Cancel is pressed, or copied back to the active + * settings if Ok is pressed. + */ + bool mEnabled; ///< the global preference for AutoReplace + LLAutoReplaceSettings mSettings; ///< settings being modified + /** @} */ + + /// convenience variable - the name of the currently selected list (if any) + std::string mSelectedListName; + /// the scrolling list of list names (one column, no headings, order manually controlled) + LLScrollListCtrl* mListNames; + /// the scroling list of keyword->replacement pairs + LLScrollListCtrl* mReplacementsList; + + /// the keyword for the entry editing pane + LLLineEditor* mKeyword; + /// saved keyword value + std::string mPreviousKeyword; + /// the replacement for the entry editing pane + LLLineEditor* mReplacement; + + /// callback for when the feature enable/disable checkbox changes + void onAutoReplaceToggled(); + /// callback for when an entry in the list of list names is selected + void onSelectList(); + + void onImportList(); + void onExportList(); + void onNewList(); + void onDeleteList(); + + void onListUp(); + void onListDown(); + + void onSelectEntry(); + void onAddEntry(); + void onDeleteEntry(); + void onSaveEntry(); + + void onSaveChanges(); + void onCancel(); + + /// updates the contents of the mListNames + void updateListNames(); + /// updates the controls associated with mListNames (depends on whether a name is selected or not) + void updateListNamesControls(); + /// updates the contents of the mReplacementsList + void updateReplacementsList(); + /// enables the components that should only be active when a keyword is selected + void enableReplacementEntry(); + /// disables the components that should only be active when a keyword is selected + void disableReplacementEntry(); + + /// called from the AddAutoReplaceList notification dialog + bool callbackNewListName(const LLSD& notification, const LLSD& response); + /// called from the RenameAutoReplaceList notification dialog + bool callbackListNameConflict(const LLSD& notification, const LLSD& response); + + bool selectedListIsFirst(); + bool selectedListIsLast(); + + void cleanUp(); +}; + +#endif // LLFLOATERAUTOREPLACESETTINGS_H diff --git a/indra/newview/llfloaterbvhpreview.cpp b/indra/newview/llfloaterbvhpreview.cpp index b050a638dc..fa0ad20fdb 100644 --- a/indra/newview/llfloaterbvhpreview.cpp +++ b/indra/newview/llfloaterbvhpreview.cpp @@ -416,6 +416,9 @@ void LLFloaterBvhPreview::draw() //----------------------------------------------------------------------------- void LLFloaterBvhPreview::resetMotion() { + if (!mAnimPreview) + return; + LLVOAvatar* avatarp = mAnimPreview->getDummyAvatar(); BOOL paused = avatarp->areAnimationsPaused(); @@ -535,6 +538,9 @@ BOOL LLFloaterBvhPreview::handleHover(S32 x, S32 y, MASK mask) //----------------------------------------------------------------------------- BOOL LLFloaterBvhPreview::handleScrollWheel(S32 x, S32 y, S32 clicks) { + if (!mAnimPreview) + return false; + mAnimPreview->zoom((F32)clicks * -0.2f); mAnimPreview->requestUpdate(); @@ -670,7 +676,7 @@ void LLFloaterBvhPreview::onCommitBaseAnim() //----------------------------------------------------------------------------- void LLFloaterBvhPreview::onCommitLoop() { - if (!getEnabled()) + if (!getEnabled() || !mAnimPreview) return; LLVOAvatar* avatarp = mAnimPreview->getDummyAvatar(); @@ -689,7 +695,7 @@ void LLFloaterBvhPreview::onCommitLoop() //----------------------------------------------------------------------------- void LLFloaterBvhPreview::onCommitLoopIn() { - if (!getEnabled()) + if (!getEnabled() || !mAnimPreview) return; LLVOAvatar* avatarp = mAnimPreview->getDummyAvatar(); @@ -709,7 +715,7 @@ void LLFloaterBvhPreview::onCommitLoopIn() //----------------------------------------------------------------------------- void LLFloaterBvhPreview::onCommitLoopOut() { - if (!getEnabled()) + if (!getEnabled() || !mAnimPreview) return; LLVOAvatar* avatarp = mAnimPreview->getDummyAvatar(); @@ -729,7 +735,7 @@ void LLFloaterBvhPreview::onCommitLoopOut() //----------------------------------------------------------------------------- void LLFloaterBvhPreview::onCommitName() { - if (!getEnabled()) + if (!getEnabled() || !mAnimPreview) return; LLVOAvatar* avatarp = mAnimPreview->getDummyAvatar(); @@ -770,7 +776,7 @@ void LLFloaterBvhPreview::onCommitEmote() //----------------------------------------------------------------------------- void LLFloaterBvhPreview::onCommitPriority() { - if (!getEnabled()) + if (!getEnabled() || !mAnimPreview) return; LLVOAvatar* avatarp = mAnimPreview->getDummyAvatar(); @@ -784,7 +790,7 @@ void LLFloaterBvhPreview::onCommitPriority() //----------------------------------------------------------------------------- void LLFloaterBvhPreview::onCommitEaseIn() { - if (!getEnabled()) + if (!getEnabled() || !mAnimPreview) return; LLVOAvatar* avatarp = mAnimPreview->getDummyAvatar(); @@ -799,7 +805,7 @@ void LLFloaterBvhPreview::onCommitEaseIn() //----------------------------------------------------------------------------- void LLFloaterBvhPreview::onCommitEaseOut() { - if (!getEnabled()) + if (!getEnabled() || !mAnimPreview) return; LLVOAvatar* avatarp = mAnimPreview->getDummyAvatar(); @@ -814,7 +820,7 @@ void LLFloaterBvhPreview::onCommitEaseOut() //----------------------------------------------------------------------------- bool LLFloaterBvhPreview::validateEaseIn(const LLSD& data) { - if (!getEnabled()) + if (!getEnabled() || !mAnimPreview) return false; LLVOAvatar* avatarp = mAnimPreview->getDummyAvatar(); @@ -834,7 +840,7 @@ bool LLFloaterBvhPreview::validateEaseIn(const LLSD& data) //----------------------------------------------------------------------------- bool LLFloaterBvhPreview::validateEaseOut(const LLSD& data) { - if (!getEnabled()) + if (!getEnabled() || !mAnimPreview) return false; LLVOAvatar* avatarp = mAnimPreview->getDummyAvatar(); @@ -1118,9 +1124,13 @@ BOOL LLPreviewAnimation::render() LLVertexBuffer::unbind(); LLGLDepthTest gls_depth(GL_TRUE); - LLDrawPoolAvatar *avatarPoolp = (LLDrawPoolAvatar *)avatarp->mDrawable->getFace(0)->getPool(); - avatarp->dirtyMesh(); - avatarPoolp->renderAvatars(avatarp); // renders only one avatar + LLFace* face = avatarp->mDrawable->getFace(0); + if (face) + { + LLDrawPoolAvatar *avatarPoolp = (LLDrawPoolAvatar *)face->getPool(); + avatarp->dirtyMesh(); + avatarPoolp->renderAvatars(avatarp); // renders only one avatar + } } gGL.color4f(1,1,1,1); diff --git a/indra/newview/llfloaterhardwaresettings.cpp b/indra/newview/llfloaterhardwaresettings.cpp index f9a403cf9f..116bd241c4 100644 --- a/indra/newview/llfloaterhardwaresettings.cpp +++ b/indra/newview/llfloaterhardwaresettings.cpp @@ -37,6 +37,7 @@ #include "llspinctrl.h" #include "llstartup.h" #include "lltextbox.h" +#include "llcombobox.h" #include "pipeline.h" // Linden library includes @@ -99,6 +100,12 @@ void LLFloaterHardwareSettings::refreshEnabledState() getChildView("vbo")->setEnabled(FALSE); } + if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderCompressTextures") || + !gGLManager.mHasVertexBufferObject) + { + getChildView("texture compression")->setEnabled(FALSE); + } + // if no windlight shaders, turn off nighttime brightness, gamma, and fog distance LLSpinCtrl* gamma_ctrl = getChild<LLSpinCtrl>("gamma"); gamma_ctrl->setEnabled(!gPipeline.canUseWindLightShaders()); @@ -142,6 +149,13 @@ BOOL LLFloaterHardwareSettings::postBuild() { childSetAction("OK", onBtnOK, this); + if (gGLManager.mIsIntel || gGLManager.mGLVersion < 3.f) + { //remove FSAA settings above "4x" + LLComboBox* combo = getChild<LLComboBox>("fsaa"); + combo->remove("8x"); + combo->remove("16x"); + } + refresh(); center(); diff --git a/indra/newview/llfloaterimagepreview.cpp b/indra/newview/llfloaterimagepreview.cpp index 92ee8ddac6..6b2492d927 100644 --- a/indra/newview/llfloaterimagepreview.cpp +++ b/indra/newview/llfloaterimagepreview.cpp @@ -704,9 +704,13 @@ BOOL LLImagePreviewAvatar::render() // make sure alpha=0 shows avatar material color LLGLDisable no_blend(GL_BLEND); - LLDrawPoolAvatar *avatarPoolp = (LLDrawPoolAvatar *)avatarp->mDrawable->getFace(0)->getPool(); - gPipeline.enableLightsPreview(); - avatarPoolp->renderAvatars(avatarp); // renders only one avatar + LLFace* face = avatarp->mDrawable->getFace(0); + if (face) + { + LLDrawPoolAvatar *avatarPoolp = (LLDrawPoolAvatar *)face->getPool(); + gPipeline.enableLightsPreview(); + avatarPoolp->renderAvatars(avatarp); // renders only one avatar + } } gGL.popUIMatrix(); diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp index ee18c95b34..61da99fe3a 100644 --- a/indra/newview/llfloaterland.cpp +++ b/indra/newview/llfloaterland.cpp @@ -1865,23 +1865,8 @@ BOOL LLPanelLandOptions::postBuild() childSetCommitCallback("ShowDirectoryCheck", onCommitAny, this); - if (gAgent.getAgentAccess().isInTransition()) - { - // during the AO transition, this combo has an Adult item. - // Post-transition, it goes away. We can remove this conditional - // after the transition and just use the "else" clause. - mCategoryCombo = getChild<LLComboBox>( "land category with adult"); - childSetCommitCallback("land category with adult", onCommitAny, this); - } - else - { - // this is the code that should be preserved post-transition - // you could also change the XML to set visibility and enabled true. - mCategoryCombo = getChild<LLComboBox>( "land category"); - childSetCommitCallback("land category", onCommitAny, this); - } - mCategoryCombo->setVisible(true); - mCategoryCombo->setEnabled(true); + mCategoryCombo = getChild<LLComboBox>( "land category"); + childSetCommitCallback("land category", onCommitAny, this); mMatureCtrl = getChild<LLCheckBoxCtrl>( "MatureCheck"); @@ -1901,6 +1886,7 @@ BOOL LLPanelLandOptions::postBuild() mSnapshotCtrl->setCommitCallback( onCommitAny, this ); mSnapshotCtrl->setAllowNoTexture ( TRUE ); mSnapshotCtrl->setImmediateFilterPermMask(PERM_COPY | PERM_TRANSFER); + mSnapshotCtrl->setDnDFilterPermMask(PERM_COPY | PERM_TRANSFER); mSnapshotCtrl->setNonImmediateFilterPermMask(PERM_COPY | PERM_TRANSFER); } else diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp index 7448f2bb2a..0a5171245a 100755 --- a/indra/newview/llfloatermodelpreview.cpp +++ b/indra/newview/llfloatermodelpreview.cpp @@ -396,7 +396,6 @@ mCalculateBtn(NULL) sInstance = this; mLastMouseX = 0; mLastMouseY = 0; - mGLName = 0; mStatusLock = new LLMutex(NULL); mModelPreview = NULL; @@ -538,11 +537,6 @@ LLFloaterModelPreview::~LLFloaterModelPreview() delete mModelPreview; } - if (mGLName) - { - LLImageGL::deleteTextures(1, &mGLName ); - } - delete mStatusLock; mStatusLock = NULL; } @@ -5053,15 +5047,7 @@ BOOL LLModelPreview::render() LLRect preview_rect; - LLFloaterModelWizard* floater_wizard = dynamic_cast<LLFloaterModelWizard*>(mFMP); - if (floater_wizard) - { - preview_rect = floater_wizard->getPreviewRect(); - } - else - { - preview_rect = mFMP->getChildView("preview_panel")->getRect(); - } + preview_rect = mFMP->getChildView("preview_panel")->getRect(); F32 aspect = (F32) preview_rect.getWidth()/preview_rect.getHeight(); @@ -5605,7 +5591,6 @@ void LLModelPreview::setPreviewLOD(S32 lod) combo_box->setCurrentByIndex((NUM_LOD-1)-mPreviewLOD); // combo box list of lods is in reverse order mFMP->childSetText("lod_file_" + lod_name[mPreviewLOD], mLODFile[mPreviewLOD]); - // the wizard has three lod drop downs LLComboBox* combo_box2 = mFMP->getChild<LLComboBox>("preview_lod_combo2"); combo_box2->setCurrentByIndex((NUM_LOD-1)-mPreviewLOD); // combo box list of lods is in reverse order diff --git a/indra/newview/llfloatermodelpreview.h b/indra/newview/llfloatermodelpreview.h index 64324854a5..ab319c30d5 100644 --- a/indra/newview/llfloatermodelpreview.h +++ b/indra/newview/llfloatermodelpreview.h @@ -30,12 +30,12 @@ #include "llfloaternamedesc.h" #include "lldynamictexture.h" -#include "llfloatermodelwizard.h" #include "llquaternion.h" #include "llmeshrepository.h" #include "llmodel.h" #include "llthread.h" #include "llviewermenufile.h" +#include "llfloatermodeluploadbase.h" class LLComboBox; class LLJoint; @@ -256,7 +256,6 @@ protected: S32 mLastMouseX; S32 mLastMouseY; LLRect mPreviewRect; - U32 mGLName; static S32 sUploadAmount; std::set<LLPointer<DecompRequest> > mCurRequest; @@ -390,9 +389,7 @@ private: protected: friend class LLModelLoader; friend class LLFloaterModelPreview; - friend class LLFloaterModelWizard; friend class LLFloaterModelPreview::DecompRequest; - friend class LLFloaterModelWizard::DecompRequest; friend class LLPhysicsDecomp; LLFloater* mFMP; diff --git a/indra/newview/llfloatermodelwizard.cpp b/indra/newview/llfloatermodelwizard.cpp deleted file mode 100644 index b517b78e5a..0000000000 --- a/indra/newview/llfloatermodelwizard.cpp +++ /dev/null @@ -1,795 +0,0 @@ -/** - * @file llfloatermodelwizard.cpp - * @author Leyla Farazha - * @brief Implementation of the LLFloaterModelWizard class. - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - - -#include "llviewerprecompiledheaders.h" - -#include "llbutton.h" -#include "lldrawable.h" -#include "llcheckboxctrl.h" -#include "llcombobox.h" -#include "llfloater.h" -#include "llfloatermodelwizard.h" -#include "llfloatermodelpreview.h" -#include "llfloaterreg.h" -#include "llsliderctrl.h" -#include "lltoolmgr.h" -#include "llviewerwindow.h" - -LLFloaterModelWizard* LLFloaterModelWizard::sInstance = NULL; - -static const std::string stateNames[]={ - "choose_file", - "optimize", - "physics", - "review", - "upload"}; - -static void swap_controls(LLUICtrl* first_ctrl, LLUICtrl* second_ctrl, bool first_ctr_visible); - -LLFloaterModelWizard::LLFloaterModelWizard(const LLSD& key) - : LLFloaterModelUploadBase(key) - ,mRecalculateGeometryBtn(NULL) - ,mRecalculatePhysicsBtn(NULL) - ,mRecalculatingPhysicsBtn(NULL) - ,mCalculateWeightsBtn(NULL) - ,mCalculatingWeightsBtn(NULL) - ,mChooseFilePreviewPanel(NULL) - ,mOptimizePreviewPanel(NULL) - ,mPhysicsPreviewPanel(NULL) -{ - mLastEnabledState = CHOOSE_FILE; - sInstance = this; - - mCommitCallbackRegistrar.add("Wizard.Choose", boost::bind(&LLFloaterModelWizard::setState, this, CHOOSE_FILE)); - mCommitCallbackRegistrar.add("Wizard.Optimize", boost::bind(&LLFloaterModelWizard::setState, this, OPTIMIZE)); - mCommitCallbackRegistrar.add("Wizard.Physics", boost::bind(&LLFloaterModelWizard::setState, this, PHYSICS)); - mCommitCallbackRegistrar.add("Wizard.Review", boost::bind(&LLFloaterModelWizard::setState, this, REVIEW)); - mCommitCallbackRegistrar.add("Wizard.Upload", boost::bind(&LLFloaterModelWizard::setState, this, UPLOAD)); -} -LLFloaterModelWizard::~LLFloaterModelWizard() -{ - sInstance = NULL; -} -void LLFloaterModelWizard::setState(int state) -{ - - mState = state; - - for(size_t t=0; t<LL_ARRAY_SIZE(stateNames); ++t) - { - LLView *view = getChildView(stateNames[t]+"_panel"); - if (view) - { - view->setVisible(state == (int) t ? TRUE : FALSE); - } - } - - LLView* current_preview_panel = NULL; - - if (state == CHOOSE_FILE) - { - mModelPreview->mViewOption["show_physics"] = false; - - current_preview_panel = mChooseFilePreviewPanel; - - getChildView("close")->setVisible(false); - getChildView("back")->setVisible(true); - getChildView("back")->setEnabled(false); - getChildView("next")->setVisible(true); - getChildView("upload")->setVisible(false); - getChildView("cancel")->setVisible(true); - mCalculateWeightsBtn->setVisible(false); - mCalculatingWeightsBtn->setVisible(false); - } - - if (state == OPTIMIZE) - { - if (mLastEnabledState < state) - { - mModelPreview->genLODs(-1); - } - - mModelPreview->mViewOption["show_physics"] = false; - - current_preview_panel = mOptimizePreviewPanel; - - getChildView("back")->setVisible(true); - getChildView("back")->setEnabled(true); - getChildView("close")->setVisible(false); - getChildView("next")->setVisible(true); - getChildView("upload")->setVisible(false); - getChildView("cancel")->setVisible(true); - mCalculateWeightsBtn->setVisible(false); - mCalculatingWeightsBtn->setVisible(false); - } - - if (state == PHYSICS) - { - if (mLastEnabledState < state) - { - mModelPreview->setPhysicsFromLOD(1); - - // Trigger the recalculate physics when first entering - // the Physics step. - onClickRecalculatePhysics(); - } - - mModelPreview->mViewOption["show_physics"] = true; - - current_preview_panel = mPhysicsPreviewPanel; - - getChildView("next")->setVisible(false); - getChildView("upload")->setVisible(false); - getChildView("close")->setVisible(false); - getChildView("back")->setVisible(true); - getChildView("back")->setEnabled(true); - getChildView("cancel")->setVisible(true); - mCalculateWeightsBtn->setVisible(true); - mCalculatingWeightsBtn->setVisible(false); - } - - if (state == REVIEW) - { - - mModelPreview->mViewOption["show_physics"] = false; - - getChildView("close")->setVisible(false); - getChildView("next")->setVisible(false); - getChildView("back")->setVisible(true); - getChildView("back")->setEnabled(true); - getChildView("upload")->setVisible(true); - getChildView("cancel")->setVisible(true); - mCalculateWeightsBtn->setVisible(false); - mCalculatingWeightsBtn->setVisible(false); - } - - if (state == UPLOAD) - { - getChildView("close")->setVisible(true); - getChildView("next")->setVisible(false); - getChildView("back")->setVisible(false); - getChildView("upload")->setVisible(false); - getChildView("cancel")->setVisible(false); - mCalculateWeightsBtn->setVisible(false); - mCalculatingWeightsBtn->setVisible(false); - } - - if (current_preview_panel) - { - LLRect rect; - current_preview_panel->localRectToOtherView(current_preview_panel->getLocalRect(), &rect, this); - - // Reduce the preview rect by 1 px to fit the borders - rect.stretch(-1); - - if (rect != mPreviewRect) - { - mPreviewRect = rect; - mModelPreview->refresh(); - } - } - updateButtons(); -} - - - -void LLFloaterModelWizard::updateButtons() -{ - if (mLastEnabledState < mState) - { - mLastEnabledState = mState; - } - - for(size_t i=0; i<LL_ARRAY_SIZE(stateNames); ++i) - { - LLButton *button = getChild<LLButton>(stateNames[i]+"_btn"); - - if (i == mState) - { - button->setEnabled(TRUE); - button->setToggleState(TRUE); - } - else if (i <= mLastEnabledState) - { - button->setEnabled(TRUE); - button->setToggleState(FALSE); - } - else - { - button->setEnabled(FALSE); - } - } -} - -void LLFloaterModelWizard::onClickSwitchToAdvanced() -{ - LLFloaterModelPreview* floater_preview = LLFloaterReg::getTypedInstance<LLFloaterModelPreview>("upload_model"); - if (!floater_preview) - { - llwarns << "FLoater model preview not found." << llendl; - return; - } - - // Open floater model preview - floater_preview->openFloater(); - - // Close the wizard - closeFloater(); - - std::string filename = getChild<LLUICtrl>("lod_file")->getValue().asString(); - if (!filename.empty()) - { - // Re-load the model to the floater model preview if it has been loaded - // into the wizard. - floater_preview->loadModel(3, filename); - } -} - -void LLFloaterModelWizard::onClickRecalculateGeometry() -{ - S32 val = getChild<LLUICtrl>("accuracy_slider")->getValue().asInteger(); - - mModelPreview->genLODs(-1, NUM_LOD - val); - - mModelPreview->refresh(); -} - -void LLFloaterModelWizard::onClickRecalculatePhysics() -{ - // Hide the "Recalculate physics" button and show the "Recalculating..." - // button instead. - swap_controls(mRecalculatePhysicsBtn, mRecalculatingPhysicsBtn, false); - - executePhysicsStage("Decompose"); -} - -void LLFloaterModelWizard::onClickCalculateUploadFee() -{ - swap_controls(mCalculateWeightsBtn, mCalculatingWeightsBtn, false); - - mModelPreview->rebuildUploadData(); - - mUploadModelUrl.clear(); - - gMeshRepo.uploadModel(mModelPreview->mUploadData, mModelPreview->mPreviewScale, - true, false, false, mUploadModelUrl, false, getWholeModelFeeObserverHandle()); -} - -void LLFloaterModelWizard::loadModel() -{ - mModelPreview->mLoading = TRUE; - - (new LLMeshFilePicker(mModelPreview, 3))->getFile(); -} - -void LLFloaterModelWizard::onClickCancel() -{ - closeFloater(); -} - -void LLFloaterModelWizard::onClickBack() -{ - setState(llmax((int) CHOOSE_FILE, mState-1)); -} - -void LLFloaterModelWizard::onClickNext() -{ - setState(llmin((int) UPLOAD, mState+1)); -} - -bool LLFloaterModelWizard::onEnableNext() -{ - return true; -} - -bool LLFloaterModelWizard::onEnableBack() -{ - return true; -} - - -//----------------------------------------------------------------------------- -// handleMouseDown() -//----------------------------------------------------------------------------- -BOOL LLFloaterModelWizard::handleMouseDown(S32 x, S32 y, MASK mask) -{ - if (mPreviewRect.pointInRect(x, y)) - { - bringToFront( x, y ); - gFocusMgr.setMouseCapture(this); - gViewerWindow->hideCursor(); - mLastMouseX = x; - mLastMouseY = y; - return TRUE; - } - - return LLFloater::handleMouseDown(x, y, mask); -} - -//----------------------------------------------------------------------------- -// handleMouseUp() -//----------------------------------------------------------------------------- -BOOL LLFloaterModelWizard::handleMouseUp(S32 x, S32 y, MASK mask) -{ - gFocusMgr.setMouseCapture(FALSE); - gViewerWindow->showCursor(); - return LLFloater::handleMouseUp(x, y, mask); -} - -//----------------------------------------------------------------------------- -// handleHover() -//----------------------------------------------------------------------------- -BOOL LLFloaterModelWizard::handleHover (S32 x, S32 y, MASK mask) -{ - MASK local_mask = mask & ~MASK_ALT; - - if (mModelPreview && hasMouseCapture()) - { - if (local_mask == MASK_PAN) - { - // pan here - mModelPreview->pan((F32)(x - mLastMouseX) * -0.005f, (F32)(y - mLastMouseY) * -0.005f); - } - else if (local_mask == MASK_ORBIT) - { - F32 yaw_radians = (F32)(x - mLastMouseX) * -0.01f; - F32 pitch_radians = (F32)(y - mLastMouseY) * 0.02f; - - mModelPreview->rotate(yaw_radians, pitch_radians); - } - else - { - - F32 yaw_radians = (F32)(x - mLastMouseX) * -0.01f; - F32 zoom_amt = (F32)(y - mLastMouseY) * 0.02f; - - mModelPreview->rotate(yaw_radians, 0.f); - mModelPreview->zoom(zoom_amt); - } - - - mModelPreview->refresh(); - - LLUI::setMousePositionLocal(this, mLastMouseX, mLastMouseY); - } - - if (!mPreviewRect.pointInRect(x, y) || !mModelPreview) - { - return LLFloater::handleHover(x, y, mask); - } - else if (local_mask == MASK_ORBIT) - { - gViewerWindow->setCursor(UI_CURSOR_TOOLCAMERA); - } - else if (local_mask == MASK_PAN) - { - gViewerWindow->setCursor(UI_CURSOR_TOOLPAN); - } - else - { - gViewerWindow->setCursor(UI_CURSOR_TOOLZOOMIN); - } - - return TRUE; -} - -//----------------------------------------------------------------------------- -// handleScrollWheel() -//----------------------------------------------------------------------------- -BOOL LLFloaterModelWizard::handleScrollWheel(S32 x, S32 y, S32 clicks) -{ - if (mPreviewRect.pointInRect(x, y) && mModelPreview) - { - mModelPreview->zoom((F32)clicks * -0.2f); - mModelPreview->refresh(); - } - - return TRUE; -} - - -void LLFloaterModelWizard::initDecompControls() -{ - LLSD key; - - static const LLCDStageData* stage = NULL; - static S32 stage_count = 0; - - if (!stage && LLConvexDecomposition::getInstance() != NULL) - { - stage_count = LLConvexDecomposition::getInstance()->getStages(&stage); - } - - static const LLCDParam* param = NULL; - static S32 param_count = 0; - if (!param && LLConvexDecomposition::getInstance() != NULL) - { - param_count = LLConvexDecomposition::getInstance()->getParameters(¶m); - } - - for (S32 j = stage_count-1; j >= 0; --j) - { - gMeshRepo.mDecompThread->mStageID[stage[j].mName] = j; - // protected against stub by stage_count being 0 for stub above - LLConvexDecomposition::getInstance()->registerCallback(j, LLPhysicsDecomp::llcdCallback); - - for (S32 i = 0; i < param_count; ++i) - { - if (param[i].mStage != j) - { - continue; - } - - std::string name(param[i].mName ? param[i].mName : ""); - std::string description(param[i].mDescription ? param[i].mDescription : ""); - - if (param[i].mType == LLCDParam::LLCD_FLOAT) - { - mDecompParams[param[i].mName] = LLSD(param[i].mDefault.mFloat); - } - else if (param[i].mType == LLCDParam::LLCD_INTEGER) - { - mDecompParams[param[i].mName] = LLSD(param[i].mDefault.mIntOrEnumValue); - } - else if (param[i].mType == LLCDParam::LLCD_BOOLEAN) - { - mDecompParams[param[i].mName] = LLSD(param[i].mDefault.mBool); - } - else if (param[i].mType == LLCDParam::LLCD_ENUM) - { - mDecompParams[param[i].mName] = LLSD(param[i].mDefault.mIntOrEnumValue); - } - } - } - - mDecompParams["Simplify Method"] = 0; // set it to retain % -} - -/*virtual*/ -void LLFloaterModelWizard::onPermissionsReceived(const LLSD& result) -{ - std::string upload_status = result["mesh_upload_status"].asString(); - // BAP HACK: handle "" for case that MeshUploadFlag cap is broken. - mHasUploadPerm = (("" == upload_status) || ("valid" == upload_status)); - - getChildView("warning_label")->setVisible(!mHasUploadPerm); - getChildView("warning_text")->setVisible(!mHasUploadPerm); -} - -/*virtual*/ -void LLFloaterModelWizard::setPermissonsErrorStatus(U32 status, const std::string& reason) -{ - llwarns << "LLFloaterModelWizard::setPermissonsErrorStatus(" << status << " : " << reason << ")" << llendl; -} - -/*virtual*/ -void LLFloaterModelWizard::onModelPhysicsFeeReceived(const LLSD& result, std::string upload_url) -{ - swap_controls(mCalculateWeightsBtn, mCalculatingWeightsBtn, true); - - // Enable the "Upload" buton if we have calculated the upload fee - // and have the permission to upload. - getChildView("upload")->setEnabled(mHasUploadPerm); - - mUploadModelUrl = upload_url; - - S32 fee = result["upload_price"].asInteger(); - childSetTextArg("review_fee", "[FEE]", llformat("%d", fee)); - childSetTextArg("charged_fee", "[FEE]", llformat("%d", fee)); - - setState(REVIEW); -} - -/*virtual*/ -void LLFloaterModelWizard::setModelPhysicsFeeErrorStatus(U32 status, const std::string& reason) -{ - swap_controls(mCalculateWeightsBtn, mCalculatingWeightsBtn, true); - - // Disable the "Review" step if it has been previously enabled. - modelChangedCallback(); - - llwarns << "LLFloaterModelWizard::setModelPhysicsFeeErrorStatus(" << status << " : " << reason << ")" << llendl; - - setState(PHYSICS); -} - -/*virtual*/ -void LLFloaterModelWizard::onModelUploadSuccess() -{ - // success! - setState(UPLOAD); -} - -/*virtual*/ -void LLFloaterModelWizard::onModelUploadFailure() -{ - // Failure. Make the user recalculate fees - setState(PHYSICS); - // Disable the "Review" step if it has been previously enabled. - if (mLastEnabledState > PHYSICS) - { - mLastEnabledState = PHYSICS; - } - - updateButtons(); -} - -//static -void LLFloaterModelWizard::executePhysicsStage(std::string stage_name) -{ - if (sInstance) - { - // Invert the slider value so that "performance" end is giving the least detailed physics, - // and the "accuracy" end is giving the most detailed physics - F64 physics_accuracy = 1 - sInstance->getChild<LLSliderCtrl>("physics_slider")->getValue().asReal(); - - sInstance->mDecompParams["Retain%"] = physics_accuracy; - - if (!sInstance->mCurRequest.empty()) - { - llinfos << "Decomposition request still pending." << llendl; - return; - } - - if (sInstance->mModelPreview) - { - for (S32 i = 0; i < sInstance->mModelPreview->mModel[LLModel::LOD_PHYSICS].size(); ++i) - { - LLModel* mdl = sInstance->mModelPreview->mModel[LLModel::LOD_PHYSICS][i]; - DecompRequest* request = new DecompRequest(stage_name, mdl); - if(request->isValid()) - { - sInstance->mCurRequest.insert(request); - gMeshRepo.mDecompThread->submitRequest(request); - } - } - } - } -} - -LLFloaterModelWizard::DecompRequest::DecompRequest(const std::string& stage, LLModel* mdl) -{ - mStage = stage; - mContinue = 1; - mModel = mdl; - mDecompID = &mdl->mDecompID; - mParams = sInstance->mDecompParams; - - //copy out positions and indices - assignData(mdl) ; -} - - -S32 LLFloaterModelWizard::DecompRequest::statusCallback(const char* status, S32 p1, S32 p2) -{ - setStatusMessage(llformat("%s: %d/%d", status, p1, p2)); - - return mContinue; -} - -void LLFloaterModelWizard::DecompRequest::completed() -{ //called from the main thread - mModel->setConvexHullDecomposition(mHull); - - if (sInstance) - { - if (sInstance->mModelPreview) - { - sInstance->mModelPreview->mDirty = true; - LLFloaterModelWizard::sInstance->mModelPreview->refresh(); - } - - sInstance->mCurRequest.erase(this); - } - - if (mStage == "Decompose") - { - executePhysicsStage("Simplify"); - } - else - { - // Decomp request is complete so we can enable the "Recalculate physics" button again. - swap_controls(sInstance->mRecalculatePhysicsBtn, sInstance->mRecalculatingPhysicsBtn, true); - } -} - - -BOOL LLFloaterModelWizard::postBuild() -{ - childSetValue("import_scale", (F32) 0.67335826); - - getChild<LLUICtrl>("browse")->setCommitCallback(boost::bind(&LLFloaterModelWizard::loadModel, this)); - //getChild<LLUICtrl>("lod_file")->setCommitCallback(boost::bind(&LLFloaterModelWizard::loadModel, this)); - getChild<LLUICtrl>("cancel")->setCommitCallback(boost::bind(&LLFloaterModelWizard::onClickCancel, this)); - getChild<LLUICtrl>("close")->setCommitCallback(boost::bind(&LLFloaterModelWizard::onClickCancel, this)); - getChild<LLUICtrl>("back")->setCommitCallback(boost::bind(&LLFloaterModelWizard::onClickBack, this)); - getChild<LLUICtrl>("next")->setCommitCallback(boost::bind(&LLFloaterModelWizard::onClickNext, this)); - getChild<LLUICtrl>("preview_lod_combo")->setCommitCallback(boost::bind(&LLFloaterModelWizard::onPreviewLODCommit, this, _1)); - getChild<LLUICtrl>("preview_lod_combo2")->setCommitCallback(boost::bind(&LLFloaterModelWizard::onPreviewLODCommit, this, _1)); - getChild<LLUICtrl>("upload")->setCommitCallback(boost::bind(&LLFloaterModelWizard::onUpload, this)); - getChild<LLUICtrl>("switch_to_advanced")->setCommitCallback(boost::bind(&LLFloaterModelWizard::onClickSwitchToAdvanced, this)); - - mRecalculateGeometryBtn = getChild<LLButton>("recalculate_geometry_btn"); - mRecalculateGeometryBtn->setCommitCallback(boost::bind(&LLFloaterModelWizard::onClickRecalculateGeometry, this)); - - mRecalculatePhysicsBtn = getChild<LLButton>("recalculate_physics_btn"); - mRecalculatePhysicsBtn->setCommitCallback(boost::bind(&LLFloaterModelWizard::onClickRecalculatePhysics, this)); - - mRecalculatingPhysicsBtn = getChild<LLButton>("recalculating_physics_btn"); - - mCalculateWeightsBtn = getChild<LLButton>("calculate"); - mCalculateWeightsBtn->setCommitCallback(boost::bind(&LLFloaterModelWizard::onClickCalculateUploadFee, this)); - - mCalculatingWeightsBtn = getChild<LLButton>("calculating"); - - mChooseFilePreviewPanel = getChild<LLView>("choose_file_preview_panel"); - mOptimizePreviewPanel = getChild<LLView>("optimize_preview_panel"); - mPhysicsPreviewPanel = getChild<LLView>("physics_preview_panel"); - - LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; - - enable_registrar.add("Next.OnEnable", boost::bind(&LLFloaterModelWizard::onEnableNext, this)); - enable_registrar.add("Back.OnEnable", boost::bind(&LLFloaterModelWizard::onEnableBack, this)); - - mModelPreview = new LLModelPreview(512, 512, this); - mModelPreview->setPreviewTarget(16.f); - mModelPreview->setDetailsCallback(boost::bind(&LLFloaterModelWizard::setDetails, this, _1, _2, _3, _4, _5)); - mModelPreview->setModelLoadedCallback(boost::bind(&LLFloaterModelWizard::modelLoadedCallback, this)); - mModelPreview->setModelUpdatedCallback(boost::bind(&LLFloaterModelWizard::modelChangedCallback, this)); - mModelPreview->mViewOption["show_textures"] = true; - - center(); - - setState(CHOOSE_FILE); - - childSetTextArg("import_dimensions", "[X]", LLStringUtil::null); - childSetTextArg("import_dimensions", "[Y]", LLStringUtil::null); - childSetTextArg("import_dimensions", "[Z]", LLStringUtil::null); - - initDecompControls(); - - requestAgentUploadPermissions(); - - return TRUE; -} - - -void LLFloaterModelWizard::setDetails(F32 x, F32 y, F32 z, F32 streaming_cost, F32 physics_cost) -{ - // iterate through all the panels, setting the dimensions - for(size_t t=0; t<LL_ARRAY_SIZE(stateNames); ++t) - { - LLPanel *panel = getChild<LLPanel>(stateNames[t]+"_panel"); - if (panel) - { - panel->childSetText("dimension_x", llformat("%.1f", x)); - panel->childSetText("dimension_y", llformat("%.1f", y)); - panel->childSetText("dimension_z", llformat("%.1f", z)); - } - } - - childSetTextArg("review_prim_equiv", "[EQUIV]", llformat("%d", mModelPreview->mResourceCost)); -} - -void LLFloaterModelWizard::modelLoadedCallback() -{ - mLastEnabledState = CHOOSE_FILE; - updateButtons(); -} - -void LLFloaterModelWizard::modelChangedCallback() -{ - // Don't allow to proceed to the "Review" step if the model has changed - // but the new upload fee hasn't been calculated yet. - if (mLastEnabledState > PHYSICS) - { - mLastEnabledState = PHYSICS; - } - - getChildView("upload")->setEnabled(false); - - updateButtons(); -} - -void LLFloaterModelWizard::onUpload() -{ - mModelPreview->rebuildUploadData(); - - gMeshRepo.uploadModel(mModelPreview->mUploadData, mModelPreview->mPreviewScale, - true, false, false, mUploadModelUrl, true, - LLHandle<LLWholeModelFeeObserver>(), getWholeModelUploadObserverHandle()); -} - -void LLFloaterModelWizard::onPreviewLODCommit(LLUICtrl* ctrl) -{ - if (!mModelPreview) - { - return; - } - - S32 which_mode = 0; - - LLComboBox* combo = (LLComboBox*) ctrl; - - which_mode = (NUM_LOD-1)-combo->getFirstSelectedIndex(); // combo box list of lods is in reverse order - - mModelPreview->setPreviewLOD(which_mode); -} - -void LLFloaterModelWizard::refresh() -{ - if (mState == CHOOSE_FILE) - { - bool model_loaded = false; - - if (mModelPreview && mModelPreview->getLoadState() == LLModelLoader::DONE) - { - model_loaded = true; - } - - getChildView("next")->setEnabled(model_loaded); - } -} - -void LLFloaterModelWizard::draw() -{ - refresh(); - - LLFloater::draw(); - - if (mModelPreview && mState < REVIEW) - { - mModelPreview->update(); - - gGL.color3f(1.f, 1.f, 1.f); - - gGL.getTexUnit(0)->bind(mModelPreview); - - gGL.begin( LLRender::QUADS ); - { - gGL.texCoord2f(0.f, 1.f); - gGL.vertex2i(mPreviewRect.mLeft, mPreviewRect.mTop); - gGL.texCoord2f(0.f, 0.f); - gGL.vertex2i(mPreviewRect.mLeft, mPreviewRect.mBottom); - gGL.texCoord2f(1.f, 0.f); - gGL.vertex2i(mPreviewRect.mRight, mPreviewRect.mBottom); - gGL.texCoord2f(1.f, 1.f); - gGL.vertex2i(mPreviewRect.mRight, mPreviewRect.mTop); - } - gGL.end(); - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - } -} - -// static -void swap_controls(LLUICtrl* first_ctrl, LLUICtrl* second_ctrl, bool first_ctr_visible) -{ - first_ctrl->setVisible(first_ctr_visible); - second_ctrl->setVisible(!first_ctr_visible); -} diff --git a/indra/newview/llfloatermodelwizard.h b/indra/newview/llfloatermodelwizard.h deleted file mode 100644 index db9b605777..0000000000 --- a/indra/newview/llfloatermodelwizard.h +++ /dev/null @@ -1,140 +0,0 @@ -/** - * @file llfloatermodelwizard.h - * - * $LicenseInfo:firstyear=2009&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LLFLOATERMODELWIZARD_H -#define LLFLOATERMODELWIZARD_H - - -#include "llmeshrepository.h" -#include "llmodel.h" -#include "llthread.h" -#include "llfloatermodeluploadbase.h" - - -class LLModelPreview; - - -class LLFloaterModelWizard : public LLFloaterModelUploadBase -{ -public: - - class DecompRequest : public LLPhysicsDecomp::Request - { - public: - S32 mContinue; - LLPointer<LLModel> mModel; - - DecompRequest(const std::string& stage, LLModel* mdl); - virtual S32 statusCallback(const char* status, S32 p1, S32 p2); - virtual void completed(); - - }; - - static LLFloaterModelWizard* sInstance; - - LLFloaterModelWizard(const LLSD& key); - virtual ~LLFloaterModelWizard(); - /*virtual*/ BOOL postBuild(); - void draw(); - void refresh(); - - BOOL handleMouseDown(S32 x, S32 y, MASK mask); - BOOL handleMouseUp(S32 x, S32 y, MASK mask); - BOOL handleHover(S32 x, S32 y, MASK mask); - BOOL handleScrollWheel(S32 x, S32 y, S32 clicks); - - void setDetails(F32 x, F32 y, F32 z, F32 streaming_cost, F32 physics_cost); - void modelLoadedCallback(); - void modelChangedCallback(); - void initDecompControls(); - - // shows warning message if agent has no permissions to upload model - /*virtual*/ void onPermissionsReceived(const LLSD& result); - - // called when error occurs during permissions request - /*virtual*/ void setPermissonsErrorStatus(U32 status, const std::string& reason); - - /*virtual*/ void onModelPhysicsFeeReceived(const LLSD& result, std::string upload_url); - - /*virtual*/ void setModelPhysicsFeeErrorStatus(U32 status, const std::string& reason); - - /*virtual*/ void onModelUploadSuccess(); - - /*virtual*/ void onModelUploadFailure(); - - const LLRect& getPreviewRect() const { return mPreviewRect; } - - LLPhysicsDecomp::decomp_params mDecompParams; - std::set<LLPointer<DecompRequest> > mCurRequest; - std::string mStatusMessage; - static void executePhysicsStage(std::string stage_name); - -private: - enum EWizardState - { - CHOOSE_FILE = 0, - OPTIMIZE, - PHYSICS, - REVIEW, - UPLOAD - }; - - void setState(int state); - void updateButtons(); - void onClickSwitchToAdvanced(); - void onClickRecalculateGeometry(); - void onClickRecalculatePhysics(); - void onClickCalculateUploadFee(); - void onClickCancel(); - void onClickBack(); - void onClickNext(); - bool onEnableNext(); - bool onEnableBack(); - void loadModel(); - void onPreviewLODCommit(LLUICtrl*); - void onUpload(); - - LLModelPreview* mModelPreview; - LLRect mPreviewRect; - int mState; - - S32 mLastMouseX; - S32 mLastMouseY; - - U32 mLastEnabledState; - - LLButton* mRecalculateGeometryBtn; - LLButton* mRecalculatePhysicsBtn; - LLButton* mRecalculatingPhysicsBtn; - LLButton* mCalculateWeightsBtn; - LLButton* mCalculatingWeightsBtn; - - LLView* mChooseFilePreviewPanel; - LLView* mOptimizePreviewPanel; - LLView* mPhysicsPreviewPanel; -}; - - -#endif diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 996cf1e212..3df68a6ea1 100755 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -35,7 +35,7 @@ #include "llfloaterpreference.h" #include "message.h" - +#include "llfloaterautoreplacesettings.h" #include "llagent.h" #include "llavatarconstants.h" #include "llcheckboxctrl.h" @@ -346,7 +346,9 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key) mCommitCallbackRegistrar.add("Pref.BlockList", boost::bind(&LLFloaterPreference::onClickBlockList, this)); mCommitCallbackRegistrar.add("Pref.Proxy", boost::bind(&LLFloaterPreference::onClickProxySettings, this)); mCommitCallbackRegistrar.add("Pref.TranslationSettings", boost::bind(&LLFloaterPreference::onClickTranslationSettings, this)); - + mCommitCallbackRegistrar.add("Pref.AutoReplace", boost::bind(&LLFloaterPreference::onClickAutoReplace, this)); + mCommitCallbackRegistrar.add("Pref.SpellChecker", boost::bind(&LLFloaterPreference::onClickSpellChecker, this)); + sSkin = gSavedSettings.getString("SkinCurrent"); mCommitCallbackRegistrar.add("Pref.ClickActionChange", boost::bind(&LLFloaterPreference::onClickActionChange, this)); @@ -354,7 +356,7 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key) gSavedSettings.getControl("NameTagShowUsernames")->getCommitSignal()->connect(boost::bind(&handleNameTagOptionChanged, _2)); gSavedSettings.getControl("NameTagShowFriends")->getCommitSignal()->connect(boost::bind(&handleNameTagOptionChanged, _2)); gSavedSettings.getControl("UseDisplayNames")->getCommitSignal()->connect(boost::bind(&handleDisplayNamesOptionChanged, _2)); - + LLAvatarPropertiesProcessor::getInstance()->addObserver( gAgent.getID(), this ); } @@ -429,6 +431,8 @@ BOOL LLFloaterPreference::postBuild() gSavedSettings.getControl("ChatBubbleOpacity")->getSignal()->connect(boost::bind(&LLFloaterPreference::onNameTagOpacityChange, this, _2)); + gSavedSettings.getControl("PreferredMaturity")->getSignal()->connect(boost::bind(&LLFloaterPreference::onChangeMaturity, this)); + LLTabContainer* tabcontainer = getChild<LLTabContainer>("pref core"); if (!tabcontainer->selectTab(gSavedSettings.getS32("LastPrefTab"))) tabcontainer->selectFirstTab(); @@ -593,6 +597,9 @@ void LLFloaterPreference::cancel() // hide translation settings floater LLFloaterReg::hideInstance("prefs_translation"); + // hide translation settings floater + LLFloaterReg::hideInstance("prefs_autoreplace"); + // cancel hardware menu LLFloaterHardwareSettings* hardware_settings = LLFloaterReg::getTypedInstance<LLFloaterHardwareSettings>("prefs_hardware_settings"); if (hardware_settings) @@ -920,7 +927,6 @@ void LLFloaterPreference::refreshSkin(void* data) self->getChild<LLRadioGroup>("skin_selection", true)->setValue(sSkin); } - void LLFloaterPreference::buildPopupLists() { LLScrollListCtrl& disabled_popups = @@ -1503,6 +1509,16 @@ void LLFloaterPreference::onClickTranslationSettings() LLFloaterReg::showInstance("prefs_translation"); } +void LLFloaterPreference::onClickAutoReplace() +{ + LLFloaterReg::showInstance("prefs_autoreplace"); +} + +void LLFloaterPreference::onClickSpellChecker() +{ + LLFloaterReg::showInstance("prefs_spellchecker"); +} + void LLFloaterPreference::onClickActionChange() { mClickActionDirty = true; diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h index ec5994e917..b71f7c647b 100644 --- a/indra/newview/llfloaterpreference.h +++ b/indra/newview/llfloaterpreference.h @@ -157,6 +157,8 @@ public: void onClickBlockList(); void onClickProxySettings(); void onClickTranslationSettings(); + void onClickAutoReplace(); + void onClickSpellChecker(); void applyUIColor(LLUICtrl* ctrl, const LLSD& param); void getUIColor(LLUICtrl* ctrl, const LLSD& param); diff --git a/indra/newview/llfloaterspellchecksettings.cpp b/indra/newview/llfloaterspellchecksettings.cpp new file mode 100644 index 0000000000..5ecdd11918 --- /dev/null +++ b/indra/newview/llfloaterspellchecksettings.cpp @@ -0,0 +1,491 @@ +/** + * @file llfloaterspellchecksettings.h + * @brief Spell checker settings floater + * +* $LicenseInfo:firstyear=2011&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llcombobox.h" +#include "llfilepicker.h" +#include "llfloaterreg.h" +#include "llfloaterspellchecksettings.h" +#include "llscrolllistctrl.h" +#include "llsdserialize.h" +#include "llspellcheck.h" +#include "lltrans.h" +#include "llviewercontrol.h" +#include "llnotificationsutil.h" + +#include <boost/algorithm/string.hpp> + +///---------------------------------------------------------------------------- +/// Class LLFloaterSpellCheckerSettings +///---------------------------------------------------------------------------- +LLFloaterSpellCheckerSettings::LLFloaterSpellCheckerSettings(const LLSD& key) + : LLFloater(key) +{ +} + +void LLFloaterSpellCheckerSettings::draw() +{ + LLFloater::draw(); + + std::vector<LLScrollListItem*> sel_items = getChild<LLScrollListCtrl>("spellcheck_available_list")->getAllSelected(); + bool enable_remove = !sel_items.empty(); + for (std::vector<LLScrollListItem*>::const_iterator sel_it = sel_items.begin(); sel_it != sel_items.end(); ++sel_it) + { + enable_remove &= LLSpellChecker::canRemoveDictionary((*sel_it)->getValue().asString()); + } + getChild<LLUICtrl>("spellcheck_remove_btn")->setEnabled(enable_remove); +} + +BOOL LLFloaterSpellCheckerSettings::postBuild(void) +{ + gSavedSettings.getControl("SpellCheck")->getSignal()->connect(boost::bind(&LLFloaterSpellCheckerSettings::refreshDictionaries, this, false)); + LLSpellChecker::setSettingsChangeCallback(boost::bind(&LLFloaterSpellCheckerSettings::onSpellCheckSettingsChange, this)); + getChild<LLUICtrl>("spellcheck_remove_btn")->setCommitCallback(boost::bind(&LLFloaterSpellCheckerSettings::onBtnRemove, this)); + getChild<LLUICtrl>("spellcheck_import_btn")->setCommitCallback(boost::bind(&LLFloaterSpellCheckerSettings::onBtnImport, this)); + getChild<LLUICtrl>("spellcheck_main_combo")->setCommitCallback(boost::bind(&LLFloaterSpellCheckerSettings::refreshDictionaries, this, false)); + getChild<LLUICtrl>("spellcheck_moveleft_btn")->setCommitCallback(boost::bind(&LLFloaterSpellCheckerSettings::onBtnMove, this, "spellcheck_active_list", "spellcheck_available_list")); + getChild<LLUICtrl>("spellcheck_moveright_btn")->setCommitCallback(boost::bind(&LLFloaterSpellCheckerSettings::onBtnMove, this, "spellcheck_available_list", "spellcheck_active_list")); + center(); + return true; +} + +void LLFloaterSpellCheckerSettings::onBtnImport() +{ + LLFloaterReg::showInstance("prefs_spellchecker_import"); +} + +void LLFloaterSpellCheckerSettings::onBtnMove(const std::string& from, const std::string& to) +{ + LLScrollListCtrl* from_ctrl = findChild<LLScrollListCtrl>(from); + LLScrollListCtrl* to_ctrl = findChild<LLScrollListCtrl>(to); + + LLSD row; + row["columns"][0]["column"] = "name"; + + std::vector<LLScrollListItem*> sel_items = from_ctrl->getAllSelected(); + std::vector<LLScrollListItem*>::const_iterator sel_it; + for ( sel_it = sel_items.begin(); sel_it != sel_items.end(); ++sel_it) + { + row["value"] = (*sel_it)->getValue(); + row["columns"][0]["value"] = (*sel_it)->getColumn(0)->getValue(); + to_ctrl->addElement(row); + to_ctrl->setSelectedByValue( (*sel_it)->getValue(), true ); + } + from_ctrl->deleteSelectedItems(); +} + +void LLFloaterSpellCheckerSettings::onClose(bool app_quitting) +{ + if (app_quitting) + { + // don't save anything + return; + } + LLFloaterReg::hideInstance("prefs_spellchecker_import"); + + std::list<std::string> list_dict; + + LLComboBox* dict_combo = findChild<LLComboBox>("spellcheck_main_combo"); + const std::string dict_name = dict_combo->getSelectedItemLabel(); + if (!dict_name.empty()) + { + list_dict.push_back(dict_name); + + LLScrollListCtrl* list_ctrl = findChild<LLScrollListCtrl>("spellcheck_active_list"); + std::vector<LLScrollListItem*> list_items = list_ctrl->getAllData(); + for (std::vector<LLScrollListItem*>::const_iterator item_it = list_items.begin(); item_it != list_items.end(); ++item_it) + { + const std::string language = (*item_it)->getValue().asString(); + if (LLSpellChecker::hasDictionary(language, true)) + { + list_dict.push_back(language); + } + } + } + gSavedSettings.setString("SpellCheckDictionary", boost::join(list_dict, ",")); +} + +void LLFloaterSpellCheckerSettings::onOpen(const LLSD& key) +{ + refreshDictionaries(true); +} + +void LLFloaterSpellCheckerSettings::onBtnRemove() +{ + std::vector<LLScrollListItem*> sel_items = getChild<LLScrollListCtrl>("spellcheck_available_list")->getAllSelected(); + for (std::vector<LLScrollListItem*>::const_iterator sel_it = sel_items.begin(); sel_it != sel_items.end(); ++sel_it) + { + LLSpellChecker::instance().removeDictionary((*sel_it)->getValue().asString()); + } +} + +void LLFloaterSpellCheckerSettings::onSpellCheckSettingsChange() +{ + refreshDictionaries(true); +} + +void LLFloaterSpellCheckerSettings::refreshDictionaries(bool from_settings) +{ + bool enabled = gSavedSettings.getBOOL("SpellCheck"); + getChild<LLUICtrl>("spellcheck_moveleft_btn")->setEnabled(enabled); + getChild<LLUICtrl>("spellcheck_moveright_btn")->setEnabled(enabled); + + // Populate the dictionary combobox + LLComboBox* dict_combo = findChild<LLComboBox>("spellcheck_main_combo"); + std::string dict_cur = dict_combo->getSelectedItemLabel(); + if ((dict_cur.empty() || from_settings) && (LLSpellChecker::getUseSpellCheck())) + { + dict_cur = LLSpellChecker::instance().getPrimaryDictionary(); + } + dict_combo->clearRows(); + + const LLSD& dict_map = LLSpellChecker::getDictionaryMap(); + if (dict_map.size()) + { + for (LLSD::array_const_iterator dict_it = dict_map.beginArray(); dict_it != dict_map.endArray(); ++dict_it) + { + const LLSD& dict = *dict_it; + if ( (dict["installed"].asBoolean()) && (dict["is_primary"].asBoolean()) && (dict.has("language")) ) + { + dict_combo->add(dict["language"].asString()); + } + } + if (!dict_combo->selectByValue(dict_cur)) + { + dict_combo->clear(); + } + } + dict_combo->sortByName(); + dict_combo->setEnabled(enabled); + + // Populate the available and active dictionary list + LLScrollListCtrl* avail_ctrl = findChild<LLScrollListCtrl>("spellcheck_available_list"); + LLScrollListCtrl* active_ctrl = findChild<LLScrollListCtrl>("spellcheck_active_list"); + + LLSpellChecker::dict_list_t active_list; + if ( ((!avail_ctrl->getItemCount()) && (!active_ctrl->getItemCount())) || (from_settings) ) + { + if (LLSpellChecker::getUseSpellCheck()) + { + active_list = LLSpellChecker::instance().getSecondaryDictionaries(); + } + } + else + { + std::vector<LLScrollListItem*> active_items = active_ctrl->getAllData(); + for (std::vector<LLScrollListItem*>::const_iterator item_it = active_items.begin(); item_it != active_items.end(); ++item_it) + { + std::string dict = (*item_it)->getValue().asString(); + if (dict_cur != dict) + { + active_list.push_back(dict); + } + } + } + + LLSD row; + row["columns"][0]["column"] = "name"; + + active_ctrl->clearRows(); + active_ctrl->setEnabled(enabled); + for (LLSpellChecker::dict_list_t::const_iterator it = active_list.begin(); it != active_list.end(); ++it) + { + const std::string language = *it; + const LLSD dict = LLSpellChecker::getDictionaryData(language); + row["value"] = language; + row["columns"][0]["value"] = (!dict["user_installed"].asBoolean()) ? language : language + " " + LLTrans::getString("UserDictionary"); + active_ctrl->addElement(row); + } + active_ctrl->sortByColumnIndex(0, true); + active_list.push_back(dict_cur); + + avail_ctrl->clearRows(); + avail_ctrl->setEnabled(enabled); + for (LLSD::array_const_iterator dict_it = dict_map.beginArray(); dict_it != dict_map.endArray(); ++dict_it) + { + const LLSD& dict = *dict_it; + const std::string language = dict["language"].asString(); + if ( (dict["installed"].asBoolean()) && (active_list.end() == std::find(active_list.begin(), active_list.end(), language)) ) + { + row["value"] = language; + row["columns"][0]["value"] = (!dict["user_installed"].asBoolean()) ? language : language + " " + LLTrans::getString("UserDictionary"); + avail_ctrl->addElement(row); + } + } + avail_ctrl->sortByColumnIndex(0, true); +} + +///---------------------------------------------------------------------------- +/// Class LLFloaterSpellCheckerImport +///---------------------------------------------------------------------------- +LLFloaterSpellCheckerImport::LLFloaterSpellCheckerImport(const LLSD& key) + : LLFloater(key) +{ +} + +BOOL LLFloaterSpellCheckerImport::postBuild(void) +{ + getChild<LLUICtrl>("dictionary_path_browse")->setCommitCallback(boost::bind(&LLFloaterSpellCheckerImport::onBtnBrowse, this)); + getChild<LLUICtrl>("ok_btn")->setCommitCallback(boost::bind(&LLFloaterSpellCheckerImport::onBtnOK, this)); + getChild<LLUICtrl>("cancel_btn")->setCommitCallback(boost::bind(&LLFloaterSpellCheckerImport::onBtnCancel, this)); + center(); + return true; +} + +void LLFloaterSpellCheckerImport::onBtnBrowse() +{ + LLFilePicker& file_picker = LLFilePicker::instance(); + if (!file_picker.getOpenFile(LLFilePicker::FFLOAD_DICTIONARY)) + { + return; + } + + std::string filepath = file_picker.getFirstFile(); + + const std::string extension = gDirUtilp->getExtension(filepath); + if ("xcu" == extension) + { + filepath = parseXcuFile(filepath); + if (filepath.empty()) + { + return; + } + } + + getChild<LLUICtrl>("dictionary_path")->setValue(filepath); + + mDictionaryDir = gDirUtilp->getDirName(filepath); + mDictionaryBasename = gDirUtilp->getBaseFileName(filepath, true); + getChild<LLUICtrl>("dictionary_name")->setValue(mDictionaryBasename); +} + +void LLFloaterSpellCheckerImport::onBtnCancel() +{ + closeFloater(false); +} + +void LLFloaterSpellCheckerImport::onBtnOK() +{ + const std::string dict_dic = mDictionaryDir + gDirUtilp->getDirDelimiter() + mDictionaryBasename + ".dic"; + const std::string dict_aff = mDictionaryDir + gDirUtilp->getDirDelimiter() + mDictionaryBasename + ".aff"; + std::string dict_language = getChild<LLUICtrl>("dictionary_language")->getValue().asString(); + LLStringUtil::trim(dict_language); + + bool imported = false; + if ( dict_language.empty() + || mDictionaryDir.empty() + || mDictionaryBasename.empty() + || ! gDirUtilp->fileExists(dict_dic) + ) + { + LLNotificationsUtil::add("SpellingDictImportRequired"); + } + else + { + std::string settings_dic = LLSpellChecker::getDictionaryUserPath() + mDictionaryBasename + ".dic"; + if ( copyFile( dict_dic, settings_dic ) ) + { + if (gDirUtilp->fileExists(dict_aff)) + { + std::string settings_aff = LLSpellChecker::getDictionaryUserPath() + mDictionaryBasename + ".aff"; + if (copyFile( dict_aff, settings_aff )) + { + imported = true; + } + else + { + LLSD args = LLSD::emptyMap(); + args["FROM_NAME"] = dict_aff; + args["TO_NAME"] = settings_aff; + LLNotificationsUtil::add("SpellingDictImportFailed", args); + } + } + else + { + LLSD args = LLSD::emptyMap(); + args["DIC_NAME"] = dict_dic; + LLNotificationsUtil::add("SpellingDictIsSecondary", args); + + imported = true; + } + } + else + { + LLSD args = LLSD::emptyMap(); + args["FROM_NAME"] = dict_dic; + args["TO_NAME"] = settings_dic; + LLNotificationsUtil::add("SpellingDictImportFailed", args); + } + } + + if ( imported ) + { + LLSD custom_dict_info; + custom_dict_info["is_primary"] = (bool)gDirUtilp->fileExists(dict_aff); + custom_dict_info["name"] = mDictionaryBasename; + custom_dict_info["language"] = dict_language; + + LLSD custom_dict_map; + llifstream custom_file_in(LLSpellChecker::getDictionaryUserPath() + "user_dictionaries.xml"); + if (custom_file_in.is_open()) + { + LLSDSerialize::fromXMLDocument(custom_dict_map, custom_file_in); + custom_file_in.close(); + } + + LLSD::array_iterator it = custom_dict_map.beginArray(); + for (; it != custom_dict_map.endArray(); ++it) + { + LLSD& dict_info = *it; + if (dict_info["name"].asString() == mDictionaryBasename) + { + dict_info = custom_dict_info; + break; + } + } + if (custom_dict_map.endArray() == it) + { + custom_dict_map.append(custom_dict_info); + } + + llofstream custom_file_out(LLSpellChecker::getDictionaryUserPath() + "user_dictionaries.xml", std::ios::trunc); + if (custom_file_out.is_open()) + { + LLSDSerialize::toPrettyXML(custom_dict_map, custom_file_out); + custom_file_out.close(); + } + + LLSpellChecker::refreshDictionaryMap(); + } + + closeFloater(false); +} + +bool LLFloaterSpellCheckerImport::copyFile(const std::string from, const std::string to) +{ + bool copied = false; + LLFILE* in = LLFile::fopen(from, "rb"); /* Flawfinder: ignore */ + if (in) + { + LLFILE* out = LLFile::fopen(to, "wb"); /* Flawfinder: ignore */ + if (out) + { + char buf[16384]; /* Flawfinder: ignore */ + size_t readbytes; + bool write_ok = true; + while(write_ok && (readbytes = fread(buf, 1, 16384, in))) /* Flawfinder: ignore */ + { + if (fwrite(buf, 1, readbytes, out) != readbytes) + { + LL_WARNS("SpellCheck") << "Short write" << LL_ENDL; + write_ok = false; + } + } + if ( write_ok ) + { + copied = true; + } + fclose(out); + } + } + fclose(in); + return copied; +} + +std::string LLFloaterSpellCheckerImport::parseXcuFile(const std::string& file_path) const +{ + LLXMLNodePtr xml_root; + if ( (!LLUICtrlFactory::getLayeredXMLNode(file_path, xml_root)) || (xml_root.isNull()) ) + { + return LLStringUtil::null; + } + + // Bury down to the "Dictionaries" parent node + LLXMLNode* dict_node = NULL; + for (LLXMLNode* outer_node = xml_root->getFirstChild(); outer_node && !dict_node; outer_node = outer_node->getNextSibling()) + { + std::string temp; + if ( (outer_node->getAttributeString("oor:name", temp)) && ("ServiceManager" == temp) ) + { + for (LLXMLNode* inner_node = outer_node->getFirstChild(); inner_node && !dict_node; inner_node = inner_node->getNextSibling()) + { + if ( (inner_node->getAttributeString("oor:name", temp)) && ("Dictionaries" == temp) ) + { + dict_node = inner_node; + break; + } + } + } + } + + if (dict_node) + { + // Iterate over all child nodes until we find one that has a <value>DICT_SPELL</value> node + for (LLXMLNode* outer_node = dict_node->getFirstChild(); outer_node; outer_node = outer_node->getNextSibling()) + { + std::string temp; + LLXMLNodePtr location_node, format_node; + for (LLXMLNode* inner_node = outer_node->getFirstChild(); inner_node; inner_node = inner_node->getNextSibling()) + { + if (inner_node->getAttributeString("oor:name", temp)) + { + if ("Locations" == temp) + { + inner_node->getChild("value", location_node, false); + } + else if ("Format" == temp) + { + inner_node->getChild("value", format_node, false); + } + } + } + if ( (format_node.isNull()) || ("DICT_SPELL" != format_node->getValue()) || (location_node.isNull()) ) + { + continue; + } + + // Found a list of file locations, return the .dic (if present) + std::list<std::string> location_list; + boost::split(location_list, location_node->getValue(), boost::is_any_of(std::string(" "))); + for (std::list<std::string>::iterator it = location_list.begin(); it != location_list.end(); ++it) + { + std::string& location = *it; + if ("\\" != gDirUtilp->getDirDelimiter()) + LLStringUtil::replaceString(location, "\\", gDirUtilp->getDirDelimiter()); + else + LLStringUtil::replaceString(location, "/", gDirUtilp->getDirDelimiter()); + LLStringUtil::replaceString(location, "%origin%", gDirUtilp->getDirName(file_path)); + if ("dic" == gDirUtilp->getExtension(location)) + { + return location; + } + } + } + } + + return LLStringUtil::null; +} diff --git a/indra/newview/llfloaterspellchecksettings.h b/indra/newview/llfloaterspellchecksettings.h new file mode 100644 index 0000000000..eded3a9133 --- /dev/null +++ b/indra/newview/llfloaterspellchecksettings.h @@ -0,0 +1,68 @@ +/** + * @file llfloaterspellchecksettings.h + * @brief Spell checker settings floater + * +* $LicenseInfo:firstyear=2011&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LLFLOATERSPELLCHECKERSETTINGS_H +#define LLFLOATERSPELLCHECKERSETTINGS_H + +#include "llfloater.h" + +class LLFloaterSpellCheckerSettings : public LLFloater +{ +public: + LLFloaterSpellCheckerSettings(const LLSD& key); + + /*virtual*/ void draw(); + /*virtual*/ BOOL postBuild(); + /*virtual*/ void onOpen(const LLSD& key); + /*virtual*/ void onClose(bool app_quitting); + +protected: + void onBtnImport(); + void onBtnMove(const std::string& from, const std::string& to); + void onBtnRemove(); + void onSpellCheckSettingsChange(); + void refreshDictionaries(bool from_settings); +}; + +class LLFloaterSpellCheckerImport : public LLFloater +{ +public: + LLFloaterSpellCheckerImport(const LLSD& key); + + /*virtual*/ BOOL postBuild(); + +protected: + void onBtnBrowse(); + void onBtnCancel(); + void onBtnOK(); + bool copyFile(const std::string from, const std::string to); + std::string parseXcuFile(const std::string& file_path) const; + + std::string mDictionaryDir; + std::string mDictionaryBasename; +}; + +#endif // LLFLOATERSPELLCHECKERSETTINGS_H diff --git a/indra/newview/llfloatertexturefetchdebugger.cpp b/indra/newview/llfloatertexturefetchdebugger.cpp new file mode 100644 index 0000000000..2b34b72055 --- /dev/null +++ b/indra/newview/llfloatertexturefetchdebugger.cpp @@ -0,0 +1,390 @@ +/** + * @file llfloatertexturefetchdebugger.cpp + * @brief LLFloaterTextureFetchDebugger class definition + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llfloatertexturefetchdebugger.h" + +#include "lluictrlfactory.h" +#include "llbutton.h" +#include "llspinctrl.h" +#include "llresmgr.h" + +#include "llmath.h" +#include "llviewerwindow.h" +#include "llappviewer.h" +#include "lltexturefetch.h" +#include "llviewercontrol.h" + +LLFloaterTextureFetchDebugger::LLFloaterTextureFetchDebugger(const LLSD& key) + : LLFloater(key), + mDebugger(NULL) +{ + setTitle("Texture Fetching Debugger Floater"); + + mCommitCallbackRegistrar.add("TexFetchDebugger.ChangeTexelPixelRatio", boost::bind(&LLFloaterTextureFetchDebugger::onChangeTexelPixelRatio, this)); + + mCommitCallbackRegistrar.add("TexFetchDebugger.Start", boost::bind(&LLFloaterTextureFetchDebugger::onClickStart, this)); + mCommitCallbackRegistrar.add("TexFetchDebugger.Clear", boost::bind(&LLFloaterTextureFetchDebugger::onClickClear, this)); + mCommitCallbackRegistrar.add("TexFetchDebugger.Close", boost::bind(&LLFloaterTextureFetchDebugger::onClickClose, this)); + + mCommitCallbackRegistrar.add("TexFetchDebugger.CacheRead", boost::bind(&LLFloaterTextureFetchDebugger::onClickCacheRead, this)); + mCommitCallbackRegistrar.add("TexFetchDebugger.CacheWrite", boost::bind(&LLFloaterTextureFetchDebugger::onClickCacheWrite, this)); + mCommitCallbackRegistrar.add("TexFetchDebugger.HTTPLoad", boost::bind(&LLFloaterTextureFetchDebugger::onClickHTTPLoad, this)); + mCommitCallbackRegistrar.add("TexFetchDebugger.Decode", boost::bind(&LLFloaterTextureFetchDebugger::onClickDecode, this)); + mCommitCallbackRegistrar.add("TexFetchDebugger.GLTexture", boost::bind(&LLFloaterTextureFetchDebugger::onClickGLTexture, this)); + + mCommitCallbackRegistrar.add("TexFetchDebugger.RefetchVisCache", boost::bind(&LLFloaterTextureFetchDebugger::onClickRefetchVisCache, this)); + mCommitCallbackRegistrar.add("TexFetchDebugger.RefetchVisHTTP", boost::bind(&LLFloaterTextureFetchDebugger::onClickRefetchVisHTTP, this)); +} +//---------------------------------------------- + +BOOL LLFloaterTextureFetchDebugger::postBuild(void) +{ + mDebugger = LLAppViewer::getTextureFetch()->getFetchDebugger(); + + //set states for buttons + mButtonStateMap["start_btn"] = true; + mButtonStateMap["close_btn"] = true; + mButtonStateMap["clear_btn"] = true; + mButtonStateMap["cacheread_btn"] = false; + mButtonStateMap["cachewrite_btn"] = false; + mButtonStateMap["http_btn"] = false; + mButtonStateMap["decode_btn"] = false; + mButtonStateMap["gl_btn"] = false; + + mButtonStateMap["refetchviscache_btn"] = true; + mButtonStateMap["refetchvishttp_btn"] = true; + + updateButtons(); + + getChild<LLUICtrl>("texel_pixel_ratio")->setValue(gSavedSettings.getF32("TexelPixelRatio")); + + return TRUE ; +} + +LLFloaterTextureFetchDebugger::~LLFloaterTextureFetchDebugger() +{ + //stop everything + mDebugger->stopDebug(); +} + +void LLFloaterTextureFetchDebugger::updateButtons() +{ + for(std::map<std::string, bool>::iterator iter = mButtonStateMap.begin(); iter != mButtonStateMap.end(); ++iter) + { + if(iter->second) + { + childEnable(iter->first.c_str()); + } + else + { + childDisable(iter->first.c_str()); + } + } +} + +void LLFloaterTextureFetchDebugger::disableButtons() +{ + childDisable("start_btn"); + childDisable("clear_btn"); + childDisable("cacheread_btn"); + childDisable("cachewrite_btn"); + childDisable("http_btn"); + childDisable("decode_btn"); + childDisable("gl_btn"); + childDisable("refetchviscache_btn"); + childDisable("refetchvishttp_btn"); +} + +void LLFloaterTextureFetchDebugger::idle() +{ + LLTextureFetchDebugger::e_debug_state state = mDebugger->getState(); + + if(mDebugger->update()) + { + switch(state) + { + case LLTextureFetchDebugger::IDLE: + break; + case LLTextureFetchDebugger::READ_CACHE: + mButtonStateMap["cachewrite_btn"] = true; + mButtonStateMap["decode_btn"] = true; + updateButtons(); + break; + case LLTextureFetchDebugger::WRITE_CACHE: + updateButtons(); + break; + case LLTextureFetchDebugger::DECODING: + mButtonStateMap["gl_btn"] = true; + updateButtons(); + break; + case LLTextureFetchDebugger::HTTP_FETCHING: + mButtonStateMap["cacheread_btn"] = true; + mButtonStateMap["cachewrite_btn"] = true; + mButtonStateMap["decode_btn"] = true; + updateButtons(); + break; + case LLTextureFetchDebugger::GL_TEX: + updateButtons(); + break; + case LLTextureFetchDebugger::REFETCH_VIS_CACHE: + updateButtons(); + case LLTextureFetchDebugger::REFETCH_VIS_HTTP: + updateButtons(); + break; + default: + break; + } + } +} + +//---------------------- +void LLFloaterTextureFetchDebugger::onChangeTexelPixelRatio() +{ + gSavedSettings.setF32("TexelPixelRatio", getChild<LLUICtrl>("texel_pixel_ratio")->getValue().asReal()); +} + +void LLFloaterTextureFetchDebugger::onClickStart() +{ + disableButtons(); + + mDebugger->startDebug(); + + mButtonStateMap["start_btn"] = false; + mButtonStateMap["cacheread_btn"] = true; + mButtonStateMap["http_btn"] = true; + updateButtons(); +} + +void LLFloaterTextureFetchDebugger::onClickClose() +{ + setVisible(FALSE); + + //stop everything + mDebugger->stopDebug(); +} + +void LLFloaterTextureFetchDebugger::onClickClear() +{ + mButtonStateMap["start_btn"] = true; + mButtonStateMap["close_btn"] = true; + mButtonStateMap["clear_btn"] = true; + mButtonStateMap["cacheread_btn"] = false; + mButtonStateMap["cachewrite_btn"] = false; + mButtonStateMap["http_btn"] = false; + mButtonStateMap["decode_btn"] = false; + mButtonStateMap["gl_btn"] = false; + mButtonStateMap["refetchviscache_btn"] = true; + mButtonStateMap["refetchvishttp_btn"] = true; + updateButtons(); + + //stop everything + mDebugger->stopDebug(); + mDebugger->clearHistory(); +} + +void LLFloaterTextureFetchDebugger::onClickCacheRead() +{ + disableButtons(); + + mDebugger->debugCacheRead(); +} + +void LLFloaterTextureFetchDebugger::onClickCacheWrite() +{ + disableButtons(); + + mDebugger->debugCacheWrite(); +} + +void LLFloaterTextureFetchDebugger::onClickHTTPLoad() +{ + disableButtons(); + + mDebugger->debugHTTP(); +} + +void LLFloaterTextureFetchDebugger::onClickDecode() +{ + disableButtons(); + + mDebugger->debugDecoder(); +} + +void LLFloaterTextureFetchDebugger::onClickGLTexture() +{ + disableButtons(); + + mDebugger->debugGLTextureCreation(); +} + +void LLFloaterTextureFetchDebugger::onClickRefetchVisCache() +{ + disableButtons(); + + mDebugger->debugRefetchVisibleFromCache(); +} + +void LLFloaterTextureFetchDebugger::onClickRefetchVisHTTP() +{ + disableButtons(); + + mDebugger->debugRefetchVisibleFromHTTP(); +} + +void LLFloaterTextureFetchDebugger::draw() +{ + //total number of fetched textures + { + getChild<LLUICtrl>("total_num_fetched_label")->setTextArg("[NUM]", llformat("%d", mDebugger->getNumFetchedTextures())); + } + + //total number of fetching requests + { + getChild<LLUICtrl>("total_num_fetching_requests_label")->setTextArg("[NUM]", llformat("%d", mDebugger->getNumFetchingRequests())); + } + + //total number of cache hits + { + getChild<LLUICtrl>("total_num_cache_hits_label")->setTextArg("[NUM]", llformat("%d", mDebugger->getNumCacheHits())); + } + + //total number of visible textures + { + getChild<LLUICtrl>("total_num_visible_tex_label")->setTextArg("[NUM]", llformat("%d", mDebugger->getNumVisibleFetchedTextures())); + } + + //total number of visible texture fetching requests + { + getChild<LLUICtrl>("total_num_visible_tex_fetch_req_label")->setTextArg("[NUM]", llformat("%d", mDebugger->getNumVisibleFetchingRequests())); + } + + //total number of fetched data + { + getChild<LLUICtrl>("total_fetched_data_label")->setTextArg("[SIZE1]", llformat("%d", mDebugger->getFetchedData() >> 10)); + getChild<LLUICtrl>("total_fetched_data_label")->setTextArg("[SIZE2]", llformat("%d", mDebugger->getDecodedData() >> 10)); + getChild<LLUICtrl>("total_fetched_data_label")->setTextArg("[PIXEL]", llformat("%.3f", mDebugger->getFetchedPixels() / 1000000.f)); + } + + //total number of visible fetched data + { + getChild<LLUICtrl>("total_fetched_vis_data_label")->setTextArg("[SIZE1]", llformat("%d", mDebugger->getVisibleFetchedData() >> 10)); + getChild<LLUICtrl>("total_fetched_vis_data_label")->setTextArg("[SIZE2]", llformat("%d", mDebugger->getVisibleDecodedData() >> 10)); + } + + //total number of rendered fetched data + { + getChild<LLUICtrl>("total_fetched_rendered_data_label")->setTextArg("[SIZE1]", llformat("%d", mDebugger->getRenderedData() >> 10)); + getChild<LLUICtrl>("total_fetched_rendered_data_label")->setTextArg("[SIZE2]", llformat("%d", mDebugger->getRenderedDecodedData() >> 10)); + getChild<LLUICtrl>("total_fetched_rendered_data_label")->setTextArg("[PIXEL]", llformat("%.3f", mDebugger->getRenderedPixels() / 1000000.f)); + } + + //total time on cache readings + if(mDebugger->getCacheReadTime() < 0.f) + { + getChild<LLUICtrl>("total_time_cache_read_label")->setTextArg("[TIME]", std::string("----")); + } + else + { + getChild<LLUICtrl>("total_time_cache_read_label")->setTextArg("[TIME]", llformat("%.3f", mDebugger->getCacheReadTime())); + } + + //total time on cache writings + if(mDebugger->getCacheWriteTime() < 0.f) + { + getChild<LLUICtrl>("total_time_cache_write_label")->setTextArg("[TIME]", std::string("----")); + } + else + { + getChild<LLUICtrl>("total_time_cache_write_label")->setTextArg("[TIME]", llformat("%.3f", mDebugger->getCacheWriteTime())); + } + + //total time on decoding + if(mDebugger->getDecodeTime() < 0.f) + { + getChild<LLUICtrl>("total_time_decode_label")->setTextArg("[TIME]", std::string("----")); + } + else + { + getChild<LLUICtrl>("total_time_decode_label")->setTextArg("[TIME]", llformat("%.3f", mDebugger->getDecodeTime())); + } + + //total time on gl texture creation + if(mDebugger->getGLCreationTime() < 0.f) + { + getChild<LLUICtrl>("total_time_gl_label")->setTextArg("[TIME]", std::string("----")); + } + else + { + getChild<LLUICtrl>("total_time_gl_label")->setTextArg("[TIME]", llformat("%.3f", mDebugger->getGLCreationTime())); + } + + //total time on HTTP fetching + if(mDebugger->getHTTPTime() < 0.f) + { + getChild<LLUICtrl>("total_time_http_label")->setTextArg("[TIME]", std::string("----")); + } + else + { + getChild<LLUICtrl>("total_time_http_label")->setTextArg("[TIME]", llformat("%.3f", mDebugger->getHTTPTime())); + } + + //total time on entire fetching + { + getChild<LLUICtrl>("total_time_fetch_label")->setTextArg("[TIME]", llformat("%.3f", mDebugger->getTotalFetchingTime())); + } + + //total time on refetching visible textures from cache + if(mDebugger->getRefetchVisCacheTime() < 0.f) + { + getChild<LLUICtrl>("total_time_refetch_vis_cache_label")->setTextArg("[TIME]", std::string("----")); + getChild<LLUICtrl>("total_time_refetch_vis_cache_label")->setTextArg("[SIZE]", std::string("----")); + getChild<LLUICtrl>("total_time_refetch_vis_cache_label")->setTextArg("[PIXEL]", std::string("----")); + } + else + { + getChild<LLUICtrl>("total_time_refetch_vis_cache_label")->setTextArg("[TIME]", llformat("%.3f", mDebugger->getRefetchVisCacheTime())); + getChild<LLUICtrl>("total_time_refetch_vis_cache_label")->setTextArg("[SIZE]", llformat("%d", mDebugger->getRefetchedData() >> 10)); + getChild<LLUICtrl>("total_time_refetch_vis_cache_label")->setTextArg("[PIXEL]", llformat("%.3f", mDebugger->getRefetchedPixels() / 1000000.f)); + } + + //total time on refetching visible textures from http + if(mDebugger->getRefetchVisHTTPTime() < 0.f) + { + getChild<LLUICtrl>("total_time_refetch_vis_http_label")->setTextArg("[TIME]", std::string("----")); + getChild<LLUICtrl>("total_time_refetch_vis_http_label")->setTextArg("[SIZE]", std::string("----")); + getChild<LLUICtrl>("total_time_refetch_vis_http_label")->setTextArg("[PIXEL]", std::string("----")); + } + else + { + getChild<LLUICtrl>("total_time_refetch_vis_http_label")->setTextArg("[TIME]", llformat("%.3f", mDebugger->getRefetchVisHTTPTime())); + getChild<LLUICtrl>("total_time_refetch_vis_http_label")->setTextArg("[SIZE]", llformat("%d", mDebugger->getRefetchedData() >> 10)); + getChild<LLUICtrl>("total_time_refetch_vis_http_label")->setTextArg("[PIXEL]", llformat("%.3f", mDebugger->getRefetchedPixels() / 1000000.f)); + } + + LLFloater::draw(); +} diff --git a/indra/newview/llfloatertexturefetchdebugger.h b/indra/newview/llfloatertexturefetchdebugger.h new file mode 100644 index 0000000000..33012c6a3d --- /dev/null +++ b/indra/newview/llfloatertexturefetchdebugger.h @@ -0,0 +1,71 @@ +/** + * @file llfloatertexturefetchdebugger.h + * @brief texture fetching debugger window, debug use only + * + * $LicenseInfo:firstyear=2004&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_FLOATER_TEXTURE_FETCH_DEBUGGER__H +#define LL_FLOATER_TEXTURE_FETCH_DEBUGGER__H + +#include "llfloater.h" +class LLTextureFetchDebugger; + +class LLFloaterTextureFetchDebugger : public LLFloater +{ + friend class LLFloaterReg; +public: + /// initialize all the callbacks for the menu + + virtual BOOL postBuild() ; + virtual void draw() ; + + void onChangeTexelPixelRatio(); + + void onClickStart(); + void onClickClear(); + void onClickClose(); + + void onClickCacheRead(); + void onClickCacheWrite(); + void onClickHTTPLoad(); + void onClickDecode(); + void onClickGLTexture(); + + void onClickRefetchVisCache(); + void onClickRefetchVisHTTP(); +public: + void idle() ; + +private: + LLFloaterTextureFetchDebugger(const LLSD& key); + virtual ~LLFloaterTextureFetchDebugger(); + + void updateButtons(); + void disableButtons(); + +private: + LLTextureFetchDebugger* mDebugger; + std::map<std::string, bool> mButtonStateMap; +}; + +#endif // LL_FLOATER_TEXTURE_FETCH_DEBUGGER__H diff --git a/indra/newview/llgiveinventory.cpp b/indra/newview/llgiveinventory.cpp index 30858871ec..72bea8db10 100644 --- a/indra/newview/llgiveinventory.cpp +++ b/indra/newview/llgiveinventory.cpp @@ -220,17 +220,25 @@ bool LLGiveInventory::doGiveInventoryItem(const LLUUID& to_agent, return res; } -void LLGiveInventory::doGiveInventoryCategory(const LLUUID& to_agent, +bool LLGiveInventory::doGiveInventoryCategory(const LLUUID& to_agent, const LLInventoryCategory* cat, - const LLUUID& im_session_id) + const LLUUID& im_session_id, + const std::string& notification_name) { - if (!cat) return; + if (!cat) + { + return false; + } llinfos << "LLGiveInventory::giveInventoryCategory() - " << cat->getUUID() << llendl; - if (!isAgentAvatarValid()) return; + if (!isAgentAvatarValid()) + { + return false; + } + bool give_successful = true; // Test out how many items are being given. LLViewerInventoryCategory::cat_array_t cats; LLViewerInventoryItem::item_array_t items; @@ -253,24 +261,24 @@ void LLGiveInventory::doGiveInventoryCategory(const LLUUID& to_agent, if (!complete) { LLNotificationsUtil::add("IncompleteInventory"); - return; + give_successful = false; } count = items.count() + cats.count(); if (count > MAX_ITEMS) { LLNotificationsUtil::add("TooManyItems"); - return; + give_successful = false; } else if (count == 0) { LLNotificationsUtil::add("NoItems"); - return; + give_successful = false; } - else + else if (give_successful) { if (0 == giveable.countNoCopy()) { - LLGiveInventory::commitGiveInventoryCategory(to_agent, cat, im_session_id); + give_successful = LLGiveInventory::commitGiveInventoryCategory(to_agent, cat, im_session_id); } else { @@ -279,9 +287,16 @@ void LLGiveInventory::doGiveInventoryCategory(const LLUUID& to_agent, LLSD payload; payload["agent_id"] = to_agent; payload["folder_id"] = cat->getUUID(); + if (!notification_name.empty()) + { + payload["success_notification"] = notification_name; + } LLNotificationsUtil::add("CannotCopyCountItems", args, payload, &LLGiveInventory::handleCopyProtectedCategory); + give_successful = false; } } + + return give_successful; } ////////////////////////////////////////////////////////////////////////// @@ -325,6 +340,7 @@ bool LLGiveInventory::handleCopyProtectedItem(const LLSD& notification, const LL S32 option = LLNotificationsUtil::getSelectedOption(notification, response); LLSD itmes = notification["payload"]["items"]; LLInventoryItem* item = NULL; + bool give_successful = true; switch(option) { case 0: // "Yes" @@ -343,15 +359,21 @@ bool LLGiveInventory::handleCopyProtectedItem(const LLSD& notification, const LL else { LLNotificationsUtil::add("CannotGiveItem"); + give_successful = false; } } + if (give_successful && notification["payload"]["success_notification"].isDefined()) + { + LLNotificationsUtil::add(notification["payload"]["success_notification"].asString()); + } break; default: // no, cancel, whatever, who cares, not yes. LLNotificationsUtil::add("TransactionCancelled"); + give_successful = false; break; } - return false; + return give_successful; } // static @@ -408,13 +430,14 @@ bool LLGiveInventory::handleCopyProtectedCategory(const LLSD& notification, cons { S32 option = LLNotificationsUtil::getSelectedOption(notification, response); LLInventoryCategory* cat = NULL; + bool give_successful = true; switch(option) { case 0: // "Yes" cat = gInventory.getCategory(notification["payload"]["folder_id"].asUUID()); if (cat) { - LLGiveInventory::commitGiveInventoryCategory(notification["payload"]["agent_id"].asUUID(), + give_successful = LLGiveInventory::commitGiveInventoryCategory(notification["payload"]["agent_id"].asUUID(), cat); LLViewerInventoryCategory::cat_array_t cats; LLViewerInventoryItem::item_array_t items; @@ -430,27 +453,37 @@ bool LLGiveInventory::handleCopyProtectedCategory(const LLSD& notification, cons gInventory.deleteObject(items.get(i)->getUUID()); } gInventory.notifyObservers(); + + if (give_successful && notification["payload"]["success_notification"].isDefined()) + { + LLNotificationsUtil::add(notification["payload"]["success_notification"].asString()); + } } else { LLNotificationsUtil::add("CannotGiveCategory"); + give_successful = false; } break; default: // no, cancel, whatever, who cares, not yes. LLNotificationsUtil::add("TransactionCancelled"); + give_successful = false; break; } - return false; + return give_successful; } // static -void LLGiveInventory::commitGiveInventoryCategory(const LLUUID& to_agent, +bool LLGiveInventory::commitGiveInventoryCategory(const LLUUID& to_agent, const LLInventoryCategory* cat, const LLUUID& im_session_id) { - if (!cat) return; + if (!cat) + { + return false; + } llinfos << "LLGiveInventory::commitGiveInventoryCategory() - " << cat->getUUID() << llendl; @@ -467,6 +500,7 @@ void LLGiveInventory::commitGiveInventoryCategory(const LLUUID& to_agent, LLInventoryModel::EXCLUDE_TRASH, giveable); + bool give_successful = true; // MAX ITEMS is based on (sizeof(uuid)+2) * count must be < // MTUBYTES or 18 * count < 1200 => count < 1200/18 => // 66. I've cut it down a bit from there to give some pad. @@ -474,12 +508,12 @@ void LLGiveInventory::commitGiveInventoryCategory(const LLUUID& to_agent, if (count > MAX_ITEMS) { LLNotificationsUtil::add("TooManyItems"); - return; + give_successful = false; } else if (count == 0) { LLNotificationsUtil::add("NoItems"); - return; + give_successful = false; } else { @@ -545,6 +579,8 @@ void LLGiveInventory::commitGiveInventoryCategory(const LLUUID& to_agent, logInventoryOffer(to_agent, im_session_id); } + + return give_successful; } // EOF diff --git a/indra/newview/llgiveinventory.h b/indra/newview/llgiveinventory.h index e1e221c75b..85bc1ed49c 100644 --- a/indra/newview/llgiveinventory.h +++ b/indra/newview/llgiveinventory.h @@ -62,9 +62,10 @@ public: /** * Gives passed inventory category to specified avatar in specified session. */ - static void doGiveInventoryCategory(const LLUUID& to_agent, + static bool doGiveInventoryCategory(const LLUUID& to_agent, const LLInventoryCategory* item, - const LLUUID &session_id = LLUUID::null); + const LLUUID &session_id = LLUUID::null, + const std::string& notification = std::string()); // give inventory item functionality static bool handleCopyProtectedItem(const LLSD& notification, const LLSD& response); @@ -85,7 +86,7 @@ private: // give inventory category functionality static bool handleCopyProtectedCategory(const LLSD& notification, const LLSD& response); - static void commitGiveInventoryCategory(const LLUUID& to_agent, + static bool commitGiveInventoryCategory(const LLUUID& to_agent, const LLInventoryCategory* cat, const LLUUID &im_session_id = LLUUID::null); diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 22ce3cd42b..5e0e0973fc 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -58,6 +58,7 @@ #include "llspeakers.h" #include "llviewerchat.h" #include "llnotificationmanager.h" +#include "llautoreplace.h" LLIMFloater::LLIMFloater(const LLUUID& session_id) : LLIMConversation(session_id), @@ -78,7 +79,7 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id) { mIsNearbyChat = false; initIMSession(session_id); - + setOverlapsScreenChannel(true); LLTransientFloaterMgr::getInstance()->addControlView(LLTransientFloaterMgr::IM, this); @@ -89,7 +90,7 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id) void LLIMFloater::onFocusLost() { LLIMModel::getInstance()->resetActiveSessionID(); - + LLChicletBar::getInstance()->getChicletPanel()->setChicletToggleState(mSessionID, false); } @@ -109,11 +110,11 @@ void LLIMFloater::onFocusReceived() void LLIMFloater::refresh() { if (mMeTyping) - { +{ // Time out if user hasn't typed for a while. if (mTypingTimeoutTimer.getElapsedTimeF32() > LLAgent::TYPING_TIMEOUT_SECS) { - setTyping(false); + setTyping(false); } } } @@ -128,7 +129,7 @@ void LLIMFloater::onClickCloseBtn() { llwarns << "Empty session." << llendl; return; - } +} bool is_call_with_chat = session->isGroupSessionType() || session->isAdHocSessionType() || session->isP2PSessionType(); @@ -194,33 +195,33 @@ void LLIMFloater::sendMsg() || (mDialog != IM_NOTHING_SPECIAL) || !mOtherParticipantUUID.isNull()) { - if (mInputEditor) - { + if (mInputEditor) + { LLWString text = mInputEditor->getWText(); LLWStringUtil::trim(text); LLWStringUtil::replaceChar(text,182,'\n'); // Convert paragraph symbols back into newlines. - if(!text.empty()) + if(!text.empty()) + { + // Truncate and convert to UTF8 for transport + std::string utf8_text = wstring_to_utf8str(text); + utf8_text = utf8str_truncate(utf8_text, MAX_MSG_BUF_SIZE - 1); + + if (mSessionInitialized) { - // Truncate and convert to UTF8 for transport - std::string utf8_text = wstring_to_utf8str(text); - utf8_text = utf8str_truncate(utf8_text, MAX_MSG_BUF_SIZE - 1); - - if (mSessionInitialized) - { LLIMModel::sendMessage(utf8_text, mSessionID, mOtherParticipantUUID, mDialog); - } - else - { - //queue up the message to send once the session is initialized - mQueuedMsgsForInit.append(utf8_text); - } + } + else + { + //queue up the message to send once the session is initialized + mQueuedMsgsForInit.append(utf8_text); + } - mInputEditor->setText(LLStringUtil::null); + mInputEditor->setText(LLStringUtil::null); - updateMessages(); - } + updateMessages(); } } +} else { llinfos << "Cannot send IM to everyone unless you're a god." << llendl; @@ -248,7 +249,7 @@ void LLIMFloater::initIMSession(const LLUUID& session_id) mSession = LLIMModel::getInstance()->findIMSession(mSessionID); if (mSession) - { +{ mIsP2PChat = mSession->isP2PSessionType(); mSessionInitialized = mSession->mSessionInitialized; @@ -315,6 +316,11 @@ BOOL LLIMFloater::postBuild() mInputEditor = getChild<LLChatEntry>("chat_editor"); mInputEditor->setMaxTextLength(1023); // enable line history support for instant message bar + // XXX stinson TODO : resolve merge conflict +#if 0 + // *TODO Establish LineEditor with autoreplace callback + mInputEditor->setAutoreplaceCallback(boost::bind(&LLAutoReplace::autoreplaceCallback, LLAutoReplace::getInstance(), _1, _2)); +#endif LLFontGL* font = LLViewerChat::getChatFont(); mInputEditor->setFont(font); @@ -354,20 +360,20 @@ BOOL LLIMFloater::postBuild() } void LLIMFloater::onAddButtonClicked() -{ + { LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLIMFloater::addSessionParticipants, this, _1), TRUE, TRUE); if (!picker) { return; - } + } // Need to disable 'ok' button when selected users are already in conversation. picker->setOkBtnEnableCb(boost::bind(&LLIMFloater::canAddSelectedToChat, this, _1)); LLFloater* root_floater = gFloaterView->getParentFloater(this); if (root_floater) - { + { root_floater->addDependentFloater(picker); - } + } } bool LLIMFloater::canAddSelectedToChat(const uuid_vec_t& uuids) @@ -402,8 +408,8 @@ bool LLIMFloater::canAddSelectedToChat(const uuid_vec_t& uuids) if (speaker_mgr) { speaker_mgr->getSpeakerList(&speaker_list, true); - } - + } + for (uuid_vec_t::const_iterator id = uuids.begin(); id != uuids.end(); ++id) { @@ -423,7 +429,7 @@ bool LLIMFloater::canAddSelectedToChat(const uuid_vec_t& uuids) } void LLIMFloater::addSessionParticipants(const uuid_vec_t& uuids) -{ + { if (mIsP2PChat) { mStartConferenceInSameFloater = true; @@ -447,12 +453,12 @@ void LLIMFloater::addSessionParticipants(const uuid_vec_t& uuids) if (is_voice_call) { LLAvatarActions::startAdhocCall(temp_ids, mSessionID); - } - else - { + } + else + { LLAvatarActions::startConference(temp_ids, mSessionID); - } } +} else { inviteToSession(uuids); @@ -549,7 +555,7 @@ void LLIMFloater::onParticipantsListChanged(LLUICtrl* ctrl) if (!avatar_list) { return; - } + } bool all_names_resolved = true; std::vector<LLSD> participants_uuids; @@ -558,7 +564,7 @@ void LLIMFloater::onParticipantsListChanged(LLUICtrl* ctrl) // Check whether we have all participants names in LLAvatarNameCache for (std::vector<LLSD>::const_iterator it = participants_uuids.begin(); it != participants_uuids.end(); ++it) - { +{ const LLUUID& id = it->asUUID(); LLAvatarName av_name; if (!LLAvatarNameCache::get(id, &av_name)) @@ -571,7 +577,7 @@ void LLIMFloater::onParticipantsListChanged(LLUICtrl* ctrl) boost::bind(&LLIMFloater::onParticipantsListChanged, this, avatar_list)); break; } - } +} if (all_names_resolved) { @@ -582,20 +588,20 @@ void LLIMFloater::onParticipantsListChanged(LLUICtrl* ctrl) const LLUUID& id = it->asUUID(); LLAvatarName av_name; if (LLAvatarNameCache::get(id, &av_name)) - { +{ avatar_names.push_back(av_name); } - } +} // We should check whether the vector is not empty to pass the assertion // that avatar_names.size() > 0 in LLAvatarActions::buildResidentsString. if (!avatar_names.empty()) - { +{ std::string ui_title; LLAvatarActions::buildResidentsString(avatar_names, ui_title); updateSessionName(ui_title, ui_title); } - } +} } //static @@ -644,7 +650,7 @@ LLIMFloater* LLIMFloater::show(const LLUUID& session_id) floater_container->addFloater(floater, TRUE, i_pt); } } - + floater->openFloater(floater->getKey()); } else @@ -786,10 +792,10 @@ BOOL LLIMFloater::getVisible() } else { - // getVisible() returns TRUE when Tabbed IM window is minimized. + // getVisible() returns TRUE when Tabbed IM window is minimized. visible = is_active && !im_container->isMinimized() && im_container->getVisible(); - } + } } else { @@ -839,21 +845,21 @@ void LLIMFloater::sessionInitReplyReceived(const LLUUID& im_session_id) } initIMFloater(); - + //*TODO here we should remove "starting session..." warning message if we added it in postBuild() (IB) //need to send delayed messaged collected while waiting for session initialization if (mQueuedMsgsForInit.size()) { - LLSD::array_iterator iter; - for ( iter = mQueuedMsgsForInit.beginArray(); + LLSD::array_iterator iter; + for ( iter = mQueuedMsgsForInit.beginArray(); iter != mQueuedMsgsForInit.endArray(); ++iter) - { - LLIMModel::sendMessage(iter->asString(), mSessionID, - mOtherParticipantUUID, mDialog); - } + { + LLIMModel::sendMessage(iter->asString(), mSessionID, + mOtherParticipantUUID, mDialog); } } +} void LLIMFloater::appendMessage(const LLChat& chat, const LLSD &args) { @@ -940,16 +946,16 @@ void LLIMFloater::updateMessages() if (chat.mNotifId.notNull() && LLNotificationsUtil::find(chat.mNotifId) != NULL) { if (++iter == iter_end) - { - break; - } - else - { - mLastMessageIndex++; - } - } - } - } + { + break; + } + else + { + mLastMessageIndex++; + } + } + } + } } void LLIMFloater::reloadMessages() @@ -986,22 +992,22 @@ void LLIMFloater::onInputEditorFocusLost(LLFocusableElement* caller, void* userd // static void LLIMFloater::onInputEditorKeystroke(LLTextEditor* caller, void* userdata) { - LLIMFloater* self = (LLIMFloater*) userdata; + LLIMFloater* self = (LLIMFloater*)userdata; std::string text = self->mInputEditor->getText(); - // Deleting all text counts as stopping typing. + // Deleting all text counts as stopping typing. self->setTyping(!text.empty()); -} + } void LLIMFloater::setTyping(bool typing) { - if (typing) + if ( typing ) { // Started or proceeded typing, reset the typing timeout timer mTypingTimeoutTimer.reset(); } - if (mMeTyping != typing) + if ( mMeTyping != typing ) { // Typing state is changed mMeTyping = typing; @@ -1013,7 +1019,7 @@ void LLIMFloater::setTyping(bool typing) // Don't want to send typing indicators to multiple people, potentially too // much network traffic. Only send in person-to-person IMs. - if (mShouldSendTypingState && mDialog == IM_NOTHING_SPECIAL) + if ( mShouldSendTypingState && mDialog == IM_NOTHING_SPECIAL ) { // Still typing, send 'start typing' notification or // send 'stop typing' notification immediately @@ -1021,24 +1027,24 @@ void LLIMFloater::setTyping(bool typing) { LLIMModel::instance().sendTypingState(mSessionID, mOtherParticipantUUID, mMeTyping); - mShouldSendTypingState = false; + mShouldSendTypingState = false; + } } - } if (!mIsNearbyChat) - { - LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID); - if (speaker_mgr) { - speaker_mgr->setSpeakerTyping(gAgent.getID(), FALSE); + LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID); + if (speaker_mgr) + { + speaker_mgr->setSpeakerTyping(gAgent.getID(), FALSE); } - } +} } void LLIMFloater::processIMTyping(const LLIMInfo* im_info, BOOL typing) { - if (typing) + if ( typing ) { // other user started typing addTypingIndicator(im_info); @@ -1061,7 +1067,7 @@ void LLIMFloater::processAgentListUpdates(const LLSD& body) if (agent_info.has("mutes")) { - BOOL moderator_muted_text = agent_info["mutes"]["text"].asBoolean(); + BOOL moderator_muted_text = agent_info["mutes"]["text"].asBoolean(); mInputEditor->setEnabled(!moderator_muted_text); std::string label; if (moderator_muted_text) @@ -1080,8 +1086,8 @@ void LLIMFloater::processAgentListUpdates(const LLSD& body) void LLIMFloater::processSessionUpdate(const LLSD& session_update) { // *TODO : verify following code when moderated mode will be implemented - if (false && session_update.has("moderated_mode") && - session_update["moderated_mode"].has("voice")) + if ( false && session_update.has("moderated_mode") && + session_update["moderated_mode"].has("voice") ) { BOOL voice_moderated = session_update["moderated_mode"]["voice"]; const std::string session_label = LLIMModel::instance().getName(mSessionID); @@ -1107,24 +1113,24 @@ BOOL LLIMFloater::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, void* cargo_data, EAcceptance* accept, - std::string& tooltip_msg) + std::string& tooltip_msg) { if (cargo_type == DAD_PERSON) { if (dropPerson(static_cast<LLUUID*>(cargo_data), drop)) - { + { *accept = ACCEPT_YES_MULTI; - } + } else - { - *accept = ACCEPT_NO; + { + *accept = ACCEPT_NO; + } } - } else if (mDialog == IM_NOTHING_SPECIAL) - { + { LLToolDragAndDrop::handleGiveDragAndDrop(mOtherParticipantUUID, mSessionID, drop, cargo_type, cargo_data, accept); - } + } return TRUE; } @@ -1134,27 +1140,27 @@ bool LLIMFloater::dropPerson(LLUUID* person_id, bool drop) bool res = person_id && person_id->notNull(); if(res) { - uuid_vec_t ids; + uuid_vec_t ids; ids.push_back(*person_id); res = canAddSelectedToChat(ids); if(res && drop) - { + { addSessionParticipants(ids); - } } +} return res; -} + } BOOL LLIMFloater::isInviteAllowed() const { - return ((IM_SESSION_CONFERENCE_START == mDialog) + return ( (IM_SESSION_CONFERENCE_START == mDialog) || (IM_SESSION_INVITE == mDialog && !gAgent.isInGroup(mSessionID)) || mIsP2PChat); } -class LLSessionInviteResponder: public LLHTTPClient::Responder +class LLSessionInviteResponder : public LLHTTPClient::Responder { public: LLSessionInviteResponder(const LLUUID& session_id) @@ -1179,37 +1185,37 @@ BOOL LLIMFloater::inviteToSession(const uuid_vec_t& ids) if (is_region_exist) { - S32 count = ids.size(); - - if (isInviteAllowed() && (count > 0)) - { - llinfos << "LLIMFloater::inviteToSession() - inviting participants" << llendl; + S32 count = ids.size(); - std::string url = region->getCapability("ChatSessionRequest"); + if( isInviteAllowed() && (count > 0) ) + { + llinfos << "LLIMFloater::inviteToSession() - inviting participants" << llendl; - LLSD data; + std::string url = region->getCapability("ChatSessionRequest"); - data["params"] = LLSD::emptyArray(); - for (int i = 0; i < count; i++) - { - data["params"].append(ids[i]); - } + LLSD data; - data["method"] = "invite"; - data["session-id"] = mSessionID; - LLHTTPClient::post( - url, - data, - new LLSessionInviteResponder(mSessionID)); - } - else + data["params"] = LLSD::emptyArray(); + for (int i = 0; i < count; i++) { - llinfos << "LLIMFloater::inviteToSession -" - << " no need to invite agents for " - << mDialog << llendl; - // successful add, because everyone that needed to get added - // was added. + data["params"].append(ids[i]); } + + data["method"] = "invite"; + data["session-id"] = mSessionID; + LLHTTPClient::post( + url, + data, + new LLSessionInviteResponder(mSessionID)); + } + else + { + llinfos << "LLIMFloater::inviteToSession -" + << " no need to invite agents for " + << mDialog << llendl; + // successful add, because everyone that needed to get added + // was added. + } } return is_region_exist; @@ -1218,17 +1224,17 @@ BOOL LLIMFloater::inviteToSession(const uuid_vec_t& ids) void LLIMFloater::addTypingIndicator(const LLIMInfo* im_info) { // We may have lost a "stop-typing" packet, don't add it twice - if (im_info && !mOtherTyping) + if ( im_info && !mOtherTyping ) { mOtherTyping = true; // Save and set new title mSavedTitle = getTitle(); - setTitle(mTypingStart); + setTitle (mTypingStart); // Update speaker LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID); - if (speaker_mgr) + if ( speaker_mgr ) { speaker_mgr->setSpeakerTyping(im_info->mFromID, TRUE); } @@ -1237,18 +1243,18 @@ void LLIMFloater::addTypingIndicator(const LLIMInfo* im_info) void LLIMFloater::removeTypingIndicator(const LLIMInfo* im_info) { - if (mOtherTyping) + if ( mOtherTyping ) { mOtherTyping = false; // Revert the title to saved one setTitle(mSavedTitle); - if (im_info) + if ( im_info ) { // Update speaker LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID); - if (speaker_mgr) + if ( speaker_mgr ) { speaker_mgr->setSpeakerTyping(im_info->mFromID, FALSE); } @@ -1318,19 +1324,19 @@ void LLIMFloater::onIMChicletCreated( const LLUUID& session_id ) LLIMFloater::addToHost(session_id); } void LLIMFloater::addToHost(const LLUUID& session_id) -{ - if (LLIMConversation::isChatMultiTab()) { + if (LLIMConversation::isChatMultiTab()) +{ LLIMFloaterContainer* im_box = LLIMFloaterContainer::findInstance(); if (!im_box) - { + { im_box = LLIMFloaterContainer::getInstance(); - } + } if (im_box && !LLIMFloater::findInstance(session_id)) - { + { LLIMFloater* new_tab = LLIMFloater::getInstance(session_id); im_box->addFloater(new_tab, FALSE, LLTabContainer::END); - } + } } } diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index c19683b1c2..386afab77f 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -180,6 +180,7 @@ void LLIMFloaterContainer::addFloater(LLFloater* floaterp, void LLIMFloaterContainer::onCloseFloater(LLUUID& id) { mSessions.erase(id); + setFocus(TRUE); } // virtual diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index cdbb7c7cca..ae08b7f8b9 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -3265,7 +3265,6 @@ public: //just like a normal IM //this is just replicated code from process_improved_im //and should really go in it's own function -jwolk - LLChat chat; std::string message = message_params["message"].asString(); std::string name = message_params["from_name"].asString(); @@ -3283,14 +3282,7 @@ public: name, LLMute::flagTextChat); - BOOL is_linden = LLMuteList::getInstance()->isLinden(name); - std::string separator_string(": "); - - chat.mMuted = is_muted && !is_linden; - chat.mFromID = from_id; - chat.mFromName = name; - - if (!is_linden && is_busy) + if (is_busy || is_muted) { return; } diff --git a/indra/newview/llinspectobject.cpp b/indra/newview/llinspectobject.cpp index acc139c569..a7b93b8030 100644 --- a/indra/newview/llinspectobject.cpp +++ b/indra/newview/llinspectobject.cpp @@ -111,6 +111,7 @@ private: private: LLUUID mObjectID; + LLUUID mPreviousObjectID; S32 mObjectFace; viewer_media_t mMediaImpl; LLMediaEntry* mMediaEntry; @@ -249,6 +250,7 @@ void LLInspectObject::onClose(bool app_quitting) { // Release selection to deselect mObjectSelection = NULL; + mPreviousObjectID = mObjectID; getChild<LLMenuButton>("gear_btn")->hideMenu(); } @@ -266,6 +268,13 @@ void LLInspectObject::update() LLSelectNode* nodep = selection->getFirstRootNode(); if (!nodep) return; + // If we don't have fresh object info yet and it's the object we inspected last time, + // keep showing the previously retrieved data until we get the update. + if (!nodep->mValid && nodep->getObject()->getID() == mPreviousObjectID) + { + return; + } + updateButtons(nodep); updateName(nodep); updateDescription(nodep); diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp index 3e14faa55e..b4be927b09 100644 --- a/indra/newview/llinventoryfilter.cpp +++ b/indra/newview/llinventoryfilter.cpp @@ -635,7 +635,7 @@ void LLInventoryFilter::setHoursAgo(U32 hours) bool are_date_limits_valid = mFilterOps.mMinDate == time_min() && mFilterOps.mMaxDate == time_max(); bool is_increasing = hours > mFilterOps.mHoursAgo; - bool is_increasing_from_zero = is_increasing && !mFilterOps.mHoursAgo; + bool is_increasing_from_zero = is_increasing && !mFilterOps.mHoursAgo && !isSinceLogoff(); // *NOTE: need to cache last filter time, in case filter goes stale BOOL less_restrictive = (are_date_limits_valid && ((is_increasing && mFilterOps.mHoursAgo)) || !hours); diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index fe65b87afd..5cb7f53bfa 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -822,6 +822,11 @@ U32 LLInventoryModel::updateItem(const LLViewerInventoryItem* item) { parent_id = findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND); new_item->setParent(parent_id); + LLInventoryModel::update_list_t update; + LLInventoryModel::LLCategoryUpdate new_folder(parent_id, 1); + update.push_back(new_folder); + accountForUpdate(update); + } item_array_t* item_array = get_ptr_in_map(mParentChildItemTree, parent_id); if(item_array) @@ -1778,6 +1783,7 @@ bool LLInventoryModel::loadSkeleton( update_map_t child_counts; cat_array_t categories; item_array_t items; + item_array_t possible_broken_links; cat_set_t invalid_categories; // Used to mark categories that weren't successfully loaded. std::string owner_id_str; owner_id.toString(owner_id_str); @@ -1826,7 +1832,7 @@ bool LLInventoryModel::loadSkeleton( LLViewerInventoryCategory* tcat = *cit; // we can safely ignore anything loaded from file, but - // not sent down in the skeleton. + // not sent down in the skeleton. Must have been removed from inventory. if(cit == not_cached) { continue; @@ -1864,6 +1870,8 @@ bool LLInventoryModel::loadSkeleton( // Add all the items loaded which are parented to a // category with a correctly cached parent S32 bad_link_count = 0; + S32 good_link_count = 0; + S32 recovered_link_count = 0; cat_map_t::iterator unparented = mCategoryMap.end(); for(item_array_t::const_iterator item_iter = items.begin(); item_iter != items.end(); @@ -1880,26 +1888,56 @@ bool LLInventoryModel::loadSkeleton( // This can happen if the linked object's baseobj is removed from the cache but the linked object is still in the cache. if (item->getIsBrokenLink()) { - bad_link_count++; + //bad_link_count++; lldebugs << "Attempted to add cached link item without baseobj present ( name: " << item->getName() << " itemID: " << item->getUUID() << " assetID: " << item->getAssetUUID() << " ). Ignoring and invalidating " << cat->getName() << " . " << llendl; - invalid_categories.insert(cit->second); + possible_broken_links.push_back(item); continue; } + else if (item->getIsLinkType()) + { + good_link_count++; + } addItem(item); cached_item_count += 1; ++child_counts[cat->getUUID()]; } } } - if (bad_link_count > 0) + if (possible_broken_links.size() > 0) { - llinfos << "Attempted to add " << bad_link_count - << " cached link items without baseobj present. " - << "The corresponding categories were invalidated." << llendl; + for(item_array_t::const_iterator item_iter = possible_broken_links.begin(); + item_iter != possible_broken_links.end(); + ++item_iter) + { + LLViewerInventoryItem *item = (*item_iter).get(); + const cat_map_t::iterator cit = mCategoryMap.find(item->getParentUUID()); + const LLViewerInventoryCategory* cat = cit->second.get(); + if (item->getIsBrokenLink()) + { + bad_link_count++; + invalid_categories.insert(cit->second); + //llinfos << "link still broken: " << item->getName() << " in folder " << cat->getName() << llendl; + } + else + { + // was marked as broken because of loading order, its actually fine to load + addItem(item); + cached_item_count += 1; + ++child_counts[cat->getUUID()]; + recovered_link_count++; + } + } + + llinfos << "Attempted to add " << bad_link_count + << " cached link items without baseobj present. " + << good_link_count << " link items were successfully added. " + << recovered_link_count << " links added in recovery. " + << "The corresponding categories were invalidated." << llendl; } + } else { @@ -2797,7 +2835,7 @@ void LLInventoryModel::processBulkUpdateInventory(LLMessageSystem* msg, void**) { LLPointer<LLViewerInventoryItem> titem = new LLViewerInventoryItem; titem->unpackMessage(msg, _PREHASH_ItemData, i); - llinfos << "unpaked item '" << titem->getName() << "' in " + llinfos << "unpacked item '" << titem->getName() << "' in " << titem->getParentUUID() << llendl; U32 callback_id; msg->getU32Fast(_PREHASH_ItemData, _PREHASH_CallbackID, callback_id); diff --git a/indra/newview/llmaniptranslate.cpp b/indra/newview/llmaniptranslate.cpp index 3a88fbd96d..f8088d04b4 100644 --- a/indra/newview/llmaniptranslate.cpp +++ b/indra/newview/llmaniptranslate.cpp @@ -60,6 +60,7 @@ #include "llworld.h" #include "llui.h" #include "pipeline.h" +#include "llviewershadermgr.h" const S32 NUM_AXES = 3; const S32 MOUSE_DRAG_SLOP = 2; // pixels @@ -1580,7 +1581,11 @@ void LLManipTranslate::renderSnapGuides() LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE, GL_GREATER); LLGLEnable stipple(GL_LINE_STIPPLE); gGL.flush(); - glLineStipple(1, 0x3333); + + if (!LLGLSLShader::sNoFixedFunction) + { + glLineStipple(1, 0x3333); + } switch (mManipPart) { @@ -1645,17 +1650,28 @@ void LLManipTranslate::highlightIntersection(LLVector3 normal, LLQuaternion grid_rotation, LLColor4 inner_color) { - if (!gSavedSettings.getBOOL("GridCrossSections")) + if (!gSavedSettings.getBOOL("GridCrossSections") || !LLGLSLShader::sNoFixedFunction) { return; } + + LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; + + U32 types[] = { LLRenderPass::PASS_SIMPLE, LLRenderPass::PASS_ALPHA, LLRenderPass::PASS_FULLBRIGHT, LLRenderPass::PASS_SHINY }; U32 num_types = LL_ARRAY_SIZE(types); GLuint stencil_mask = 0xFFFFFFFF; //stencil in volumes + gGL.flush(); + + if (shader) + { + gClipProgram.bind(); + } + { glStencilMask(stencil_mask); glClearStencil(1); @@ -1666,6 +1682,7 @@ void LLManipTranslate::highlightIntersection(LLVector3 normal, glStencilFunc(GL_ALWAYS, 0, stencil_mask); gGL.setColorMask(false, false); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gGL.diffuseColor4f(1,1,1,1); //setup clip plane @@ -1675,10 +1692,12 @@ void LLManipTranslate::highlightIntersection(LLVector3 normal, normal = -normal; } F32 d = -(selection_center * normal); - F64 plane[] = { normal.mV[0], normal.mV[1], normal.mV[2], d }; - LLGLEnable clip(GL_CLIP_PLANE0); - glClipPlane(GL_CLIP_PLANE0, plane); + glh::vec4f plane(normal.mV[0], normal.mV[1], normal.mV[2], d ); + + gGL.getModelviewMatrix().inverse().mult_vec_matrix(plane); + gClipProgram.uniform4fv("clip_plane", 1, plane.v); + BOOL particles = gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES); BOOL clouds = gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_CLOUDS); @@ -1729,6 +1748,11 @@ void LLManipTranslate::highlightIntersection(LLVector3 normal, F32 sz = mGridSizeMeters; F32 tiles = sz; + if (shader) + { + shader->bind(); + } + //draw volume/plane intersections { gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); diff --git a/indra/newview/llmarketplacefunctions.cpp b/indra/newview/llmarketplacefunctions.cpp index 93dd82957f..51df868faa 100644 --- a/indra/newview/llmarketplacefunctions.cpp +++ b/indra/newview/llmarketplacefunctions.cpp @@ -336,13 +336,19 @@ namespace LLMarketplaceImport // Interface class // +static const F32 MARKET_IMPORTER_UPDATE_FREQUENCY = 1.0f; //static void LLMarketplaceInventoryImporter::update() { if (instanceExists()) { - LLMarketplaceInventoryImporter::instance().updateImport(); + static LLTimer update_timer; + if (update_timer.hasExpired()) + { + LLMarketplaceInventoryImporter::instance().updateImport(); + update_timer.setTimerExpirySec(MARKET_IMPORTER_UPDATE_FREQUENCY); + } } } diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index f461c7e46f..bc7f522848 100755 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -1620,7 +1620,7 @@ void LLMeshUploadThread::doWholeModelUpload() mCurlRequest->process(); //sleep for 10ms to prevent eating a whole core apr_sleep(10000); - } while (mCurlRequest->getQueued() > 0); + } while (!LLAppViewer::isQuitting() && mCurlRequest->getQueued() > 0); } delete mCurlRequest; @@ -1659,7 +1659,7 @@ void LLMeshUploadThread::requestWholeModelFee() mCurlRequest->process(); //sleep for 10ms to prevent eating a whole core apr_sleep(10000); - } while (mCurlRequest->getQueued() > 0); + } while (!LLApp::isQuitting() && mCurlRequest->getQueued() > 0); delete mCurlRequest; mCurlRequest = NULL; diff --git a/indra/newview/llnavigationbar.cpp b/indra/newview/llnavigationbar.cpp index 2a08cb1845..95caa2731a 100644 --- a/indra/newview/llnavigationbar.cpp +++ b/indra/newview/llnavigationbar.cpp @@ -267,7 +267,6 @@ LLNavigationBar::LLNavigationBar() mBtnForward(NULL), mBtnHome(NULL), mCmbLocation(NULL), - mPurgeTPHistoryItems(false), mSaveToLocationHistory(false) { buildFromFile( "panel_navigation_bar.xml"); @@ -338,12 +337,6 @@ void LLNavigationBar::setVisible(BOOL visible) void LLNavigationBar::draw() { - if(mPurgeTPHistoryItems) - { - LLTeleportHistory::getInstance()->purgeItems(); - mPurgeTPHistoryItems = false; - } - if (isBackgroundVisible()) { static LLUICachedControl<S32> drop_shadow_floater ("DropShadowFloater", 0); @@ -687,7 +680,7 @@ void LLNavigationBar::clearHistoryCache() LLLocationHistory* lh = LLLocationHistory::getInstance(); lh->removeItems(); lh->save(); - mPurgeTPHistoryItems= true; + LLTeleportHistory::getInstance()->purgeItems(); } int LLNavigationBar::getDefNavBarHeight() diff --git a/indra/newview/llnavigationbar.h b/indra/newview/llnavigationbar.h index e4ce9e3998..7878bab24e 100644 --- a/indra/newview/llnavigationbar.h +++ b/indra/newview/llnavigationbar.h @@ -145,7 +145,6 @@ private: boost::signals2::connection mTeleportFailedConnection; boost::signals2::connection mTeleportFinishConnection; boost::signals2::connection mHistoryMenuConnection; - bool mPurgeTPHistoryItems; // if true, save location to location history when teleport finishes bool mSaveToLocationHistory; }; diff --git a/indra/newview/llnotificationscripthandler.cpp b/indra/newview/llnotificationscripthandler.cpp index 9f7d0cc2f5..7e9c0d4f4b 100644 --- a/indra/newview/llnotificationscripthandler.cpp +++ b/indra/newview/llnotificationscripthandler.cpp @@ -88,7 +88,7 @@ bool LLScriptHandler::processNotification(const LLNotificationPtr& notification) } else { - LLToastNotifyPanel* notify_box = new LLToastNotifyPanel(notification); + LLToastPanel* notify_box = LLToastPanel::buidPanelFromNotification(notification); LLToast::Params p; p.notif_id = notification->getID(); diff --git a/indra/newview/llpaneleditwearable.cpp b/indra/newview/llpaneleditwearable.cpp index 03404e816b..d58d6d536c 100644 --- a/indra/newview/llpaneleditwearable.cpp +++ b/indra/newview/llpaneleditwearable.cpp @@ -574,6 +574,7 @@ static void init_texture_ctrl(LLPanelEditWearable* self, LLPanel* panel, const L texture_ctrl->setAllowNoTexture(entry->mAllowNoTexture); // Don't allow (no copy) or (notransfer) textures to be selected. texture_ctrl->setImmediateFilterPermMask(PERM_NONE); + texture_ctrl->setDnDFilterPermMask(PERM_NONE); texture_ctrl->setNonImmediateFilterPermMask(PERM_NONE); } } diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index 7301b305b2..3e29805446 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -38,6 +38,7 @@ #include "llfontgl.h" // project includes +#include "llagentdata.h" #include "llbutton.h" #include "llcheckboxctrl.h" #include "llcolorswatch.h" @@ -46,6 +47,7 @@ #include "llface.h" #include "lllineeditor.h" #include "llmediaentry.h" +#include "llnotificationsutil.h" #include "llresmgr.h" #include "llselectmgr.h" #include "llspinctrl.h" @@ -104,27 +106,11 @@ BOOL LLPanelFace::postBuild() mTextureCtrl->setOnCancelCallback( boost::bind(&LLPanelFace::onCancelTexture, this, _2) ); mTextureCtrl->setOnSelectCallback( boost::bind(&LLPanelFace::onSelectTexture, this, _2) ); mTextureCtrl->setDragCallback(boost::bind(&LLPanelFace::onDragTexture, this, _2)); + mTextureCtrl->setOnTextureSelectedCallback(boost::bind(&LLPanelFace::onTextureSelectionChanged, this, _1)); mTextureCtrl->setFollowsTop(); mTextureCtrl->setFollowsLeft(); - // Don't allow (no copy) or (no transfer) textures to be selected during immediate mode - mTextureCtrl->setImmediateFilterPermMask(PERM_COPY | PERM_TRANSFER); - // Allow any texture to be used during non-immediate mode. - mTextureCtrl->setNonImmediateFilterPermMask(PERM_NONE); - LLAggregatePermissions texture_perms; - if (LLSelectMgr::getInstance()->selectGetAggregateTexturePermissions(texture_perms)) - { - BOOL can_copy = - texture_perms.getValue(PERM_COPY) == LLAggregatePermissions::AP_EMPTY || - texture_perms.getValue(PERM_COPY) == LLAggregatePermissions::AP_ALL; - BOOL can_transfer = - texture_perms.getValue(PERM_TRANSFER) == LLAggregatePermissions::AP_EMPTY || - texture_perms.getValue(PERM_TRANSFER) == LLAggregatePermissions::AP_ALL; - mTextureCtrl->setCanApplyImmediately(can_copy && can_transfer); - } - else - { - mTextureCtrl->setCanApplyImmediately(FALSE); - } + mTextureCtrl->setImmediateFilterPermMask(PERM_NONE); + mTextureCtrl->setDnDFilterPermMask(PERM_COPY | PERM_TRANSFER); } mColorSwatch = getChild<LLColorSwatchCtrl>("colorswatch"); @@ -595,28 +581,6 @@ void LLPanelFace::getState() } - LLAggregatePermissions texture_perms; - if(texture_ctrl) - { -// texture_ctrl->setValid( editable ); - - if (LLSelectMgr::getInstance()->selectGetAggregateTexturePermissions(texture_perms)) - { - BOOL can_copy = - texture_perms.getValue(PERM_COPY) == LLAggregatePermissions::AP_EMPTY || - texture_perms.getValue(PERM_COPY) == LLAggregatePermissions::AP_ALL; - BOOL can_transfer = - texture_perms.getValue(PERM_TRANSFER) == LLAggregatePermissions::AP_EMPTY || - texture_perms.getValue(PERM_TRANSFER) == LLAggregatePermissions::AP_ALL; - texture_ctrl->setCanApplyImmediately(can_copy && can_transfer); - } - else - { - texture_ctrl->setCanApplyImmediately(FALSE); - } - } - - // planar align bool align_planar = false; bool identical_planar_aligned = false; @@ -1190,3 +1154,35 @@ void LLPanelFace::onCommitPlanarAlign(LLUICtrl* ctrl, void* userdata) self->sendTextureInfo(); } +void LLPanelFace::onTextureSelectionChanged(LLInventoryItem* itemp) +{ + LLTextureCtrl* texture_ctrl = getChild<LLTextureCtrl>("texture control"); + if (texture_ctrl) + { + LLUUID obj_owner_id; + std::string obj_owner_name; + LLSelectMgr::instance().selectGetOwner(obj_owner_id, obj_owner_name); + + LLSaleInfo sale_info; + LLSelectMgr::instance().selectGetSaleInfo(sale_info); + + bool can_copy = itemp->getPermissions().allowCopyBy(gAgentID); // do we have perm to copy this texture? + bool can_transfer = itemp->getPermissions().allowOperationBy(PERM_TRANSFER, gAgentID); // do we have perm to transfer this texture? + bool is_object_owner = gAgentID == obj_owner_id; // does object for which we are going to apply texture belong to the agent? + bool not_for_sale = !sale_info.isForSale(); // is object for which we are going to apply texture not for sale? + + if (can_copy && can_transfer) + { + texture_ctrl->setCanApply(true, true); + return; + } + + // if texture has (no-transfer) attribute it can be applied only for object which we own and is not for sale + texture_ctrl->setCanApply(false, can_transfer ? true : is_object_owner && not_for_sale); + + if (gSavedSettings.getBOOL("TextureLivePreview")) + { + LLNotificationsUtil::add("LivePreviewUnavailable"); + } + } +} diff --git a/indra/newview/llpanelface.h b/indra/newview/llpanelface.h index 42be9b257f..3b5a9b1398 100644 --- a/indra/newview/llpanelface.h +++ b/indra/newview/llpanelface.h @@ -91,6 +91,15 @@ protected: static void onClickAutoFix(void*); static F32 valueGlow(LLViewerObject* object, S32 face); +private: + + /* + * Checks whether the selected texture from the LLFloaterTexturePicker can be applied to the currently selected object. + * If agent selects texture which is not allowed to be applied for the currently selected object, + * all controls of the floater texture picker which allow to apply the texture will be disabled. + */ + void onTextureSelectionChanged(LLInventoryItem* itemp); + }; #endif diff --git a/indra/newview/llpanellandmedia.cpp b/indra/newview/llpanellandmedia.cpp index b3adfac8a2..26cd3ff1c1 100644 --- a/indra/newview/llpanellandmedia.cpp +++ b/indra/newview/llpanellandmedia.cpp @@ -85,6 +85,7 @@ BOOL LLPanelLandMedia::postBuild() mMediaTextureCtrl->setCommitCallback( onCommitAny, this ); mMediaTextureCtrl->setAllowNoTexture ( TRUE ); mMediaTextureCtrl->setImmediateFilterPermMask(PERM_COPY | PERM_TRANSFER); + mMediaTextureCtrl->setDnDFilterPermMask(PERM_COPY | PERM_TRANSFER); mMediaTextureCtrl->setNonImmediateFilterPermMask(PERM_COPY | PERM_TRANSFER); mMediaAutoScaleCheck = getChild<LLCheckBoxCtrl>("media_auto_scale"); diff --git a/indra/newview/llpanelnearbymedia.cpp b/indra/newview/llpanelnearbymedia.cpp index c01adc3c35..a50d9074f7 100644 --- a/indra/newview/llpanelnearbymedia.cpp +++ b/indra/newview/llpanelnearbymedia.cpp @@ -176,7 +176,7 @@ void LLPanelNearByMedia::handleMediaAutoPlayChanged(const LLSD& newvalue) { // update mParcelAudioAutoStart if AUTO_PLAY_MEDIA_SETTING changes mParcelAudioAutoStart = gSavedSettings.getBOOL(LLViewerMedia::AUTO_PLAY_MEDIA_SETTING) && - gSavedSettings.getBOOL("MediaTentativeAutoPlay"); + gSavedSettings.getBOOL("MediaTentativeAutoPlay"); } /*virtual*/ diff --git a/indra/newview/llpanelobject.cpp b/indra/newview/llpanelobject.cpp index 1f77e7a602..7dfe529b73 100644 --- a/indra/newview/llpanelobject.cpp +++ b/indra/newview/llpanelobject.cpp @@ -245,6 +245,7 @@ BOOL LLPanelObject::postBuild() mCtrlSculptTexture->setDropCallback( boost::bind(&LLPanelObject::onDropSculpt, this, _2 )); // Don't allow (no copy) or (no transfer) textures to be selected during immediate mode mCtrlSculptTexture->setImmediateFilterPermMask(PERM_COPY | PERM_TRANSFER); + mCtrlSculptTexture->setDnDFilterPermMask(PERM_COPY | PERM_TRANSFER); // Allow any texture to be used during non-immediate mode. mCtrlSculptTexture->setNonImmediateFilterPermMask(PERM_NONE); LLAggregatePermissions texture_perms; diff --git a/indra/newview/llprogressview.cpp b/indra/newview/llprogressview.cpp index 5d7a5b1c59..f86e583b9e 100644 --- a/indra/newview/llprogressview.cpp +++ b/indra/newview/llprogressview.cpp @@ -40,6 +40,7 @@ #include "llagent.h" #include "llbutton.h" +#include "llcallbacklist.h" #include "llfocusmgr.h" #include "llnotifications.h" #include "llprogressbar.h" @@ -72,6 +73,8 @@ LLProgressView::LLProgressView() mStartupComplete(false) { mUpdateEvents.listen("self", boost::bind(&LLProgressView::handleUpdate, this, _1)); + mFadeToWorldTimer.stop(); + mFadeFromLoginTimer.stop(); } BOOL LLProgressView::postBuild() @@ -87,8 +90,6 @@ BOOL LLProgressView::postBuild() mCancelBtn = getChild<LLButton>("cancel_btn"); mCancelBtn->setClickedCallback( LLProgressView::onCancelButtonClicked, NULL ); - mFadeToWorldTimer.stop(); - mFadeFromLoginTimer.stop(); getChild<LLTextBox>("title_text")->setText(LLStringExplicit(LLAppViewer::instance()->getSecondLifeTitle())); @@ -106,6 +107,9 @@ BOOL LLProgressView::postBuild() LLProgressView::~LLProgressView() { + // Just in case something went wrong, make sure we deregister our idle callback. + gIdleCallbacks.deleteFunction(onIdle, this); + gFocusMgr.releaseFocusIfNeeded( this ); sInstance = NULL; @@ -154,6 +158,7 @@ void LLProgressView::revealIntroPanel() } mFadeFromLoginTimer.start(); + gIdleCallbacks.addFunction(onIdle, this); } void LLProgressView::setStartupComplete() @@ -236,13 +241,6 @@ void LLProgressView::draw() } LLPanel::draw(); - - if (mFadeFromLoginTimer.getElapsedTimeF32() > FADE_TO_WORLD_TIME ) - { - mFadeFromLoginTimer.stop(); - LLPanelLogin::closePanel(); - } - return; } @@ -424,3 +422,21 @@ void LLProgressView::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent even } } } + + +// static +void LLProgressView::onIdle(void* user_data) +{ + LLProgressView* self = (LLProgressView*) user_data; + + // Close login panel on mFadeToWorldTimer expiration. + if (self->mFadeFromLoginTimer.getStarted() && + self->mFadeFromLoginTimer.getElapsedTimeF32() > FADE_TO_WORLD_TIME) + { + self->mFadeFromLoginTimer.stop(); + LLPanelLogin::closePanel(); + + // Nothing to do anymore. + gIdleCallbacks.deleteFunction(onIdle, user_data); + } +} diff --git a/indra/newview/llprogressview.h b/indra/newview/llprogressview.h index fac00ad04d..813576b21d 100644 --- a/indra/newview/llprogressview.h +++ b/indra/newview/llprogressview.h @@ -41,6 +41,8 @@ class LLProgressView : public LLViewerMediaObserver { + LOG_CLASS(LLProgressView); + public: LLProgressView(); virtual ~LLProgressView(); @@ -74,10 +76,6 @@ public: static void onClickMessage(void*); bool onAlertModal(const LLSD& sd); - // note - this is not just hiding the intro panel - it also hides the parent panel - // and is used when the intro is finished and we want to show the world - void removeIntroPanel(); - protected: LLProgressBar* mProgressBar; LLMediaCtrl* mMediaCtrl; @@ -96,6 +94,7 @@ protected: LLEventStream mUpdateEvents; bool handleUpdate(const LLSD& event_data); + static void onIdle(void* user_data); }; #endif // LL_LLPROGRESSVIEW_H diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index 6111255a66..a55565909f 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -1508,6 +1508,49 @@ struct LLSelectMgrSendFunctor : public LLSelectedObjectFunctor } }; +void LLObjectSelection::applyNoCopyTextureToTEs(LLViewerInventoryItem* item) +{ + if (!item) + { + return; + } + LLViewerTexture* image = LLViewerTextureManager::getFetchedTexture(item->getAssetUUID()); + + for (iterator iter = begin(); iter != end(); ++iter) + { + LLSelectNode* node = *iter; + LLViewerObject* object = (*iter)->getObject(); + if (!object) + { + continue; + } + + S32 num_tes = llmin((S32)object->getNumTEs(), (S32)object->getNumFaces()); + bool texture_copied = false; + for (S32 te = 0; te < num_tes; ++te) + { + if (node->isTESelected(te)) + { + //(no-copy) textures must be moved to the object's inventory only once + // without making any copies + if (!texture_copied) + { + LLToolDragAndDrop::handleDropTextureProtections(object, item, LLToolDragAndDrop::SOURCE_AGENT, LLUUID::null); + texture_copied = true; + } + + // apply texture for the selected faces + LLViewerStats::getInstance()->incStat(LLViewerStats::ST_EDIT_TEXTURE_COUNT ); + object->setTEImage(te, image); + dialog_refresh_all(); + + // send the update to the simulator + object->sendTEUpdate(); + } + } + } +} + //----------------------------------------------------------------------------- // selectionSetImage() //----------------------------------------------------------------------------- @@ -1559,8 +1602,18 @@ void LLSelectMgr::selectionSetImage(const LLUUID& imageid) } return true; } - } setfunc(item, imageid); - getSelection()->applyToTEs(&setfunc); + }; + + if (item && !item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID())) + { + getSelection()->applyNoCopyTextureToTEs(item); + } + else + { + f setfunc(item, imageid); + getSelection()->applyToTEs(&setfunc); + } + struct g : public LLSelectedObjectFunctor { @@ -3051,11 +3104,11 @@ bool LLSelectMgr::confirmDelete(const LLSD& notification, const LLSD& response, // TODO: Make sure you have delete permissions on all of them. const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); // attempt to derez into the trash. - LLDeRezInfo* info = new LLDeRezInfo(DRD_TRASH, trash_id); + LLDeRezInfo info(DRD_TRASH, trash_id); LLSelectMgr::getInstance()->sendListToRegions("DeRezObject", packDeRezHeader, packObjectLocalID, - (void*)info, + (void*) &info, SEND_ONLY_ROOTS); // VEFFECT: Delete Object - one effect for all deletes if (LLSelectMgr::getInstance()->mSelectedObjects->mSelectType != SELECT_TYPE_HUD) @@ -3745,13 +3798,15 @@ void LLSelectMgr::deselectAllIfTooFar() void LLSelectMgr::selectionSetObjectName(const std::string& name) { + std::string name_copy(name); + // we only work correctly if 1 object is selected. if(mSelectedObjects->getRootObjectCount() == 1) { sendListToRegions("ObjectName", packAgentAndSessionID, packObjectName, - (void*)(new std::string(name)), + (void*)(&name_copy), SEND_ONLY_ROOTS); } else if(mSelectedObjects->getObjectCount() == 1) @@ -3759,20 +3814,22 @@ void LLSelectMgr::selectionSetObjectName(const std::string& name) sendListToRegions("ObjectName", packAgentAndSessionID, packObjectName, - (void*)(new std::string(name)), + (void*)(&name_copy), SEND_INDIVIDUALS); } } void LLSelectMgr::selectionSetObjectDescription(const std::string& desc) { + std::string desc_copy(desc); + // we only work correctly if 1 object is selected. if(mSelectedObjects->getRootObjectCount() == 1) { sendListToRegions("ObjectDescription", packAgentAndSessionID, packObjectDescription, - (void*)(new std::string(desc)), + (void*)(&desc_copy), SEND_ONLY_ROOTS); } else if(mSelectedObjects->getObjectCount() == 1) @@ -3780,7 +3837,7 @@ void LLSelectMgr::selectionSetObjectDescription(const std::string& desc) sendListToRegions("ObjectDescription", packAgentAndSessionID, packObjectDescription, - (void*)(new std::string(desc)), + (void*)(&desc_copy), SEND_INDIVIDUALS); } } @@ -4298,15 +4355,14 @@ void LLSelectMgr::packObjectName(LLSelectNode* node, void* user_data) gMessageSystem->addU32Fast(_PREHASH_LocalID, node->getObject()->getLocalID()); gMessageSystem->addStringFast(_PREHASH_Name, *name); } - delete name; } // static void LLSelectMgr::packObjectDescription(LLSelectNode* node, void* user_data) { const std::string* desc = (const std::string*)user_data; - if(!desc->empty()) - { + if(desc) + { // Empty (non-null, but zero length) descriptions are OK gMessageSystem->nextBlockFast(_PREHASH_ObjectData); gMessageSystem->addU32Fast(_PREHASH_LocalID, node->getObject()->getLocalID()); gMessageSystem->addStringFast(_PREHASH_Description, *desc); @@ -5580,7 +5636,7 @@ void pushWireframe(LLDrawable* drawable) for (S32 i = 0; i < volume->getNumVolumeFaces(); ++i) { const LLVolumeFace& face = volume->getVolumeFace(i); - LLVertexBuffer::drawElements(LLRender::TRIANGLES, face.mPositions, face.mTexCoords, face.mNumIndices, face.mIndices); + LLVertexBuffer::drawElements(LLRender::TRIANGLES, face.mPositions, NULL, face.mNumIndices, face.mIndices); } } @@ -5607,7 +5663,7 @@ void LLSelectNode::renderOneWireframe(const LLColor4& color) if (shader) { - gHighlightProgram.bind(); + gDebugProgram.bind(); } gGL.matrixMode(LLRender::MM_MODELVIEW); diff --git a/indra/newview/llselectmgr.h b/indra/newview/llselectmgr.h index 87ada5ac6b..94606b9fba 100644 --- a/indra/newview/llselectmgr.h +++ b/indra/newview/llselectmgr.h @@ -307,6 +307,15 @@ public: bool applyToRootNodes(LLSelectedNodeFunctor* func, bool firstonly = false); bool applyToNodes(LLSelectedNodeFunctor* func, bool firstonly = false); + /* + * Used to apply (no-copy) textures to the selected object or + * selected face/faces of the object. + * This method moves (no-copy) texture to the object's inventory + * and doesn't make copy of the texture for each face. + * Then this only texture is used for all selected faces. + */ + void applyNoCopyTextureToTEs(LLViewerInventoryItem* item); + ESelectType getSelectType() const { return mSelectType; } private: diff --git a/indra/newview/llsidepaneltaskinfo.cpp b/indra/newview/llsidepaneltaskinfo.cpp index 24cb559fd0..64b82aa0bb 100644 --- a/indra/newview/llsidepaneltaskinfo.cpp +++ b/indra/newview/llsidepaneltaskinfo.cpp @@ -94,7 +94,7 @@ BOOL LLSidepanelTaskInfo::postBuild() mPayBtn = getChild<LLButton>("pay_btn"); mPayBtn->setClickedCallback(boost::bind(&LLSidepanelTaskInfo::onPayButtonClicked, this)); mBuyBtn = getChild<LLButton>("buy_btn"); - mBuyBtn->setClickedCallback(boost::bind(&LLSidepanelTaskInfo::onBuyButtonClicked, this)); + mBuyBtn->setClickedCallback(boost::bind(&handle_buy)); mDetailsBtn = getChild<LLButton>("details_btn"); mDetailsBtn->setClickedCallback(boost::bind(&LLSidepanelTaskInfo::onDetailsButtonClicked, this)); @@ -1114,8 +1114,6 @@ void LLSidepanelTaskInfo::doClickAction(U8 click_action) // Set click action back to its old value U8 click_action = 0; LLSelectMgr::getInstance()->selectionGetClickAction(&click_action); -// box->setCurrentByIndex((S32)click_action); - return; } } diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index 1333862855..de7fb542f8 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -85,12 +85,32 @@ static F32 sCurMaxTexPriority = 1.f; class LLOcclusionQueryPool : public LLGLNamePool { +public: + LLOcclusionQueryPool() + { + mCurQuery = 1; + } + protected: + + std::list<GLuint> mAvailableName; + GLuint mCurQuery; + virtual GLuint allocateName() { - GLuint name; - glGenQueriesARB(1, &name); - return name; + GLuint ret = 0; + + if (!mAvailableName.empty()) + { + ret = mAvailableName.front(); + mAvailableName.pop_front(); + } + else + { + ret = mCurQuery++; + } + + return ret; } virtual void releaseName(GLuint name) @@ -98,7 +118,8 @@ protected: #if LL_TRACK_PENDING_OCCLUSION_QUERIES LLSpatialGroup::sPendingQueries.erase(name); #endif - glDeleteQueriesARB(1, &name); + llassert(std::find(mAvailableName.begin(), mAvailableName.end(), name) == mAvailableName.end()); + mAvailableName.push_back(name); } }; @@ -259,79 +280,39 @@ U8* get_box_fan_indices_ptr(LLCamera* camera, const LLVector4a& center) return (U8*) (sOcclusionIndices+cypher*8); } - -static LLFastTimer::DeclareTimer FTM_BUILD_OCCLUSION("Build Occlusion"); - -void LLSpatialGroup::buildOcclusion() +//create a vertex buffer for efficiently rendering cubes +LLVertexBuffer* ll_create_cube_vb(U32 type_mask, U32 usage) { - //if (mOcclusionVerts.isNull()) - { - mOcclusionVerts = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX, - LLVertexBuffer::sUseStreamDraw ? mBufferUsage : 0); //if GL has a hard time with VBOs, don't use them for occlusion culling. - mOcclusionVerts->allocateBuffer(8, 64, true); - - LLStrider<U16> idx; - mOcclusionVerts->getIndexStrider(idx); - for (U32 i = 0; i < 64; i++) - { - *idx++ = sOcclusionIndices[i]; - } - } + LLVertexBuffer* ret = new LLVertexBuffer(type_mask, usage); - LLVector4a fudge; - fudge.splat(SG_OCCLUSION_FUDGE); - - LLVector4a r; - r.setAdd(mBounds[1], fudge); + ret->allocateBuffer(8, 64, true); LLStrider<LLVector3> pos; - - { - LLFastTimer t(FTM_BUILD_OCCLUSION); - mOcclusionVerts->getVertexStrider(pos); - } + LLStrider<U16> idx; - { - LLVector4a* v = (LLVector4a*) pos.get(); + ret->getVertexStrider(pos); + ret->getIndexStrider(idx); - const LLVector4a& c = mBounds[0]; - const LLVector4a& s = r; - - static const LLVector4a octant[] = - { - LLVector4a(-1.f, -1.f, -1.f), - LLVector4a(-1.f, -1.f, 1.f), - LLVector4a(-1.f, 1.f, -1.f), - LLVector4a(-1.f, 1.f, 1.f), - - LLVector4a(1.f, -1.f, -1.f), - LLVector4a(1.f, -1.f, 1.f), - LLVector4a(1.f, 1.f, -1.f), - LLVector4a(1.f, 1.f, 1.f), - }; - - //vertex positions are encoded so the 3 bits of their vertex index - //correspond to their axis facing, with bit position 3,2,1 matching - //axis facing x,y,z, bit set meaning positive facing, bit clear - //meaning negative facing - - for (S32 i = 0; i < 8; ++i) - { - LLVector4a p; - p.setMul(s, octant[i]); - p.add(c); - v[i] = p; - } - } - + pos[0] = LLVector3(-1,-1,-1); + pos[1] = LLVector3(-1,-1, 1); + pos[2] = LLVector3(-1, 1,-1); + pos[3] = LLVector3(-1, 1, 1); + pos[4] = LLVector3( 1,-1,-1); + pos[5] = LLVector3( 1,-1, 1); + pos[6] = LLVector3( 1, 1,-1); + pos[7] = LLVector3( 1, 1, 1); + + for (U32 i = 0; i < 64; i++) { - mOcclusionVerts->flush(); - LLVertexBuffer::unbind(); + idx[i] = sOcclusionIndices[i]; } - clearState(LLSpatialGroup::OCCLUSION_DIRTY); + ret->flush(); + + return ret; } +static LLFastTimer::DeclareTimer FTM_BUILD_OCCLUSION("Build Occlusion"); BOOL earlyFail(LLCamera* camera, LLSpatialGroup* group); @@ -394,8 +375,6 @@ LLSpatialGroup::~LLSpatialGroup() } } - mOcclusionVerts = NULL; - LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); clearDrawMap(); clearAtlasList() ; @@ -687,6 +666,11 @@ void LLSpatialGroup::rebuildGeom() if (!isDead()) { mSpatialPartition->rebuildGeom(this); + + if (isState(LLSpatialGroup::MESH_DIRTY)) + { + gPipeline.markMeshDirty(this); + } } } @@ -699,6 +683,9 @@ void LLSpatialGroup::rebuildMesh() } static LLFastTimer::DeclareTimer FTM_REBUILD_VBO("VBO Rebuilt"); +static LLFastTimer::DeclareTimer FTM_ADD_GEOMETRY_COUNT("Add Geometry"); +static LLFastTimer::DeclareTimer FTM_CREATE_VB("Create VB"); +static LLFastTimer::DeclareTimer FTM_GET_GEOMETRY("Get Geometry"); void LLSpatialPartition::rebuildGeom(LLSpatialGroup* group) { @@ -720,27 +707,36 @@ void LLSpatialPartition::rebuildGeom(LLSpatialGroup* group) //get geometry count U32 index_count = 0; U32 vertex_count = 0; - - addGeometryCount(group, vertex_count, index_count); + + { + LLFastTimer t(FTM_ADD_GEOMETRY_COUNT); + addGeometryCount(group, vertex_count, index_count); + } if (vertex_count > 0 && index_count > 0) { //create vertex buffer containing volume geometry for this node - group->mBuilt = 1.f; - if (group->mVertexBuffer.isNull() || - !group->mVertexBuffer->isWriteable() || - (group->mBufferUsage != group->mVertexBuffer->getUsage() && LLVertexBuffer::sEnableVBOs)) { - group->mVertexBuffer = createVertexBuffer(mVertexDataMask, group->mBufferUsage); - group->mVertexBuffer->allocateBuffer(vertex_count, index_count, true); - stop_glerror(); + LLFastTimer t(FTM_CREATE_VB); + group->mBuilt = 1.f; + if (group->mVertexBuffer.isNull() || + !group->mVertexBuffer->isWriteable() || + (group->mBufferUsage != group->mVertexBuffer->getUsage() && LLVertexBuffer::sEnableVBOs)) + { + group->mVertexBuffer = createVertexBuffer(mVertexDataMask, group->mBufferUsage); + group->mVertexBuffer->allocateBuffer(vertex_count, index_count, true); + stop_glerror(); + } + else + { + group->mVertexBuffer->resizeBuffer(vertex_count, index_count); + stop_glerror(); + } } - else + { - group->mVertexBuffer->resizeBuffer(vertex_count, index_count); - stop_glerror(); + LLFastTimer t(FTM_GET_GEOMETRY); + getGeometry(group); } - - getGeometry(group); } else { @@ -932,11 +928,6 @@ void LLSpatialGroup::shift(const LLVector4a &offset) setState(GEOM_DIRTY); gPipeline.markRebuild(this, TRUE); } - - if (mOcclusionVerts.notNull()) - { - setState(OCCLUSION_DIRTY); - } } class LLSpatialSetState : public LLSpatialGroup::OctreeTraveler @@ -1186,6 +1177,7 @@ void LLSpatialGroup::clearOcclusionState(U32 state, S32 mode) //====================================== LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) : + mObjectBoxSize(1.f), mState(0), mGeometryBytes(0), mSurfaceArea(0.f), @@ -1234,8 +1226,6 @@ LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) : mVisible[i] = 0; } - mOcclusionVerts = NULL; - mRadius = 1; mPixelArea = 1024.f; } @@ -1464,10 +1454,14 @@ void LLSpatialGroup::handleChildRemoval(const OctreeNode* parent, const OctreeNo unbound(); } -void LLSpatialGroup::destroyGL() +void LLSpatialGroup::destroyGL(bool keep_occlusion) { setState(LLSpatialGroup::GEOM_DIRTY | LLSpatialGroup::IMAGE_DIRTY); - gPipeline.markRebuild(this, TRUE); + + if (!keep_occlusion) + { //going to need a rebuild + gPipeline.markRebuild(this, TRUE); + } mLastUpdateTime = gFrameTimeSeconds; mVertexBuffer = NULL; @@ -1475,16 +1469,18 @@ void LLSpatialGroup::destroyGL() clearDrawMap(); - for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++) + if (!keep_occlusion) { - if (mOcclusionQuery[i]) + for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++) { - sQueryPool.release(mOcclusionQuery[i]); - mOcclusionQuery[i] = 0; + if (mOcclusionQuery[i]) + { + sQueryPool.release(mOcclusionQuery[i]); + mOcclusionQuery[i] = 0; + } } } - mOcclusionVerts = NULL; for (LLSpatialGroup::element_iter i = getData().begin(); i != getData().end(); ++i) { @@ -1492,7 +1488,10 @@ void LLSpatialGroup::destroyGL() for (S32 j = 0; j < drawable->getNumFaces(); j++) { LLFace* facep = drawable->getFace(j); - facep->clearVertexBuffer(); + if (facep) + { + facep->clearVertexBuffer(); + } } } } @@ -1555,15 +1554,13 @@ BOOL LLSpatialGroup::rebound() mBounds[1].mul(0.5f); } - setState(OCCLUSION_DIRTY); - clearState(DIRTY); return TRUE; } static LLFastTimer::DeclareTimer FTM_OCCLUSION_READBACK("Readback Occlusion"); -static LLFastTimer::DeclareTimer FTM_OCCLUSION_WAIT("Wait"); +static LLFastTimer::DeclareTimer FTM_OCCLUSION_WAIT("Occlusion Wait"); void LLSpatialGroup::checkOcclusion() { @@ -1583,7 +1580,9 @@ void LLSpatialGroup::checkOcclusion() { glGetQueryObjectuivARB(mOcclusionQuery[LLViewerCamera::sCurCameraID], GL_QUERY_RESULT_AVAILABLE_ARB, &available); - if (mOcclusionIssued[LLViewerCamera::sCurCameraID] < gFrameCount) + static LLCachedControl<bool> wait_for_query(gSavedSettings, "RenderSynchronousOcclusion"); + + if (wait_for_query && mOcclusionIssued[LLViewerCamera::sCurCameraID] < gFrameCount) { //query was issued last frame, wait until it's available S32 max_loop = 1024; LLFastTimer t(FTM_OCCLUSION_WAIT); @@ -1634,7 +1633,9 @@ void LLSpatialGroup::checkOcclusion() else { assert_states_valid(this); + setOcclusionState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF); + assert_states_valid(this); } @@ -1689,12 +1690,6 @@ void LLSpatialGroup::doOcclusion(LLCamera* camera) mOcclusionQuery[LLViewerCamera::sCurCameraID] = sQueryPool.allocate(); } - if (mOcclusionVerts.isNull() || isState(LLSpatialGroup::OCCLUSION_DIRTY)) - { - LLFastTimer t(FTM_OCCLUSION_BUILD); - buildOcclusion(); - } - // Depth clamp all water to avoid it being culled as a result of being // behind the far clip plane, and in the case of edge water to avoid // it being culled while still visible. @@ -1725,10 +1720,13 @@ void LLSpatialGroup::doOcclusion(LLCamera* camera) glBeginQueryARB(mode, mOcclusionQuery[LLViewerCamera::sCurCameraID]); } - { - LLFastTimer t(FTM_OCCLUSION_SET_BUFFER); - mOcclusionVerts->setBuffer(LLVertexBuffer::MAP_VERTEX); - } + LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; + llassert(shader); + + shader->uniform3fv(LLShaderMgr::BOX_CENTER, 1, mBounds[0].getF32ptr()); + shader->uniform3f(LLShaderMgr::BOX_SIZE, mBounds[1][0]+SG_OCCLUSION_FUDGE, + mBounds[1][1]+SG_OCCLUSION_FUDGE, + mBounds[1][2]+SG_OCCLUSION_FUDGE); if (!use_depth_clamp && mSpatialPartition->mDrawableType == LLDrawPool::POOL_VOIDWATER) { @@ -1737,12 +1735,12 @@ void LLSpatialGroup::doOcclusion(LLCamera* camera) LLGLSquashToFarClip squash(glh_get_current_projection(), 1); if (camera->getOrigin().isExactlyZero()) { //origin is invalid, draw entire box - mOcclusionVerts->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, 0); - mOcclusionVerts->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, b111*8); + gPipeline.mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, 0); + gPipeline.mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, b111*8); } else { - mOcclusionVerts->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, mBounds[0])); + gPipeline.mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, mBounds[0])); } } else @@ -1750,12 +1748,12 @@ void LLSpatialGroup::doOcclusion(LLCamera* camera) LLFastTimer t(FTM_OCCLUSION_DRAW); if (camera->getOrigin().isExactlyZero()) { //origin is invalid, draw entire box - mOcclusionVerts->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, 0); - mOcclusionVerts->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, b111*8); + gPipeline.mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, 0); + gPipeline.mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, b111*8); } else { - mOcclusionVerts->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, mBounds[0])); + gPipeline.mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, mBounds[0])); } } @@ -2479,18 +2477,21 @@ void pushVerts(LLSpatialGroup* group, U32 mask) void pushVerts(LLFace* face, U32 mask) { - llassert(face->verify()); + if (face) + { + llassert(face->verify()); - LLVertexBuffer* buffer = face->getVertexBuffer(); + LLVertexBuffer* buffer = face->getVertexBuffer(); - if (buffer && (face->getGeomCount() >= 3)) - { - buffer->setBuffer(mask); - U16 start = face->getGeomStart(); - U16 end = start + face->getGeomCount()-1; - U32 count = face->getIndicesCount(); - U16 offset = face->getIndicesStart(); - buffer->drawRange(LLRender::TRIANGLES, start, end, count, offset); + if (buffer && (face->getGeomCount() >= 3)) + { + buffer->setBuffer(mask); + U16 start = face->getGeomStart(); + U16 end = start + face->getGeomCount()-1; + U32 count = face->getIndicesCount(); + U16 offset = face->getIndicesStart(); + buffer->drawRange(LLRender::TRIANGLES, start, end, count, offset); + } } } @@ -2627,7 +2628,7 @@ void renderOctree(LLSpatialGroup* group) for (S32 j = 0; j < drawable->getNumFaces(); j++) { LLFace* face = drawable->getFace(j); - if (face->getVertexBuffer()) + if (face && face->getVertexBuffer()) { if (gFrameTimeSeconds - face->mLastUpdateTime < 0.5f) { @@ -2756,19 +2757,6 @@ void renderVisibility(LLSpatialGroup* group, LLCamera* camera) gGL.diffuseColor4f(0.f, 0.75f, 0.f, 0.5f); pushBufferVerts(group, LLVertexBuffer::MAP_VERTEX); } - /*else if (camera && group->mOcclusionVerts.notNull()) - { - LLVertexBuffer::unbind(); - group->mOcclusionVerts->setBuffer(LLVertexBuffer::MAP_VERTEX); - - gGL.diffuseColor4f(1.0f, 0.f, 0.f, 0.5f); - group->mOcclusionVerts->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, group->mBounds[0])); - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - - gGL.diffuseColor4f(1.0f, 1.f, 1.f, 1.0f); - group->mOcclusionVerts->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, group->mBounds[0])); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - }*/ } } @@ -2998,15 +2986,17 @@ void renderBoundingBox(LLDrawable* drawable, BOOL set_color = TRUE) for (S32 i = 0; i < drawable->getNumFaces(); i++) { LLFace* facep = drawable->getFace(i); + if (facep) + { + ext = facep->mExtents; - ext = facep->mExtents; - - pos.setAdd(ext[0], ext[1]); - pos.mul(0.5f); - size.setSub(ext[1], ext[0]); - size.mul(0.5f); + pos.setAdd(ext[0], ext[1]); + pos.mul(0.5f); + size.setSub(ext[1], ext[0]); + size.mul(0.5f); - drawBoxOutline(pos,size); + drawBoxOutline(pos,size); + } } //render drawable bounding box @@ -3498,18 +3488,21 @@ void renderPhysicsShapes(LLSpatialGroup* group) for (S32 i = 0; i < drawable->getNumFaces(); ++i) { LLFace* face = drawable->getFace(i); - LLVertexBuffer* buff = face->getVertexBuffer(); - if (buff) + if (face) { - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + LLVertexBuffer* buff = face->getVertexBuffer(); + if (buff) + { + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - buff->setBuffer(LLVertexBuffer::MAP_VERTEX); - gGL.diffuseColor3f(0.2f, 0.5f, 0.3f); - buff->draw(LLRender::TRIANGLES, buff->getNumIndices(), 0); + buff->setBuffer(LLVertexBuffer::MAP_VERTEX); + gGL.diffuseColor3f(0.2f, 0.5f, 0.3f); + buff->draw(LLRender::TRIANGLES, buff->getNumIndices(), 0); - gGL.diffuseColor3f(0.2f, 1.f, 0.3f); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - buff->draw(LLRender::TRIANGLES, buff->getNumIndices(), 0); + gGL.diffuseColor3f(0.2f, 1.f, 0.3f); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + buff->draw(LLRender::TRIANGLES, buff->getNumIndices(), 0); + } } } } @@ -3533,6 +3526,7 @@ void renderTexturePriority(LLDrawable* drawable) //LLViewerTexture* imagep = facep->getTexture(); //if (imagep) + if (facep) { //F32 vsize = imagep->mMaxVirtualSize; @@ -3585,7 +3579,11 @@ void renderPoints(LLDrawable* drawablep) gGL.diffuseColor3f(1,1,1); for (S32 i = 0; i < drawablep->getNumFaces(); i++) { - gGL.vertex3fv(drawablep->getFace(i)->mCenterLocal.mV); + LLFace * face = drawablep->getFace(i); + if (face) + { + gGL.vertex3fv(face->mCenterLocal.mV); + } } gGL.end(); } @@ -3647,6 +3645,110 @@ void renderShadowFrusta(LLDrawInfo* params) gGL.setSceneBlendType(LLRender::BT_ALPHA); } +void renderTexelDensity(LLDrawable* drawable) +{ + if (LLViewerTexture::sDebugTexelsMode == LLViewerTexture::DEBUG_TEXELS_OFF + || LLViewerTexture::sCheckerBoardImagep.isNull()) + { + return; + } + + LLGLEnable _(GL_BLEND); + //gObjectFullbrightProgram.bind(); + + LLMatrix4 checkerboard_matrix; + S32 discard_level = -1; + + for (S32 f = 0; f < drawable->getNumFaces(); f++) + { + LLFace* facep = drawable->getFace(f); + LLVertexBuffer* buffer = facep->getVertexBuffer(); + LLViewerTexture* texturep = facep->getTexture(); + + if (texturep == NULL) continue; + + switch(LLViewerTexture::sDebugTexelsMode) + { + case LLViewerTexture::DEBUG_TEXELS_CURRENT: + discard_level = -1; + break; + case LLViewerTexture::DEBUG_TEXELS_DESIRED: + { + LLViewerFetchedTexture* fetched_texturep = dynamic_cast<LLViewerFetchedTexture*>(texturep); + discard_level = fetched_texturep ? fetched_texturep->getDesiredDiscardLevel() : -1; + break; + } + default: + case LLViewerTexture::DEBUG_TEXELS_FULL: + discard_level = 0; + break; + } + + checkerboard_matrix.initScale(LLVector3(texturep->getWidth(discard_level) / 8, texturep->getHeight(discard_level) / 8, 1.f)); + + gGL.getTexUnit(0)->bind(LLViewerTexture::sCheckerBoardImagep, TRUE); + gGL.matrixMode(LLRender::MM_TEXTURE); + gGL.loadMatrix((GLfloat*)&checkerboard_matrix.mMatrix); + + if (buffer && (facep->getGeomCount() >= 3)) + { + buffer->setBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0); + U16 start = facep->getGeomStart(); + U16 end = start + facep->getGeomCount()-1; + U32 count = facep->getIndicesCount(); + U16 offset = facep->getIndicesStart(); + buffer->drawRange(LLRender::TRIANGLES, start, end, count, offset); + } + + gGL.loadIdentity(); + gGL.matrixMode(LLRender::MM_MODELVIEW); + } + + //S32 num_textures = llmax(1, (S32)params->mTextureList.size()); + + //for (S32 i = 0; i < num_textures; i++) + //{ + // LLViewerTexture* texturep = params->mTextureList.empty() ? params->mTexture.get() : params->mTextureList[i].get(); + // if (texturep == NULL) continue; + + // LLMatrix4 checkboard_matrix; + // S32 discard_level = -1; + // switch(LLViewerTexture::sDebugTexelsMode) + // { + // case LLViewerTexture::DEBUG_TEXELS_CURRENT: + // discard_level = -1; + // break; + // case LLViewerTexture::DEBUG_TEXELS_DESIRED: + // { + // LLViewerFetchedTexture* fetched_texturep = dynamic_cast<LLViewerFetchedTexture*>(texturep); + // discard_level = fetched_texturep ? fetched_texturep->getDesiredDiscardLevel() : -1; + // break; + // } + // default: + // case LLViewerTexture::DEBUG_TEXELS_FULL: + // discard_level = 0; + // break; + // } + + // checkboard_matrix.initScale(LLVector3(texturep->getWidth(discard_level) / 8, texturep->getHeight(discard_level) / 8, 1.f)); + // gGL.getTexUnit(i)->activate(); + + // glMatrixMode(GL_TEXTURE); + // glPushMatrix(); + // glLoadIdentity(); + // //gGL.matrixMode(LLRender::MM_TEXTURE); + // glLoadMatrixf((GLfloat*) checkboard_matrix.mMatrix); + + // gGL.getTexUnit(i)->bind(LLViewerTexture::sCheckerBoardImagep, TRUE); + + // pushVerts(params, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_NORMAL ); + + // glPopMatrix(); + // glMatrixMode(GL_MODELVIEW); + // //gGL.matrixMode(LLRender::MM_MODELVIEW); + //} +} + void renderLights(LLDrawable* drawablep) { @@ -3662,7 +3764,11 @@ void renderLights(LLDrawable* drawablep) for (S32 i = 0; i < drawablep->getNumFaces(); i++) { - pushVerts(drawablep->getFace(i), LLVertexBuffer::MAP_VERTEX); + LLFace * face = drawablep->getFace(i); + if (face) + { + pushVerts(face, LLVertexBuffer::MAP_VERTEX); + } } const LLVector4a* ext = drawablep->getSpatialExtents(); @@ -4042,6 +4148,10 @@ public: { renderComplexityDisplay(drawable); } + if(gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY)) + { + renderTexelDensity(drawable); + } LLVOAvatar* avatar = dynamic_cast<LLVOAvatar*>(drawable->getVObj().get()); @@ -4060,18 +4170,21 @@ public: for (U32 i = 0; i < drawable->getNumFaces(); ++i) { LLFace* facep = drawable->getFace(i); - U8 index = facep->getTextureIndex(); - if (facep->mDrawInfo) + if (facep) { - if (index < 255) + U8 index = facep->getTextureIndex(); + if (facep->mDrawInfo) { - if (facep->mDrawInfo->mTextureList.size() <= index) - { - llerrs << "Face texture index out of bounds." << llendl; - } - else if (facep->mDrawInfo->mTextureList[index] != facep->getTexture()) + if (index < 255) { - llerrs << "Face texture index incorrect." << llendl; + if (facep->mDrawInfo->mTextureList.size() <= index) + { + llerrs << "Face texture index out of bounds." << llendl; + } + else if (facep->mDrawInfo->mTextureList[index] != facep->getTexture()) + { + llerrs << "Face texture index incorrect." << llendl; + } } } } @@ -4291,7 +4404,8 @@ void LLSpatialPartition::renderDebug() LLPipeline::RENDER_DEBUG_AGENT_TARGET | //LLPipeline::RENDER_DEBUG_BUILD_QUEUE | LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA | - LLPipeline::RENDER_DEBUG_RENDER_COMPLEXITY)) + LLPipeline::RENDER_DEBUG_RENDER_COMPLEXITY | + LLPipeline::RENDER_DEBUG_TEXEL_DENSITY)) { return; } diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h index 6c14ecf452..f0e4f15a83 100644 --- a/indra/newview/llspatialpartition.h +++ b/indra/newview/llspatialpartition.h @@ -263,11 +263,10 @@ public: SKIP_FRUSTUM_CHECK = 0x00000020, IN_IMAGE_QUEUE = 0x00000040, IMAGE_DIRTY = 0x00000080, - OCCLUSION_DIRTY = 0x00000100, - MESH_DIRTY = 0x00000200, - NEW_DRAWINFO = 0x00000400, - IN_BUILD_Q1 = 0x00000800, - IN_BUILD_Q2 = 0x00001000, + MESH_DIRTY = 0x00000100, + NEW_DRAWINFO = 0x00000200, + IN_BUILD_Q1 = 0x00000400, + IN_BUILD_Q2 = 0x00000800, STATE_MASK = 0x0000FFFF, } eSpatialState; @@ -313,10 +312,9 @@ public: BOOL boundObjects(BOOL empty, LLVector4a& newMin, LLVector4a& newMax); void unbound(); BOOL rebound(); - void buildOcclusion(); //rebuild mOcclusionVerts void checkOcclusion(); //read back last occlusion query (if any) void doOcclusion(LLCamera* camera); //issue occlusion query - void destroyGL(); + void destroyGL(bool keep_occlusion = false); void updateDistance(LLCamera& camera); BOOL needsUpdate(); @@ -378,6 +376,8 @@ public: LLVector4a mObjectBounds[2]; // bounding box (center, size) of objects in this node LLVector4a mViewAngle; LLVector4a mLastUpdateViewAngle; + + F32 mObjectBoxSize; //cached mObjectBounds[1].getLength3() private: U32 mCurUpdatingTime ; @@ -413,7 +413,6 @@ public: LLSpatialPartition* mSpatialPartition; LLPointer<LLVertexBuffer> mVertexBuffer; - LLPointer<LLVertexBuffer> mOcclusionVerts; GLuint mOcclusionQuery[LLViewerCamera::NUM_CAMERAS]; U32 mBufferUsage; @@ -655,6 +654,7 @@ class LLParticlePartition : public LLSpatialPartition { public: LLParticlePartition(); + virtual void rebuildGeom(LLSpatialGroup* group); virtual void getGeometry(LLSpatialGroup* group); virtual void addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32& index_count); virtual F32 calcPixelArea(LLSpatialGroup* group, LLCamera& camera); @@ -669,10 +669,14 @@ public: }; //spatial partition for grass (implemented in LLVOGrass.cpp) -class LLGrassPartition : public LLParticlePartition +class LLGrassPartition : public LLSpatialPartition { public: LLGrassPartition(); + virtual void getGeometry(LLSpatialGroup* group); + virtual void addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32& index_count); +protected: + U32 mRenderPass; }; //class for wrangling geometry out of volumes (implemented in LLVOVolume.cpp) diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 65fd6d7019..0b70184920 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -240,6 +240,7 @@ static bool mLoginStatePastUI = false; boost::scoped_ptr<LLEventPump> LLStartUp::sStateWatcher(new LLEventStream("StartupState")); boost::scoped_ptr<LLStartupListener> LLStartUp::sListener(new LLStartupListener()); +boost::scoped_ptr<LLViewerStats::PhaseMap> LLStartUp::sPhases(new LLViewerStats::PhaseMap); // // local function declaration @@ -739,6 +740,7 @@ bool idle_startup() { display_startup(); initialize_edit_menu(); + initialize_spellcheck_menu(); display_startup(); init_menus(); display_startup(); @@ -2699,7 +2701,10 @@ void LLStartUp::setStartupState( EStartupState state ) LL_INFOS("AppInit") << "Startup state changing from " << getStartupStateString() << " to " << startupStateToString(state) << LL_ENDL; + + sPhases->stopPhase(getStartupStateString()); gStartupState = state; + sPhases->startPhase(getStartupStateString()); postStartupState(); } @@ -3205,17 +3210,6 @@ bool process_login_success_response() gSavedSettings.setU32("PreferredMaturity", preferredMaturity); } - // During the AO transition, this flag will be true. Then the flag will - // go away. After the AO transition, this code and all the code that - // uses it can be deleted. - text = response["ao_transition"].asString(); - if (!text.empty()) - { - if (text == "1") - { - gAgent.setAOTransition(); - } - } text = response["start_location"].asString(); if(!text.empty()) diff --git a/indra/newview/llstartup.h b/indra/newview/llstartup.h index 0a18ef1b2d..3754aaf966 100644 --- a/indra/newview/llstartup.h +++ b/indra/newview/llstartup.h @@ -34,6 +34,8 @@ class LLEventPump; class LLStartupListener; class LLSLURL; +#include "llviewerstats.h" + // functions bool idle_startup(); void release_start_screen(); @@ -113,6 +115,7 @@ public: static bool startLLProxy(); // Initialize the SOCKS 5 proxy + static LLViewerStats::PhaseMap& getPhases() { return *sPhases; } private: static LLSLURL sStartSLURL; @@ -120,6 +123,7 @@ private: static EStartupState gStartupState; // Do not set directly, use LLStartup::setStartupState static boost::scoped_ptr<LLEventPump> sStateWatcher; static boost::scoped_ptr<LLStartupListener> sListener; + static boost::scoped_ptr<LLViewerStats::PhaseMap> sPhases; }; diff --git a/indra/newview/lltexlayer.cpp b/indra/newview/lltexlayer.cpp index 6f6d5dbf12..467115c928 100644 --- a/indra/newview/lltexlayer.cpp +++ b/indra/newview/lltexlayer.cpp @@ -55,6 +55,9 @@ using namespace LLVOAvatarDefines; static const S32 BAKE_UPLOAD_ATTEMPTS = 7; static const F32 BAKE_UPLOAD_RETRY_DELAY = 2.f; // actual delay grows by power of 2 each attempt +// runway consolidate +extern std::string self_av_string(); + class LLTexLayerInfo { friend class LLTexLayer; @@ -494,7 +497,6 @@ void LLTexLayerSetBuffer::doUpload() } LLPointer<LLImageJ2C> compressedImage = new LLImageJ2C; - compressedImage->setRate(0.f); const char* comment_text = LINDEN_J2C_COMMENT_PREFIX "RGBHM"; // writes into baked_color_data. 5 channels (rgb, heightfield/alpha, mask) if (compressedImage->encode(baked_image, comment_text)) { @@ -577,7 +579,7 @@ void LLTexLayerSetBuffer::doUpload() args["BODYREGION"] = mTexLayerSet->getBodyRegionName(); args["RESOLUTION"] = lod_str; LLNotificationsUtil::add("AvatarRezSelfBakedTextureUploadNotification",args); - llinfos << "Uploading [ name: " << mTexLayerSet->getBodyRegionName() << " res:" << lod_str << " time:" << (U32)mNeedsUploadTimer.getElapsedTimeF32() << " ]" << llendl; + LL_DEBUGS("Avatar") << self_av_string() << "Uploading [ name: " << mTexLayerSet->getBodyRegionName() << " res:" << lod_str << " time:" << (U32)mNeedsUploadTimer.getElapsedTimeF32() << " ]" << LL_ENDL; } } else @@ -631,7 +633,7 @@ void LLTexLayerSetBuffer::doUpdate() args["BODYREGION"] = mTexLayerSet->getBodyRegionName(); args["RESOLUTION"] = lod_str; LLNotificationsUtil::add("AvatarRezSelfBakedTextureUpdateNotification",args); - llinfos << "Locally updating [ name: " << mTexLayerSet->getBodyRegionName() << " res:" << lod_str << " time:" << (U32)mNeedsUpdateTimer.getElapsedTimeF32() << " ]" << llendl; + LL_DEBUGS("Avatar") << self_av_string() << "Locally updating [ name: " << mTexLayerSet->getBodyRegionName() << " res:" << lod_str << " time:" << (U32)mNeedsUpdateTimer.getElapsedTimeF32() << " ]" << LL_ENDL; } } diff --git a/indra/newview/lltextureatlas.cpp b/indra/newview/lltextureatlas.cpp index d2e4b01732..f8c1bca8ae 100644 --- a/indra/newview/lltextureatlas.cpp +++ b/indra/newview/lltextureatlas.cpp @@ -116,7 +116,6 @@ LLGLuint LLTextureAtlas::insertSubTexture(LLImageGL* source_gl_tex, S32 discard_ return 0 ; } - glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, TRUE); glTexSubImage2D(GL_TEXTURE_2D, 0, xoffset, yoffset, w, h, mGLTexturep->getPrimaryFormat(), mGLTexturep->getFormatType(), raw_image->getData()); diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index cb59f704a5..2d3f144588 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -98,6 +98,7 @@ public: LLTextureCtrl* owner, const std::string& label, PermissionMask immediate_filter_perm_mask, + PermissionMask dnd_filter_perm_mask, PermissionMask non_immediate_filter_perm_mask, BOOL can_apply_immediately, LLUIImagePtr fallback_image_name); @@ -135,6 +136,9 @@ public: void onFilterEdit(const std::string& search_string ); + void setCanApply(bool can_preview, bool can_apply); + void setTextureSelectedCallback(texture_selected_callback cb) {mTextureSelectedCallback = cb;} + static void onBtnSetToDefault( void* userdata ); static void onBtnSelect( void* userdata ); static void onBtnCancel( void* userdata ); @@ -176,6 +180,7 @@ protected: LLFilterEditor* mFilterEdit; LLInventoryPanel* mInventoryPanel; PermissionMask mImmediateFilterPermMask; + PermissionMask mDnDFilterPermMask; PermissionMask mNonImmediateFilterPermMask; BOOL mCanApplyImmediately; BOOL mNoCopyTextureSelected; @@ -185,12 +190,18 @@ protected: LLRadioGroup* mModeSelector; LLScrollListCtrl* mLocalScrollCtrl; + +private: + bool mCanApply; + bool mCanPreview; + texture_selected_callback mTextureSelectedCallback; }; LLFloaterTexturePicker::LLFloaterTexturePicker( LLTextureCtrl* owner, const std::string& label, PermissionMask immediate_filter_perm_mask, + PermissionMask dnd_filter_perm_mask, PermissionMask non_immediate_filter_perm_mask, BOOL can_apply_immediately, LLUIImagePtr fallback_image) @@ -206,9 +217,12 @@ LLFloaterTexturePicker::LLFloaterTexturePicker( mActive( TRUE ), mFilterEdit(NULL), mImmediateFilterPermMask(immediate_filter_perm_mask), + mDnDFilterPermMask(dnd_filter_perm_mask), mNonImmediateFilterPermMask(non_immediate_filter_perm_mask), mContextConeOpacity(0.f), - mSelectedItemPinned( FALSE ) + mSelectedItemPinned( FALSE ), + mCanApply(true), + mCanPreview(true) { buildFromFile("floater_texture_ctrl.xml"); mCanApplyImmediately = can_apply_immediately; @@ -320,7 +334,7 @@ BOOL LLFloaterTexturePicker::handleDragAndDrop( if (xfer) item_perm_mask |= PERM_TRANSFER; //PermissionMask filter_perm_mask = getFilterPermMask(); Commented out due to no-copy texture loss. - PermissionMask filter_perm_mask = mImmediateFilterPermMask; + PermissionMask filter_perm_mask = mDnDFilterPermMask; if ( (item_perm_mask & filter_perm_mask) == filter_perm_mask ) { if (drop) @@ -465,7 +479,7 @@ BOOL LLFloaterTexturePicker::postBuild() mNoCopyTextureSelected = FALSE; - getChild<LLUICtrl>("apply_immediate_check")->setValue(gSavedSettings.getBOOL("ApplyTextureImmediately")); + getChild<LLUICtrl>("apply_immediate_check")->setValue(gSavedSettings.getBOOL("TextureLivePreview")); childSetCommitCallback("apply_immediate_check", onApplyImmediateCheck, this); if (!mCanApplyImmediately) @@ -547,7 +561,7 @@ void LLFloaterTexturePicker::draw() // if we're inactive, gray out "apply immediate" checkbox getChildView("show_folders_check")->setEnabled(mActive && mCanApplyImmediately && !mNoCopyTextureSelected); - getChildView("Select")->setEnabled(mActive); + getChildView("Select")->setEnabled(mActive && mCanApply); getChildView("Pipette")->setEnabled(mActive); getChild<LLUICtrl>("Pipette")->setValue(LLToolMgr::getInstance()->getCurrentTool() == LLToolPipette::getInstance()); @@ -703,8 +717,7 @@ PermissionMask LLFloaterTexturePicker::getFilterPermMask() void LLFloaterTexturePicker::commitIfImmediateSet() { - bool apply_immediate = getChild<LLUICtrl>("apply_immediate_check")->getValue().asBoolean(); - if (!mNoCopyTextureSelected && apply_immediate && mOwner) + if (!mNoCopyTextureSelected && mOwner && mCanApply) { mOwner->onFloaterCommit(LLTextureCtrl::TEXTURE_CHANGE); } @@ -714,6 +727,7 @@ void LLFloaterTexturePicker::commitIfImmediateSet() void LLFloaterTexturePicker::onBtnSetToDefault(void* userdata) { LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata; + self->setCanApply(true, true); if (self->mOwner) { self->setImageID( self->mOwner->getDefaultImageAssetID() ); @@ -725,6 +739,7 @@ void LLFloaterTexturePicker::onBtnSetToDefault(void* userdata) void LLFloaterTexturePicker::onBtnWhite(void* userdata) { LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata; + self->setCanApply(true, true); self->setImageID( self->mWhiteImageAssetID ); self->commitIfImmediateSet(); } @@ -805,13 +820,17 @@ void LLFloaterTexturePicker::onSelectionChange(const std::deque<LLFolderViewItem mNoCopyTextureSelected = FALSE; if (itemp) { + if (!mTextureSelectedCallback.empty()) + { + mTextureSelectedCallback(itemp); + } if (!itemp->getPermissions().allowCopyBy(gAgent.getID())) { mNoCopyTextureSelected = TRUE; } mImageAssetID = itemp->getAssetUUID(); mViewModel->setDirty(); // *TODO: shouldn't we be using setValue() here? - if (user_action) + if (user_action && mCanPreview) { // only commit intentional selections, not implicit ones commitIfImmediateSet(); @@ -948,7 +967,7 @@ void LLFloaterTexturePicker::onApplyImmediateCheck(LLUICtrl* ctrl, void *user_da LLFloaterTexturePicker* picker = (LLFloaterTexturePicker*)user_data; LLCheckBoxCtrl* check_box = (LLCheckBoxCtrl*)ctrl; - gSavedSettings.setBOOL("ApplyTextureImmediately", check_box->get()); + gSavedSettings.setBOOL("TextureLivePreview", check_box->get()); picker->updateFilterPermMask(); picker->commitIfImmediateSet(); @@ -959,6 +978,16 @@ void LLFloaterTexturePicker::updateFilterPermMask() //mInventoryPanel->setFilterPermMask( getFilterPermMask() ); Commented out due to no-copy texture loss. } +void LLFloaterTexturePicker::setCanApply(bool can_preview, bool can_apply) +{ + getChildRef<LLUICtrl>("Select").setEnabled(can_apply); + getChildRef<LLUICtrl>("preview_disabled").setVisible(!can_preview); + getChildRef<LLUICtrl>("apply_immediate_check").setVisible(can_preview); + + mCanApply = can_apply; + mCanPreview = can_preview ? gSavedSettings.getBOOL("TextureLivePreview") : false; +} + void LLFloaterTexturePicker::onFilterEdit(const std::string& search_string ) { std::string upper_case_search_string = search_string; @@ -1109,6 +1138,15 @@ void LLTextureCtrl::setCanApplyImmediately(BOOL b) } } +void LLTextureCtrl::setCanApply(bool can_preview, bool can_apply) +{ + LLFloaterTexturePicker* floaterp = dynamic_cast<LLFloaterTexturePicker*>(mFloaterHandle.get()); + if( floaterp ) + { + floaterp->setCanApply(can_preview, can_apply); + } +} + void LLTextureCtrl::setVisible( BOOL visible ) { if( !visible ) @@ -1189,12 +1227,19 @@ void LLTextureCtrl::showPicker(BOOL take_focus) this, mLabel, mImmediateFilterPermMask, + mDnDFilterPermMask, mNonImmediateFilterPermMask, mCanApplyImmediately, mFallbackImage); mFloaterHandle = floaterp->getHandle(); + LLFloaterTexturePicker* texture_floaterp = dynamic_cast<LLFloaterTexturePicker*>(floaterp); + if (texture_floaterp && mOnTextureSelectedCallback) + { + texture_floaterp->setTextureSelectedCallback(mOnTextureSelectedCallback); + } + LLFloater* root_floater = gFloaterView->getParentFloater(this); if (root_floater) root_floater->addDependentFloater(floaterp); @@ -1319,6 +1364,16 @@ void LLTextureCtrl::onFloaterCommit(ETexturePickOp op, LLUUID id) } } +void LLTextureCtrl::setOnTextureSelectedCallback(texture_selected_callback cb) +{ + mOnTextureSelectedCallback = cb; + LLFloaterTexturePicker* floaterp = dynamic_cast<LLFloaterTexturePicker*>(mFloaterHandle.get()); + if (floaterp) + { + floaterp->setTextureSelectedCallback(cb); + } +} + void LLTextureCtrl::setImageAssetName(const std::string& name) { LLPointer<LLUIImage> imagep = LLUI::getUIImage(name); diff --git a/indra/newview/lltexturectrl.h b/indra/newview/lltexturectrl.h index 3abe84dcc3..599d9c70c5 100644 --- a/indra/newview/lltexturectrl.h +++ b/indra/newview/lltexturectrl.h @@ -43,6 +43,7 @@ class LLViewerFetchedTexture; // used for setting drag & drop callbacks. typedef boost::function<BOOL (LLUICtrl*, LLInventoryItem*)> drag_n_drop_callback; +typedef boost::function<void (LLInventoryItem*)> texture_selected_callback; ////////////////////////////////////////////////////////////////////////////////////////// @@ -147,8 +148,12 @@ public: void setCaption(const std::string& caption); void setCanApplyImmediately(BOOL b); + void setCanApply(bool can_preview, bool can_apply); + void setImmediateFilterPermMask(PermissionMask mask) { mImmediateFilterPermMask = mask; } + void setDnDFilterPermMask(PermissionMask mask) + { mDnDFilterPermMask = mask; } void setNonImmediateFilterPermMask(PermissionMask mask) { mNonImmediateFilterPermMask = mask; } PermissionMask getImmediateFilterPermMask() { return mImmediateFilterPermMask; } @@ -172,6 +177,11 @@ public: void setOnSelectCallback(commit_callback_t cb) { mOnSelectCallback = cb; } + /* + * callback for changing texture selection in inventory list of texture floater + */ + void setOnTextureSelectedCallback(texture_selected_callback cb); + void setShowLoadingPlaceholder(BOOL showLoadingPlaceholder); LLViewerFetchedTexture* getTexture() { return mTexturep; } @@ -185,6 +195,7 @@ private: drag_n_drop_callback mDropCallback; commit_callback_t mOnCancelCallback; commit_callback_t mOnSelectCallback; + texture_selected_callback mOnTextureSelectedCallback; LLPointer<LLViewerFetchedTexture> mTexturep; LLUIColor mBorderColor; LLUUID mImageItemID; @@ -198,6 +209,7 @@ private: std::string mLabel; BOOL mAllowNoTexture; // If true, the user can select "none" as an option PermissionMask mImmediateFilterPermMask; + PermissionMask mDnDFilterPermMask; PermissionMask mNonImmediateFilterPermMask; BOOL mCanApplyImmediately; BOOL mCommitOnSelection; diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index f18aa8b4e6..7e6dfbc9d9 100644..100755 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -52,12 +52,20 @@ #include "llviewerstats.h" #include "llviewerassetstats.h" #include "llworld.h" +#include "llsdutil.h" +#include "llstartup.h" +#include "llviewerstats.h" + +bool LLTextureFetchDebugger::sDebuggerEnabled = false ; +LLStat LLTextureFetch::sCacheHitRate("texture_cache_hits", 128); +LLStat LLTextureFetch::sCacheReadLatency("texture_cache_read_latency", 128); ////////////////////////////////////////////////////////////////////////////// class LLTextureFetchWorker : public LLWorkerClass { friend class LLTextureFetch; friend class HTTPGetResponder; + friend class LLTextureFetchDebugger; private: class CacheReadResponder : public LLTextureCache::ReadResponder @@ -242,6 +250,8 @@ private: S32 mDecodedDiscard; LLFrameTimer mRequestedTimer; LLFrameTimer mFetchTimer; + LLTimer mCacheReadTimer; + F32 mCacheReadTime; LLTextureCache::handle_t mCacheReadHandle; LLTextureCache::handle_t mCacheWriteHandle; U8* mBuffer; @@ -258,6 +268,7 @@ private: BOOL mNeedsAux; BOOL mHaveAllData; BOOL mInLocalCache; + BOOL mInCache; bool mCanUseHTTP ; bool mCanUseNET ; //can get from asset server. S32 mHTTPFailCount; @@ -653,6 +664,7 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher, mRequestedDiscard(-1), mLoadedDiscard(-1), mDecodedDiscard(-1), + mCacheReadTime(0.f), mCacheReadHandle(LLTextureCache::nullHandle()), mCacheWriteHandle(LLTextureCache::nullHandle()), mBuffer(NULL), @@ -669,6 +681,7 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher, mNeedsAux(FALSE), mHaveAllData(FALSE), mInLocalCache(FALSE), + mInCache(FALSE), mCanUseHTTP(true), mHTTPFailCount(0), mRetryAttempt(0), @@ -838,6 +851,8 @@ void LLTextureFetchWorker::startWork(S32 param) // Called from LLWorkerThread::processRequest() bool LLTextureFetchWorker::doWork(S32 param) { + static const F32 FETCHING_TIMEOUT = 120.f;//seconds + LLMutexLock lock(&mWorkMutex); if ((mFetcher->isQuitting() || getFlags(LLWorkerClass::WCF_DELETE_REQUESTED))) @@ -896,6 +911,7 @@ bool LLTextureFetchWorker::doWork(S32 param) mCacheReadHandle = LLTextureCache::nullHandle(); mCacheWriteHandle = LLTextureCache::nullHandle(); mState = LOAD_FROM_TEXTURE_CACHE; + mInCache = FALSE; mDesiredSize = llmax(mDesiredSize, TEXTURE_CACHE_ENTRY_SIZE); // min desired size is TEXTURE_CACHE_ENTRY_SIZE LL_DEBUGS("Texture") << mID << ": Priority: " << llformat("%8.0f",mImagePriority) << " Desired Discard: " << mDesiredDiscard << " Desired Size: " << mDesiredSize << LL_ENDL; @@ -926,6 +942,7 @@ bool LLTextureFetchWorker::doWork(S32 param) CacheReadResponder* responder = new CacheReadResponder(mFetcher, mID, mFormattedImage); mCacheReadHandle = mFetcher->mTextureCache->readFromCache(filename, mID, cache_priority, offset, size, responder); + mCacheReadTimer.reset(); } else if (mUrl.empty()) { @@ -934,6 +951,7 @@ bool LLTextureFetchWorker::doWork(S32 param) CacheReadResponder* responder = new CacheReadResponder(mFetcher, mID, mFormattedImage); mCacheReadHandle = mFetcher->mTextureCache->readFromCache(mID, cache_priority, offset, size, responder); + mCacheReadTimer.reset(); } else if(mCanUseHTTP) { @@ -982,11 +1000,12 @@ bool LLTextureFetchWorker::doWork(S32 param) llassert_always(mFormattedImage->getDataSize() > 0); mLoadedDiscard = mDesiredDiscard; mState = DECODE_IMAGE; + mInCache = TRUE; mWriteToCacheState = NOT_WRITE ; LL_DEBUGS("Texture") << mID << ": Cached. Bytes: " << mFormattedImage->getDataSize() << " Size: " << llformat("%dx%d",mFormattedImage->getWidth(),mFormattedImage->getHeight()) << " Desired Discard: " << mDesiredDiscard << " Desired Size: " << mDesiredSize << LL_ENDL; - // fall through + LLTextureFetch::sCacheHitRate.addValue(100.f); } else { @@ -1002,6 +1021,7 @@ bool LLTextureFetchWorker::doWork(S32 param) mState = LOAD_FROM_NETWORK; } // fall through + LLTextureFetch::sCacheHitRate.addValue(0.f); } } @@ -1177,6 +1197,8 @@ bool LLTextureFetchWorker::doWork(S32 param) bool res = false; if (!mUrl.empty()) { + mRequestedTimer.reset(); + mLoaded = FALSE; mGetStatus = 0; mGetReason.clear(); @@ -1335,6 +1357,13 @@ bool LLTextureFetchWorker::doWork(S32 param) } else { + if(FETCHING_TIMEOUT < mRequestedTimer.getElapsedTimeF32()) + { + //timeout, abort. + mState = DONE; + return true; + } + setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); return false; } @@ -1396,6 +1425,11 @@ bool LLTextureFetchWorker::doWork(S32 param) { if (mDecoded) { + if(mFetcher->getFetchDebugger() && !mInLocalCache) + { + mFetcher->getFetchDebugger()->addHistoryEntry(this); + } + if (mDecodedDiscard < 0) { LL_DEBUGS("Texture") << mID << ": Failed to Decode." << LL_ENDL; @@ -1780,6 +1814,7 @@ void LLTextureFetchWorker::callbackDecoded(bool success, LLImageRaw* raw, LLImag mDecoded = TRUE; // llinfos << mID << " : DECODE COMPLETE " << llendl; setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); + mCacheReadTime = mCacheReadTimer.getElapsedTimeF32(); } ////////////////////////////////////////////////////////////////////////////// @@ -1824,11 +1859,19 @@ LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* image mHTTPTextureBits(0), mTotalHTTPRequests(0), mCurlGetRequest(NULL), - mQAMode(qa_mode) + mQAMode(qa_mode), + mFetchDebugger(NULL), + mFetcherLocked(FALSE) { mCurlPOSTRequestCount = 0; mMaxBandwidth = gSavedSettings.getF32("ThrottleBandwidthKBPS"); mTextureInfo.setUpLogging(gSavedSettings.getBOOL("LogTextureDownloadsToViewerLog"), gSavedSettings.getBOOL("LogTextureDownloadsToSimulator"), gSavedSettings.getU32("TextureLoggingThreshold")); + + LLTextureFetchDebugger::sDebuggerEnabled = gSavedSettings.getBOOL("TextureFetchDebuggerEnabled"); + if(LLTextureFetchDebugger::isEnabled()) + { + mFetchDebugger = new LLTextureFetchDebugger(this, cache, imagedecodethread) ; + } } LLTextureFetch::~LLTextureFetch() @@ -1843,11 +1886,17 @@ LLTextureFetch::~LLTextureFetch() } // ~LLQueuedThread() called here + + delete mFetchDebugger; } bool LLTextureFetch::createRequest(const std::string& url, const LLUUID& id, const LLHost& host, F32 priority, S32 w, S32 h, S32 c, S32 desired_discard, bool needs_aux, bool can_use_http) { + if(mFetcherLocked) + { + return false; + } if (mDebugPause) { return false; @@ -2092,6 +2141,11 @@ bool LLTextureFetch::getRequestFinished(const LLUUID& id, S32& discard_level, discard_level = worker->mDecodedDiscard; raw = worker->mRawImage; aux = worker->mAuxImage; + F32 cache_read_time = worker->mCacheReadTime; + if (cache_read_time != 0.f) + { + sCacheReadLatency.addValue(cache_read_time * 1000.f); + } res = true; LL_DEBUGS("Texture") << id << ": Request Finished. State: " << worker->mState << " Discard: " << discard_level << LL_ENDL; worker->unlockWorkMutex(); @@ -2222,7 +2276,13 @@ S32 LLTextureFetch::update(F32 max_time_ms) if (!mDebugPause) { - sendRequestListToSimulators(); + // this is the startup state when send_complete_agent_movement() message is sent. + // Before this, the RequestImages message sent by sendRequestListToSimulators + // won't work so don't bother trying + if (LLStartUp::getStartupState() > STATE_AGENT_SEND) + { + sendRequestListToSimulators(); + } } if (!mThreaded) @@ -2258,6 +2318,11 @@ void LLTextureFetch::startThread() { // Construct mCurlGetRequest from Worker Thread mCurlGetRequest = new LLCurlRequest(); + + if(mFetchDebugger) + { + mFetchDebugger->setCurlGetRequest(mCurlGetRequest); + } } // WORKER THREAD @@ -2266,6 +2331,10 @@ void LLTextureFetch::endThread() // Destroy mCurlGetRequest from Worker Thread delete mCurlGetRequest; mCurlGetRequest = NULL; + if(mFetchDebugger) + { + mFetchDebugger->setCurlGetRequest(NULL); + } } // WORKER THREAD @@ -2803,7 +2872,6 @@ void LLTextureFetch::cmdDoWork() } } - ////////////////////////////////////////////////////////////////////////////// // Private (anonymous) class methods implementing the command scheme. @@ -2959,7 +3027,7 @@ TFReqSendMetrics::doWork(LLTextureFetch * fetcher) // In QA mode, Metrics submode, log the result for ease of testing if (fetcher->isQAMode()) { - LL_INFOS("Textures") << merged_llsd << LL_ENDL; + LL_INFOS("Textures") << ll_pretty_print_sd(merged_llsd) << LL_ENDL; } gViewerAssetStatsThread1->reset(); @@ -3007,5 +3075,659 @@ truncate_viewer_metrics(int max_regions, LLSD & metrics) } // end of anonymous namespace +/////////////////////////////////////////////////////////////////////////////////////////// +//Start LLTextureFetchDebugger +/////////////////////////////////////////////////////////////////////////////////////////// +//--------------------- +class LLDebuggerCacheReadResponder : public LLTextureCache::ReadResponder +{ +public: + LLDebuggerCacheReadResponder(LLTextureFetchDebugger* debugger, S32 id, LLImageFormatted* image) + : mDebugger(debugger), mID(id) + { + setImage(image); + } + virtual void completed(bool success) + { + mDebugger->callbackCacheRead(mID, success, mFormattedImage, mImageSize, mImageLocal); + } +private: + LLTextureFetchDebugger* mDebugger; + S32 mID; +}; + +class LLDebuggerCacheWriteResponder : public LLTextureCache::WriteResponder +{ +public: + LLDebuggerCacheWriteResponder(LLTextureFetchDebugger* debugger, S32 id) + : mDebugger(debugger), mID(id) + { + } + virtual void completed(bool success) + { + mDebugger->callbackCacheWrite(mID, success); + } +private: + LLTextureFetchDebugger* mDebugger; + S32 mID; +}; + +class LLDebuggerDecodeResponder : public LLImageDecodeThread::Responder +{ +public: + LLDebuggerDecodeResponder(LLTextureFetchDebugger* debugger, S32 id) + : mDebugger(debugger), mID(id) + { + } + virtual void completed(bool success, LLImageRaw* raw, LLImageRaw* aux) + { + mDebugger->callbackDecoded(mID, success, raw, aux); + } +private: + LLTextureFetchDebugger* mDebugger; + S32 mID; +}; + +class LLDebuggerHTTPResponder : public LLCurl::Responder +{ +public: + LLDebuggerHTTPResponder(LLTextureFetchDebugger* debugger, S32 index) + : mDebugger(debugger), mIndex(index) + { + } + virtual void completedRaw(U32 status, const std::string& reason, + const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer) + { + bool success = false; + bool partial = false; + if (HTTP_OK <= status && status < HTTP_MULTIPLE_CHOICES) + { + success = true; + if (HTTP_PARTIAL_CONTENT == status) // partial information + { + partial = true; + } + } + if (!success) + { + llinfos << "Fetch Debugger : CURL GET FAILED, index = " << mIndex << ", status:" << status << " reason:" << reason << llendl; + } + mDebugger->callbackHTTP(mIndex, channels, buffer, partial, success); + } + virtual bool followRedir() + { + return true; + } +private: + LLTextureFetchDebugger* mDebugger; + S32 mIndex; +}; + +LLTextureFetchDebugger::LLTextureFetchDebugger(LLTextureFetch* fetcher, LLTextureCache* cache, LLImageDecodeThread* imagedecodethread) : + mFetcher(fetcher), + mTextureCache(cache), + mImageDecodeThread(imagedecodethread), + mCurlGetRequest(NULL) +{ + init(); +} + +LLTextureFetchDebugger::~LLTextureFetchDebugger() +{ + mFetchingHistory.clear(); + stopDebug(); +} + +void LLTextureFetchDebugger::init() +{ + mState = IDLE; + + mCacheReadTime = -1.f; + mCacheWriteTime = -1.f; + mDecodingTime = -1.f; + mHTTPTime = -1.f; + mGLCreationTime = -1.f; + mTotalFetchingTime = 0.f; + mRefetchVisCacheTime = -1.f; + mRefetchVisHTTPTime = -1.f; + + mNumFetchedTextures = 0; + mNumCacheHits = 0; + mNumVisibleFetchedTextures = 0; + mNumVisibleFetchingRequests = 0; + mFetchedData = 0; + mDecodedData = 0; + mVisibleFetchedData = 0; + mVisibleDecodedData = 0; + mRenderedData = 0; + mRenderedDecodedData = 0; + mFetchedPixels = 0; + mRenderedPixels = 0; + mRefetchedData = 0; + mRefetchedPixels = 0; + + mFreezeHistory = FALSE; +} + +void LLTextureFetchDebugger::startDebug() +{ + //lock the fetcher + mFetcher->lockFetcher(true); + mFreezeHistory = TRUE; + + //clear the current fetching queue + gTextureList.clearFetchingRequests(); + + //wait for all works to be done + while(1) + { + S32 pending = 0; + pending += LLAppViewer::getTextureCache()->update(1); + pending += LLAppViewer::getImageDecodeThread()->update(1); + pending += LLAppViewer::getTextureFetch()->update(1); + if(!pending) + { + break; + } + } + + //collect statistics + mTotalFetchingTime = gDebugTimers[0].getElapsedTimeF32() - mTotalFetchingTime; + + std::set<LLUUID> fetched_textures; + S32 size = mFetchingHistory.size(); + for(S32 i = 0 ; i < size; i++) + { + bool in_list = true; + if(fetched_textures.find(mFetchingHistory[i].mID) == fetched_textures.end()) + { + fetched_textures.insert(mFetchingHistory[i].mID); + in_list = false; + } + + LLViewerFetchedTexture* tex = LLViewerTextureManager::findFetchedTexture(mFetchingHistory[i].mID); + if(tex && tex->isJustBound()) //visible + { + if(!in_list) + { + mNumVisibleFetchedTextures++; + } + mNumVisibleFetchingRequests++; + + mVisibleFetchedData += mFetchingHistory[i].mFetchedSize; + mVisibleDecodedData += mFetchingHistory[i].mDecodedSize; + + if(tex->getDiscardLevel() >= mFetchingHistory[i].mDecodedLevel) + { + mRenderedData += mFetchingHistory[i].mFetchedSize; + mRenderedDecodedData += mFetchingHistory[i].mDecodedSize; + mRenderedPixels += tex->getWidth() * tex->getHeight(); + } + } + } + + mNumFetchedTextures = fetched_textures.size(); +} + +void LLTextureFetchDebugger::stopDebug() +{ + //clear the current debug work + S32 size = mFetchingHistory.size(); + switch(mState) + { + case READ_CACHE: + for(S32 i = 0 ; i < size; i++) + { + if (mFetchingHistory[i]. mCacheHandle != LLTextureCache::nullHandle()) + { + mTextureCache->readComplete(mFetchingHistory[i].mCacheHandle, true); + } + } + break; + case WRITE_CACHE: + for(S32 i = 0 ; i < size; i++) + { + if (mFetchingHistory[i].mCacheHandle != LLTextureCache::nullHandle()) + { + mTextureCache->writeComplete(mFetchingHistory[i].mCacheHandle, true); + } + } + break; + case DECODING: + break; + case HTTP_FETCHING: + break; + case GL_TEX: + break; + default: + break; + } + + while(1) + { + if(update()) + { + break; + } + } + + //unlock the fetcher + mFetcher->lockFetcher(false); + mFreezeHistory = FALSE; + mTotalFetchingTime = gDebugTimers[0].getElapsedTimeF32(); //reset +} + +//called in the main thread and when the fetching queue is empty +void LLTextureFetchDebugger::clearHistory() +{ + mFetchingHistory.clear(); + init(); +} + +void LLTextureFetchDebugger::addHistoryEntry(LLTextureFetchWorker* worker) +{ + if(mFreezeHistory) + { + mRefetchedPixels += worker->mRawImage->getWidth() * worker->mRawImage->getHeight(); + mRefetchedData += worker->mFormattedImage->getDataSize(); + return; + } + + if(worker->mInCache) + { + mNumCacheHits++; + } + mFetchedData += worker->mFormattedImage->getDataSize(); + mDecodedData += worker->mRawImage->getDataSize(); + mFetchedPixels += worker->mRawImage->getWidth() * worker->mRawImage->getHeight(); + + mFetchingHistory.push_back(FetchEntry(worker->mID, worker->mDesiredSize, worker->mDecodedDiscard, worker->mFormattedImage->getDataSize(), worker->mRawImage->getDataSize())); + //mFetchingHistory.push_back(FetchEntry(worker->mID, worker->mDesiredSize, worker->mHaveAllData ? 0 : worker->mLoadedDiscard, worker->mFormattedImage->getComponents(), + //worker->mDecodedDiscard, worker->mFormattedImage->getDataSize(), worker->mRawImage->getDataSize())); +} + +void LLTextureFetchDebugger::lockCache() +{ +} + +void LLTextureFetchDebugger::unlockCache() +{ +} + +void LLTextureFetchDebugger::debugCacheRead() +{ + lockCache(); + llassert_always(mState == IDLE); + mTimer.reset(); + mState = READ_CACHE; + + S32 size = mFetchingHistory.size(); + for(S32 i = 0 ; i < size ; i++) + { + mFetchingHistory[i].mFormattedImage = NULL; + mFetchingHistory[i].mCacheHandle = mTextureCache->readFromCache(mFetchingHistory[i].mID, LLWorkerThread::PRIORITY_NORMAL, 0, mFetchingHistory[i].mFetchedSize, + new LLDebuggerCacheReadResponder(this, i, mFetchingHistory[i].mFormattedImage)); + } +} + +void LLTextureFetchDebugger::clearCache() +{ + S32 size = mFetchingHistory.size(); + { + std::set<LLUUID> deleted_list; + for(S32 i = 0 ; i < size ; i++) + { + if(deleted_list.find(mFetchingHistory[i].mID) == deleted_list.end()) + { + deleted_list.insert(mFetchingHistory[i].mID); + mTextureCache->removeFromCache(mFetchingHistory[i].mID); + } + } + } +} + +void LLTextureFetchDebugger::debugCacheWrite() +{ + //remove from cache + clearCache(); + + lockCache(); + llassert_always(mState == IDLE); + mTimer.reset(); + mState = WRITE_CACHE; + + S32 size = mFetchingHistory.size(); + for(S32 i = 0 ; i < size ; i++) + { + if(mFetchingHistory[i].mFormattedImage.notNull()) + { + mFetchingHistory[i].mCacheHandle = mTextureCache->writeToCache(mFetchingHistory[i].mID, LLWorkerThread::PRIORITY_NORMAL, + mFetchingHistory[i].mFormattedImage->getData(), mFetchingHistory[i].mFetchedSize, + mFetchingHistory[i].mDecodedLevel == 0 ? mFetchingHistory[i].mFetchedSize : mFetchingHistory[i].mFetchedSize + 1, + new LLDebuggerCacheWriteResponder(this, i)); + } + } +} + +void LLTextureFetchDebugger::lockDecoder() +{ +} + +void LLTextureFetchDebugger::unlockDecoder() +{ +} + +void LLTextureFetchDebugger::debugDecoder() +{ + lockDecoder(); + llassert_always(mState == IDLE); + mTimer.reset(); + mState = DECODING; + + S32 size = mFetchingHistory.size(); + for(S32 i = 0 ; i < size ; i++) + { + if(mFetchingHistory[i].mFormattedImage.isNull()) + { + continue; + } + + mImageDecodeThread->decodeImage(mFetchingHistory[i].mFormattedImage, LLWorkerThread::PRIORITY_NORMAL, + mFetchingHistory[i].mDecodedLevel, mFetchingHistory[i].mNeedsAux, + new LLDebuggerDecodeResponder(this, i)); + } +} + +void LLTextureFetchDebugger::debugHTTP() +{ + llassert_always(mState == IDLE); + + LLViewerRegion* region = gAgent.getRegion(); + if (!region) + { + llinfos << "Fetch Debugger : Current region undefined. Cannot fetch textures through HTTP." << llendl; + return; + } + + mHTTPUrl = region->getHttpUrl(); + if (mHTTPUrl.empty()) + { + llinfos << "Fetch Debugger : Current region URL undefined. Cannot fetch textures through HTTP." << llendl; + return; + } + + mTimer.reset(); + mState = HTTP_FETCHING; + + S32 size = mFetchingHistory.size(); + for (S32 i = 0 ; i < size ; i++) + { + mFetchingHistory[i].mCurlState = FetchEntry::CURL_NOT_DONE; + mFetchingHistory[i].mCurlReceivedSize = 0; + mFetchingHistory[i].mHTTPFailCount = 0; + } + mNbCurlRequests = 0; + mNbCurlCompleted = 0; + + fillCurlQueue(); +} + +S32 LLTextureFetchDebugger::fillCurlQueue() +{ + if (mNbCurlRequests == 24) + return mNbCurlRequests; + + S32 size = mFetchingHistory.size(); + for (S32 i = 0 ; i < size ; i++) + { + if (mFetchingHistory[i].mCurlState != FetchEntry::CURL_NOT_DONE) + continue; + std::string texture_url = mHTTPUrl + "/?texture_id=" + mFetchingHistory[i].mID.asString().c_str(); + S32 requestedSize = mFetchingHistory[i].mRequestedSize; + // We request the whole file if the size was not set. + requestedSize = llmax(0,requestedSize); + // We request the whole file if the size was set to an absurdly high value (meaning all file) + requestedSize = (requestedSize == 33554432 ? 0 : requestedSize); + std::vector<std::string> headers; + headers.push_back("Accept: image/x-j2c"); + bool res = mCurlGetRequest->getByteRange(texture_url, headers, 0, requestedSize, new LLDebuggerHTTPResponder(this, i)); + if (res) + { + mFetchingHistory[i].mCurlState = FetchEntry::CURL_IN_PROGRESS; + mNbCurlRequests++; + // Hack + if (mNbCurlRequests == 24) + break; + } + else + { + break; + } + } + //llinfos << "Fetch Debugger : Having " << mNbCurlRequests << " requests through the curl thread." << llendl; + return mNbCurlRequests; +} + +void LLTextureFetchDebugger::debugGLTextureCreation() +{ + llassert_always(mState == IDLE); + mState = GL_TEX; + std::vector<LLViewerFetchedTexture*> tex_list; + + S32 size = mFetchingHistory.size(); + for(S32 i = 0 ; i < size ; i++) + { + if(mFetchingHistory[i].mRawImage.notNull()) + { + LLViewerFetchedTexture* tex = gTextureList.findImage(mFetchingHistory[i].mID) ; + if(tex && !tex->isForSculptOnly()) + { + tex->destroyGLTexture() ; + tex_list.push_back(tex); + } + } + } + + mTimer.reset(); + S32 j = 0 ; + S32 size1 = tex_list.size(); + for(S32 i = 0 ; i < size && j < size1; i++) + { + if(mFetchingHistory[i].mRawImage.notNull()) + { + if(mFetchingHistory[i].mID == tex_list[j]->getID()) + { + tex_list[j]->createGLTexture(mFetchingHistory[i].mDecodedLevel, mFetchingHistory[i].mRawImage, 0, TRUE, tex_list[j]->getBoostLevel()); + j++; + } + } + } + + mGLCreationTime = mTimer.getElapsedTimeF32() ; + return; +} + +//clear fetching results of all textures. +void LLTextureFetchDebugger::clearTextures() +{ + S32 size = mFetchingHistory.size(); + for(S32 i = 0 ; i < size ; i++) + { + LLViewerFetchedTexture* tex = gTextureList.findImage(mFetchingHistory[i].mID) ; + if(tex) + { + tex->clearFetchedResults() ; + } + } +} + +void LLTextureFetchDebugger::debugRefetchVisibleFromCache() +{ + llassert_always(mState == IDLE); + mState = REFETCH_VIS_CACHE; + + clearTextures(); + + mTimer.reset(); + mFetcher->lockFetcher(false); +} + +void LLTextureFetchDebugger::debugRefetchVisibleFromHTTP() +{ + llassert_always(mState == IDLE); + mState = REFETCH_VIS_HTTP; + + clearCache(); + clearTextures(); + + mTimer.reset(); + mFetcher->lockFetcher(false); +} + +bool LLTextureFetchDebugger::update() +{ + switch(mState) + { + case READ_CACHE: + if(!mTextureCache->update(1)) + { + mCacheReadTime = mTimer.getElapsedTimeF32() ; + mState = IDLE; + unlockCache(); + } + break; + case WRITE_CACHE: + if(!mTextureCache->update(1)) + { + mCacheWriteTime = mTimer.getElapsedTimeF32() ; + mState = IDLE; + unlockCache(); + } + break; + case DECODING: + if(!mImageDecodeThread->update(1)) + { + mDecodingTime = mTimer.getElapsedTimeF32() ; + mState = IDLE; + unlockDecoder(); + } + break; + case HTTP_FETCHING: + mCurlGetRequest->process(); + LLCurl::getCurlThread()->update(1); + if (!fillCurlQueue() && mNbCurlCompleted == mFetchingHistory.size()) + { + mHTTPTime = mTimer.getElapsedTimeF32() ; + mState = IDLE; + } + break; + case GL_TEX: + mState = IDLE; + break; + case REFETCH_VIS_CACHE: + if (LLAppViewer::getTextureFetch()->getNumRequests() == 0) + { + mRefetchVisCacheTime = gDebugTimers[0].getElapsedTimeF32() - mTotalFetchingTime; + mState = IDLE; + mFetcher->lockFetcher(true); + } + break; + case REFETCH_VIS_HTTP: + if (LLAppViewer::getTextureFetch()->getNumRequests() == 0) + { + mRefetchVisHTTPTime = gDebugTimers[0].getElapsedTimeF32() - mTotalFetchingTime; + mState = IDLE; + mFetcher->lockFetcher(true); + } + break; + default: + mState = IDLE; + break; + } + + return mState == IDLE; +} + +void LLTextureFetchDebugger::callbackCacheRead(S32 id, bool success, LLImageFormatted* image, + S32 imagesize, BOOL islocal) +{ + if (success) + { + mFetchingHistory[id].mFormattedImage = image; + } + mTextureCache->readComplete(mFetchingHistory[id].mCacheHandle, false); + mFetchingHistory[id].mCacheHandle = LLTextureCache::nullHandle(); +} + +void LLTextureFetchDebugger::callbackCacheWrite(S32 id, bool success) +{ + mTextureCache->writeComplete(mFetchingHistory[id].mCacheHandle); + mFetchingHistory[id].mCacheHandle = LLTextureCache::nullHandle(); +} + +void LLTextureFetchDebugger::callbackDecoded(S32 id, bool success, LLImageRaw* raw, LLImageRaw* aux) +{ + if (success) + { + llassert_always(raw); + mFetchingHistory[id].mRawImage = raw; + } +} + +void LLTextureFetchDebugger::callbackHTTP(S32 id, const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer, + bool partial, bool success) +{ + mNbCurlRequests--; + if (success) + { + mFetchingHistory[id].mCurlState = FetchEntry::CURL_DONE; + mNbCurlCompleted++; + + S32 data_size = buffer->countAfter(channels.in(), NULL); + mFetchingHistory[id].mCurlReceivedSize += data_size; + //llinfos << "Fetch Debugger : got results for " << id << ", data_size = " << data_size << ", received = " << mFetchingHistory[id].mCurlReceivedSize << ", requested = " << mFetchingHistory[id].mRequestedSize << ", partial = " << partial << llendl; + if ((mFetchingHistory[id].mCurlReceivedSize >= mFetchingHistory[id].mRequestedSize) || !partial || (mFetchingHistory[id].mRequestedSize == 600)) + { + U8* d_buffer = (U8*)ALLOCATE_MEM(LLImageBase::getPrivatePool(), data_size); + buffer->readAfter(channels.in(), NULL, d_buffer, data_size); + + llassert_always(mFetchingHistory[id].mFormattedImage.isNull()); + { + // For now, create formatted image based on extension + std::string texture_url = mHTTPUrl + "/?texture_id=" + mFetchingHistory[id].mID.asString().c_str(); + std::string extension = gDirUtilp->getExtension(texture_url); + mFetchingHistory[id].mFormattedImage = LLImageFormatted::createFromType(LLImageBase::getCodecFromExtension(extension)); + if (mFetchingHistory[id].mFormattedImage.isNull()) + { + mFetchingHistory[id].mFormattedImage = new LLImageJ2C; // default + } + } + + mFetchingHistory[id].mFormattedImage->setData(d_buffer, data_size); + } + } + else //failed + { + mFetchingHistory[id].mHTTPFailCount++; + if(mFetchingHistory[id].mHTTPFailCount < 5) + { + // Fetch will have to be redone + mFetchingHistory[id].mCurlState = FetchEntry::CURL_NOT_DONE; + } + else //skip + { + mFetchingHistory[id].mCurlState = FetchEntry::CURL_DONE; + mNbCurlCompleted++; + } + } +} + + +//--------------------- +/////////////////////////////////////////////////////////////////////////////////////////// +//End LLTextureFetchDebugger +/////////////////////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h index 35df7d816f..107e1623b0 100644 --- a/indra/newview/lltexturefetch.h +++ b/indra/newview/lltexturefetch.h @@ -34,14 +34,17 @@ #include "llcurl.h" #include "lltextureinfo.h" #include "llapr.h" +#include "llimageworker.h" +//#include "lltexturecache.h" class LLViewerTexture; class LLTextureFetchWorker; class HTTPGetResponder; -class LLTextureCache; class LLImageDecodeThread; class LLHost; class LLViewerAssetStats; +class LLTextureFetchDebugger; +class LLTextureCache; // Interface class class LLTextureFetch : public LLWorkerThread @@ -164,6 +167,9 @@ private: LLMutex mQueueMutex; //to protect mRequestMap and mCommands only LLMutex mNetworkQueueMutex; //to protect mNetworkQueue, mHTTPTextureQueue and mCancelQueue. + static LLStat sCacheHitRate; + static LLStat sCacheReadLatency; + LLTextureCache* mTextureCache; LLImageDecodeThread* mImageDecodeThread; LLCurlRequest* mCurlGetRequest; @@ -209,7 +215,195 @@ public: // attempt to log metrics follows a break in the metrics stream // reporting due to either startup or a problem POSTing data. static volatile bool svMetricsDataBreak; + +private: + //debug use + LLTextureFetchDebugger* mFetchDebugger; + bool mFetcherLocked; + +public: + //debug use + LLTextureFetchDebugger* getFetchDebugger() { return mFetchDebugger;} + void lockFetcher(bool lock) { mFetcherLocked = lock;} }; +//debug use +class LLTextureFetchDebugger +{ + friend class LLTextureFetch; +public: + LLTextureFetchDebugger(LLTextureFetch* fetcher, LLTextureCache* cache, LLImageDecodeThread* imagedecodethread) ; + ~LLTextureFetchDebugger(); + +public: + enum e_debug_state + { + IDLE = 0, + READ_CACHE, + WRITE_CACHE, + DECODING, + HTTP_FETCHING, + GL_TEX, + REFETCH_VIS_CACHE, + REFETCH_VIS_HTTP, + REFETCH_ALL_CACHE, + REFETCH_ALL_HTTP, + INVALID + }; + +private: + struct FetchEntry + { + enum e_curl_state + { + CURL_NOT_DONE = 0, + CURL_IN_PROGRESS, + CURL_DONE + }; + LLUUID mID; + S32 mRequestedSize; + S32 mDecodedLevel; + S32 mFetchedSize; + S32 mDecodedSize; + BOOL mNeedsAux; + U32 mCacheHandle; + LLPointer<LLImageFormatted> mFormattedImage; + LLPointer<LLImageRaw> mRawImage; + e_curl_state mCurlState; + S32 mCurlReceivedSize; + S32 mHTTPFailCount; + + FetchEntry() : + mDecodedLevel(-1), + mFetchedSize(0), + mDecodedSize(0) + {} + FetchEntry(LLUUID& id, S32 r_size, /*S32 f_discard, S32 c,*/ S32 level, S32 f_size, S32 d_size) : + mID(id), + mRequestedSize(r_size), + mDecodedLevel(level), + mFetchedSize(f_size), + mDecodedSize(d_size), + mNeedsAux(false), + mHTTPFailCount(0) + {} + }; + std::vector<FetchEntry> mFetchingHistory; + + e_debug_state mState; + + F32 mCacheReadTime; + F32 mCacheWriteTime; + F32 mDecodingTime; + F32 mHTTPTime; + F32 mGLCreationTime; + + F32 mTotalFetchingTime; + F32 mRefetchVisCacheTime; + F32 mRefetchVisHTTPTime; + + LLTimer mTimer; + + LLTextureFetch* mFetcher; + LLTextureCache* mTextureCache; + LLImageDecodeThread* mImageDecodeThread; + LLCurlRequest* mCurlGetRequest; + + S32 mNumFetchedTextures; + S32 mNumCacheHits; + S32 mNumVisibleFetchedTextures; + S32 mNumVisibleFetchingRequests; + U32 mFetchedData; + U32 mDecodedData; + U32 mVisibleFetchedData; + U32 mVisibleDecodedData; + U32 mRenderedData; + U32 mRenderedDecodedData; + U32 mFetchedPixels; + U32 mRenderedPixels; + U32 mRefetchedData; + U32 mRefetchedPixels; + + BOOL mFreezeHistory; + + std::string mHTTPUrl; + S32 mNbCurlRequests; + S32 mNbCurlCompleted; + +public: + bool update(); //called in the main thread once per frame + + //fetching history + void clearHistory(); + void addHistoryEntry(LLTextureFetchWorker* worker); + + void setCurlGetRequest(LLCurlRequest* request) { mCurlGetRequest = request;} + + void startDebug(); + void stopDebug(); //stop everything + void debugCacheRead(); + void debugCacheWrite(); + void debugHTTP(); + void debugDecoder(); + void debugGLTextureCreation(); + void debugRefetchVisibleFromCache(); + void debugRefetchVisibleFromHTTP(); + + void callbackCacheRead(S32 id, bool success, LLImageFormatted* image, + S32 imagesize, BOOL islocal); + void callbackCacheWrite(S32 id, bool success); + void callbackDecoded(S32 id, bool success, LLImageRaw* raw, LLImageRaw* aux); + void callbackHTTP(S32 id, const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer, + bool partial, bool success); + + + e_debug_state getState() {return mState;} + S32 getNumFetchedTextures() {return mNumFetchedTextures;} + S32 getNumFetchingRequests() {return mFetchingHistory.size();} + S32 getNumCacheHits() {return mNumCacheHits;} + S32 getNumVisibleFetchedTextures() {return mNumVisibleFetchedTextures;} + S32 getNumVisibleFetchingRequests() {return mNumVisibleFetchingRequests;} + U32 getFetchedData() {return mFetchedData;} + U32 getDecodedData() {return mDecodedData;} + U32 getVisibleFetchedData() {return mVisibleFetchedData;} + U32 getVisibleDecodedData() {return mVisibleDecodedData;} + U32 getRenderedData() {return mRenderedData;} + U32 getRenderedDecodedData() {return mRenderedDecodedData;} + U32 getFetchedPixels() {return mFetchedPixels;} + U32 getRenderedPixels() {return mRenderedPixels;} + U32 getRefetchedData() {return mRefetchedData;} + U32 getRefetchedPixels() {return mRefetchedPixels;} + + F32 getCacheReadTime() {return mCacheReadTime;} + F32 getCacheWriteTime() {return mCacheWriteTime;} + F32 getDecodeTime() {return mDecodingTime;} + F32 getGLCreationTime() {return mGLCreationTime;} + F32 getHTTPTime() {return mHTTPTime;} + F32 getTotalFetchingTime() {return mTotalFetchingTime;} + F32 getRefetchVisCacheTime() {return mRefetchVisCacheTime;} + F32 getRefetchVisHTTPTime() {return mRefetchVisHTTPTime;} + +private: + void init(); + void clearTextures();//clear fetching results of all textures. + void clearCache(); + + void lockFetcher(); + void unlockFetcher(); + + void lockCache(); + void unlockCache(); + + void lockDecoder(); + void unlockDecoder(); + + S32 fillCurlQueue(); + +private: + static bool sDebuggerEnabled; +public: + static bool isEnabled() {return sDebuggerEnabled;} +}; #endif // LL_LLTEXTUREFETCH_H diff --git a/indra/newview/lltextureview.cpp b/indra/newview/lltextureview.cpp index 5b41a05f2a..52d085dd2c 100644 --- a/indra/newview/lltextureview.cpp +++ b/indra/newview/lltextureview.cpp @@ -57,8 +57,6 @@ extern F32 texmem_lower_bound_scale; LLTextureView *gTextureView = NULL; -LLTextureSizeView *gTextureSizeView = NULL; -LLTextureSizeView *gTextureCategoryView = NULL; #define HIGH_PRIORITY 100000000.f @@ -513,7 +511,7 @@ void LLGLTexMemBar::draw() F32 cache_usage = (F32)BYTES_TO_MEGA_BYTES(LLAppViewer::getTextureCache()->getUsage()) ; F32 cache_max_usage = (F32)BYTES_TO_MEGA_BYTES(LLAppViewer::getTextureCache()->getMaxUsage()) ; S32 line_height = LLFontGL::getFontMonospace()->getLineHeight(); - S32 v_offset = (S32)((texture_bar_height + 2.2f) * mTextureView->mNumTextureBars + 2.0f); + S32 v_offset = 0;//(S32)((texture_bar_height + 2.2f) * mTextureView->mNumTextureBars + 2.0f); F32 total_texture_downloaded = (F32)gTotalTextureBytes / (1024 * 1024); F32 total_object_downloaded = (F32)gTotalObjectBytes / (1024 * 1024); U32 total_http_requests = LLAppViewer::getTextureFetch()->getTotalNumHTTPRequests() ; @@ -527,80 +525,24 @@ void LLGLTexMemBar::draw() LLFontGL::getFontMonospace()->renderUTF8(text, 0, 0, v_offset + line_height*6, text_color, LLFontGL::LEFT, LLFontGL::TOP); - text = llformat("GL Tot: %d/%d MB Bound: %d/%d MB FBO: %d MB Raw Tot: %d MB Bias: %.2f Cache: %.1f/%.1f MB Net Tot Tex: %.1f MB Tot Obj: %.1f MB Tot Htp: %d", + text = llformat("GL Tot: %d/%d MB Bound: %d/%d MB FBO: %d MB Raw Tot: %d MB Bias: %.2f Cache: %.1f/%.1f MB", total_mem, max_total_mem, bound_mem, max_bound_mem, LLRenderTarget::sBytesAllocated/(1024*1024), LLImageRaw::sGlobalRawMemory >> 20, discard_bias, - cache_usage, cache_max_usage, total_texture_downloaded, total_object_downloaded, total_http_requests); - //, cache_entries, cache_max_entries - - LLFontGL::getFontMonospace()->renderUTF8(text, 0, 0, v_offset + line_height*3, + cache_usage, cache_max_usage); + LLFontGL::getFontMonospace()->renderUTF8(text, 0, 0, v_offset + line_height*4, text_color, LLFontGL::LEFT, LLFontGL::TOP); - //---------------------------------------------------------------------------- -#if 0 - S32 bar_left = 400; - S32 bar_width = 200; - S32 top = line_height*3 - 2 + v_offset; - S32 bottom = top - 6; - S32 left = bar_left; - S32 right = left + bar_width; - F32 bar_scale; - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - // GL Mem Bar - - left = bar_left; - text = "GL"; - LLFontGL::getFontMonospace()->renderUTF8(text, 0, left, line_height*3, + text = llformat("Net Tot Tex: %.1f MB Tot Obj: %.1f MB Tot Htp: %d", + total_texture_downloaded, total_object_downloaded, total_http_requests); + //, cache_entries, cache_max_entries + LLFontGL::getFontMonospace()->renderUTF8(text, 0, 0, v_offset + line_height*3, text_color, LLFontGL::LEFT, LLFontGL::TOP); - - left = bar_left+20; - right = left + bar_width; - - gGL.color4f(0.5f, 0.5f, 0.5f, 0.75f); // grey - gl_rect_2d(left, top, right, bottom); - - bar_scale = (F32)bar_width / (max_total_mem * 1.5f); - right = left + llfloor(total_mem * bar_scale); - right = llclamp(right, bar_left, bar_left + bar_width); - - color = (total_mem < llfloor(max_total_mem * texmem_lower_bound_scale)) ? LLColor4::green : - (total_mem < max_total_mem) ? LLColor4::yellow : LLColor4::red; - color[VALPHA] = .75f; - gGL.diffuseColor4fv(color.mV); - - gl_rect_2d(left, top, right, bottom); // red/yellow/green - - // - bar_left += bar_width + bar_space; - //top = bottom - 2; bottom = top - 6; - - // Bound Mem Bar - - left = bar_left; - text = "GL"; - LLFontGL::getFontMonospace()->renderUTF8(text, 0, left, line_height*3, - text_color, LLFontGL::LEFT, LLFontGL::TOP); - left = bar_left + 20; - right = left + bar_width; - - gGL.color4f(0.5f, 0.5f, 0.5f, 0.75f); - gl_rect_2d(left, top, right, bottom); - - color = (bound_mem < llfloor(max_bound_mem * texmem_lower_bound_scale)) ? LLColor4::green : - (bound_mem < max_bound_mem) ? LLColor4::yellow : LLColor4::red; - color[VALPHA] = .75f; - gGL.diffuseColor4fv(color.mV); - gl_rect_2d(left, top, right, bottom); -#else S32 left = 0 ; -#endif //---------------------------------------------------------------------------- text = llformat("Textures: %d Fetch: %d(%d) Pkts:%d(%d) Cache R/W: %d/%d LFS:%d RAW:%d HTP:%d DEC:%d CRE:%d", @@ -669,8 +611,7 @@ BOOL LLGLTexMemBar::handleMouseDown(S32 x, S32 y, MASK mask) LLRect LLGLTexMemBar::getRequiredRect() { LLRect rect; - //rect.mTop = 50; - rect.mTop = 0; + rect.mTop = 50; //LLFontGL::getFontMonospace()->getLineHeight() * 6; return rect; } @@ -954,9 +895,11 @@ void LLTextureView::draw() LLRect tmbr; tmbp.name("gl texmem bar"); tmbp.rect(tmbr); + tmbp.follows.flags = FOLLOWS_LEFT|FOLLOWS_TOP; tmbp.texture_view(this); mGLTexMemBar = LLUICtrlFactory::create<LLGLTexMemBar>(tmbp); - addChildInBack(mGLTexMemBar); + addChild(mGLTexMemBar); + sendChildToFront(mGLTexMemBar); LLAvatarTexBar::Params atbp; LLRect atbr; @@ -965,16 +908,13 @@ void LLTextureView::draw() atbp.rect(atbr); mAvatarTexBar = LLUICtrlFactory::create<LLAvatarTexBar>(atbp); addChild(mAvatarTexBar); + sendChildToFront(mAvatarTexBar); reshape(getRect().getWidth(), getRect().getHeight(), TRUE); - /* - count = gTextureList.getNumImages(); - std::string info_string; - info_string = llformat("Global Info:\nTexture Count: %d", count); - mInfoTextp->setText(info_string); - */ - + LLUI::popMatrix(); + LLUI::pushMatrix(); + LLUI::translate((F32)getRect().mLeft, (F32)getRect().mBottom); for (child_list_const_iter_t child_iter = getChildList()->begin(); child_iter != getChildList()->end(); ++child_iter) @@ -1049,302 +989,4 @@ BOOL LLTextureView::handleKey(KEY key, MASK mask, BOOL called_from_parent) return FALSE; } -//----------------------------------------------------------------- -LLTextureSizeView::LLTextureSizeView(const LLTextureSizeView::Params& p) : LLContainerView(p) -{ - setVisible(FALSE) ; - - mTextureSizeBarWidth = 30 ; -} - -LLTextureSizeView::~LLTextureSizeView() -{ - if(mTextureSizeBar.size()) - { - for(U32 i = 0 ; i < mTextureSizeBar.size() ; i++) - { - delete mTextureSizeBar[i] ; - } - mTextureSizeBar.clear() ; - } -} -void LLTextureSizeView::draw() -{ - if(mType == TEXTURE_MEM_OVER_SIZE) - { - drawTextureSizeGraph(); - } - else - { - drawTextureCategoryGraph() ; - } - - LLView::draw(); -} - -BOOL LLTextureSizeView::handleHover(S32 x, S32 y, MASK mask) -{ - if(x > mTextureSizeBarRect.mLeft && x < mTextureSizeBarRect.mRight) - { - mTextureSizeBar[(x - mTextureSizeBarRect.mLeft) / mTextureSizeBarWidth]->handleHover(x, y, mask, (mType == TEXTURE_MEM_OVER_SIZE)) ; - } - - return TRUE ; -} - -//draw real-time texture mem bar over size -void LLTextureSizeView::drawTextureSizeGraph() -{ - if(mTextureSizeBar.size() == 0) - { - S32 line_height = LLFontGL::getFontMonospace()->getLineHeight(); - mTextureSizeBar.resize(LLImageGL::sTextureLoadedCounter.size()) ; - mTextureSizeBarRect.set(700, line_height * 2 + 400, 700 + mTextureSizeBar.size() * mTextureSizeBarWidth, line_height * 2) ; - - for(U32 i = 0 ; i < mTextureSizeBar.size() ; i++) - { - mTextureSizeBar[i] = new LLGLTexSizeBar(i, mTextureSizeBarRect.mLeft + i * mTextureSizeBarWidth , - line_height * 2, mTextureSizeBarRect.mLeft + (i + 1) * mTextureSizeBarWidth, line_height) ; - } - } - - F32 size_bar_scale = drawTextureSizeDistributionGraph() ; - for(U32 i = 0 ; i < mTextureSizeBar.size() ; i++) - { - mTextureSizeBar[i]->setTop(LLImageGL::sTextureLoadedCounter[i], LLImageGL::sTextureBoundCounter[i], size_bar_scale) ; - mTextureSizeBar[i]->draw() ; - } - LLImageGL::resetCurTexSizebar(); -} - -//draw background of texture size bar graph -F32 LLTextureSizeView::drawTextureSizeDistributionGraph() -{ - //scale - F32 scale = 1.0f ; - - LLGLSUIDefault gls_ui; - - { - S32 count = 0 ; - for(U32 i = 0 ; i < LLImageGL::sTextureLoadedCounter.size() ; i++) - { - if(LLImageGL::sTextureLoadedCounter[i] > count) - { - count = LLImageGL::sTextureLoadedCounter[i] ; - } - } - if(count > mTextureSizeBarRect.getHeight()) - { - scale = (F32)mTextureSizeBarRect.getHeight() / count ; - } - } - - S32 line_height = LLFontGL::getFontMonospace()->getLineHeight(); - S32 left = mTextureSizeBarRect.mLeft ; - S32 bottom = mTextureSizeBarRect.mBottom ; - S32 right = mTextureSizeBarRect.mRight ; - S32 top = mTextureSizeBarRect.mTop ; - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - //background rect - gl_rect_2d(left - 25, top + 30, right + 100, bottom - 25, LLColor4(0.0f, 0.0f, 0.0f, 0.25f)) ; - - //-------------------------------------------------- - gGL.color4f(1.0f, 0.5f, 0.5f, 0.75f); - gl_line_2d(left, bottom, right, bottom) ; //x axis - gl_line_2d(left, bottom, left, top) ; //y axis - - //ruler - //-------------------------------------------------- - gGL.color4f(1.0f, 0.5f, 0.5f, 0.5f); - for(S32 i = bottom + 50 ; i <= top ; i += 50) - { - gl_line_2d(left, i, right, i) ; - } - - //texts - //-------------------------------------------------- - F32 text_color[] = {1.f, 1.f, 1.f, 0.75f}; - std::string text; - - //------- - //x axis: size label - text = llformat("%d", 0) ; - LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + 12, bottom - line_height / 2, - text_color, LLFontGL::LEFT, LLFontGL::TOP); - for(U32 i = 1 ; i < mTextureSizeBar.size() ; i++) - { - text = llformat("%d", (1 << (i / 2)) + ((i & 1) ? ((1 << (i / 2)) >> 1) : 0)) ; - LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + i * mTextureSizeBarWidth + 12, bottom - line_height / 2, - text_color, LLFontGL::LEFT, LLFontGL::TOP); - } - text = llformat("(w + h)/2") ; - LLFontGL::getFontMonospace()->renderUTF8(text, 0, right + 10, bottom - line_height / 2, - text_color, LLFontGL::LEFT, LLFontGL::TOP); - //------- - - //y axis: number label - for(S32 i = bottom + 50 ; i <= top ; i += 50) - { - text = llformat("%d", (S32)((i - bottom) / scale)) ; - LLFontGL::getFontMonospace()->renderUTF8(text, 0, left - 20, i + line_height / 2 , - text_color, LLFontGL::LEFT, LLFontGL::TOP); - LLFontGL::getFontMonospace()->renderUTF8(text, 0, right + 5, i + line_height / 2 , - text_color, LLFontGL::LEFT, LLFontGL::TOP); - } - - //-------------------------------------------------- - F32 loaded_color[] = {1.0f, 0.0f, 0.0f, 0.75f}; - gl_rect_2d(left + 70, top + line_height * 2, left + 90, top + line_height, loaded_color) ; - text = llformat("Loaded") ; - LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + 100, top + line_height * 2, - loaded_color, LLFontGL::LEFT, LLFontGL::TOP); - - F32 bound_color[] = {1.0f, 1.0f, 0.0f, 0.75f}; - gl_rect_2d(left + 170, top + line_height * 2, left + 190, top + line_height, bound_color) ; - text = llformat("Bound") ; - LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + 200, top + line_height * 2, - bound_color, LLFontGL::LEFT, LLFontGL::TOP); - - //-------------------------------------------------- - - //title - text = llformat("Texture Size Distribution") ; - LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + 250, top + line_height * 3, - text_color, LLFontGL::LEFT, LLFontGL::TOP); - return scale ; -} - -//draw real-time texture mem bar over category -void LLTextureSizeView::drawTextureCategoryGraph() -{ - if(mTextureSizeBar.size() == 0) - { - S32 line_height = LLFontGL::getFontMonospace()->getLineHeight(); - mTextureSizeBar.resize(LLViewerTexture::getTotalNumOfCategories()) ; - mTextureSizeBarRect.set(700, line_height * 2 + 400, 700 + mTextureSizeBar.size() * mTextureSizeBarWidth, line_height * 2) ; - - for(U32 i = 0 ; i < mTextureSizeBar.size() ; i++) - { - mTextureSizeBar[i] = new LLGLTexSizeBar(i, mTextureSizeBarRect.mLeft + i * mTextureSizeBarWidth , - line_height * 2, mTextureSizeBarRect.mLeft + (i + 1) * mTextureSizeBarWidth, line_height) ; - } - } - - F32 size_bar_scale = drawTextureCategoryDistributionGraph() ; - for(U32 i = 0 ; i < mTextureSizeBar.size() ; i++) - { - U32 k = LLViewerTexture::getIndexFromCategory(i) ; - mTextureSizeBar[i]->setTop(LLImageGL::sTextureMemByCategory[k] >> 20, LLImageGL::sTextureMemByCategoryBound[k] >> 20, size_bar_scale) ; - mTextureSizeBar[i]->draw() ; - } - LLImageGL::resetCurTexSizebar(); -} - -//draw background for TEXTURE_MEM_OVER_CATEGORY -F32 LLTextureSizeView::drawTextureCategoryDistributionGraph() -{ - //scale - F32 scale = 4.0f ; - - LLGLSUIDefault gls_ui; - - { - S32 count = 0 ; - for(U32 i = 0 ; i < LLImageGL::sTextureMemByCategory.size() ; i++) - { - S32 tmp = LLImageGL::sTextureMemByCategory[i] >> 20 ; - if(tmp > count) - { - count = tmp ; - } - } - if(count > mTextureSizeBarRect.getHeight() * 0.25f) - { - scale = (F32)mTextureSizeBarRect.getHeight() * 0.25f / count ; - } - } - - S32 line_height = LLFontGL::getFontMonospace()->getLineHeight(); - S32 left = mTextureSizeBarRect.mLeft ; - S32 bottom = mTextureSizeBarRect.mBottom ; - S32 right = mTextureSizeBarRect.mRight ; - S32 top = mTextureSizeBarRect.mTop ; - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - //background rect - gl_rect_2d(left - 25, top + 30, right + 100, bottom - 25, LLColor4(0.0f, 0.0f, 0.0f, 0.25f)) ; - - //-------------------------------------------------- - gGL.color4f(1.0f, 0.5f, 0.5f, 0.75f); - gl_line_2d(left, bottom, right, bottom) ; //x axis - gl_line_2d(left, bottom, left, top) ; //y axis - - //ruler - //-------------------------------------------------- - gGL.color4f(1.0f, 0.5f, 0.5f, 0.5f); - for(S32 i = bottom + 50 ; i <= top ; i += 50) - { - gl_line_2d(left, i, right, i) ; - } - - //texts - //-------------------------------------------------- - F32 text_color[] = {1.f, 1.f, 1.f, 0.75f}; - std::string text; - - //------- - //x axis: size label - static char category[LLViewerTexture::MAX_GL_IMAGE_CATEGORY][4] = - {"Non", "Bak", "Av", "Cld", "Scp", "Hi", "Trn", "Slt", "Hud", "Bsf", "UI", "Pvw", "Map", "Mvs", "Slf", "Loc", "Scr", "Dyn", "Mdi", "ALT", "Oth" } ; - - text = llformat("%s", category[0]) ; - LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + 12, bottom - line_height / 2, - text_color, LLFontGL::LEFT, LLFontGL::TOP); - for(U32 i = 1 ; i < mTextureSizeBar.size() ; i++) - { - text = llformat("%s", category[i]) ; - LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + i * mTextureSizeBarWidth + 12, bottom - line_height / 2, - text_color, LLFontGL::LEFT, LLFontGL::TOP); - } - //------- - - //y axis: number label - for(S32 i = bottom + 50 ; i <= top ; i += 50) - { - text = llformat("%d", (S32)((i - bottom) / scale)) ; - LLFontGL::getFontMonospace()->renderUTF8(text, 0, left - 20, i + line_height / 2 , - text_color, LLFontGL::LEFT, LLFontGL::TOP); - LLFontGL::getFontMonospace()->renderUTF8(text, 0, right + 5, i + line_height / 2 , - text_color, LLFontGL::LEFT, LLFontGL::TOP); - } - text = llformat("MB") ; - LLFontGL::getFontMonospace()->renderUTF8(text, 0, left - 20, top + line_height * 2 , - text_color, LLFontGL::LEFT, LLFontGL::TOP); - //-------------------------------------------------- - F32 loaded_color[] = {1.0f, 0.0f, 0.0f, 0.75f}; - gl_rect_2d(left + 70, top + line_height * 2, left + 90, top + line_height, loaded_color) ; - text = llformat("Loaded") ; - LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + 100, top + line_height * 2, - loaded_color, - LLFontGL::LEFT, LLFontGL::TOP); - - F32 bound_color[] = {1.0f, 1.0f, 0.0f, 0.75f}; - gl_rect_2d(left + 170, top + line_height * 2, left + 190, top + line_height, bound_color) ; - text = llformat("Bound") ; - LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + 200, top + line_height * 2, - bound_color, LLFontGL::LEFT, LLFontGL::TOP); - - //-------------------------------------------------- - - //title - text = llformat("Texture Category Distribution") ; - LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + 250, top + line_height * 3, - text_color, LLFontGL::LEFT, LLFontGL::TOP); - - return scale ; -} diff --git a/indra/newview/lltextureview.h b/indra/newview/lltextureview.h index 3723eb737b..900b4e17d8 100644 --- a/indra/newview/lltextureview.h +++ b/indra/newview/lltextureview.h @@ -75,41 +75,6 @@ public: }; class LLGLTexSizeBar; -class LLTextureSizeView : public LLContainerView -{ -protected: - LLTextureSizeView(const Params&); - friend class LLUICtrlFactory; -public: - ~LLTextureSizeView(); - - /*virtual*/ void draw(); - /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask) ; - - void setType(S32 type) {mType = type ;} - enum - { - TEXTURE_MEM_OVER_SIZE, - TEXTURE_MEM_OVER_CATEGORY - }; -private: - //draw background for TEXTURE_MEM_OVER_SIZE - F32 drawTextureSizeDistributionGraph() ; - //draw real-time texture mem bar over size - void drawTextureSizeGraph(); - - //draw background for TEXTURE_MEM_OVER_CATEGORY - F32 drawTextureCategoryDistributionGraph() ; - //draw real-time texture mem bar over category - void drawTextureCategoryGraph(); -private: - std::vector<LLGLTexSizeBar*> mTextureSizeBar ; - LLRect mTextureSizeBarRect ; - S32 mTextureSizeBarWidth ; - S32 mType ; -}; extern LLTextureView *gTextureView; -extern LLTextureSizeView *gTextureSizeView; -extern LLTextureSizeView *gTextureCategoryView; #endif // LL_TEXTURE_VIEW_H diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp index 807d8e03d9..4a49922656 100644 --- a/indra/newview/lltoastnotifypanel.cpp +++ b/indra/newview/lltoastnotifypanel.cpp @@ -60,7 +60,7 @@ LLToastNotifyPanel::LLToastNotifyPanel(const LLNotificationPtr& notification, co LLInstanceTracker<LLToastNotifyPanel, LLUUID>(notification->getID()) { init(rect, show_images); -} + } void LLToastNotifyPanel::addDefaultButton() { LLSD form_element; @@ -131,10 +131,10 @@ LLToastNotifyPanel::~LLToastNotifyPanel() std::for_each(mBtnCallbackData.begin(), mBtnCallbackData.end(), DeletePointer()); if (mIsTip) - { - LLNotifications::getInstance()->cancel(mNotification); + { + LLNotifications::getInstance()->cancel(mNotification); + } } -} void LLToastNotifyPanel::updateButtonsLayout(const std::vector<index_button_pair_t>& buttons, S32 h_pad) { @@ -341,7 +341,7 @@ void LLToastNotifyPanel::onClickButton(void* data) { response[button_name] = true; } - + // disable all buttons self->mControlPanel->setEnabled(FALSE); @@ -387,10 +387,10 @@ void LLToastNotifyPanel::init( LLRect rect, bool show_images ) mMessage = mNotification->getMessage(); // init font variables if (!sFont) - { +{ sFont = LLFontGL::getFontSansSerif(); sFontSmall = LLFontGL::getFontSansSerifSmall(); - } +} // initialize setFocusRoot(!mIsTip); // get a form for the notification @@ -425,41 +425,41 @@ void LLToastNotifyPanel::init( LLRect rect, bool show_images ) adjustPanelForTipNotice(); } else - { +{ std::vector<index_button_pair_t> buttons; buttons.reserve(mNumOptions); S32 buttons_width = 0; // create all buttons and accumulate they total width to reshape mControlPanel for (S32 i = 0; i < mNumOptions; i++) - { + { LLSD form_element = form->getElement(i); if (form_element["type"].asString() != "button") - { + { // not a button. continue; - } + } if (form_element["name"].asString() == TEXTBOX_MAGIC_TOKEN) { // a textbox pretending to be a button. continue; - } + } LLButton* new_button = createButton(form_element, TRUE); buttons_width += new_button->getRect().getWidth(); S32 index = form_element["index"].asInteger(); buttons.push_back(index_button_pair_t(index,new_button)); - } +} if (buttons.empty()) - { +{ addDefaultButton(); - } + } else - { + { const S32 button_panel_width = mControlPanel->getRect().getWidth();// do not change width of the panel S32 button_panel_height = mControlPanel->getRect().getHeight(); //try get an average h_pad to spread out buttons S32 h_pad = (button_panel_width - buttons_width) / (S32(buttons.size())); if(h_pad < 2*HPAD) - { + { /* * Probably it is a scriptdialog toast * for a scriptdialog toast h_pad can be < 2*HPAD if we have a lot of buttons. @@ -468,12 +468,12 @@ void LLToastNotifyPanel::init( LLRect rect, bool show_images ) S32 button_per_row = button_panel_width / BUTTON_WIDTH; h_pad = (button_panel_width % BUTTON_WIDTH) / (button_per_row - 1);// -1 because we do not need space after last button in a row if(h_pad < 2*HPAD) // still not enough space between buttons ? - { + { h_pad = 2*HPAD; - } - } + } +} if (mIsScriptDialog) - { +{ // we are using default width for script buttons so we can determinate button_rows //to get a number of rows we divide the required width of the buttons to button_panel_width S32 button_rows = llceil(F32(buttons.size() - 1) * (BUTTON_WIDTH + h_pad) / button_panel_width); @@ -484,13 +484,13 @@ void LLToastNotifyPanel::init( LLRect rect, bool show_images ) button_panel_height = button_rows * (BTN_HEIGHT + VPAD) + IGNORE_BTN_TOP_DELTA + BOTTOM_PAD; } else - { + { // in common case buttons can have different widths so we need to calculate button_rows according to buttons_width //S32 button_rows = llceil(F32(buttons.size()) * (buttons_width + h_pad) / button_panel_width); S32 button_rows = llceil(F32((buttons.size() - 1) * h_pad + buttons_width) / button_panel_width); //calculate required panel height button_panel_height = button_rows * (BTN_HEIGHT + VPAD) + BOTTOM_PAD; - } +} // we need to keep min width and max height to make visible all buttons, because width of the toast can not be changed adjustPanelForScriptNotice(button_panel_width, button_panel_height); @@ -544,11 +544,11 @@ LLIMToastNotifyPanel::~LLIMToastNotifyPanel() } void LLIMToastNotifyPanel::reshape(S32 width, S32 height, BOOL called_from_parent /* = TRUE */) -{ + { LLToastPanel::reshape(width, height, called_from_parent); snapToMessageHeight(mTextBox, MAX_LENGTH); -} + } void LLIMToastNotifyPanel::compactButtons() { @@ -588,9 +588,9 @@ void LLIMToastNotifyPanel::compactButtons() } void LLIMToastNotifyPanel::updateNotification() -{ + { init(LLRect(), true); -} + } void LLIMToastNotifyPanel::init( LLRect rect, bool show_images ) { diff --git a/indra/newview/lltoastpanel.cpp b/indra/newview/lltoastpanel.cpp index 09f8dcf83c..187aee207c 100644 --- a/indra/newview/lltoastpanel.cpp +++ b/indra/newview/lltoastpanel.cpp @@ -29,7 +29,9 @@ #include "llpanelgenerictip.h" #include "llpanelonlinestatus.h" #include "llnotifications.h" +#include "lltoastnotifypanel.h" #include "lltoastpanel.h" +#include "lltoastscriptquestion.h" //static const S32 LLToastPanel::MIN_PANEL_HEIGHT = 40; // VPAD(4)*2 + ICON_HEIGHT(32) @@ -109,6 +111,17 @@ LLToastPanel* LLToastPanel::buidPanelFromNotification( res = new LLPanelGenericTip(notification); } } + else if("notify" == notification->getType()) + { + if (notification->getPriority() == NOTIFICATION_PRIORITY_CRITICAL) + { + res = new LLToastScriptQuestion(notification); + } + else + { + res = new LLToastNotifyPanel(notification); + } + } /* else if(...) create all other specific non-public toast panel diff --git a/indra/newview/lltoastscriptquestion.cpp b/indra/newview/lltoastscriptquestion.cpp new file mode 100644 index 0000000000..91ba8c0247 --- /dev/null +++ b/indra/newview/lltoastscriptquestion.cpp @@ -0,0 +1,130 @@ +/** + * @file lltoastscriptquestion.cpp + * + * $LicenseInfo:firstyear=2010&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llbutton.h" +#include "llnotifications.h" +#include "lltoastscriptquestion.h" + +const int LEFT_PAD = 10; +const int BUTTON_HEIGHT = 27; +const int MAX_LINES_COUNT = 50; + +LLToastScriptQuestion::LLToastScriptQuestion(const LLNotificationPtr& notification) +: +LLToastPanel(notification) +{ + buildFromFile("panel_script_question_toast.xml"); +} + +BOOL LLToastScriptQuestion::postBuild() +{ + createButtons(); + + LLTextBox* mMessage = getChild<LLTextBox>("top_info_message"); + LLTextBox* mFooter = getChild<LLTextBox>("bottom_info_message"); + + mMessage->setValue(mNotification->getMessage()); + mFooter->setValue(mNotification->getFooter()); + + snapToMessageHeight(); + + return TRUE; +} +void LLToastScriptQuestion::snapToMessageHeight() +{ + LLTextBox* mMessage = getChild<LLTextBox>("top_info_message"); + LLTextBox* mFooter = getChild<LLTextBox>("bottom_info_message"); + if (!mMessage || !mFooter) + { + return; + } + + if (mMessage->getVisible() && mFooter->getVisible()) + { + S32 heightDelta = 0; + S32 maxTextHeight = (mMessage->getFont()->getLineHeight() * MAX_LINES_COUNT) + + (mFooter->getFont()->getLineHeight() * MAX_LINES_COUNT); + + LLRect messageRect = mMessage->getRect(); + LLRect footerRect = mFooter->getRect(); + + S32 oldTextHeight = messageRect.getHeight() + footerRect.getHeight(); + + S32 requiredTextHeight = mMessage->getTextBoundingRect().getHeight() + mFooter->getTextBoundingRect().getHeight(); + S32 newTextHeight = llmin(requiredTextHeight, maxTextHeight); + + heightDelta = newTextHeight - oldTextHeight - heightDelta; + + reshape( getRect().getWidth(), llmax(getRect().getHeight() + heightDelta, MIN_PANEL_HEIGHT)); + } +} + +void LLToastScriptQuestion::createButtons() +{ + LLNotificationFormPtr form = mNotification->getForm(); + int num_elements = form->getNumElements(); + int buttons_width = 0; + + for (int i = 0; i < num_elements; ++i) + { + LLSD form_element = form->getElement(i); + if ("button" == form_element["type"].asString()) + { + LLButton::Params p; + const LLFontGL* font = LLFontGL::getFontSansSerif(); + p.name(form_element["name"].asString()); + p.label(form_element["text"].asString()); + p.layout("topleft"); + p.font(font); + p.rect.height(BUTTON_HEIGHT); + p.click_callback.function(boost::bind(&LLToastScriptQuestion::onButtonClicked, this, form_element["name"].asString())); + p.rect.left = LEFT_PAD; + p.rect.width = font->getWidth(form_element["text"].asString()); + p.auto_resize = true; + p.follows.flags(FOLLOWS_LEFT | FOLLOWS_BOTTOM); + p.image_color(LLUIColorTable::instance().getColor("ButtonCautionImageColor")); + p.image_color_disabled(LLUIColorTable::instance().getColor("ButtonCautionImageColor")); + + LLButton* button = LLUICtrlFactory::create<LLButton>(p); + button->autoResize(); + getChild<LLPanel>("buttons_panel")->addChild(button); + + LLRect rect = button->getRect(); + rect.setLeftTopAndSize(buttons_width, rect.mTop, rect.getWidth(), rect.getHeight()); + button->setRect(rect); + + buttons_width += rect.getWidth() + LEFT_PAD; + } + } +} + +void LLToastScriptQuestion::onButtonClicked(std::string btn_name) +{ + LLSD response = mNotification->getResponseTemplate(); + response[btn_name] = true; + mNotification->respond(response); +} diff --git a/indra/newview/lltoastscriptquestion.h b/indra/newview/lltoastscriptquestion.h new file mode 100644 index 0000000000..3a557f60f6 --- /dev/null +++ b/indra/newview/lltoastscriptquestion.h @@ -0,0 +1,49 @@ +/** + * @file lltoastscriptquestion.h + * + * $LicenseInfo:firstyear=2010&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "lltoastpanel.h" + +#ifndef LLTOASTSCRIPTQUESTION_H_ +#define LLTOASTSCRIPTQUESTION_H_ + +class LLToastScriptQuestion : public LLToastPanel +{ + LOG_CLASS(LLToastScriptQuestion); + +public: + LLToastScriptQuestion(const LLNotificationPtr& notification); + virtual BOOL postBuild(); + virtual ~LLToastScriptQuestion(){}; + +private: + void snapToMessageHeight(); + + void createButtons(); + void onButtonClicked(std::string btn_name); +}; + +#endif /* LLTOASTSCRIPTQUESTION_H_ */ diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index 86708b46d5..2680e4451b 100644 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -1039,7 +1039,14 @@ BOOL LLToolDragAndDrop::handleDropTextureProtections(LLViewerObject* hit_obj, } } // Add the texture item to the target object's inventory. - hit_obj->updateInventory(new_item, TASK_INVENTORY_ITEM_KEY, true); + if (LLAssetType::AT_TEXTURE == new_item->getType()) + { + hit_obj->updateTextureInventory(new_item, TASK_INVENTORY_ITEM_KEY, true); + } + else + { + hit_obj->updateInventory(new_item, TASK_INVENTORY_ITEM_KEY, true); + } // TODO: Check to see if adding the item was successful; if not, then // we should return false here. } @@ -1054,7 +1061,14 @@ BOOL LLToolDragAndDrop::handleDropTextureProtections(LLViewerObject* hit_obj, // *FIX: may want to make sure agent can paint hit_obj. // Add the texture item to the target object's inventory. - hit_obj->updateInventory(new_item, TASK_INVENTORY_ITEM_KEY, true); + if (LLAssetType::AT_TEXTURE == new_item->getType()) + { + hit_obj->updateTextureInventory(new_item, TASK_INVENTORY_ITEM_KEY, true); + } + else + { + hit_obj->updateInventory(new_item, TASK_INVENTORY_ITEM_KEY, true); + } // Force the object to update its refetch its inventory so it has this texture. hit_obj->fetchInventoryFromServer(); // TODO: Check to see if adding the item was successful; if not, then diff --git a/indra/newview/lltooldraganddrop.h b/indra/newview/lltooldraganddrop.h index 44980ffdb3..f17300a76a 100644 --- a/indra/newview/lltooldraganddrop.h +++ b/indra/newview/lltooldraganddrop.h @@ -94,6 +94,13 @@ public: static S32 getOperationId() { return sOperationId; } + // deal with permissions of object, etc. returns TRUE if drop can + // proceed, otherwise FALSE. + static BOOL handleDropTextureProtections(LLViewerObject* hit_obj, + LLInventoryItem* item, + LLToolDragAndDrop::ESource source, + const LLUUID& src_id); + protected: enum EDropTarget { @@ -220,13 +227,6 @@ protected: // inventory items to determine if a drop would be ok. static EAcceptance willObjectAcceptInventory(LLViewerObject* obj, LLInventoryItem* item); - // deal with permissions of object, etc. returns TRUE if drop can - // proceed, otherwise FALSE. - static BOOL handleDropTextureProtections(LLViewerObject* hit_obj, - LLInventoryItem* item, - LLToolDragAndDrop::ESource source, - const LLUUID& src_id); - public: // helper functions static BOOL isInventoryDropAcceptable(LLViewerObject* obj, LLInventoryItem* item) { return (ACCEPT_YES_COPY_SINGLE <= willObjectAcceptInventory(obj, item)); } diff --git a/indra/newview/lltoolmorph.cpp b/indra/newview/lltoolmorph.cpp index 718201e381..0d5daf129f 100644 --- a/indra/newview/lltoolmorph.cpp +++ b/indra/newview/lltoolmorph.cpp @@ -225,7 +225,8 @@ BOOL LLVisualParamHint::render() LLViewerCamera::getInstance()->setPerspective(FALSE, mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight, FALSE); - if (gAgentAvatarp->mDrawable.notNull()) + if (gAgentAvatarp->mDrawable.notNull() && + gAgentAvatarp->mDrawable->getFace(0)) { LLDrawPoolAvatar *avatarPoolp = (LLDrawPoolAvatar *)gAgentAvatarp->mDrawable->getFace(0)->getPool(); LLGLDepthTest gls_depth(GL_TRUE, GL_TRUE); diff --git a/indra/newview/lltracker.cpp b/indra/newview/lltracker.cpp index bf1f8808a7..cbd16e873d 100644 --- a/indra/newview/lltracker.cpp +++ b/indra/newview/lltracker.cpp @@ -251,7 +251,7 @@ void LLTracker::render3D() instance()->mBeaconText->setDoFade(FALSE); } - F32 dist = gFloaterWorldMap->getDistanceToDestination(instance()->mTrackedPositionGlobal, 0.0f); + F32 dist = gFloaterWorldMap->getDistanceToDestination(instance()->getTrackedPositionGlobal(), 0.0f); if (dist < DESTINATION_REACHED_RADIUS) { instance()->stopTrackingAvatar(); diff --git a/indra/newview/llviewerassetstats.cpp b/indra/newview/llviewerassetstats.cpp index e621cf647e..4c59fd0371 100644 --- a/indra/newview/llviewerassetstats.cpp +++ b/indra/newview/llviewerassetstats.cpp @@ -30,6 +30,7 @@ #include "llregionhandle.h" #include "stdtypes.h" +#include "llvoavatar.h" /* * Classes and utility functions for per-thread and per-region @@ -126,6 +127,8 @@ LLViewerAssetStats::PerRegionStats::merge(const LLViewerAssetStats::PerRegionSta mFPS.merge(src.mFPS); } + // Avatar stats - data all comes from main thread, so leave alone. + // Requests for (int i = 0; i < LL_ARRAY_SIZE(mRequests); ++i) { @@ -133,6 +136,7 @@ LLViewerAssetStats::PerRegionStats::merge(const LLViewerAssetStats::PerRegionSta mRequests[i].mDequeued.merge(src.mRequests[i].mDequeued); mRequests[i].mResponse.merge(src.mRequests[i].mResponse); } + } @@ -156,7 +160,9 @@ LLViewerAssetStats::LLViewerAssetStats() LLViewerAssetStats::LLViewerAssetStats(const LLViewerAssetStats & src) : mRegionHandle(src.mRegionHandle), - mResetTimestamp(src.mResetTimestamp) + mResetTimestamp(src.mResetTimestamp), + mPhaseStats(src.mPhaseStats), + mAvatarRezStates(src.mAvatarRezStates) { const PerRegionContainer::const_iterator it_end(src.mRegionStats.end()); for (PerRegionContainer::const_iterator it(src.mRegionStats.begin()); it_end != it; ++it) @@ -252,6 +258,17 @@ LLViewerAssetStats::recordFPS(F32 fps) mCurRegionStats->mFPS.record(fps); } +void +LLViewerAssetStats::recordAvatarStats() +{ + std::vector<S32> rez_counts; + LLVOAvatar::getNearbyRezzedStats(rez_counts); + mAvatarRezStates = rez_counts; + mPhaseStats.clear(); + mPhaseStats["cloud"] = LLViewerStats::PhaseMap::getPhaseStats("cloud"); + mPhaseStats["cloud-or-gray"] = LLViewerStats::PhaseMap::getPhaseStats("cloud-or-gray"); +} + LLSD LLViewerAssetStats::asLLSD(bool compact_output) { @@ -282,6 +299,11 @@ LLViewerAssetStats::asLLSD(bool compact_output) static const LLSD::String max_tag("max"); static const LLSD::String mean_tag("mean"); + // Avatar sub-tags + static const LLSD::String avatar_tag("avatar"); + static const LLSD::String avatar_nearby_tag("nearby"); + static const LLSD::String avatar_phase_stats_tag("phase_stats"); + const duration_t now = LLViewerAssetStatsFF::get_timestamp(); mCurRegionStats->accumulateTime(now); @@ -329,7 +351,6 @@ LLViewerAssetStats::asLLSD(bool compact_output) slot[max_tag] = LLSD(F64(stats.mFPS.getMax())); slot[mean_tag] = LLSD(F64(stats.mFPS.getMean())); } - U32 grid_x(0), grid_y(0); grid_from_region_handle(it->first, &grid_x, &grid_y); reg_stat["grid_x"] = LLSD::Integer(grid_x); @@ -341,6 +362,16 @@ LLViewerAssetStats::asLLSD(bool compact_output) LLSD ret = LLSD::emptyMap(); ret["regions"] = regions; ret["duration"] = LLSD::Real((now - mResetTimestamp) * 1.0e-6); + LLSD avatar_info; + avatar_info[avatar_nearby_tag] = LLSD::emptyArray(); + for (S32 rez_stat=0; rez_stat < mAvatarRezStates.size(); ++rez_stat) + { + std::string rez_status_name = LLVOAvatar::rezStatusToString(rez_stat); + avatar_info[avatar_nearby_tag][rez_status_name] = mAvatarRezStates[rez_stat]; + } + avatar_info[avatar_phase_stats_tag]["cloud"] = mPhaseStats["cloud"].getData(); + avatar_info[avatar_phase_stats_tag]["cloud-or-gray"] = mPhaseStats["cloud-or-gray"].getData(); + ret[avatar_tag] = avatar_info; return ret; } @@ -439,6 +470,14 @@ record_fps_main(F32 fps) gViewerAssetStatsMain->recordFPS(fps); } +void +record_avatar_stats() +{ + if (! gViewerAssetStatsMain) + return; + + gViewerAssetStatsMain->recordAvatarStats(); +} // 'thread1' - should be for TextureFetch thread diff --git a/indra/newview/llviewerassetstats.h b/indra/newview/llviewerassetstats.h index 73ec5974b2..8319752230 100644 --- a/indra/newview/llviewerassetstats.h +++ b/indra/newview/llviewerassetstats.h @@ -36,6 +36,7 @@ #include "llviewerassetstorage.h" #include "llsimplestat.h" #include "llsd.h" +#include "llvoavatar.h" /** * @class LLViewerAssetStats @@ -181,6 +182,9 @@ public: // Frames-Per-Second Samples void recordFPS(F32 fps); + // Avatar-related statistics + void recordAvatarStats(); + // Merge a source instance into a destination instance. This is // conceptually an 'operator+=()' method: // - counts are added @@ -252,6 +256,10 @@ protected: // Time of last reset duration_t mResetTimestamp; + + // Nearby avatar stats + std::vector<S32> mAvatarRezStates; + LLViewerStats::phase_stats_t mPhaseStats; }; @@ -310,6 +318,7 @@ void record_response_main(LLViewerAssetType::EType at, bool with_http, bool is_t void record_fps_main(F32 fps); +void record_avatar_stats(); /** * Region context, event and duration loggers for Thread 1. diff --git a/indra/newview/llvieweraudio.cpp b/indra/newview/llvieweraudio.cpp index 2447f5dea8..8d8c401dac 100644 --- a/indra/newview/llvieweraudio.cpp +++ b/indra/newview/llvieweraudio.cpp @@ -41,6 +41,7 @@ #include "llstartup.h" #include "llviewerparcelmgr.h" #include "llparcel.h" +#include "llviewermessage.h" ///////////////////////////////////////////////////////// @@ -49,15 +50,22 @@ LLViewerAudio::LLViewerAudio() : mFadeState(FADE_IDLE), mFadeTime(), mIdleListnerActive(false), - mForcedTeleportFade(false) + mForcedTeleportFade(false), + mWasPlaying(false) { mTeleportFailedConnection = LLViewerParcelMgr::getInstance()-> setTeleportFailedCallback(boost::bind(&LLViewerAudio::onTeleportFailed, this)); + mTeleportFinishedConnection = LLViewerParcelMgr::getInstance()-> + setTeleportFinishedCallback(boost::bind(&LLViewerAudio::onTeleportFinished, this, _1, _2)); + mTeleportStartedConnection = LLViewerMessage::getInstance()-> + setTeleportStartedCallback(boost::bind(&LLViewerAudio::onTeleportStarted, this)); } LLViewerAudio::~LLViewerAudio() { mTeleportFailedConnection.disconnect(); + mTeleportFinishedConnection.disconnect(); + mTeleportStartedConnection.disconnect(); } void LLViewerAudio::registerIdleListener() @@ -67,7 +75,6 @@ void LLViewerAudio::registerIdleListener() mIdleListnerActive = true; doOnIdleRepeating(boost::bind(boost::bind(&LLViewerAudio::onIdleUpdate, this))); } - } void LLViewerAudio::startInternetStreamWithAutoFade(std::string streamURI) @@ -245,16 +252,54 @@ F32 LLViewerAudio::getFadeVolume() return fade_volume; } +void LLViewerAudio::onTeleportStarted() +{ + if (!LLViewerAudio::getInstance()->getForcedTeleportFade()) + { + // Even though the music was turned off it was starting up (with autoplay disabled) occasionally + // after a failed teleport or after an intra-parcel teleport. Also, the music sometimes was not + // restarting after a successful intra-parcel teleport. Setting mWasPlaying fixes these issues. + LLViewerAudio::getInstance()->setWasPlaying(!gAudiop->getInternetStreamURL().empty()); + LLViewerAudio::getInstance()->setForcedTeleportFade(true); + LLViewerAudio::getInstance()->startInternetStreamWithAutoFade(LLStringUtil::null); + LLViewerAudio::getInstance()->setNextStreamURI(LLStringUtil::null); + } +} + void LLViewerAudio::onTeleportFailed() { - if (gAudiop) + // Calling audio_update_volume makes sure that the music stream is properly set to be restored to + // its previous value + audio_update_volume(false); + + if (gAudiop && mWasPlaying) + { + LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); + if (parcel) + { + mNextStreamURI = parcel->getMusicURL(); + llinfos << "Teleport failed -- setting music stream to " << mNextStreamURI << llendl; + } + } + mWasPlaying = false; +} + +void LLViewerAudio::onTeleportFinished(const LLVector3d& pos, const bool& local) +{ + // Calling audio_update_volume makes sure that the music stream is properly set to be restored to + // its previous value + audio_update_volume(false); + + if (gAudiop && local && mWasPlaying) { LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); if (parcel) { mNextStreamURI = parcel->getMusicURL(); + llinfos << "Intraparcel teleport -- setting music stream to " << mNextStreamURI << llendl; } } + mWasPlaying = false; } void init_audio() @@ -360,15 +405,9 @@ void audio_update_volume(bool force_update) // Streaming Music if (gAudiop) { - if (progress_view_visible && !LLViewerAudio::getInstance()->getForcedTeleportFade()) - { - LLViewerAudio::getInstance()->setForcedTeleportFade(true); - LLViewerAudio::getInstance()->startInternetStreamWithAutoFade(LLStringUtil::null); - LLViewerAudio::getInstance()->setNextStreamURI(LLStringUtil::null); - } - - if (!progress_view_visible && LLViewerAudio::getInstance()->getForcedTeleportFade() == true) + if (!progress_view_visible && LLViewerAudio::getInstance()->getForcedTeleportFade()) { + LLViewerAudio::getInstance()->setWasPlaying(!gAudiop->getInternetStreamURL().empty()); LLViewerAudio::getInstance()->setForcedTeleportFade(false); } diff --git a/indra/newview/llvieweraudio.h b/indra/newview/llvieweraudio.h index a3da9fc6b8..8c302c6549 100644 --- a/indra/newview/llvieweraudio.h +++ b/indra/newview/llvieweraudio.h @@ -66,6 +66,7 @@ public: bool getForcedTeleportFade() { return mForcedTeleportFade; }; void setForcedTeleportFade(bool fade) { mForcedTeleportFade = fade;} ; void setNextStreamURI(std::string stream) { mNextStreamURI = stream; } ; + void setWasPlaying(bool playing) { mWasPlaying = playing;} ; private: @@ -76,13 +77,17 @@ private: LLFrameTimer stream_fade_timer; bool mIdleListnerActive; bool mForcedTeleportFade; + bool mWasPlaying; boost::signals2::connection mTeleportFailedConnection; + boost::signals2::connection mTeleportFinishedConnection; + boost::signals2::connection mTeleportStartedConnection; void registerIdleListener(); void deregisterIdleListener() { mIdleListnerActive = false; }; void startFading(); void onTeleportFailed(); - + void onTeleportFinished(const LLVector3d& pos, const bool& local); + void onTeleportStarted(); }; #endif //LL_VIEWER_H diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index ab45aae5cc..dec1615246 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -71,8 +71,12 @@ #include "llpaneloutfitsinventory.h" #include "llpanellogin.h" #include "llpaneltopinfobar.h" +#include "llspellcheck.h" #include "llupdaterservice.h" +// Third party library includes +#include <boost/algorithm/string.hpp> + #ifdef TOGGLE_HACKED_GODLIKE_VIEWER BOOL gHackGodmode = FALSE; #endif @@ -87,7 +91,6 @@ std::string gLastRunVersion; extern BOOL gResizeScreenTexture; extern BOOL gDebugGL; -extern BOOL gAuditTexture; //////////////////////////////////////////////////////////////////////////// // Listeners @@ -326,7 +329,7 @@ static bool handleJoystickChanged(const LLSD& newvalue) static bool handleUseOcclusionChanged(const LLSD& newvalue) { - LLPipeline::sUseOcclusion = (newvalue.asBoolean() && gGLManager.mHasOcclusionQuery + LLPipeline::sUseOcclusion = (newvalue.asBoolean() && gGLManager.mHasOcclusionQuery && LLGLSLShader::sNoFixedFunction && LLFeatureManager::getInstance()->isFeatureAvailable("UseOcclusion") && !gUseWireframe) ? 2 : 0; return true; } @@ -338,15 +341,6 @@ static bool handleUploadBakedTexOldChanged(const LLSD& newvalue) } -static bool handleNumpadControlChanged(const LLSD& newvalue) -{ - if (gKeyboard) - { - gKeyboard->setNumpadDistinct(static_cast<LLKeyboard::e_numpad_distinct>(newvalue.asInteger())); - } - return true; -} - static bool handleWLSkyDetailChanged(const LLSD&) { if (gSky.mVOWLSkyp.notNull()) @@ -411,12 +405,6 @@ static bool handleRenderUseImpostorsChanged(const LLSD& newvalue) return true; } -static bool handleAuditTextureChanged(const LLSD& newvalue) -{ - gAuditTexture = newvalue.asBoolean(); - return true; -} - static bool handleRenderDebugGLChanged(const LLSD& newvalue) { gDebugGL = newvalue.asBoolean() || gDebugSession; @@ -508,6 +496,25 @@ bool handleForceShowGrid(const LLSD& newvalue) return true; } +bool handleSpellCheckChanged() +{ + if (gSavedSettings.getBOOL("SpellCheck")) + { + std::list<std::string> dict_list; + std::string dict_setting = gSavedSettings.getString("SpellCheckDictionary"); + boost::split(dict_list, dict_setting, boost::is_any_of(std::string(","))); + if (!dict_list.empty()) + { + LLSpellChecker::setUseSpellCheck(dict_list.front()); + dict_list.pop_front(); + LLSpellChecker::instance().setSecondaryDictionaries(dict_list); + return true; + } + } + LLSpellChecker::setUseSpellCheck(LLStringUtil::null); + return true; +} + bool toggle_agent_pause(const LLSD& newvalue) { if ( newvalue.asBoolean() ) @@ -618,7 +625,6 @@ void settings_setup_listeners() gSavedSettings.getControl("RenderDeferredSSAO")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2)); gSavedSettings.getControl("RenderPerformanceTest")->getSignal()->connect(boost::bind(&handleRenderPerfTestChanged, _2)); gSavedSettings.getControl("TextureMemory")->getSignal()->connect(boost::bind(&handleVideoMemoryChanged, _2)); - gSavedSettings.getControl("AuditTexture")->getSignal()->connect(boost::bind(&handleAuditTextureChanged, _2)); gSavedSettings.getControl("ChatFontSize")->getSignal()->connect(boost::bind(&handleChatFontSizeChanged, _2)); gSavedSettings.getControl("ChatPersistTime")->getSignal()->connect(boost::bind(&handleChatPersistTimeChanged, _2)); gSavedSettings.getControl("ConsoleMaxLines")->getSignal()->connect(boost::bind(&handleConsoleMaxLinesChanged, _2)); @@ -645,7 +651,6 @@ void settings_setup_listeners() gSavedSettings.getControl("RenderUseStreamVBO")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2)); gSavedSettings.getControl("RenderPreferStreamDraw")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2)); gSavedSettings.getControl("WLSkyDetail")->getSignal()->connect(boost::bind(&handleWLSkyDetailChanged, _2)); - gSavedSettings.getControl("NumpadControl")->getSignal()->connect(boost::bind(&handleNumpadControlChanged, _2)); gSavedSettings.getControl("JoystickAxis0")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); gSavedSettings.getControl("JoystickAxis1")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); gSavedSettings.getControl("JoystickAxis2")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); @@ -714,6 +719,8 @@ void settings_setup_listeners() gSavedSettings.getControl("UpdaterServiceSetting")->getSignal()->connect(boost::bind(&toggle_updater_service_active, _2)); gSavedSettings.getControl("ForceShowGrid")->getSignal()->connect(boost::bind(&handleForceShowGrid, _2)); gSavedSettings.getControl("RenderTransparentWater")->getSignal()->connect(boost::bind(&handleRenderTransparentWaterChanged, _2)); + gSavedSettings.getControl("SpellCheck")->getSignal()->connect(boost::bind(&handleSpellCheckChanged)); + gSavedSettings.getControl("SpellCheckDictionary")->getSignal()->connect(boost::bind(&handleSpellCheckChanged)); } #if TEST_CACHED_CONTROL diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index 0adb187dd2..4571d08050 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -383,15 +383,24 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) const std::string& message = gAgent.getTeleportMessage(); switch( gAgent.getTeleportState() ) { + case LLAgent::TELEPORT_PENDING: + gTeleportDisplayTimer.reset(); + gViewerWindow->setShowProgress(TRUE); + gViewerWindow->setProgressPercent(llmin(teleport_percent, 0.0f)); + gAgent.setTeleportMessage(LLAgent::sTeleportProgressMessages["pending"]); + gViewerWindow->setProgressString(LLAgent::sTeleportProgressMessages["pending"]); + break; + case LLAgent::TELEPORT_START: // Transition to REQUESTED. Viewer has sent some kind // of TeleportRequest to the source simulator gTeleportDisplayTimer.reset(); gViewerWindow->setShowProgress(TRUE); - gViewerWindow->setProgressPercent(0); + gViewerWindow->setProgressPercent(llmin(teleport_percent, 0.0f)); gAgent.setTeleportState( LLAgent::TELEPORT_REQUESTED ); gAgent.setTeleportMessage( LLAgent::sTeleportProgressMessages["requesting"]); + gViewerWindow->setProgressString(LLAgent::sTeleportProgressMessages["requesting"]); break; case LLAgent::TELEPORT_REQUESTED: @@ -622,11 +631,6 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) LLSpatialGroup::sNoDelete = TRUE; LLTexUnit::sWhiteTexture = LLViewerFetchedTexture::sWhiteImagep->getTexName(); - /*if (LLPipeline::sUseOcclusion && LLPipeline::sRenderDeferred) - { //force occlusion on for all render types if doing deferred render (tighter shadow frustum) - LLPipeline::sUseOcclusion = 3; - }*/ - S32 occlusion = LLPipeline::sUseOcclusion; if (gDepthDirty) { //depth buffer is invalid, don't overwrite occlusion state @@ -755,12 +759,12 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) gTextureList.updateImages(max_image_decode_time); } - { + /*{ LLFastTimer t(FTM_IMAGE_UPDATE_DELETE); //remove dead textures from GL LLImageGL::deleteDeadTextures(); stop_glerror(); - } + }*/ } LLGLState::checkStates(); @@ -889,6 +893,28 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) { LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD; LLMemType mt_rg(LLMemType::MTYPE_DISPLAY_RENDER_GEOM); + + if (gSavedSettings.getBOOL("RenderDepthPrePass") && LLGLSLShader::sNoFixedFunction) + { + gGL.setColorMask(false, false); + + U32 types[] = { + LLRenderPass::PASS_SIMPLE, + LLRenderPass::PASS_FULLBRIGHT, + LLRenderPass::PASS_SHINY + }; + + U32 num_types = LL_ARRAY_SIZE(types); + gOcclusionProgram.bind(); + for (U32 i = 0; i < num_types; i++) + { + gPipeline.renderObjects(types[i], LLVertexBuffer::MAP_VERTEX, FALSE); + } + + gOcclusionProgram.unbind(); + } + + gGL.setColorMask(true, false); if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender) { diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index bf12b08321..e45426a8d6 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -30,7 +30,7 @@ #include "llfloaterreg.h" #include "llviewerfloaterreg.h" - +#include "llfloaterautoreplacesettings.h" #include "llcompilequeue.h" #include "llcallfloater.h" #include "llfasttimerview.h" @@ -78,7 +78,6 @@ #include "llfloaterlandholdings.h" #include "llfloatermap.h" #include "llfloatermemleak.h" -#include "llfloatermodelwizard.h" #include "llfloaternamedesc.h" #include "llfloaternotificationsconsole.h" #include "llfloaterobjectweights.h" @@ -100,9 +99,11 @@ #include "llfloatersidepanelcontainer.h" #include "llfloatersnapshot.h" #include "llfloatersounddevices.h" +#include "llfloaterspellchecksettings.h" #include "llfloatertelehub.h" #include "llfloatertestinspectors.h" #include "llfloatertestlistview.h" +#include "llfloatertexturefetchdebugger.h" #include "llfloatertools.h" #include "llfloatertos.h" #include "llfloatertopobjects.h" @@ -227,6 +228,11 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("land_holdings", "floater_land_holdings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterLandHoldings>); LLFloaterReg::add("mem_leaking", "floater_mem_leaking.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMemLeak>); + + if(gSavedSettings.getBOOL("TextureFetchDebuggerEnabled")) + { + LLFloaterReg::add("tex_fetch_debugger", "floater_texture_fetch_debugger.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterTextureFetchDebugger>); + } LLFloaterReg::add("media_settings", "floater_media_settings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMediaSettings>); LLFloaterReg::add("message_critical", "floater_critical.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterTOS>); LLFloaterReg::add("message_tos", "floater_tos.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterTOS>); @@ -248,7 +254,10 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("preferences", "floater_preferences.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPreference>); LLFloaterReg::add("prefs_proxy", "floater_preferences_proxy.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPreferenceProxy>); LLFloaterReg::add("prefs_hardware_settings", "floater_hardware_settings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterHardwareSettings>); + LLFloaterReg::add("prefs_spellchecker_import", "floater_spellcheck_import.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSpellCheckerImport>); LLFloaterReg::add("prefs_translation", "floater_translation_settings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterTranslationSettings>); + LLFloaterReg::add("prefs_spellchecker", "floater_spellcheck.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSpellCheckerSettings>); + LLFloaterReg::add("prefs_autoreplace", "floater_autoreplace.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAutoReplaceSettings>); LLFloaterReg::add("perm_prefs", "floater_perm_prefs.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPerms>); LLFloaterReg::add("picks", "floater_picks.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSidePanelContainer>); LLFloaterReg::add("pref_joystick", "floater_joystick.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterJoystick>); @@ -298,7 +307,6 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("upload_anim_anim", "floater_animation_anim_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAnimPreview>, "upload"); LLFloaterReg::add("upload_image", "floater_image_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterImagePreview>, "upload"); LLFloaterReg::add("upload_model", "floater_model_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterModelPreview>, "upload"); - LLFloaterReg::add("upload_model_wizard", "floater_model_wizard.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterModelWizard>); LLFloaterReg::add("upload_script", "floater_script_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterScriptPreview>, "upload"); LLFloaterReg::add("upload_sound", "floater_sound_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSoundPreview>, "upload"); diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index d81b016fc1..a187318eb7 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -342,8 +342,8 @@ void LLViewerInventoryItem::cloneViewerItem(LLPointer<LLViewerInventoryItem>& ne void LLViewerInventoryItem::removeFromServer() { - llinfos << "Removing inventory item " << mUUID << " from server." - << llendl; + lldebugs << "Removing inventory item " << mUUID << " from server." + << llendl; LLInventoryModel::LLCategoryUpdate up(mParentUUID, -1); gInventory.accountForUpdate(up); diff --git a/indra/newview/llviewerjointattachment.cpp b/indra/newview/llviewerjointattachment.cpp index 4e14824e69..3a04bbed4f 100644 --- a/indra/newview/llviewerjointattachment.cpp +++ b/indra/newview/llviewerjointattachment.cpp @@ -127,7 +127,11 @@ void LLViewerJointAttachment::setupDrawable(LLViewerObject *object) { for (S32 face_num = 0; face_num < object->mDrawable->getNumFaces(); face_num++) { - object->mDrawable->getFace(face_num)->setState(LLFace::HUD_RENDER); + LLFace *face = object->mDrawable->getFace(face_num); + if (face) + { + face->setState(LLFace::HUD_RENDER); + } } } @@ -146,7 +150,11 @@ void LLViewerJointAttachment::setupDrawable(LLViewerObject *object) { for (S32 face_num = 0; face_num < childp->mDrawable->getNumFaces(); face_num++) { - childp->mDrawable->getFace(face_num)->setState(LLFace::HUD_RENDER); + LLFace * face = childp->mDrawable->getFace(face_num); + if (face) + { + face->setState(LLFace::HUD_RENDER); + } } } } @@ -254,7 +262,11 @@ void LLViewerJointAttachment::removeObject(LLViewerObject *object) { for (S32 face_num = 0; face_num < object->mDrawable->getNumFaces(); face_num++) { - object->mDrawable->getFace(face_num)->clearState(LLFace::HUD_RENDER); + LLFace * face = object->mDrawable->getFace(face_num); + if (face) + { + face->clearState(LLFace::HUD_RENDER); + } } } } @@ -272,7 +284,11 @@ void LLViewerJointAttachment::removeObject(LLViewerObject *object) { for (S32 face_num = 0; face_num < childp->mDrawable->getNumFaces(); face_num++) { - childp->mDrawable->getFace(face_num)->clearState(LLFace::HUD_RENDER); + LLFace * face = childp->mDrawable->getFace(face_num); + if (face) + { + face->clearState(LLFace::HUD_RENDER); + } } } } diff --git a/indra/newview/llviewerjointmesh.cpp b/indra/newview/llviewerjointmesh.cpp index e052e37393..f029ae5302 100644 --- a/indra/newview/llviewerjointmesh.cpp +++ b/indra/newview/llviewerjointmesh.cpp @@ -576,7 +576,6 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy) { old_mode = mTexture->getAddressMode(); } - gGL.getTexUnit(diffuse_channel)->bind(mTexture.get()); gGL.getTexUnit(diffuse_channel)->bind(mTexture); gGL.getTexUnit(diffuse_channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); } diff --git a/indra/newview/llviewerjointmesh.h b/indra/newview/llviewerjointmesh.h index 0191f0cae8..dd5dae1dc1 100644 --- a/indra/newview/llviewerjointmesh.h +++ b/indra/newview/llviewerjointmesh.h @@ -61,6 +61,7 @@ public: //----------------------------------------------------------------------------- class LLViewerJointMesh : public LLViewerJoint { + friend class LLVOAvatar; protected: LLColor4 mColor; // color value // LLColor4 mSpecular; // specular color (always white for now) diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 903d7228e4..7ab5a01c5f 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -86,6 +86,7 @@ #include "llrootview.h" #include "llsceneview.h" #include "llselectmgr.h" +#include "llspellcheckmenuhandler.h" #include "llstatusbar.h" #include "lltextureview.h" #include "lltoolcomp.h" @@ -93,6 +94,7 @@ #include "lltoolpie.h" #include "lltoolselectland.h" #include "lltrans.h" +#include "llviewerdisplay.h" //for gWindowResized #include "llviewergenericmessage.h" #include "llviewerhelp.h" #include "llviewermenufile.h" // init_menu_file() @@ -205,7 +207,7 @@ BOOL enable_take(); void handle_take(); void handle_object_show_inspector(); void handle_avatar_show_inspector(); -bool confirm_take(const LLSD& notification, const LLSD& response); +bool confirm_take(const LLSD& notification, const LLSD& response, LLObjectSelectionHandle selection_handle); void handle_buy_object(LLSaleInfo sale_info); void handle_buy_contents(LLSaleInfo sale_info); @@ -299,7 +301,6 @@ BOOL enable_buy_land(void*); void handle_test_male(void *); void handle_test_female(void *); -void handle_toggle_pg(void*); void handle_dump_attachments(void *); void handle_dump_avatar_local_textures(void*); void handle_debug_avatar_textures(void*); @@ -516,14 +517,6 @@ class LLAdvancedToggleConsole : public view_listener_t { toggle_visibility( (void*)static_cast<LLUICtrl*>(gDebugView->mDebugConsolep)); } - else if (gTextureSizeView && "texture size" == console_type) - { - toggle_visibility( (void*)gTextureSizeView ); - } - else if (gTextureCategoryView && "texture category" == console_type) - { - toggle_visibility( (void*)gTextureCategoryView ); - } else if ("fast timers" == console_type) { LLFloaterReg::toggleInstance("fast_timers"); @@ -556,14 +549,6 @@ class LLAdvancedCheckConsole : public view_listener_t { new_value = get_visibility( (void*)((LLView*)gDebugView->mDebugConsolep) ); } - else if (gTextureSizeView && "texture size" == console_type) - { - new_value = get_visibility( (void*)gTextureSizeView ); - } - else if (gTextureCategoryView && "texture category" == console_type) - { - new_value = get_visibility( (void*)gTextureCategoryView ); - } else if ("fast timers" == console_type) { new_value = LLFloaterReg::instanceVisible("fast_timers"); @@ -866,6 +851,73 @@ class LLAdvancedCheckFeature : public view_listener_t } }; +class LLAdvancedCheckDisplayTextureDensity : public view_listener_t +{ + bool handleEvent(const LLSD& userdata) + { + std::string mode = userdata.asString(); + if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY)) + { + return mode == "none"; + } + if (mode == "current") + { + return LLViewerTexture::sDebugTexelsMode == LLViewerTexture::DEBUG_TEXELS_CURRENT; + } + else if (mode == "desired") + { + return LLViewerTexture::sDebugTexelsMode == LLViewerTexture::DEBUG_TEXELS_DESIRED; + } + else if (mode == "full") + { + return LLViewerTexture::sDebugTexelsMode == LLViewerTexture::DEBUG_TEXELS_FULL; + } + return false; + } +}; + +class LLAdvancedSetDisplayTextureDensity : public view_listener_t +{ + bool handleEvent(const LLSD& userdata) + { + std::string mode = userdata.asString(); + if (mode == "none") + { + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY) == TRUE) + { + gPipeline.toggleRenderDebug((void*)LLPipeline::RENDER_DEBUG_TEXEL_DENSITY); + } + LLViewerTexture::sDebugTexelsMode = LLViewerTexture::DEBUG_TEXELS_OFF; + } + else if (mode == "current") + { + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY) == FALSE) + { + gPipeline.toggleRenderDebug((void*)LLPipeline::RENDER_DEBUG_TEXEL_DENSITY); + } + LLViewerTexture::sDebugTexelsMode = LLViewerTexture::DEBUG_TEXELS_CURRENT; + } + else if (mode == "desired") + { + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY) == FALSE) + { + gPipeline.toggleRenderDebug((void*)LLPipeline::RENDER_DEBUG_TEXEL_DENSITY); + } + gPipeline.setRenderDebugFeatureControl(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY, true); + LLViewerTexture::sDebugTexelsMode = LLViewerTexture::DEBUG_TEXELS_DESIRED; + } + else if (mode == "full") + { + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY) == FALSE) + { + gPipeline.toggleRenderDebug((void*)LLPipeline::RENDER_DEBUG_TEXEL_DENSITY); + } + LLViewerTexture::sDebugTexelsMode = LLViewerTexture::DEBUG_TEXELS_FULL; + } + return true; + } +}; + ////////////////// // INFO DISPLAY // @@ -980,6 +1032,10 @@ U32 info_display_from_string(std::string info_display) { return LLPipeline::RENDER_DEBUG_WIND_VECTORS; } + else if ("texel density" == info_display) + { + return LLPipeline::RENDER_DEBUG_TEXEL_DENSITY; + } else { return 0; @@ -1118,6 +1174,7 @@ class LLAdvancedToggleWireframe : public view_listener_t bool handleEvent(const LLSD& userdata) { gUseWireframe = !(gUseWireframe); + gWindowResized = TRUE; LLPipeline::updateRenderDeferred(); gPipeline.resetVertexBuffers(); return true; @@ -1586,23 +1643,6 @@ class LLAdvancedTestFemale : public view_listener_t } }; - - -/////////////// -// TOGGLE PG // -/////////////// - - -class LLAdvancedTogglePG : public view_listener_t -{ - bool handleEvent(const LLSD& userdata) - { - handle_toggle_pg(NULL); - return true; - } -}; - - class LLAdvancedForceParamsToDefault : public view_listener_t { bool handleEvent(const LLSD& userdata) @@ -1982,7 +2022,6 @@ class LLAdvancedCompressImage : public view_listener_t }; - ///////////////////////// // SHOW DEBUG SETTINGS // ///////////////////////// @@ -2245,6 +2284,14 @@ class LLDevelopSetLoggingLevel : public view_listener_t } }; +class LLDevelopTextureFetchDebugger : public view_listener_t +{ + bool handleEvent(const LLSD& userdata) + { + return gSavedSettings.getBOOL("TextureFetchDebuggerEnabled"); + } +}; + ////////////////// // ADMIN MENU // ////////////////// @@ -4439,7 +4486,10 @@ void handle_take() LLNotification::Params params("ConfirmObjectTakeLock"); params.payload(payload); - params.functor.function(confirm_take); + // MAINT-290 + // Reason: Showing the confirmation dialog resets object selection, thus there is nothing to derez. + // Fix: pass selection to the confirm_take, so that selection doesn't "die" after confirmation dialog is opened + params.functor.function(boost::bind(confirm_take, _1, _2, LLSelectMgr::instance().getSelection())); if(locked_but_takeable_object || !you_own_everything) @@ -4492,7 +4542,7 @@ void handle_avatar_show_inspector() -bool confirm_take(const LLSD& notification, const LLSD& response) +bool confirm_take(const LLSD& notification, const LLSD& response, LLObjectSelectionHandle selection_handle) { S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if(enable_take() && (option == 0)) @@ -5045,6 +5095,78 @@ class LLEditDelete : public view_listener_t } }; +void handle_spellcheck_replace_with_suggestion(const LLUICtrl* ctrl, const LLSD& param) +{ + const LLContextMenu* menu = dynamic_cast<const LLContextMenu*>(ctrl->getParent()); + LLSpellCheckMenuHandler* spellcheck_handler = (menu) ? dynamic_cast<LLSpellCheckMenuHandler*>(menu->getSpawningView()) : NULL; + if ( (!spellcheck_handler) || (!spellcheck_handler->getSpellCheck()) ) + { + return; + } + + U32 index = 0; + if ( (!LLStringUtil::convertToU32(param.asString(), index)) || (index >= spellcheck_handler->getSuggestionCount()) ) + { + return; + } + + spellcheck_handler->replaceWithSuggestion(index); +} + +bool visible_spellcheck_suggestion(LLUICtrl* ctrl, const LLSD& param) +{ + LLMenuItemGL* item = dynamic_cast<LLMenuItemGL*>(ctrl); + const LLContextMenu* menu = (item) ? dynamic_cast<const LLContextMenu*>(item->getParent()) : NULL; + const LLSpellCheckMenuHandler* spellcheck_handler = (menu) ? dynamic_cast<const LLSpellCheckMenuHandler*>(menu->getSpawningView()) : NULL; + if ( (!spellcheck_handler) || (!spellcheck_handler->getSpellCheck()) ) + { + return false; + } + + U32 index = 0; + if ( (!LLStringUtil::convertToU32(param.asString(), index)) || (index >= spellcheck_handler->getSuggestionCount()) ) + { + return false; + } + + item->setLabel(spellcheck_handler->getSuggestion(index)); + return true; +} + +void handle_spellcheck_add_to_dictionary(const LLUICtrl* ctrl) +{ + const LLContextMenu* menu = dynamic_cast<const LLContextMenu*>(ctrl->getParent()); + LLSpellCheckMenuHandler* spellcheck_handler = (menu) ? dynamic_cast<LLSpellCheckMenuHandler*>(menu->getSpawningView()) : NULL; + if ( (spellcheck_handler) && (spellcheck_handler->canAddToDictionary()) ) + { + spellcheck_handler->addToDictionary(); + } +} + +bool enable_spellcheck_add_to_dictionary(const LLUICtrl* ctrl) +{ + const LLContextMenu* menu = dynamic_cast<const LLContextMenu*>(ctrl->getParent()); + const LLSpellCheckMenuHandler* spellcheck_handler = (menu) ? dynamic_cast<const LLSpellCheckMenuHandler*>(menu->getSpawningView()) : NULL; + return (spellcheck_handler) && (spellcheck_handler->canAddToDictionary()); +} + +void handle_spellcheck_add_to_ignore(const LLUICtrl* ctrl) +{ + const LLContextMenu* menu = dynamic_cast<const LLContextMenu*>(ctrl->getParent()); + LLSpellCheckMenuHandler* spellcheck_handler = (menu) ? dynamic_cast<LLSpellCheckMenuHandler*>(menu->getSpawningView()) : NULL; + if ( (spellcheck_handler) && (spellcheck_handler->canAddToIgnore()) ) + { + spellcheck_handler->addToIgnore(); + } +} + +bool enable_spellcheck_add_to_ignore(const LLUICtrl* ctrl) +{ + const LLContextMenu* menu = dynamic_cast<const LLContextMenu*>(ctrl->getParent()); + const LLSpellCheckMenuHandler* spellcheck_handler = (menu) ? dynamic_cast<const LLSpellCheckMenuHandler*>(menu->getSpawningView()) : NULL; + return (spellcheck_handler) && (spellcheck_handler->canAddToIgnore()); +} + bool enable_object_delete() { bool new_value = @@ -5290,6 +5412,14 @@ void toggle_debug_menus(void*) // } // +class LLCommunicateBlockList : public view_listener_t +{ + bool handleEvent(const LLSD& userdata) + { + LLFloaterSidePanelContainer::showPanel("people", "panel_block_list_sidetray", LLSD()); + return true; + } +}; class LLWorldSetHomeLocation : public view_listener_t { @@ -6661,15 +6791,6 @@ void handle_test_female(void*) //gGestureList.requestResetFromServer( FALSE ); } -void handle_toggle_pg(void*) -{ - gAgent.setTeen( !gAgent.isTeen() ); - - LLFloaterWorldMap::reloadIcons(NULL); - - llinfos << "PG status set to " << (S32)gAgent.isTeen() << llendl; -} - void handle_dump_attachments(void*) { if(!isAgentAvatarValid()) return; @@ -7995,6 +8116,19 @@ void initialize_edit_menu() } +void initialize_spellcheck_menu() +{ + LLUICtrl::CommitCallbackRegistry::Registrar& commit = LLUICtrl::CommitCallbackRegistry::currentRegistrar(); + LLUICtrl::EnableCallbackRegistry::Registrar& enable = LLUICtrl::EnableCallbackRegistry::currentRegistrar(); + + commit.add("SpellCheck.ReplaceWithSuggestion", boost::bind(&handle_spellcheck_replace_with_suggestion, _1, _2)); + enable.add("SpellCheck.VisibleSuggestion", boost::bind(&visible_spellcheck_suggestion, _1, _2)); + commit.add("SpellCheck.AddToDictionary", boost::bind(&handle_spellcheck_add_to_dictionary, _1)); + enable.add("SpellCheck.EnableAddToDictionary", boost::bind(&enable_spellcheck_add_to_dictionary, _1)); + commit.add("SpellCheck.AddToIgnore", boost::bind(&handle_spellcheck_add_to_ignore, _1)); + enable.add("SpellCheck.EnableAddToIgnore", boost::bind(&enable_spellcheck_add_to_ignore, _1)); +} + void initialize_menus() { // A parameterized event handler used as ctrl-8/9/0 zoom controls below. @@ -8075,6 +8209,9 @@ void initialize_menus() // Me > Movement view_listener_t::addMenu(new LLAdvancedAgentFlyingInfo(), "Agent.getFlying"); + + // Communicate + view_listener_t::addMenu(new LLCommunicateBlockList(), "Communicate.BlockList"); // World menu view_listener_t::addMenu(new LLWorldAlwaysRun(), "World.AlwaysRun"); @@ -8155,6 +8292,10 @@ void initialize_menus() //// Advanced > Render > Features view_listener_t::addMenu(new LLAdvancedToggleFeature(), "Advanced.ToggleFeature"); view_listener_t::addMenu(new LLAdvancedCheckFeature(), "Advanced.CheckFeature"); + + view_listener_t::addMenu(new LLAdvancedCheckDisplayTextureDensity(), "Advanced.CheckDisplayTextureDensity"); + view_listener_t::addMenu(new LLAdvancedSetDisplayTextureDensity(), "Advanced.SetDisplayTextureDensity"); + // Advanced > Render > Info Displays view_listener_t::addMenu(new LLAdvancedToggleInfoDisplay(), "Advanced.ToggleInfoDisplay"); view_listener_t::addMenu(new LLAdvancedCheckInfoDisplay(), "Advanced.CheckInfoDisplay"); @@ -8230,7 +8371,6 @@ void initialize_menus() view_listener_t::addMenu(new LLAdvancedTestMale(), "Advanced.TestMale"); view_listener_t::addMenu(new LLAdvancedTestFemale(), "Advanced.TestFemale"); - view_listener_t::addMenu(new LLAdvancedTogglePG(), "Advanced.TogglePG"); // Advanced > Character (toplevel) view_listener_t::addMenu(new LLAdvancedForceParamsToDefault(), "Advanced.ForceParamsToDefault"); @@ -8286,6 +8426,9 @@ void initialize_menus() // Develop >Set logging level view_listener_t::addMenu(new LLDevelopCheckLoggingLevel(), "Develop.CheckLoggingLevel"); view_listener_t::addMenu(new LLDevelopSetLoggingLevel(), "Develop.SetLoggingLevel"); + + //Develop (Texture Fetch Debug Console) + view_listener_t::addMenu(new LLDevelopTextureFetchDebugger(), "Develop.SetTexFetchDebugger"); // Admin >Object view_listener_t::addMenu(new LLAdminForceTakeCopy(), "Admin.ForceTakeCopy"); diff --git a/indra/newview/llviewermenu.h b/indra/newview/llviewermenu.h index 87cb4efbc4..8c40762865 100644 --- a/indra/newview/llviewermenu.h +++ b/indra/newview/llviewermenu.h @@ -39,6 +39,7 @@ class LLObjectSelection; class LLSelectNode; void initialize_edit_menu(); +void initialize_spellcheck_menu(); void init_menus(); void cleanup_menus(); diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 03c113ecb3..d03a58e9e3 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -42,6 +42,7 @@ #include "llinventorydefines.h" #include "lllslconstants.h" #include "llregionhandle.h" +#include "llsd.h" #include "llsdserialize.h" #include "llteleportflags.h" #include "lltransactionflags.h" @@ -107,6 +108,7 @@ #include "llagentui.h" #include "llpanelblockedlist.h" #include "llpanelplaceprofile.h" +#include "llviewerregion.h" #include <boost/algorithm/string/split.hpp> // #include <boost/regex.hpp> @@ -2045,6 +2047,46 @@ bool lure_callback(const LLSD& notification, const LLSD& response) } static LLNotificationFunctorRegistration lure_callback_reg("TeleportOffered", lure_callback); +bool mature_lure_callback(const LLSD& notification, const LLSD& response) +{ + S32 option = 0; + if (response.isInteger()) + { + option = response.asInteger(); + } + else + { + option = LLNotificationsUtil::getSelectedOption(notification, response); + } + + LLUUID from_id = notification["payload"]["from_id"].asUUID(); + LLUUID lure_id = notification["payload"]["lure_id"].asUUID(); + BOOL godlike = notification["payload"]["godlike"].asBoolean(); + U8 region_access = static_cast<U8>(notification["payload"]["region_maturity"].asInteger()); + + switch(option) + { + case 0: + { + // accept + gSavedSettings.setU32("PreferredMaturity", static_cast<U32>(region_access)); + gAgent.setMaturityRatingChangeDuringTeleport(region_access); + gAgent.teleportViaLure(lure_id, godlike); + } + break; + case 1: + default: + // decline + send_simple_im(from_id, + LLStringUtil::null, + IM_LURE_DECLINED, + lure_id); + break; + } + return false; +} +static LLNotificationFunctorRegistration mature_lure_callback_reg("TeleportOffered_MaturityExceeded", mature_lure_callback); + bool goto_url_callback(const LLSD& notification, const LLSD& response) { std::string url = notification["payload"]["url"].asString(); @@ -2759,7 +2801,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) case IM_SESSION_SEND: { - if (!is_linden && is_busy) + if (is_busy) { return; } @@ -2823,7 +2865,11 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) chat.mSourceType = CHAT_SOURCE_OBJECT; - if(SYSTEM_FROM == name) + // To conclude that the source type of message is CHAT_SOURCE_SYSTEM it's not + // enough to check only from name (i.e. fromName = "Second Life"). For example + // source type of messages from objects called "Second Life" should not be CHAT_SOURCE_SYSTEM. + bool chat_from_system = (SYSTEM_FROM == name) && region_id.isNull() && position.isNull(); + if(chat_from_system) { // System's UUID is NULL (fixes EXT-4766) chat.mFromID = LLUUID::null; @@ -2848,7 +2894,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) // Note: lie to Nearby Chat, pretending that this is NOT an IM, because // IMs from obejcts don't open IM sessions. LLNearbyChat* nearby_chat = LLNearbyChat::getInstance(); - if(SYSTEM_FROM != name && nearby_chat) + if(!chat_from_system && nearby_chat) { chat.mOwnerID = from_id; LLSD args; @@ -2866,7 +2912,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) //Object IMs send with from name: 'Second Life' need to be displayed also in notification toasts (EXT-1590) - if (SYSTEM_FROM != name) break; + if (!chat_from_system) break; LLSD substitutions; substitutions["NAME"] = name; @@ -2931,15 +2977,54 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) { LLVector3 pos, look_at; U64 region_handle(0); - U8 region_access(0); + U8 region_access(SIM_ACCESS_MIN); std::string region_info = ll_safe_string((char*)binary_bucket, binary_bucket_size); std::string region_access_str = LLStringUtil::null; std::string region_access_icn = LLStringUtil::null; + std::string region_access_lc = LLStringUtil::null; + + bool canUserAccessDstRegion = true; + bool doesUserRequireMaturityIncrease = false; if (parse_lure_bucket(region_info, region_handle, pos, look_at, region_access)) { region_access_str = LLViewerRegion::accessToString(region_access); region_access_icn = LLViewerRegion::getAccessIcon(region_access); + region_access_lc = region_access_str; + LLStringUtil::toLower(region_access_lc); + + if (!gAgent.isGodlike()) + { + switch (region_access) + { + case SIM_ACCESS_MIN : + case SIM_ACCESS_PG : + break; + case SIM_ACCESS_MATURE : + if (gAgent.isTeen()) + { + canUserAccessDstRegion = false; + } + else if (gAgent.prefersPG()) + { + doesUserRequireMaturityIncrease = true; + } + break; + case SIM_ACCESS_ADULT : + if (!gAgent.isAdult()) + { + canUserAccessDstRegion = false; + } + else if (!gAgent.prefersAdult()) + { + doesUserRequireMaturityIncrease = true; + } + break; + default : + llassert(0); + break; + } + } } LLSD args; @@ -2948,28 +3033,130 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) args["MESSAGE"] = message; args["MATURITY_STR"] = region_access_str; args["MATURITY_ICON"] = region_access_icn; + args["REGION_CONTENT_MATURITY"] = region_access_lc; LLSD payload; payload["from_id"] = from_id; payload["lure_id"] = session_id; payload["godlike"] = FALSE; + payload["region_maturity"] = region_access; + + if (!canUserAccessDstRegion) + { + LLNotification::Params params("TeleportOffered_MaturityBlocked"); + params.substitutions = args; + params.payload = payload; + LLPostponedNotification::add<LLPostponedOfferNotification>( params, from_id, false); + send_simple_im(from_id, LLTrans::getString("TeleportMaturityExceeded"), IM_NOTHING_SPECIAL, session_id); + send_simple_im(from_id, LLStringUtil::null, IM_LURE_DECLINED, session_id); + } + else if (doesUserRequireMaturityIncrease) + { + LLNotification::Params params("TeleportOffered_MaturityExceeded"); + params.substitutions = args; + params.payload = payload; + LLPostponedNotification::add<LLPostponedOfferNotification>( params, from_id, false); + } + else + { + LLNotification::Params params("TeleportOffered"); + params.substitutions = args; + params.payload = payload; + LLPostponedNotification::add<LLPostponedOfferNotification>( params, from_id, false); + } - LLNotification::Params params("TeleportOffered"); - params.substitutions = args; - params.payload = payload; - LLPostponedNotification::add<LLPostponedOfferNotification>( params, from_id, false); } } break; case IM_GODLIKE_LURE_USER: { + LLVector3 pos, look_at; + U64 region_handle(0); + U8 region_access(SIM_ACCESS_MIN); + std::string region_info = ll_safe_string((char*)binary_bucket, binary_bucket_size); + std::string region_access_str = LLStringUtil::null; + std::string region_access_icn = LLStringUtil::null; + std::string region_access_lc = LLStringUtil::null; + + bool canUserAccessDstRegion = true; + bool doesUserRequireMaturityIncrease = false; + + if (parse_lure_bucket(region_info, region_handle, pos, look_at, region_access)) + { + region_access_str = LLViewerRegion::accessToString(region_access); + region_access_icn = LLViewerRegion::getAccessIcon(region_access); + region_access_lc = region_access_str; + LLStringUtil::toLower(region_access_lc); + + if (!gAgent.isGodlike()) + { + switch (region_access) + { + case SIM_ACCESS_MIN : + case SIM_ACCESS_PG : + break; + case SIM_ACCESS_MATURE : + if (gAgent.isTeen()) + { + canUserAccessDstRegion = false; + } + else if (gAgent.prefersPG()) + { + doesUserRequireMaturityIncrease = true; + } + break; + case SIM_ACCESS_ADULT : + if (!gAgent.isAdult()) + { + canUserAccessDstRegion = false; + } + else if (!gAgent.prefersAdult()) + { + doesUserRequireMaturityIncrease = true; + } + break; + default : + llassert(0); + break; + } + } + } + + LLSD args; + // *TODO: Translate -> [FIRST] [LAST] (maybe) + args["NAME_SLURL"] = LLSLURL("agent", from_id, "about").getSLURLString(); + args["MESSAGE"] = message; + args["MATURITY_STR"] = region_access_str; + args["MATURITY_ICON"] = region_access_icn; + args["REGION_CONTENT_MATURITY"] = region_access_lc; LLSD payload; payload["from_id"] = from_id; payload["lure_id"] = session_id; payload["godlike"] = TRUE; - // do not show a message box, because you're about to be - // teleported. - LLNotifications::instance().forceResponse(LLNotification::Params("TeleportOffered").payload(payload), 0); + payload["region_maturity"] = region_access; + + if (!canUserAccessDstRegion) + { + LLNotification::Params params("TeleportOffered_MaturityBlocked"); + params.substitutions = args; + params.payload = payload; + LLPostponedNotification::add<LLPostponedOfferNotification>( params, from_id, false); + send_simple_im(from_id, LLTrans::getString("TeleportMaturityExceeded"), IM_NOTHING_SPECIAL, session_id); + send_simple_im(from_id, LLStringUtil::null, IM_LURE_DECLINED, session_id); + } + else if (doesUserRequireMaturityIncrease) + { + LLNotification::Params params("TeleportOffered_MaturityExceeded"); + params.substitutions = args; + params.payload = payload; + LLPostponedNotification::add<LLPostponedOfferNotification>( params, from_id, false); + } + else + { + // do not show a message box, because you're about to be + // teleported. + LLNotifications::instance().forceResponse(LLNotification::Params("TeleportOffered").payload(payload), 0); + } } break; @@ -3492,6 +3679,9 @@ void process_teleport_start(LLMessageSystem *msg, void**) LL_DEBUGS("Messaging") << "Got TeleportStart with TeleportFlags=" << teleport_flags << ". gTeleportDisplay: " << gTeleportDisplay << ", gAgent.mTeleportState: " << gAgent.getTeleportState() << LL_ENDL; + // *NOTE: The server sends two StartTeleport packets when you are teleporting to a LM + LLViewerMessage::getInstance()->mTeleportStartedSignal(); + if (teleport_flags & TELEPORT_FLAGS_DISABLE_CANCEL) { gViewerWindow->setProgressCancelButtonVisible(FALSE); @@ -3511,11 +3701,17 @@ void process_teleport_start(LLMessageSystem *msg, void**) make_ui_sound("UISndTeleportOut"); LL_INFOS("Messaging") << "Teleport initiated by remote TeleportStart message with TeleportFlags: " << teleport_flags << LL_ENDL; + // Don't call LLFirstUse::useTeleport here because this could be // due to being killed, which would send you home, not to a Telehub } } +boost::signals2::connection LLViewerMessage::setTeleportStartedCallback(teleport_started_callback_t cb) +{ + return mTeleportStartedSignal.connect(cb); +} + void process_teleport_progress(LLMessageSystem* msg, void**) { LLUUID agent_id; @@ -4115,6 +4311,8 @@ void send_agent_update(BOOL force_send, BOOL send_reliable) head_rot_chg = dot(last_head_rot, head_rotation); + //static S32 msg_number = 0; // Used for diagnostic log messages + if (force_send || (cam_center_chg.magVec() > TRANSLATE_THRESHOLD) || (head_rot_chg < THRESHOLD_HEAD_ROT_QDOT) || @@ -4123,19 +4321,20 @@ void send_agent_update(BOOL force_send, BOOL send_reliable) control_flag_change != 0 || flag_change != 0) { -/* + /* Diagnotics to show why we send the AgentUpdate message. Also un-commment the msg_number code above and below this block + msg_number += 1; if (head_rot_chg < THRESHOLD_HEAD_ROT_QDOT) { - //LL_INFOS("Messaging") << "head rot " << head_rotation << LL_ENDL; - LL_INFOS("Messaging") << "head_rot_chg = " << head_rot_chg << LL_ENDL; + //LL_INFOS("Messaging") << " head rot " << head_rotation << LL_ENDL; + LL_INFOS("Messaging") << "msg " << msg_number << ", frame " << LLFrameTimer::getFrameCount() << ", head_rot_chg " << head_rot_chg << LL_ENDL; } if (cam_rot_chg.magVec() > ROTATION_THRESHOLD) { - LL_INFOS("Messaging") << "cam rot " << cam_rot_chg.magVec() << LL_ENDL; + LL_INFOS("Messaging") << "msg " << msg_number << ", frame " << LLFrameTimer::getFrameCount() << ", cam rot " << cam_rot_chg.magVec() << LL_ENDL; } if (cam_center_chg.magVec() > TRANSLATE_THRESHOLD) { - LL_INFOS("Messaging") << "cam center " << cam_center_chg.magVec() << LL_ENDL; + LL_INFOS("Messaging") << "msg " << msg_number << ", frame " << LLFrameTimer::getFrameCount() << ", cam center " << cam_center_chg.magVec() << LL_ENDL; } // if (drag_delta_chg.magVec() > TRANSLATE_THRESHOLD) // { @@ -4143,9 +4342,9 @@ void send_agent_update(BOOL force_send, BOOL send_reliable) // } if (control_flag_change) { - LL_INFOS("Messaging") << "dcf = " << control_flag_change << LL_ENDL; + LL_INFOS("Messaging") << "msg " << msg_number << ", frame " << LLFrameTimer::getFrameCount() << ", dcf = " << control_flag_change << LL_ENDL; } -*/ + */ duplicate_count = 0; } @@ -4180,6 +4379,26 @@ void send_agent_update(BOOL force_send, BOOL send_reliable) if (duplicate_count < DUP_MSGS && !gDisconnected) { + /* More diagnostics to count AgentUpdate messages + static S32 update_sec = 0; + static S32 update_count = 0; + static S32 max_update_count = 0; + S32 cur_sec = lltrunc( LLTimer::getTotalSeconds() ); + update_count += 1; + if (cur_sec != update_sec) + { + if (update_sec != 0) + { + update_sec = cur_sec; + //msg_number = 0; + max_update_count = llmax(max_update_count, update_count); + llinfos << "Sent " << update_count << " AgentUpdate messages per second, max is " << max_update_count << llendl; + } + update_sec = cur_sec; + update_count = 0; + } + */ + LLFastTimer t(FTM_AGENT_UPDATE_SEND); // Build the message msg->newMessageFast(_PREHASH_AgentUpdate); @@ -4348,8 +4567,6 @@ void process_kill_object(LLMessageSystem *mesgsys, void **user_data) LL_DEBUGS("Messaging") << "Kill message for local " << local_id << LL_ENDL; } - LLSelectMgr::getInstance()->removeObjectFromSelections(id); - // ...don't kill the avatar if (!(id == gAgentID)) { @@ -4372,6 +4589,12 @@ void process_kill_object(LLMessageSystem *mesgsys, void **user_data) gObjectList.mNumUnknownKills++; } } + + // We should remove the object from selection after it is marked dead by gObjectList to make LLToolGrab, + // which is using the object, release the mouse capture correctly when the object dies. + // See LLToolGrab::handleHoverActive() and LLToolGrab::handleHoverNonPhysical(). + LLSelectMgr::getInstance()->removeObjectFromSelections(id); + } } @@ -5440,23 +5663,35 @@ static void process_money_balance_reply_extended(LLMessageSystem* msg) } } - - -bool handle_special_notification_callback(const LLSD& notification, const LLSD& response) +bool handle_prompt_for_maturity_level_change_callback(const LLSD& notification, const LLSD& response) { S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if (0 == option) { // set the preference to the maturity of the region we're calling - int preferredMaturity = notification["payload"]["_region_access"].asInteger(); - gSavedSettings.setU32("PreferredMaturity", preferredMaturity); - gAgent.sendMaturityPreferenceToServer(preferredMaturity); + U8 preferredMaturity = static_cast<U8>(notification["payload"]["_region_access"].asInteger()); + gSavedSettings.setU32("PreferredMaturity", static_cast<U32>(preferredMaturity)); + } + + return false; +} - // notify user that the maturity preference has been changed - LLSD args; - args["RATING"] = LLViewerRegion::accessToString(preferredMaturity); - LLNotificationsUtil::add("PreferredMaturityChanged", args); +bool handle_prompt_for_maturity_level_change_and_reteleport_callback(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + + if (0 == option) + { + // set the preference to the maturity of the region we're calling + U8 preferredMaturity = static_cast<U8>(notification["payload"]["_region_access"].asInteger()); + gSavedSettings.setU32("PreferredMaturity", static_cast<U32>(preferredMaturity)); + gAgent.setMaturityRatingChangeDuringTeleport(preferredMaturity); + gAgent.restartFailedTeleportRequest(); + } + else + { + gAgent.clearTeleportRequest(); } return false; @@ -5465,39 +5700,148 @@ bool handle_special_notification_callback(const LLSD& notification, const LLSD& // some of the server notifications need special handling. This is where we do that. bool handle_special_notification(std::string notificationID, LLSD& llsdBlock) { - int regionAccess = llsdBlock["_region_access"].asInteger(); - llsdBlock["REGIONMATURITY"] = LLViewerRegion::accessToString(regionAccess); + U8 regionAccess = static_cast<U8>(llsdBlock["_region_access"].asInteger()); + std::string regionMaturity = LLViewerRegion::accessToString(regionAccess); + LLStringUtil::toLower(regionMaturity); + llsdBlock["REGIONMATURITY"] = regionMaturity; - // we're going to throw the LLSD in there in case anyone ever wants to use it - LLNotificationsUtil::add(notificationID+"_Notify", llsdBlock); + bool returnValue = false; + LLNotificationPtr maturityLevelNotification; + std::string notifySuffix = "_Notify"; + if (regionAccess == SIM_ACCESS_MATURE) + { + if (gAgent.isTeen()) + { + gAgent.clearTeleportRequest(); + maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_AdultsOnlyContent", llsdBlock); + returnValue = true; + + notifySuffix = "_NotifyAdultsOnly"; + } + else if (gAgent.prefersPG()) + { + maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_Change", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_callback); + returnValue = true; + } + else if (LLStringUtil::compareStrings(notificationID, "RegionEntryAccessBlocked") == 0) + { + maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_PreferencesOutOfSync", llsdBlock, llsdBlock); + returnValue = true; + } + } + else if (regionAccess == SIM_ACCESS_ADULT) + { + if (!gAgent.isAdult()) + { + gAgent.clearTeleportRequest(); + maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_AdultsOnlyContent", llsdBlock); + returnValue = true; + + notifySuffix = "_NotifyAdultsOnly"; + } + else if (gAgent.prefersPG() || gAgent.prefersMature()) + { + maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_Change", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_callback); + returnValue = true; + } + else if (LLStringUtil::compareStrings(notificationID, "RegionEntryAccessBlocked") == 0) + { + maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_PreferencesOutOfSync", llsdBlock, llsdBlock); + returnValue = true; + } + } + + if ((maturityLevelNotification == NULL) || maturityLevelNotification->isIgnored()) + { + // Given a simple notification if no maturityLevelNotification is set or it is ignore + LLNotificationsUtil::add(notificationID + notifySuffix, llsdBlock); + } + + return returnValue; +} + +// some of the server notifications need special handling. This is where we do that. +bool handle_teleport_access_blocked(LLSD& llsdBlock) +{ + std::string notificationID("TeleportEntryAccessBlocked"); + U8 regionAccess = static_cast<U8>(llsdBlock["_region_access"].asInteger()); + std::string regionMaturity = LLViewerRegion::accessToString(regionAccess); + LLStringUtil::toLower(regionMaturity); + llsdBlock["REGIONMATURITY"] = regionMaturity; + bool returnValue = false; + LLNotificationPtr maturityLevelNotification; + std::string notifySuffix = "_Notify"; if (regionAccess == SIM_ACCESS_MATURE) { if (gAgent.isTeen()) { - LLNotificationsUtil::add(notificationID+"_KB", llsdBlock); - return true; + gAgent.clearTeleportRequest(); + maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_AdultsOnlyContent", llsdBlock); + returnValue = true; + + notifySuffix = "_NotifyAdultsOnly"; } else if (gAgent.prefersPG()) { - LLNotificationsUtil::add(notificationID+"_Change", llsdBlock, llsdBlock, handle_special_notification_callback); - return true; + if (gAgent.hasRestartableFailedTeleportRequest()) + { + maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_ChangeAndReTeleport", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_and_reteleport_callback); + returnValue = true; + } + else + { + gAgent.clearTeleportRequest(); + maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_Change", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_callback); + returnValue = true; + } + } + else + { + gAgent.clearTeleportRequest(); + maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_PreferencesOutOfSync", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_callback); + returnValue = true; } } else if (regionAccess == SIM_ACCESS_ADULT) { if (!gAgent.isAdult()) { - LLNotificationsUtil::add(notificationID+"_KB", llsdBlock); - return true; + gAgent.clearTeleportRequest(); + maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_AdultsOnlyContent", llsdBlock); + returnValue = true; + + notifySuffix = "_NotifyAdultsOnly"; } else if (gAgent.prefersPG() || gAgent.prefersMature()) { - LLNotificationsUtil::add(notificationID+"_Change", llsdBlock, llsdBlock, handle_special_notification_callback); - return true; + if (gAgent.hasRestartableFailedTeleportRequest()) + { + maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_ChangeAndReTeleport", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_and_reteleport_callback); + returnValue = true; + } + else + { + gAgent.clearTeleportRequest(); + maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_Change", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_callback); + returnValue = true; + } + } + else + { + gAgent.clearTeleportRequest(); + maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_PreferencesOutOfSync", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_callback); + returnValue = true; } } - return false; + + if ((maturityLevelNotification == NULL) || maturityLevelNotification->isIgnored()) + { + // Given a simple notification if no maturityLevelNotification is set or it is ignore + LLNotificationsUtil::add(notificationID + notifySuffix, llsdBlock); + } + + return returnValue; } bool attempt_standard_notification(LLMessageSystem* msgsystem) @@ -5541,16 +5885,20 @@ bool attempt_standard_notification(LLMessageSystem* msgsystem) RegionEntryAccessBlocked RegionEntryAccessBlocked_Notify + RegionEntryAccessBlocked_NotifyAdultsOnly RegionEntryAccessBlocked_Change - RegionEntryAccessBlocked_KB + RegionEntryAccessBlocked_AdultsOnlyContent + RegionEntryAccessBlocked_ChangeAndReTeleport LandClaimAccessBlocked LandClaimAccessBlocked_Notify + LandClaimAccessBlocked_NotifyAdultsOnly LandClaimAccessBlocked_Change - LandClaimAccessBlocked_KB + LandClaimAccessBlocked_AdultsOnlyContent LandBuyAccessBlocked LandBuyAccessBlocked_Notify + LandBuyAccessBlocked_NotifyAdultsOnly LandBuyAccessBlocked_Change - LandBuyAccessBlocked_KB + LandBuyAccessBlocked_AdultsOnlyContent -----------------------------------------------------------------------*/ if (handle_special_notification(notificationID, llsdBlock)) @@ -5602,6 +5950,30 @@ void process_alert_message(LLMessageSystem *msgsystem, void **user_data) } } +bool handle_not_age_verified_alert(const std::string &pAlertName) +{ + LLNotificationPtr notification = LLNotificationsUtil::add(pAlertName); + if ((notification == NULL) || notification->isIgnored()) + { + LLNotificationsUtil::add(pAlertName + "_Notify"); + } + + return true; +} + +bool handle_special_alerts(const std::string &pAlertName) +{ + bool isHandled = false; + + if (LLStringUtil::compareStrings(pAlertName, "NotAgeVerified") == 0) + { + + isHandled = handle_not_age_verified_alert(pAlertName); + } + + return isHandled; +} + void process_alert_core(const std::string& message, BOOL modal) { // HACK -- handle callbacks for specific alerts. It also is localized in notifications.xml @@ -5625,7 +5997,10 @@ void process_alert_core(const std::string& message, BOOL modal) // Allow the server to spawn a named alert so that server alerts can be // translated out of English. std::string alert_name(message.substr(ALERT_PREFIX.length())); - LLNotificationsUtil::add(alert_name); + if (!handle_special_alerts(alert_name)) + { + LLNotificationsUtil::add(alert_name); + } } else if (message.find(NOTIFY_PREFIX) == 0) { @@ -6027,16 +6402,21 @@ void process_script_question(LLMessageSystem *msg, void **user_data) args["OBJECTNAME"] = object_name; args["NAME"] = LLCacheName::cleanFullName(owner_name); + BOOL has_not_only_debit = questions ^ LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_DEBIT]; // check the received permission flags against each permission for (S32 i = 0; i < SCRIPT_PERMISSION_EOF; i++) { if (questions & LSCRIPTRunTimePermissionBits[i]) { count++; - script_question += " " + LLTrans::getString(SCRIPT_QUESTIONS[i]) + "\n"; // check whether permission question should cause special caution dialog caution |= (SCRIPT_QUESTION_IS_CAUTION[i]); + + if (("ScriptTakeMoney" == SCRIPT_QUESTIONS[i]) && has_not_only_debit) + continue; + + script_question += " " + LLTrans::getString(SCRIPT_QUESTIONS[i]) + "\n"; } } args["QUESTIONS"] = script_question; @@ -6052,6 +6432,10 @@ void process_script_question(LLMessageSystem *msg, void **user_data) // check whether cautions are even enabled or not if (gSavedSettings.getBOOL("PermissionsCautionEnabled")) { + if (caution) + { + args["FOOTERTEXT"] = (count > 1) ? LLTrans::getString("AdditionalPermissionsRequestHeader") + "\n\n" + script_question : ""; + } // display the caution permissions prompt LLNotificationsUtil::add(caution ? "ScriptQuestionCaution" : "ScriptQuestion", args, payload); } @@ -6202,6 +6586,9 @@ void process_teleport_failed(LLMessageSystem *msg, void**) std::string big_reason; LLSD args; + // Let the interested parties know that teleport failed. + LLViewerParcelMgr::getInstance()->onTeleportFailed(); + // if we have additional alert data if (msg->has(_PREHASH_AlertInfo) && msg->getSizeFast(_PREHASH_AlertInfo, _PREHASH_Message) > 0) { @@ -6231,7 +6618,7 @@ void process_teleport_failed(LLMessageSystem *msg, void**) else { // change notification name in this special case - if (handle_special_notification("RegionEntryAccessBlocked", llsd_block)) + if (handle_teleport_access_blocked(llsd_block)) { if( gAgent.getTeleportState() != LLAgent::TELEPORT_NONE ) { @@ -6260,9 +6647,6 @@ void process_teleport_failed(LLMessageSystem *msg, void**) LLNotificationsUtil::add("CouldNotTeleportReason", args); - // Let the interested parties know that teleport failed. - LLViewerParcelMgr::getInstance()->onTeleportFailed(); - if( gAgent.getTeleportState() != LLAgent::TELEPORT_NONE ) { gAgent.setTeleportState( LLAgent::TELEPORT_NONE ); diff --git a/indra/newview/llviewermessage.h b/indra/newview/llviewermessage.h index 46bfb2dad0..594c22ed9c 100644 --- a/indra/newview/llviewermessage.h +++ b/indra/newview/llviewermessage.h @@ -37,6 +37,9 @@ #include "llnotifications.h" #include "llextendedstatus.h" +#include <boost/function.hpp> +#include <boost/signals2.hpp> + // // Forward declarations // @@ -205,6 +208,15 @@ bool highlight_offered_object(const LLUUID& obj_id); void set_dad_inventory_item(LLInventoryItem* inv_item, const LLUUID& into_folder_uuid); void set_dad_inbox_object(const LLUUID& object_id); +class LLViewerMessage : public LLSingleton<LLViewerMessage> +{ +public: + typedef boost::function<void()> teleport_started_callback_t; + typedef boost::signals2::signal<void()> teleport_started_signal_t; + boost::signals2::connection setTeleportStartedCallback(teleport_started_callback_t cb); + + teleport_started_signal_t mTeleportStartedSignal; +}; class LLOfferInfo : public LLNotificationResponderInterface { @@ -253,5 +265,3 @@ private: void process_feature_disabled_message(LLMessageSystem* msg, void**); #endif - - diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index cd300accb7..67c87a6c63 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -432,7 +432,9 @@ void LLViewerObject::dump() const llinfos << "PositionAgent: " << getPositionAgent() << llendl; llinfos << "PositionGlobal: " << getPositionGlobal() << llendl; llinfos << "Velocity: " << getVelocity() << llendl; - if (mDrawable.notNull() && mDrawable->getNumFaces()) + if (mDrawable.notNull() && + mDrawable->getNumFaces() && + mDrawable->getFace(0)) { LLFacePool *poolp = mDrawable->getFace(0)->getPool(); if (poolp) @@ -2389,10 +2391,11 @@ void LLViewerObject::interpolateLinearMotion(const F64 & time, const F32 & dt) { // This will put the object underground, but we can't tell if it will stop // at ground level or not min_height = LLWorld::getInstance()->getMinAllowedZ(this, new_pos_global); + // Cap maximum height + new_pos.mV[VZ] = llmin(LLWorld::getInstance()->getRegionMaxHeight(), new_pos.mV[VZ]); } new_pos.mV[VZ] = llmax(min_height, new_pos.mV[VZ]); - new_pos.mV[VZ] = llmin(LLWorld::getInstance()->getRegionMaxHeight(), new_pos.mV[VZ]); // Check to see if it's going off the region LLVector3 temp(new_pos); @@ -2798,6 +2801,23 @@ void LLViewerObject::processTaskInvFile(void** user_data, S32 error_code, LLExtS (object = gObjectList.findObject(ft->mTaskID))) { object->loadTaskInvFile(ft->mFilename); + + LLInventoryObject::object_list_t::iterator it = object->mInventory->begin(); + LLInventoryObject::object_list_t::iterator end = object->mInventory->end(); + std::list<LLUUID>& pending_lst = object->mPendingInventoryItemsIDs; + + for (; it != end && pending_lst.size(); ++it) + { + LLViewerInventoryItem* item = dynamic_cast<LLViewerInventoryItem*>(it->get()); + if(item && item->getType() != LLAssetType::AT_CATEGORY) + { + std::list<LLUUID>::iterator id_it = std::find(pending_lst.begin(), pending_lst.begin(), item->getAssetUUID()); + if (id_it != pending_lst.end()) + { + pending_lst.erase(id_it); + } + } + } } else { @@ -2904,13 +2924,40 @@ void LLViewerObject::removeInventory(const LLUUID& item_id) ++mInventorySerialNum; } +bool LLViewerObject::isTextureInInventory(LLViewerInventoryItem* item) +{ + bool result = false; + + if (item && LLAssetType::AT_TEXTURE == item->getType()) + { + std::list<LLUUID>::iterator begin = mPendingInventoryItemsIDs.begin(); + std::list<LLUUID>::iterator end = mPendingInventoryItemsIDs.end(); + + bool is_fetching = std::find(begin, end, item->getAssetUUID()) != end; + bool is_fetched = getInventoryItemByAsset(item->getAssetUUID()) != NULL; + + result = is_fetched || is_fetching; + } + + return result; +} + +void LLViewerObject::updateTextureInventory(LLViewerInventoryItem* item, U8 key, bool is_new) +{ + if (item && !isTextureInInventory(item)) + { + mPendingInventoryItemsIDs.push_back(item->getAssetUUID()); + updateInventory(item, key, is_new); + } +} + void LLViewerObject::updateInventory( LLViewerInventoryItem* item, U8 key, bool is_new) { LLMemType mt(LLMemType::MTYPE_OBJECT); - + // This slices the object into what we're concerned about on the // viewer. The simulator will take the permissions and transfer // ownership. @@ -4477,7 +4524,11 @@ U32 LLViewerObject::getNumVertices() const num_faces = mDrawable->getNumFaces(); for (i = 0; i < num_faces; i++) { - num_vertices += mDrawable->getFace(i)->getGeomCount(); + LLFace * facep = mDrawable->getFace(i); + if (facep) + { + num_vertices += facep->getGeomCount(); + } } } return num_vertices; @@ -4492,7 +4543,11 @@ U32 LLViewerObject::getNumIndices() const num_faces = mDrawable->getNumFaces(); for (i = 0; i < num_faces; i++) { - num_indices += mDrawable->getFace(i)->getIndicesCount(); + LLFace * facep = mDrawable->getFace(i); + if (facep) + { + num_indices += facep->getIndicesCount(); + } } } return num_indices; diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index c8152e1539..409108266e 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -432,12 +432,15 @@ public: // manager until we have better iterators. void updateInventory(LLViewerInventoryItem* item, U8 key, bool is_new); void updateInventoryLocal(LLInventoryItem* item, U8 key); // Update without messaging. + void updateTextureInventory(LLViewerInventoryItem* item, U8 key, bool is_new); LLInventoryObject* getInventoryObject(const LLUUID& item_id); void getInventoryContents(LLInventoryObject::object_list_t& objects); LLInventoryObject* getInventoryRoot(); LLViewerInventoryItem* getInventoryItemByAsset(const LLUUID& asset_id); S16 getInventorySerial() const { return mInventorySerialNum; } + bool isTextureInInventory(LLViewerInventoryItem* item); + // These functions does viewer-side only object inventory modifications void updateViewerInventoryAsset( const LLViewerInventoryItem* item, @@ -684,6 +687,10 @@ protected: F32 mAppAngle; // Apparent visual arc in degrees F32 mPixelArea; // Apparent area in pixels + // IDs of of all items in the object's content which are added to the object's content, + // but not updated on the server yet. After item was updated, its ID will be removed from this list. + std::list<LLUUID> mPendingInventoryItemsIDs; + // This is the object's inventory from the viewer's perspective. LLInventoryObject::object_list_t* mInventory; class LLInventoryCallbackInfo diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp index 6912faa9ec..beb68c1cbb 100644 --- a/indra/newview/llviewerobjectlist.cpp +++ b/indra/newview/llviewerobjectlist.cpp @@ -91,8 +91,9 @@ extern LLPipeline gPipeline; // Statics for object lookup tables. U32 LLViewerObjectList::sSimulatorMachineIndex = 1; // Not zero deliberately, to speed up index check. -std::map<U64, U32> LLViewerObjectList::sIPAndPortToIndex; +std::map<U64, U32> LLViewerObjectList::sIPAndPortToIndex; std::map<U64, LLUUID> LLViewerObjectList::sIndexAndLocalIDToUUID; +LLStat LLViewerObjectList::sCacheHitRate("object_cache_hits", 128); LLViewerObjectList::LLViewerObjectList() { @@ -542,6 +543,8 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, } justCreated = TRUE; mNumNewObjects++; + sCacheHitRate.addValue(cached ? 100.f : 0.f); + } @@ -1718,7 +1721,10 @@ void LLViewerObjectList::generatePickList(LLCamera &camera) LLViewerObject* last_objectp = NULL; for (S32 face_num = 0; face_num < drawablep->getNumFaces(); face_num++) { - LLViewerObject* objectp = drawablep->getFace(face_num)->getViewerObject(); + LLFace * facep = drawablep->getFace(face_num); + if (!facep) continue; + + LLViewerObject* objectp = facep->getViewerObject(); if (objectp && objectp != last_objectp) { diff --git a/indra/newview/llviewerobjectlist.h b/indra/newview/llviewerobjectlist.h index c5f2a2c1ee..64925f46ae 100644 --- a/indra/newview/llviewerobjectlist.h +++ b/indra/newview/llviewerobjectlist.h @@ -192,6 +192,8 @@ protected: std::vector<OrphanInfo> mOrphanChildren; // UUID's of orphaned objects S32 mNumOrphans; + static LLStat sCacheHitRate; + typedef std::vector<LLPointer<LLViewerObject> > vobj_list_t; vobj_list_t mObjects; diff --git a/indra/newview/llviewerparcelmgr.cpp b/indra/newview/llviewerparcelmgr.cpp index 9db784101d..ae9c31bfe7 100644 --- a/indra/newview/llviewerparcelmgr.cpp +++ b/indra/newview/llviewerparcelmgr.cpp @@ -82,7 +82,6 @@ LLPointer<LLViewerTexture> sBlockedImage; LLPointer<LLViewerTexture> sPassImage; // Local functions -void optionally_start_music(const std::string& music_url); void callback_start_music(S32 option, void* data); void optionally_prepare_video(const LLParcel *parcelp); void callback_prepare_video(S32 option, void* data); @@ -1589,7 +1588,7 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use if (instance->mTeleportInProgress) { instance->mTeleportInProgress = FALSE; - instance->mTeleportFinishedSignal(gAgent.getPositionGlobal()); + instance->mTeleportFinishedSignal(gAgent.getPositionGlobal(), false); } } } @@ -1773,13 +1772,13 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use }; } -void optionally_start_music(const std::string& music_url) +void LLViewerParcelMgr::optionally_start_music(const std::string& music_url) { if (gSavedSettings.getBOOL("AudioStreamingMusic")) { // only play music when you enter a new parcel if the UI control for this // was not *explicitly* stopped by the user. (part of SL-4878) - LLPanelNearByMedia* nearby_media_panel = gStatusBar->getNearbyMediaPanel();; + LLPanelNearByMedia* nearby_media_panel = gStatusBar->getNearbyMediaPanel(); if ((nearby_media_panel && nearby_media_panel->getParcelAudioAutoStart()) || // or they have expressed no opinion in the UI, but have autoplay on... @@ -2559,7 +2558,7 @@ void LLViewerParcelMgr::onTeleportFinished(bool local, const LLVector3d& new_pos { // Local teleport. We already have the agent parcel data. // Emit the signal immediately. - getInstance()->mTeleportFinishedSignal(new_pos); + getInstance()->mTeleportFinishedSignal(new_pos, local); } else { diff --git a/indra/newview/llviewerparcelmgr.h b/indra/newview/llviewerparcelmgr.h index cac8d8391c..2a11549426 100644 --- a/indra/newview/llviewerparcelmgr.h +++ b/indra/newview/llviewerparcelmgr.h @@ -78,8 +78,8 @@ class LLViewerParcelMgr : public LLSingleton<LLViewerParcelMgr> { public: - typedef boost::function<void (const LLVector3d&)> teleport_finished_callback_t; - typedef boost::signals2::signal<void (const LLVector3d&)> teleport_finished_signal_t; + typedef boost::function<void (const LLVector3d&, const bool& local)> teleport_finished_callback_t; + typedef boost::signals2::signal<void (const LLVector3d&, const bool&)> teleport_finished_signal_t; typedef boost::function<void()> parcel_changed_callback_t; typedef boost::signals2::signal<void()> parcel_changed_signal_t; @@ -275,6 +275,8 @@ public: // *NOTE: Taken out 2005-03-21. Phoenix. //void makeLandmarkAtSelection(); + static void optionally_start_music(const std::string& music_url); + static void processParcelOverlay(LLMessageSystem *msg, void **user_data); static void processParcelProperties(LLMessageSystem *msg, void **user_data); static void processParcelAccessListReply(LLMessageSystem *msg, void **user); diff --git a/indra/newview/llviewerpartsim.cpp b/indra/newview/llviewerpartsim.cpp index 6b3e04348a..345023dbfa 100644 --- a/indra/newview/llviewerpartsim.cpp +++ b/indra/newview/llviewerpartsim.cpp @@ -476,7 +476,7 @@ void LLViewerPartSim::checkParticleCount(U32 size) LLViewerPartSim::LLViewerPartSim() { LLMemType mt(LLMemType::MTYPE_PARTICLES); - sMaxParticleCount = gSavedSettings.getS32("RenderMaxPartCount"); + sMaxParticleCount = llmin(gSavedSettings.getS32("RenderMaxPartCount"), LL_MAX_PARTICLE_COUNT); static U32 id_seed = 0; mID = ++id_seed; } diff --git a/indra/newview/llviewerpartsim.h b/indra/newview/llviewerpartsim.h index 3e20f999c0..c9959c63ec 100644 --- a/indra/newview/llviewerpartsim.h +++ b/indra/newview/llviewerpartsim.h @@ -39,6 +39,8 @@ class LLViewerRegion; class LLViewerTexture; class LLVOPartGroup; +#define LL_MAX_PARTICLE_COUNT 8192 + typedef void (*LLVPCallback)(LLViewerPart &part, const F32 dt); /////////////////// diff --git a/indra/newview/llviewerprecompiledheaders.h b/indra/newview/llviewerprecompiledheaders.h index f738b84bb9..6c8a827ba3 100644 --- a/indra/newview/llviewerprecompiledheaders.h +++ b/indra/newview/llviewerprecompiledheaders.h @@ -57,6 +57,8 @@ #include "lldeleteutils.h" #include "imageids.h" #include "indra_constants.h" +#include "llinitparam.h" + //#include "linden_common.h" //#include "llpreprocessor.h" #include "llallocator.h" @@ -124,7 +126,5 @@ // Library includes from llmessage project #include "llcachename.h" -// Library includes from llxuixml -#include "llinitparam.h" #endif diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index e3cb985ddb..f3771e93d9 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -655,6 +655,31 @@ std::string LLViewerRegion::accessToShortString(U8 sim_access) } // static +U8 LLViewerRegion::shortStringToAccess(const std::string &sim_access) +{ + U8 accessValue; + + if (LLStringUtil::compareStrings(sim_access, "PG") == 0) + { + accessValue = SIM_ACCESS_PG; + } + else if (LLStringUtil::compareStrings(sim_access, "M") == 0) + { + accessValue = SIM_ACCESS_MATURE; + } + else if (LLStringUtil::compareStrings(sim_access, "A") == 0) + { + accessValue = SIM_ACCESS_ADULT; + } + else + { + accessValue = SIM_ACCESS_MIN; + } + + return accessValue; +} + +// static void LLViewerRegion::processRegionInfo(LLMessageSystem* msg, void**) { // send it to 'observers' diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h index c483c6ef52..7280c7f2e6 100644 --- a/indra/newview/llviewerregion.h +++ b/indra/newview/llviewerregion.h @@ -202,6 +202,7 @@ public: // Returns "M", "PG", "A" etc. static std::string accessToShortString(U8 sim_access); + static U8 shortStringToAccess(const std::string &sim_access); // Return access icon name static std::string getAccessIcon(U8 sim_access); diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 10c61c01d5..a6c564a6a1 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -63,8 +63,16 @@ bool LLViewerShaderMgr::sSkipReload = false; LLVector4 gShinyOrigin; +//transform shaders +LLGLSLShader gTransformPositionProgram; +LLGLSLShader gTransformTexCoordProgram; +LLGLSLShader gTransformNormalProgram; +LLGLSLShader gTransformColorProgram; +LLGLSLShader gTransformBinormalProgram; + //utility shaders LLGLSLShader gOcclusionProgram; +LLGLSLShader gOcclusionCubeProgram; LLGLSLShader gCustomAlphaProgram; LLGLSLShader gGlowCombineProgram; LLGLSLShader gSplatTextureRectProgram; @@ -72,6 +80,7 @@ LLGLSLShader gGlowCombineFXAAProgram; LLGLSLShader gTwoTextureAddProgram; LLGLSLShader gOneTextureNoColorProgram; LLGLSLShader gDebugProgram; +LLGLSLShader gClipProgram; LLGLSLShader gAlphaMaskProgram; //object shaders @@ -178,6 +187,7 @@ LLGLSLShader gDeferredSunProgram; LLGLSLShader gDeferredBlurLightProgram; LLGLSLShader gDeferredSoftenProgram; LLGLSLShader gDeferredShadowProgram; +LLGLSLShader gDeferredShadowCubeProgram; LLGLSLShader gDeferredShadowAlphaMaskProgram; LLGLSLShader gDeferredAvatarShadowProgram; LLGLSLShader gDeferredAttachmentShadowProgram; @@ -437,7 +447,8 @@ void LLViewerShaderMgr::setShaders() S32 wl_class = 2; S32 water_class = 2; S32 deferred_class = 0; - + S32 transform_class = gGLManager.mHasTransformFeedback ? 1 : 0; + if (LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred") && gSavedSettings.getBOOL("RenderDeferred") && gSavedSettings.getBOOL("RenderAvatarVP") && @@ -475,6 +486,7 @@ void LLViewerShaderMgr::setShaders() gSky.mVOSkyp->forceSkyUpdate(); } + // Load lighting shaders mVertexShaderLevel[SHADER_LIGHTING] = light_class; mVertexShaderLevel[SHADER_INTERFACE] = light_class; @@ -484,6 +496,7 @@ void LLViewerShaderMgr::setShaders() mVertexShaderLevel[SHADER_EFFECT] = effect_class; mVertexShaderLevel[SHADER_WINDLIGHT] = wl_class; mVertexShaderLevel[SHADER_DEFERRED] = deferred_class; + mVertexShaderLevel[SHADER_TRANSFORM] = transform_class; BOOL loaded = loadBasicShaders(); @@ -493,65 +506,109 @@ void LLViewerShaderMgr::setShaders() gPipeline.mVertexShadersLoaded = 1; // Load all shaders to set max levels - loadShadersEnvironment(); - loadShadersWater(); - loadShadersWindLight(); - loadShadersEffects(); - loadShadersInterface(); + loaded = loadShadersEnvironment(); + + if (loaded) + { + loaded = loadShadersWater(); + } + + if (loaded) + { + loaded = loadShadersWindLight(); + } + + if (loaded) + { + loaded = loadShadersEffects(); + } + + if (loaded) + { + loaded = loadShadersInterface(); + } - // Load max avatar shaders to set the max level - mVertexShaderLevel[SHADER_AVATAR] = 3; - mMaxAvatarShaderLevel = 3; - - if (gSavedSettings.getBOOL("RenderAvatarVP") && loadShadersObject()) - { //hardware skinning is enabled and rigged attachment shaders loaded correctly - BOOL avatar_cloth = gSavedSettings.getBOOL("RenderAvatarCloth"); - S32 avatar_class = 1; - - // cloth is a class3 shader - if(avatar_cloth) - { - avatar_class = 3; - } + if (loaded) + { + loaded = loadTransformShaders(); + } - // Set the actual level - mVertexShaderLevel[SHADER_AVATAR] = avatar_class; - loadShadersAvatar(); - if (mVertexShaderLevel[SHADER_AVATAR] != avatar_class) - { - if (mVertexShaderLevel[SHADER_AVATAR] == 0) + if (loaded) + { + // Load max avatar shaders to set the max level + mVertexShaderLevel[SHADER_AVATAR] = 3; + mMaxAvatarShaderLevel = 3; + + if (gSavedSettings.getBOOL("RenderAvatarVP") && loadShadersObject()) + { //hardware skinning is enabled and rigged attachment shaders loaded correctly + BOOL avatar_cloth = gSavedSettings.getBOOL("RenderAvatarCloth"); + S32 avatar_class = 1; + + // cloth is a class3 shader + if(avatar_cloth) { - gSavedSettings.setBOOL("RenderAvatarVP", FALSE); + avatar_class = 3; } - if(llmax(mVertexShaderLevel[SHADER_AVATAR]-1,0) >= 3) + + // Set the actual level + mVertexShaderLevel[SHADER_AVATAR] = avatar_class; + loadShadersAvatar(); + if (mVertexShaderLevel[SHADER_AVATAR] != avatar_class) { - avatar_cloth = true; + if (mVertexShaderLevel[SHADER_AVATAR] == 0) + { + gSavedSettings.setBOOL("RenderAvatarVP", FALSE); + } + if(llmax(mVertexShaderLevel[SHADER_AVATAR]-1,0) >= 3) + { + avatar_cloth = true; + } + else + { + avatar_cloth = false; + } + gSavedSettings.setBOOL("RenderAvatarCloth", avatar_cloth); } - else + } + else + { //hardware skinning not possible, neither is deferred rendering + mVertexShaderLevel[SHADER_AVATAR] = 0; + mVertexShaderLevel[SHADER_DEFERRED] = 0; + + if (gSavedSettings.getBOOL("RenderAvatarVP")) { - avatar_cloth = false; + gSavedSettings.setBOOL("RenderDeferred", FALSE); + gSavedSettings.setBOOL("RenderAvatarCloth", FALSE); + gSavedSettings.setBOOL("RenderAvatarVP", FALSE); } - gSavedSettings.setBOOL("RenderAvatarCloth", avatar_cloth); + + loadShadersAvatar(); // unloads + + loaded = loadShadersObject(); } } - else - { //hardware skinning not possible, neither is deferred rendering - mVertexShaderLevel[SHADER_AVATAR] = 0; - mVertexShaderLevel[SHADER_DEFERRED] = 0; - - if (gSavedSettings.getBOOL("RenderAvatarVP")) - { - gSavedSettings.setBOOL("RenderDeferred", FALSE); - gSavedSettings.setBOOL("RenderAvatarCloth", FALSE); - gSavedSettings.setBOOL("RenderAvatarVP", FALSE); + + if (!loaded) + { //some shader absolutely could not load, try to fall back to a simpler setting + if (gSavedSettings.getBOOL("WindLightUseAtmosShaders")) + { //disable windlight and try again + gSavedSettings.setBOOL("WindLightUseAtmosShaders", FALSE); + reentrance = false; + setShaders(); + return; } - loadShadersAvatar(); // unloads - loadShadersObject(); - } + if (gSavedSettings.getBOOL("VertexShaderEnable")) + { //disable shaders outright and try again + gSavedSettings.setBOOL("VertexShaderEnable", FALSE); + reentrance = false; + setShaders(); + return; + } + } - if (!loadShadersDeferred()) - { + if (loaded && !loadShadersDeferred()) + { //everything else succeeded but deferred failed, disable deferred and try again gSavedSettings.setBOOL("RenderDeferred", FALSE); reentrance = false; setShaders(); @@ -600,7 +657,9 @@ void LLViewerShaderMgr::setShaders() void LLViewerShaderMgr::unloadShaders() { gOcclusionProgram.unload(); + gOcclusionCubeProgram.unload(); gDebugProgram.unload(); + gClipProgram.unload(); gAlphaMaskProgram.unload(); gUIProgram.unload(); gCustomAlphaProgram.unload(); @@ -692,6 +751,12 @@ void LLViewerShaderMgr::unloadShaders() gDeferredSkinnedBumpProgram.unload(); gDeferredSkinnedAlphaProgram.unload(); + gTransformPositionProgram.unload(); + gTransformTexCoordProgram.unload(); + gTransformNormalProgram.unload(); + gTransformColorProgram.unload(); + gTransformBinormalProgram.unload(); + mVertexShaderLevel[SHADER_LIGHTING] = 0; mVertexShaderLevel[SHADER_OBJECT] = 0; mVertexShaderLevel[SHADER_AVATAR] = 0; @@ -700,6 +765,7 @@ void LLViewerShaderMgr::unloadShaders() mVertexShaderLevel[SHADER_INTERFACE] = 0; mVertexShaderLevel[SHADER_EFFECT] = 0; mVertexShaderLevel[SHADER_WINDLIGHT] = 0; + mVertexShaderLevel[SHADER_TRANSFORM] = 0; gPipeline.mVertexShadersLoaded = 0; } @@ -828,7 +894,7 @@ BOOL LLViewerShaderMgr::loadShadersEnvironment() if (mVertexShaderLevel[SHADER_ENVIRONMENT] == 0) { gTerrainProgram.unload(); - return FALSE; + return TRUE; } if (success) @@ -868,7 +934,7 @@ BOOL LLViewerShaderMgr::loadShadersWater() gWaterProgram.unload(); gUnderWaterProgram.unload(); gTerrainWaterProgram.unload(); - return FALSE; + return TRUE; } if (success) @@ -953,7 +1019,7 @@ BOOL LLViewerShaderMgr::loadShadersEffects() gGlowExtractProgram.unload(); gPostColorFilterProgram.unload(); gPostNightVisionProgram.unload(); - return FALSE; + return TRUE; } if (success) @@ -1013,6 +1079,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredBlurLightProgram.unload(); gDeferredSoftenProgram.unload(); gDeferredShadowProgram.unload(); + gDeferredShadowCubeProgram.unload(); gDeferredShadowAlphaMaskProgram.unload(); gDeferredAvatarShadowProgram.unload(); gDeferredAttachmentShadowProgram.unload(); @@ -1200,7 +1267,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredSpotLightProgram.mName = "Deferred SpotLight Shader"; gDeferredSpotLightProgram.mShaderFiles.clear(); gDeferredSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/pointLightV.glsl", GL_VERTEX_SHADER_ARB)); - gDeferredSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/multiSpotLightF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/spotLightF.glsl", GL_FRAGMENT_SHADER_ARB)); gDeferredSpotLightProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; success = gDeferredSpotLightProgram.createShader(NULL, NULL); } @@ -1209,7 +1276,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() { gDeferredMultiSpotLightProgram.mName = "Deferred MultiSpotLight Shader"; gDeferredMultiSpotLightProgram.mShaderFiles.clear(); - gDeferredMultiSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/pointLightV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredMultiSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/multiPointLightV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredMultiSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/multiSpotLightF.glsl", GL_FRAGMENT_SHADER_ARB)); gDeferredMultiSpotLightProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; success = gDeferredMultiSpotLightProgram.createShader(NULL, NULL); @@ -1368,6 +1435,16 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() if (success) { + gDeferredShadowCubeProgram.mName = "Deferred Shadow Cube Shader"; + gDeferredShadowCubeProgram.mShaderFiles.clear(); + gDeferredShadowCubeProgram.mShaderFiles.push_back(make_pair("deferred/shadowCubeV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredShadowCubeProgram.mShaderFiles.push_back(make_pair("deferred/shadowF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredShadowCubeProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredShadowCubeProgram.createShader(NULL, NULL); + } + + if (success) + { gDeferredShadowAlphaMaskProgram.mName = "Deferred Shadow Alpha Mask Shader"; gDeferredShadowAlphaMaskProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels; gDeferredShadowAlphaMaskProgram.mShaderFiles.clear(); @@ -2410,7 +2487,7 @@ BOOL LLViewerShaderMgr::loadShadersAvatar() gAvatarWaterProgram.unload(); gAvatarEyeballProgram.unload(); gAvatarPickProgram.unload(); - return FALSE; + return TRUE; } if (success) @@ -2504,7 +2581,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface() if (mVertexShaderLevel[SHADER_INTERFACE] == 0) { gHighlightProgram.unload(); - return FALSE; + return TRUE; } if (success) @@ -2647,6 +2724,16 @@ BOOL LLViewerShaderMgr::loadShadersInterface() if (success) { + gOcclusionCubeProgram.mName = "Occlusion Cube Shader"; + gOcclusionCubeProgram.mShaderFiles.clear(); + gOcclusionCubeProgram.mShaderFiles.push_back(make_pair("interface/occlusionCubeV.glsl", GL_VERTEX_SHADER_ARB)); + gOcclusionCubeProgram.mShaderFiles.push_back(make_pair("interface/occlusionF.glsl", GL_FRAGMENT_SHADER_ARB)); + gOcclusionCubeProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE]; + success = gOcclusionCubeProgram.createShader(NULL, NULL); + } + + if (success) + { gDebugProgram.mName = "Debug Shader"; gDebugProgram.mShaderFiles.clear(); gDebugProgram.mShaderFiles.push_back(make_pair("interface/debugV.glsl", GL_VERTEX_SHADER_ARB)); @@ -2657,6 +2744,16 @@ BOOL LLViewerShaderMgr::loadShadersInterface() if (success) { + gClipProgram.mName = "Clip Shader"; + gClipProgram.mShaderFiles.clear(); + gClipProgram.mShaderFiles.push_back(make_pair("interface/clipV.glsl", GL_VERTEX_SHADER_ARB)); + gClipProgram.mShaderFiles.push_back(make_pair("interface/clipF.glsl", GL_FRAGMENT_SHADER_ARB)); + gClipProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE]; + success = gClipProgram.createShader(NULL, NULL); + } + + if (success) + { gAlphaMaskProgram.mName = "Alpha Mask Shader"; gAlphaMaskProgram.mShaderFiles.clear(); gAlphaMaskProgram.mShaderFiles.push_back(make_pair("interface/alphamaskV.glsl", GL_VERTEX_SHADER_ARB)); @@ -2682,7 +2779,7 @@ BOOL LLViewerShaderMgr::loadShadersWindLight() { gWLSkyProgram.unload(); gWLCloudProgram.unload(); - return FALSE; + return TRUE; } if (success) @@ -2712,6 +2809,95 @@ BOOL LLViewerShaderMgr::loadShadersWindLight() return success; } +BOOL LLViewerShaderMgr::loadTransformShaders() +{ + BOOL success = TRUE; + + if (mVertexShaderLevel[SHADER_TRANSFORM] < 1) + { + gTransformPositionProgram.unload(); + gTransformTexCoordProgram.unload(); + gTransformNormalProgram.unload(); + gTransformColorProgram.unload(); + gTransformBinormalProgram.unload(); + return TRUE; + } + + if (success) + { + gTransformPositionProgram.mName = "Position Transform Shader"; + gTransformPositionProgram.mShaderFiles.clear(); + gTransformPositionProgram.mShaderFiles.push_back(make_pair("transform/positionV.glsl", GL_VERTEX_SHADER_ARB)); + gTransformPositionProgram.mShaderLevel = mVertexShaderLevel[SHADER_TRANSFORM]; + + const char* varyings[] = { + "position_out", + "texture_index_out", + }; + + success = gTransformPositionProgram.createShader(NULL, NULL, 2, varyings); + } + + if (success) + { + gTransformTexCoordProgram.mName = "TexCoord Transform Shader"; + gTransformTexCoordProgram.mShaderFiles.clear(); + gTransformTexCoordProgram.mShaderFiles.push_back(make_pair("transform/texcoordV.glsl", GL_VERTEX_SHADER_ARB)); + gTransformTexCoordProgram.mShaderLevel = mVertexShaderLevel[SHADER_TRANSFORM]; + + const char* varyings[] = { + "texcoord_out", + }; + + success = gTransformTexCoordProgram.createShader(NULL, NULL, 1, varyings); + } + + if (success) + { + gTransformNormalProgram.mName = "Normal Transform Shader"; + gTransformNormalProgram.mShaderFiles.clear(); + gTransformNormalProgram.mShaderFiles.push_back(make_pair("transform/normalV.glsl", GL_VERTEX_SHADER_ARB)); + gTransformNormalProgram.mShaderLevel = mVertexShaderLevel[SHADER_TRANSFORM]; + + const char* varyings[] = { + "normal_out", + }; + + success = gTransformNormalProgram.createShader(NULL, NULL, 1, varyings); + } + + if (success) + { + gTransformColorProgram.mName = "Color Transform Shader"; + gTransformColorProgram.mShaderFiles.clear(); + gTransformColorProgram.mShaderFiles.push_back(make_pair("transform/colorV.glsl", GL_VERTEX_SHADER_ARB)); + gTransformColorProgram.mShaderLevel = mVertexShaderLevel[SHADER_TRANSFORM]; + + const char* varyings[] = { + "color_out", + }; + + success = gTransformColorProgram.createShader(NULL, NULL, 1, varyings); + } + + if (success) + { + gTransformBinormalProgram.mName = "Binormal Transform Shader"; + gTransformBinormalProgram.mShaderFiles.clear(); + gTransformBinormalProgram.mShaderFiles.push_back(make_pair("transform/binormalV.glsl", GL_VERTEX_SHADER_ARB)); + gTransformBinormalProgram.mShaderLevel = mVertexShaderLevel[SHADER_TRANSFORM]; + + const char* varyings[] = { + "binormal_out", + }; + + success = gTransformBinormalProgram.createShader(NULL, NULL, 1, varyings); + } + + + return success; +} + std::string LLViewerShaderMgr::getShaderDirPrefix(void) { return gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "shaders/class"); diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h index 95eb551bf1..8f7ff8dd2f 100644 --- a/indra/newview/llviewershadermgr.h +++ b/indra/newview/llviewershadermgr.h @@ -54,6 +54,7 @@ public: BOOL loadShadersWater(); BOOL loadShadersInterface(); BOOL loadShadersWindLight(); + BOOL loadTransformShaders(); std::vector<S32> mVertexShaderLevel; S32 mMaxAvatarShaderLevel; @@ -69,6 +70,7 @@ public: SHADER_WINDLIGHT, SHADER_WATER, SHADER_DEFERRED, + SHADER_TRANSFORM, SHADER_COUNT }; @@ -209,13 +211,24 @@ inline bool operator != (LLViewerShaderMgr::shader_iter const & a, LLViewerShade extern LLVector4 gShinyOrigin; +//transform shaders +extern LLGLSLShader gTransformPositionProgram; +extern LLGLSLShader gTransformTexCoordProgram; +extern LLGLSLShader gTransformNormalProgram; +extern LLGLSLShader gTransformColorProgram; +extern LLGLSLShader gTransformBinormalProgram; + + + //utility shaders extern LLGLSLShader gOcclusionProgram; +extern LLGLSLShader gOcclusionCubeProgram; extern LLGLSLShader gCustomAlphaProgram; extern LLGLSLShader gGlowCombineProgram; extern LLGLSLShader gSplatTextureRectProgram; extern LLGLSLShader gGlowCombineFXAAProgram; extern LLGLSLShader gDebugProgram; +extern LLGLSLShader gClipProgram; extern LLGLSLShader gAlphaMaskProgram; //output tex0[tc0] + tex1[tc1] @@ -328,6 +341,7 @@ extern LLGLSLShader gDeferredBlurLightProgram; extern LLGLSLShader gDeferredAvatarProgram; extern LLGLSLShader gDeferredSoftenProgram; extern LLGLSLShader gDeferredShadowProgram; +extern LLGLSLShader gDeferredShadowCubeProgram; extern LLGLSLShader gDeferredShadowAlphaMaskProgram; extern LLGLSLShader gDeferredPostProgram; extern LLGLSLShader gDeferredCoFProgram; diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp index c88122f22c..28f4ec72f3 100644 --- a/indra/newview/llviewerstats.cpp +++ b/indra/newview/llviewerstats.cpp @@ -789,6 +789,24 @@ void send_stats() system["gpu_class"] = (S32)LLFeatureManager::getInstance()->getGPUClass(); system["gpu_vendor"] = gGLManager.mGLVendorShort; system["gpu_version"] = gGLManager.mDriverVersionVendorString; + system["opengl_version"] = gGLManager.mGLVersionString; + + S32 shader_level = 0; + if (LLPipeline::sRenderDeferred) + { + shader_level = 3; + } + else if (gPipeline.canUseWindLightShadersOnObjects()) + { + shader_level = 2; + } + else if (gPipeline.canUseVertexShaders()) + { + shader_level = 1; + } + + + system["shader_level"] = shader_level; LLSD &download = body["downloads"]; @@ -860,3 +878,110 @@ void send_stats() LLHTTPClient::post(url, body, new ViewerStatsResponder()); } +LLFrameTimer& LLViewerStats::PhaseMap::getPhaseTimer(const std::string& phase_name) +{ + phase_map_t::iterator iter = mPhaseMap.find(phase_name); + if (iter == mPhaseMap.end()) + { + LLFrameTimer timer; + mPhaseMap[phase_name] = timer; + } + LLFrameTimer& timer = mPhaseMap[phase_name]; + return timer; +} + +void LLViewerStats::PhaseMap::startPhase(const std::string& phase_name) +{ + LLFrameTimer& timer = getPhaseTimer(phase_name); + lldebugs << "startPhase " << phase_name << llendl; + timer.unpause(); +} + +void LLViewerStats::PhaseMap::stopPhase(const std::string& phase_name) +{ + phase_map_t::iterator iter = mPhaseMap.find(phase_name); + if (iter != mPhaseMap.end()) + { + if (iter->second.getStarted()) + { + // Going from started to paused state - record stats. + recordPhaseStat(phase_name,iter->second.getElapsedTimeF32()); + } + lldebugs << "stopPhase " << phase_name << llendl; + iter->second.pause(); + } + else + { + lldebugs << "stopPhase " << phase_name << " is not started, no-op" << llendl; + } +} + +void LLViewerStats::PhaseMap::stopAllPhases() +{ + for (phase_map_t::iterator iter = mPhaseMap.begin(); + iter != mPhaseMap.end(); ++iter) + { + const std::string& phase_name = iter->first; + if (iter->second.getStarted()) + { + // Going from started to paused state - record stats. + recordPhaseStat(phase_name,iter->second.getElapsedTimeF32()); + } + lldebugs << "stopPhase (all) " << phase_name << llendl; + iter->second.pause(); + } +} + +void LLViewerStats::PhaseMap::clearPhases() +{ + lldebugs << "clearPhases" << llendl; + + mPhaseMap.clear(); +} + +LLSD LLViewerStats::PhaseMap::dumpPhases() +{ + LLSD result; + for (phase_map_t::iterator iter = mPhaseMap.begin(); iter != mPhaseMap.end(); ++iter) + { + const std::string& phase_name = iter->first; + result[phase_name]["completed"] = !(iter->second.getStarted()); + result[phase_name]["elapsed"] = iter->second.getElapsedTimeF32(); +#if 0 // global stats for each phase seem like overkill here + phase_stats_t::iterator stats_iter = sPhaseStats.find(phase_name); + if (stats_iter != sPhaseStats.end()) + { + result[phase_name]["stats"] = stats_iter->second.getData(); + } +#endif + } + return result; +} + +// static initializer +//static +LLViewerStats::phase_stats_t LLViewerStats::PhaseMap::sStats; + +LLViewerStats::PhaseMap::PhaseMap() +{ +} + +// static +LLViewerStats::StatsAccumulator& LLViewerStats::PhaseMap::getPhaseStats(const std::string& phase_name) +{ + phase_stats_t::iterator it = sStats.find(phase_name); + if (it == sStats.end()) + { + LLViewerStats::StatsAccumulator new_stats; + sStats[phase_name] = new_stats; + } + return sStats[phase_name]; +} + +// static +void LLViewerStats::PhaseMap::recordPhaseStat(const std::string& phase_name, F32 value) +{ + LLViewerStats::StatsAccumulator& stats = getPhaseStats(phase_name); + stats.push(value); +} + diff --git a/indra/newview/llviewerstats.h b/indra/newview/llviewerstats.h index f91a1241fe..750d963f69 100644 --- a/indra/newview/llviewerstats.h +++ b/indra/newview/llviewerstats.h @@ -244,7 +244,7 @@ public: inline F32 getStdDev() const { const F32 mean = getMean(); - return (mCount == 0) ? 0.f : sqrt( mSumOfSquares/mCount - (mean * mean) ); + return (mCount < 2) ? 0.f : sqrt(llmax(0.f,mSumOfSquares/mCount - (mean * mean))); } inline U32 getCount() const @@ -274,7 +274,28 @@ public: }; StatsAccumulator mAgentPositionSnaps; - + + // Phase tracking (originally put in for avatar rezzing), tracking + // progress of active/completed phases for activities like outfit changing. + typedef std::map<std::string,LLFrameTimer> phase_map_t; + typedef std::map<std::string,StatsAccumulator> phase_stats_t; + class PhaseMap + { + private: + phase_map_t mPhaseMap; + static phase_stats_t sStats; + public: + PhaseMap(); + LLFrameTimer& getPhaseTimer(const std::string& phase_name); + void startPhase(const std::string& phase_name); + void stopPhase(const std::string& phase_name); + void stopAllPhases(); + void clearPhases(); + LLSD dumpPhases(); + static StatsAccumulator& getPhaseStats(const std::string& phase_name); + static void recordPhaseStat(const std::string& phase_name, F32 value); + }; + private: F64 mStats[ST_COUNT]; diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 61236edc86..7f638a24bf 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -67,6 +67,7 @@ // statics LLPointer<LLViewerTexture> LLViewerTexture::sNullImagep = NULL; LLPointer<LLViewerTexture> LLViewerTexture::sBlackImagep = NULL; +LLPointer<LLViewerTexture> LLViewerTexture::sCheckerBoardImagep = NULL; LLPointer<LLViewerFetchedTexture> LLViewerFetchedTexture::sMissingAssetImagep = NULL; LLPointer<LLViewerFetchedTexture> LLViewerFetchedTexture::sWhiteImagep = NULL; LLPointer<LLViewerFetchedTexture> LLViewerFetchedTexture::sDefaultImagep = NULL; @@ -87,6 +88,7 @@ S32 LLViewerTexture::sMaxBoundTextureMemInMegaBytes = 0; S32 LLViewerTexture::sMaxTotalTextureMemInMegaBytes = 0; S32 LLViewerTexture::sMaxDesiredTextureMemInBytes = 0 ; S8 LLViewerTexture::sCameraMovingDiscardBias = 0 ; +F32 LLViewerTexture::sCameraMovingBias = 0.0f ; S32 LLViewerTexture::sMaxSculptRez = 128 ; //max sculpt image size const S32 MAX_CACHED_RAW_IMAGE_AREA = 64 * 64 ; const S32 MAX_CACHED_RAW_SCULPT_IMAGE_AREA = LLViewerTexture::sMaxSculptRez * LLViewerTexture::sMaxSculptRez ; @@ -96,6 +98,9 @@ S32 LLViewerTexture::sMaxSmallImageSize = MAX_CACHED_RAW_IMAGE_AREA ; BOOL LLViewerTexture::sFreezeImageScalingDown = FALSE ; F32 LLViewerTexture::sCurrentTime = 0.0f ; BOOL LLViewerTexture::sUseTextureAtlas = FALSE ; +F32 LLViewerTexture::sTexelPixelRatio = 1.0f; + +LLViewerTexture::EDebugTexels LLViewerTexture::sDebugTexelsMode = LLViewerTexture::DEBUG_TEXELS_OFF; const F32 desired_discard_bias_min = -2.0f; // -max number of levels to improve image quality by const F32 desired_discard_bias_max = (F32)MAX_DISCARD_LEVEL; // max number of levels to reduce image quality by @@ -175,7 +180,12 @@ LLViewerTexture* LLViewerTextureManager::findTexture(const LLUUID& id) } return tex ; } - + +LLViewerFetchedTexture* LLViewerTextureManager::findFetchedTexture(const LLUUID& id) +{ + return gTextureList.findImage(id); +} + LLViewerMediaTexture* LLViewerTextureManager::findMediaTexture(const LLUUID &media_id) { return LLViewerMediaTexture::findMediaTexture(media_id) ; @@ -347,6 +357,21 @@ void LLViewerTextureManager::init() LLViewerFetchedTexture::sSmokeImagep = LLViewerTextureManager::getFetchedTexture(IMG_SMOKE, TRUE, LLViewerTexture::BOOST_UI); LLViewerFetchedTexture::sSmokeImagep->setNoDelete() ; + image_raw = new LLImageRaw(32,32,3); + data = image_raw->getData(); + + for (S32 i = 0; i < (32*32*3); i+=3) + { + S32 x = (i % (32*3)) / (3*16); + S32 y = i / (32*3*16); + U8 color = ((x + y) % 2) * 255; + data[i] = color; + data[i+1] = color; + data[i+2] = color; + } + + LLViewerTexture::sCheckerBoardImagep = LLViewerTextureManager::getLocalTexture(image_raw.get(), TRUE); + LLViewerTexture::initClass() ; if (LLMetricPerformanceTesterBasic::isMetricLogRequested(sTesterName) && !LLMetricPerformanceTesterBasic::getTester(sTesterName)) @@ -367,6 +392,7 @@ void LLViewerTextureManager::cleanup() LLImageGL::sDefaultGLTexture = NULL ; LLViewerTexture::sNullImagep = NULL; LLViewerTexture::sBlackImagep = NULL; + LLViewerTexture::sCheckerBoardImagep = NULL; LLViewerFetchedTexture::sDefaultImagep = NULL; LLViewerFetchedTexture::sSmokeImagep = NULL; LLViewerFetchedTexture::sMissingAssetImagep = NULL; @@ -383,11 +409,7 @@ void LLViewerTextureManager::cleanup() void LLViewerTexture::initClass() { LLImageGL::sDefaultGLTexture = LLViewerFetchedTexture::sDefaultImagep->getGLTexture() ; - - if(gAuditTexture) - { - LLImageGL::setHighlightTexture(LLViewerTexture::OTHER) ; - } + sTexelPixelRatio = gSavedSettings.getF32("TexelPixelRatio"); } // static @@ -534,7 +556,8 @@ void LLViewerTexture::updateClass(const F32 velocity, const F32 angular_velocity F32 camera_moving_speed = LLViewerCamera::getInstance()->getAverageSpeed() ; F32 camera_angular_speed = LLViewerCamera::getInstance()->getAverageAngularSpeed(); - sCameraMovingDiscardBias = (S8)llmax(0.2f * camera_moving_speed, 2.0f * camera_angular_speed - 1) ; + sCameraMovingBias = llmax(0.2f * camera_moving_speed, 2.0f * camera_angular_speed - 1); + sCameraMovingDiscardBias = (S8)(sCameraMovingBias); LLViewerTexture::sFreezeImageScalingDown = (BYTES_TO_MEGA_BYTES(sBoundTextureMemoryInBytes) < 0.75f * sMaxBoundTextureMemInMegaBytes * texmem_middle_bound_scale) && (BYTES_TO_MEGA_BYTES(sTotalTextureMemoryInBytes) < 0.75f * sMaxTotalTextureMemInMegaBytes * texmem_middle_bound_scale) ; @@ -655,10 +678,6 @@ void LLViewerTexture::setBoostLevel(S32 level) { setNoDelete() ; } - if(gAuditTexture) - { - setCategory(mBoostLevel); - } } } @@ -712,6 +731,7 @@ void LLViewerTexture::addTextureStats(F32 virtual_size, BOOL needs_gltexture) co mNeedsGLTexture = TRUE ; } + virtual_size *= sTexelPixelRatio; if(!mMaxVirtualSizeResetCounter) { //flag to reset the values because the old values are used. @@ -1287,6 +1307,7 @@ void LLViewerFetchedTexture::cleanup() mCachedRawDiscardLevel = -1 ; mCachedRawImageReady = FALSE ; mSavedRawImage = NULL ; + mSavedRawDiscardLevel = -1; } void LLViewerFetchedTexture::setForSculpt() @@ -1377,10 +1398,10 @@ void LLViewerFetchedTexture::dump() // ONLY called from LLViewerFetchedTextureList void LLViewerFetchedTexture::destroyTexture() { - if(LLImageGL::sGlobalTextureMemoryInBytes < sMaxDesiredTextureMemInBytes)//not ready to release unused memory. - { - return ; - } + //if(LLImageGL::sGlobalTextureMemoryInBytes < sMaxDesiredTextureMemInBytes)//not ready to release unused memory. + //{ + // return ; + //} if (mNeedsCreateTexture)//return if in the process of generating a new texture. { return ; @@ -1880,6 +1901,8 @@ S32 LLViewerFetchedTexture::getCurrentDiscardLevelForFetching() bool LLViewerFetchedTexture::updateFetch() { static LLCachedControl<bool> textures_decode_disabled(gSavedSettings,"TextureDecodeDisabled"); + static LLCachedControl<F32> sCameraMotionThreshold(gSavedSettings,"TextureCameraMotionThreshold"); + static LLCachedControl<S32> sCameraMotionBoost(gSavedSettings,"TextureCameraMotionBoost"); if(textures_decode_disabled) { return false ; @@ -2042,18 +2065,24 @@ bool LLViewerFetchedTexture::updateFetch() // make_request = false; //} - if(make_request) + if (make_request) { - //load the texture progressively. + // Load the texture progressively: we try not to rush to the desired discard too fast. + // If the camera is not moving, we do not tweak the discard level notch by notch but go to the desired discard with larger boosted steps + // This mitigates the "textures stay blurry" problem when loading while not killing the texture memory while moving around S32 delta_level = (mBoostLevel > LLViewerTexture::BOOST_NONE) ? 2 : 1 ; - if(current_discard < 0) + if (current_discard < 0) { desired_discard = llmax(desired_discard, getMaxDiscardLevel() - delta_level); } - else + else if (LLViewerTexture::sCameraMovingBias < sCameraMotionThreshold) { - desired_discard = llmax(desired_discard, current_discard - delta_level); + desired_discard = llmax(desired_discard, current_discard - sCameraMotionBoost); } + else + { + desired_discard = llmax(desired_discard, current_discard - delta_level); + } if (mIsFetching) { @@ -2121,6 +2150,30 @@ bool LLViewerFetchedTexture::updateFetch() return mIsFetching ? true : false; } +void LLViewerFetchedTexture::clearFetchedResults() +{ + llassert_always(!mNeedsCreateTexture && !mIsFetching); + + cleanup(); + destroyGLTexture(); + + if(getDiscardLevel() >= 0) //sculpty texture, force to invalidate + { + mGLTexturep->forceToInvalidateGLTexture(); + } +} + +void LLViewerFetchedTexture::forceToDeleteRequest() +{ + if (mHasFetcher) + { + LLAppViewer::getTextureFetch()->deleteRequest(getID(), true); + mHasFetcher = FALSE; + mIsFetching = FALSE ; + resetTextureStats(); + } +} + void LLViewerFetchedTexture::setIsMissingAsset() { if (mUrl.empty()) @@ -3290,10 +3343,14 @@ LLViewerMediaTexture::LLViewerMediaTexture(const LLUUID& id, BOOL usemipmaps, LL sMediaMap.insert(std::make_pair(id, this)); mGLTexturep = gl_image ; + if(mGLTexturep.isNull()) { generateGLTexture() ; } + + mGLTexturep->setAllowCompression(false); + mGLTexturep->setNeedsAlphaAndPickMask(FALSE) ; mIsPlaying = FALSE ; diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h index b96441127d..f1105c3705 100644 --- a/indra/newview/llviewertexture.h +++ b/indra/newview/llviewertexture.h @@ -139,6 +139,7 @@ public: OTHER, MAX_GL_IMAGE_CATEGORY }; + static S32 getTotalNumOfCategories() ; static S32 getIndexFromCategory(S32 category) ; static S32 getCategoryFromIndex(S32 index) ; @@ -263,6 +264,9 @@ protected: void reorganizeVolumeList() ; void setTexelsPerImage(); private: + friend class LLBumpImageList; + friend class LLUIImageList; + //note: do not make this function public. /*virtual*/ LLImageGL* getGLTexture() const ; virtual void switchToCachedImage(); @@ -309,6 +313,7 @@ protected: } LLGLTextureState; LLGLTextureState mTextureState ; + static F32 sTexelPixelRatio; public: static const U32 sCurrentFileVersion; static S32 sImageCount; @@ -323,6 +328,7 @@ public: static S32 sMaxTotalTextureMemInMegaBytes; static S32 sMaxDesiredTextureMemInBytes ; static S8 sCameraMovingDiscardBias; + static F32 sCameraMovingBias; static S32 sMaxSculptRez ; static S32 sMinLargeImageSize ; static S32 sMaxSmallImageSize ; @@ -330,8 +336,19 @@ public: static F32 sCurrentTime ; static BOOL sUseTextureAtlas ; + enum EDebugTexels + { + DEBUG_TEXELS_OFF, + DEBUG_TEXELS_CURRENT, + DEBUG_TEXELS_DESIRED, + DEBUG_TEXELS_FULL + }; + + static EDebugTexels sDebugTexelsMode; + static LLPointer<LLViewerTexture> sNullImagep; // Null texture for non-textured objects. static LLPointer<LLViewerTexture> sBlackImagep; // Texture to show NOTHING (pure black) + static LLPointer<LLViewerTexture> sCheckerBoardImagep; // Texture to show NOTHING (pure black) }; @@ -420,6 +437,8 @@ public: bool updateFetch(); + void clearFetchedResults(); //clear all fetched results, for debug use. + // Override the computation of discard levels if we know the exact output // size of the image. Used for UI textures to not decode, even if we have // more data. @@ -478,6 +497,7 @@ public: BOOL hasFetcher() const { return mHasFetcher;} void setCanUseHTTP(bool can_use_http) {mCanUseHTTP = can_use_http;} + void forceToDeleteRequest(); protected: /*virtual*/ void switchToCachedImage(); S32 getCurrentDiscardLevelForFetching() ; @@ -687,6 +707,7 @@ public: //"find-texture" just check if the texture exists, if yes, return it, otherwise return null. // static LLViewerTexture* findTexture(const LLUUID& id) ; + static LLViewerFetchedTexture* findFetchedTexture(const LLUUID& id) ; static LLViewerMediaTexture* findMediaTexture(const LLUUID& id) ; static LLViewerMediaTexture* createMediaTexture(const LLUUID& id, BOOL usemipmaps = TRUE, LLImageGL* gl_image = NULL) ; diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index 089f45ca89..9a6c0569a9 100644 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -58,6 +58,7 @@ #include "pipeline.h" #include "llappviewer.h" #include "llxuiparser.h" +#include "llagent.h" //////////////////////////////////////////////////////////////////////////// @@ -597,6 +598,12 @@ static LLFastTimer::DeclareTimer FTM_IMAGE_STATS("Stats"); void LLViewerTextureList::updateImages(F32 max_time) { + if(gAgent.getTeleportState() != LLAgent::TELEPORT_NONE) + { + clearFetchingRequests(); + return; + } + LLAppViewer::getTextureFetch()->setTextureBandwidth(LLViewerStats::getInstance()->mTextureKBitStat.getMeanPerSec()); LLViewerStats::getInstance()->mNumImagesStat.addValue(sNumImages); @@ -659,6 +666,24 @@ void LLViewerTextureList::updateImages(F32 max_time) } } +void LLViewerTextureList::clearFetchingRequests() +{ + if (LLAppViewer::getTextureFetch()->getNumRequests() == 0) + { + return; + } + + for (image_priority_list_t::iterator iter = mImageList.begin(); + iter != mImageList.end(); ++iter) + { + LLViewerFetchedTexture* image = *iter; + if(image->hasFetcher()) + { + image->forceToDeleteRequest() ; + } + } +} + void LLViewerTextureList::updateImagesDecodePriorities() { // Update the decode priority for N images each frame @@ -680,7 +705,7 @@ void LLViewerTextureList::updateImagesDecodePriorities() // Flush formatted images using a lazy flush // const F32 LAZY_FLUSH_TIMEOUT = 30.f; // stop decoding - const F32 MAX_INACTIVE_TIME = 50.f; // actually delete + const F32 MAX_INACTIVE_TIME = 20.f; // actually delete S32 min_refs = 3; // 1 for mImageList, 1 for mUUIDMap, 1 for local reference S32 num_refs = imagep->getNumRefs(); @@ -1030,7 +1055,6 @@ LLPointer<LLImageJ2C> LLViewerTextureList::convertToUploadFile(LLPointer<LLImage { raw_image->biasedScaleToPowerOfTwo(LLViewerFetchedTexture::MAX_IMAGE_SIZE_DEFAULT); LLPointer<LLImageJ2C> compressedImage = new LLImageJ2C(); - compressedImage->setRate(0.f); if (gSavedSettings.getBOOL("LosslessJ2CUpload") && (raw_image->getWidth() * raw_image->getHeight() <= LL_IMAGE_REZ_LOSSLESS_CUTOFF * LL_IMAGE_REZ_LOSSLESS_CUTOFF)) @@ -1432,6 +1456,9 @@ LLUIImagePtr LLUIImageList::loadUIImage(LLViewerFetchedTexture* imagep, const st imagep->setAddressMode(LLTexUnit::TAM_CLAMP); + //don't compress UI images + imagep->getGLTexture()->setAllowCompression(false); + //all UI images are non-deletable imagep->setNoDelete(); diff --git a/indra/newview/llviewertexturelist.h b/indra/newview/llviewertexturelist.h index b386c73d2a..e89997fe28 100644 --- a/indra/newview/llviewertexturelist.h +++ b/indra/newview/llviewertexturelist.h @@ -110,6 +110,8 @@ public: void doPreloadImages(); void doPrefetchImages(); + void clearFetchingRequests(); + static S32 getMinVideoRamSetting(); static S32 getMaxVideoRamSetting(bool get_recommended = false); @@ -164,7 +166,7 @@ private: // Request image from a specific host, used for baked avatar textures. // Implemented in header in case someone changes default params above. JC LLViewerFetchedTexture* getImageFromHost(const LLUUID& image_id, LLHost host) - { return getImage(image_id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, host); } + { return getImage(image_id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, host); } public: typedef std::set<LLPointer<LLViewerFetchedTexture> > image_list_t; diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 258bc5b698..c2cec9a335 100755 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -176,6 +176,7 @@ #include "llviewershadermgr.h" #include "llviewerstats.h" #include "llvoavatarself.h" +#include "llvopartgroup.h" #include "llvovolume.h" #include "llworld.h" #include "llworldmapview.h" @@ -535,7 +536,10 @@ public: } - addText(xpos, ypos, llformat("%d MB Vertex Data (%d MB Pooled)", LLVertexBuffer::sAllocatedBytes/(1024*1024), LLVBOPool::sBytesPooled/(1024*1024))); + addText(xpos, ypos, llformat("%d MB Index Data (%d MB Pooled, %d KIndices)", LLVertexBuffer::sAllocatedIndexBytes/(1024*1024), LLVBOPool::sIndexBytesPooled/(1024*1024), LLVertexBuffer::sIndexCount/1024)); + ypos += y_inc; + + addText(xpos, ypos, llformat("%d MB Vertex Data (%d MB Pooled, %d KVerts)", LLVertexBuffer::sAllocatedBytes/(1024*1024), LLVBOPool::sBytesPooled/(1024*1024), LLVertexBuffer::sVertexCount/1024)); ypos += y_inc; addText(xpos, ypos, llformat("%d Vertex Buffers", LLVertexBuffer::sGLCount)); @@ -611,7 +615,7 @@ public: addText(xpos, ypos, llformat("%d/%d Mesh HTTP Requests/Retries", LLMeshRepository::sHTTPRequestCount, LLMeshRepository::sHTTPRetryCount)); ypos += y_inc; - + addText(xpos, ypos, llformat("%d/%d Mesh LOD Pending/Processing", LLMeshRepository::sLODPending, LLMeshRepository::sLODProcessing)); ypos += y_inc; @@ -743,40 +747,41 @@ public: if (gSavedSettings.getBOOL("DebugShowTextureInfo")) { LLViewerObject* objectp = NULL ; - //objectp = = gAgentCamera.getFocusObject(); LLSelectNode* nodep = LLSelectMgr::instance().getHoverNode(); if (nodep) { - objectp = nodep->getObject(); + objectp = nodep->getObject(); } + if (objectp && !objectp->isDead()) { S32 num_faces = objectp->mDrawable->getNumFaces() ; - + std::set<LLViewerFetchedTexture*> tex_list; + for(S32 i = 0 ; i < num_faces; i++) { LLFace* facep = objectp->mDrawable->getFace(i) ; if(facep) - { - //addText(xpos, ypos, llformat("ts_min: %.3f ts_max: %.3f tt_min: %.3f tt_max: %.3f", facep->mTexExtents[0].mV[0], facep->mTexExtents[1].mV[0], - // facep->mTexExtents[0].mV[1], facep->mTexExtents[1].mV[1])); - //ypos += y_inc; - - addText(xpos, ypos, llformat("v_size: %.3f: p_size: %.3f", facep->getVirtualSize(), facep->getPixelArea())); - ypos += y_inc; - - //const LLTextureEntry *tep = facep->getTextureEntry(); - //if(tep) - //{ - // addText(xpos, ypos, llformat("scale_s: %.3f: scale_t: %.3f", tep->mScaleS, tep->mScaleT)) ; - // ypos += y_inc; - //} - - LLViewerTexture* tex = facep->getTexture() ; + { + LLViewerFetchedTexture* tex = dynamic_cast<LLViewerFetchedTexture*>(facep->getTexture()) ; if(tex) { - addText(xpos, ypos, llformat("ID: %s v_size: %.3f", tex->getID().asString().c_str(), tex->getMaxVirtualSize())); + if(tex_list.find(tex) != tex_list.end()) + { + continue ; //already displayed. + } + tex_list.insert(tex); + + std::string uuid_str; + tex->getID().toString(uuid_str); + uuid_str = uuid_str.substr(0,7); + + addText(xpos, ypos, llformat("ID: %s v_size: %.3f", uuid_str.c_str(), tex->getMaxVirtualSize())); + ypos += y_inc; + + addText(xpos, ypos, llformat("discard level: %d desired level: %d Missing: %s", tex->getDiscardLevel(), + tex->getDesiredDiscardLevel(), tex->isMissingAsset() ? "Y" : "N")); ypos += y_inc; } } @@ -1702,9 +1707,6 @@ LLViewerWindow::LLViewerWindow(const Params& p) // Can't have spaces in settings.ini strings, so use underscores instead and convert them. LLStringUtil::replaceChar(mOverlayTitle, '_', ' '); - // sync the keyboard's setting with the saved setting - gSavedSettings.getControl("NumpadControl")->firePropertyChanged(); - mDebugText = new LLDebugText(this); mWorldViewRectScaled = calcScaledRect(mWorldViewRectRaw, mDisplayScale); @@ -1971,12 +1973,12 @@ void LLViewerWindow::shutdownViews() gMorphView->setVisible(FALSE); } llinfos << "Global views cleaned." << llendl ; - + // DEV-40930: Clear sModalStack. Otherwise, any LLModalDialog left open // will crump with LL_ERRS. LLModalDialog::shutdownModals(); llinfos << "LLModalDialog shut down." << llendl; - + // destroy the nav bar, not currently part of gViewerWindow // *TODO: Make LLNavigationBar part of gViewerWindow if (LLNavigationBar::instanceExists()) @@ -1984,17 +1986,17 @@ void LLViewerWindow::shutdownViews() delete LLNavigationBar::getInstance(); } llinfos << "LLNavigationBar destroyed." << llendl ; - + // destroy menus after instantiating navbar above, as it needs // access to gMenuHolder cleanup_menus(); llinfos << "menus destroyed." << llendl ; - + // Delete all child views. delete mRootView; mRootView = NULL; llinfos << "RootView deleted." << llendl ; - + // Automatically deleted as children of mRootView. Fix the globals. gStatusBar = NULL; gIMMgr = NULL; @@ -4658,6 +4660,8 @@ void LLViewerWindow::stopGL(BOOL save_state) LLVOAvatar::destroyGL(); stop_glerror(); + LLVOPartGroup::destroyGL(); + LLViewerDynamicTexture::destroyGL(); stop_glerror(); @@ -4711,7 +4715,8 @@ void LLViewerWindow::restoreGL(const std::string& progress_message) gBumpImageList.restoreGL(); LLViewerDynamicTexture::restoreGL(); LLVOAvatar::restoreGL(); - + LLVOPartGroup::restoreGL(); + gResizeScreenTexture = TRUE; gWindowResized = TRUE; @@ -5194,8 +5199,10 @@ void LLPickInfo::getSurfaceInfo() if (objectp->mDrawable.notNull() && mObjectFace > -1) { LLFace* facep = objectp->mDrawable->getFace(mObjectFace); - - mUVCoords = facep->surfaceToTexture(mSTCoords, mIntersection, mNormal); + if (facep) + { + mUVCoords = facep->surfaceToTexture(mSTCoords, mIntersection, mNormal); + } } // and XY coords: diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 82dadf1dc8..e5362261cf 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -102,6 +102,8 @@ #include "llvoicevisualizer.h" // Ventrella #include "lldebugmessagebox.h" +#include "llsdutil.h" + extern F32 SPEED_ADJUST_MAX; extern F32 SPEED_ADJUST_MAX_SEC; extern F32 ANIM_SPEED_MAX; @@ -243,10 +245,10 @@ struct LLVOAvatarCollisionVolumeInfo : public LLInitParam::Block<LLVOAvatarColli }; struct LLVOAvatarChildJoint : public LLInitParam::ChoiceBlock<LLVOAvatarChildJoint> -{ + { Alternative<Lazy<struct LLVOAvatarBoneInfo, IS_A_BLOCK> > bone; Alternative<LLVOAvatarCollisionVolumeInfo> collision_volume; - + LLVOAvatarChildJoint() : bone("bone"), collision_volume("collision_volume") @@ -638,7 +640,6 @@ F32 LLVOAvatar::sLODFactor = 1.f; F32 LLVOAvatar::sPhysicsLODFactor = 1.f; BOOL LLVOAvatar::sUseImpostors = FALSE; BOOL LLVOAvatar::sJointDebug = FALSE; - F32 LLVOAvatar::sUnbakedTime = 0.f; F32 LLVOAvatar::sUnbakedUpdateTime = 0.f; F32 LLVOAvatar::sGreyTime = 0.f; @@ -694,13 +695,16 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, mNeedsSkin(FALSE), mLastSkinTime(0.f), mUpdatePeriod(1), + mFirstFullyVisible(TRUE), mFullyLoaded(FALSE), mPreviousFullyLoaded(FALSE), mFullyLoadedInitialized(FALSE), mSupportsAlphaLayers(FALSE), mLoadedCallbacksPaused(FALSE), mHasPelvisOffset( FALSE ), - mRenderUnloadedAvatar(LLCachedControl<bool>(gSavedSettings, "RenderUnloadedAvatar")) + mRenderUnloadedAvatar(LLCachedControl<bool>(gSavedSettings, "RenderUnloadedAvatar")), + mLastRezzedStatus(-1) + { LLMemType mt(LLMemType::MTYPE_AVATAR); //VTResume(); // VTune @@ -785,32 +789,46 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, mLastPelvisFixup = 0.0f; } +std::string LLVOAvatar::avString() const +{ + std::string viz_string = LLVOAvatar::rezStatusToString(getRezzedStatus()); + return " Avatar '" + getFullname() + "' " + viz_string + " "; +} + +void LLVOAvatar::debugAvatarRezTime(std::string notification_name, std::string comment) +{ + LL_INFOS("Avatar") << "REZTIME: [ " << (U32)mDebugExistenceTimer.getElapsedTimeF32() + << "sec ]" + << avString() + << "RuthTimer " << (U32)mRuthDebugTimer.getElapsedTimeF32() + << " Notification " << notification_name + << " : " << comment + << llendl; + + if (gSavedSettings.getBOOL("DebugAvatarRezTime")) + { + LLSD args; + args["EXISTENCE"] = llformat("%d",(U32)mDebugExistenceTimer.getElapsedTimeF32()); + args["TIME"] = llformat("%d",(U32)mRuthDebugTimer.getElapsedTimeF32()); + args["NAME"] = getFullname(); + LLNotificationsUtil::add(notification_name,args); + } +} + //------------------------------------------------------------------------ // LLVOAvatar::~LLVOAvatar() //------------------------------------------------------------------------ LLVOAvatar::~LLVOAvatar() { - if (gSavedSettings.getBOOL("DebugAvatarRezTime")) - { if (!mFullyLoaded) { - llinfos << "REZTIME: [ " << (U32)mDebugExistenceTimer.getElapsedTimeF32() << "sec ] Avatar '" << getFullname() << "' left after " << (U32)mRuthDebugTimer.getElapsedTimeF32() << " seconds as cloud." << llendl; - LLSD args; - args["EXISTENCE"] = llformat("%d",(U32)mDebugExistenceTimer.getElapsedTimeF32()); - args["TIME"] = llformat("%d",(U32)mRuthDebugTimer.getElapsedTimeF32()); - args["NAME"] = getFullname(); - LLNotificationsUtil::add("AvatarRezLeftCloudNotification",args); + debugAvatarRezTime("AvatarRezLeftCloudNotification","left after ruth seconds as cloud"); } else { - llinfos << "REZTIME: [ " << (U32)mDebugExistenceTimer.getElapsedTimeF32() << "sec ] Avatar '" << getFullname() << "' left." << llendl; - LLSD args; - args["EXISTENCE"] = llformat("%d",(U32)mDebugExistenceTimer.getElapsedTimeF32()); - args["NAME"] = getFullname(); - LLNotificationsUtil::add("AvatarRezLeftNotification",args); + debugAvatarRezTime("AvatarRezLeftNotification","left sometime after declouding"); } - } lldebugs << "LLVOAvatar Destructor (0x" << this << ") id:" << mID << llendl; mRoot.removeAllChildren(); @@ -859,6 +877,8 @@ LLVOAvatar::~LLVOAvatar() mAnimationSources.clear(); LLLoadedCallbackEntry::cleanUpCallbackList(&mCallbackTextureList) ; + getPhases().clearPhases(); + lldebugs << "LLVOAvatar Destructor end" << llendl; } @@ -896,6 +916,55 @@ BOOL LLVOAvatar::isFullyBaked() return TRUE; } +BOOL LLVOAvatar::isFullyTextured() const +{ + for (S32 i = 0; i < mMeshLOD.size(); i++) + { + LLViewerJoint* joint = (LLViewerJoint*) mMeshLOD[i]; + if (i==MESH_ID_SKIRT && !isWearingWearableType(LLWearableType::WT_SKIRT)) + { + continue; // don't care about skirt textures if we're not wearing one. + } + if (!joint) + { + continue; // nonexistent LOD OK. + } + std::vector<LLViewerJointMesh*>::iterator meshIter = joint->mMeshParts.begin(); + if (meshIter != joint->mMeshParts.end()) + { + LLViewerJointMesh *mesh = (LLViewerJointMesh *) *meshIter; + if (!mesh) + { + continue; // nonexistent mesh OK + } + if (mesh->mTexture.notNull() && mesh->mTexture->hasGLTexture()) + { + continue; // Mesh exists and has a baked texture. + } + if (mesh->mLayerSet && mesh->mLayerSet->hasComposite()) + { + continue; // Mesh exists and has a composite texture. + } + // Fail + return FALSE; + } + } + return TRUE; +} + +BOOL LLVOAvatar::hasGray() const +{ + return !getIsCloud() && !isFullyTextured(); +} + +S32 LLVOAvatar::getRezzedStatus() const +{ + if (getIsCloud()) return 0; + if (isFullyTextured()) return 2; + llassert(hasGray()); + return 1; // gray +} + void LLVOAvatar::deleteLayerSetCaches(bool clearAll) { for (U32 i = 0; i < mBakedTextureDatas.size(); i++) @@ -911,7 +980,7 @@ void LLVOAvatar::deleteLayerSetCaches(bool clearAll) } if (mBakedTextureDatas[i].mMaskTexName) { - glDeleteTextures(1, (GLuint*)&(mBakedTextureDatas[i].mMaskTexName)); + LLImageGL::deleteTextures(LLTexUnit::TT_TEXTURE, 0, -1, 1, (GLuint*)&(mBakedTextureDatas[i].mMaskTexName)); mBakedTextureDatas[i].mMaskTexName = 0 ; } } @@ -943,6 +1012,31 @@ BOOL LLVOAvatar::areAllNearbyInstancesBaked(S32& grey_avatars) } // static +void LLVOAvatar::getNearbyRezzedStats(std::vector<S32>& counts) +{ + counts.clear(); + counts.resize(3); + for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin(); + iter != LLCharacter::sInstances.end(); ++iter) + { + LLVOAvatar* inst = (LLVOAvatar*) *iter; + if (!inst) + continue; + S32 rez_status = inst->getRezzedStatus(); + counts[rez_status]++; + } +} + +// static +std::string LLVOAvatar::rezStatusToString(S32 rez_status) +{ + if (rez_status==0) return "cloud"; + if (rez_status==1) return "gray"; + if (rez_status==2) return "textured"; + return "unknown"; +} + +// static void LLVOAvatar::dumpBakedStatus() { LLVector3d camera_pos_global = gAgentCamera.getCameraPositionGlobal(); @@ -1660,7 +1754,7 @@ BOOL LLVOAvatar::parseSkeletonFile(const std::string& filename) //------------------------------------------------------------------------- // parse the file //------------------------------------------------------------------------- - + LLXMLNodePtr skeleton_xml; BOOL parsesuccess = LLXMLNode::parseFile(filename, skeleton_xml, NULL); @@ -1731,7 +1825,7 @@ BOOL LLVOAvatar::setupBone(const LLVOAvatarChildJoint& info, LLViewerJoint* pare { return FALSE; } - } + } } else // collision volume { @@ -1792,9 +1886,9 @@ BOOL LLVOAvatar::buildSkeleton(const LLVOAvatarSkeletonInfo *info) if (!setupBone(info->skeleton_root, NULL, current_volume_num, current_joint_num)) { - llerrs << "Error parsing bone in skeleton file" << llendl; - return FALSE; - } + llerrs << "Error parsing bone in skeleton file" << llendl; + return FALSE; + } return TRUE; } @@ -2004,13 +2098,19 @@ void LLVOAvatar::releaseMeshData() if (mDrawable.notNull()) { LLFace* facep = mDrawable->getFace(0); + if (facep) + { facep->setSize(0, 0); for(S32 i = mNumInitFaces ; i < mDrawable->getNumFaces(); i++) { facep = mDrawable->getFace(i); + if (facep) + { facep->setSize(0, 0); } } + } + } for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); iter != mAttachmentPoints.end(); @@ -2093,15 +2193,20 @@ void LLVOAvatar::updateMeshData() part_index-- ; } - LLFace* facep ; + LLFace* facep = NULL; if(f_num < mDrawable->getNumFaces()) { facep = mDrawable->getFace(f_num); } else { - facep = mDrawable->addFace(mDrawable->getFace(0)->getPool(), mDrawable->getFace(0)->getTexture()) ; + facep = mDrawable->getFace(0); + if (facep) + { + facep = mDrawable->addFace(facep->getPool(), facep->getTexture()) ; + } } + if (!facep) continue; // resize immediately facep->setSize(num_vertices, num_indices); @@ -2252,18 +2357,12 @@ U32 LLVOAvatar::processUpdateMessage(LLMessageSystem *mesgsys, U32 retval = LLViewerObject::processUpdateMessage(mesgsys, user_data, block_num, update_type, dp); // Print out arrival information once we have name of avatar. - if (gSavedSettings.getBOOL("DebugAvatarRezTime")) - { if (has_name && getNVPair("FirstName")) { mDebugExistenceTimer.reset(); - LLSD args; - args["EXISTENCE"] = llformat("%d",(U32)mDebugExistenceTimer.getElapsedTimeF32()); - args["NAME"] = getFullname(); - LLNotificationsUtil::add("AvatarRezArrivedNotification",args); - llinfos << "REZTIME: [ " << (U32)mDebugExistenceTimer.getElapsedTimeF32() << "sec ] Avatar '" << getFullname() << "' arrived." << llendl; + debugAvatarRezTime("AvatarRezArrivedNotification","avatar arrived"); } - } + if(retval & LLViewerObject::INVALID_UPDATE) { if (isSelf()) @@ -2773,16 +2872,16 @@ void LLVOAvatar::idleUpdateLoadingEffect() // update visibility when avatar is partially loaded if (updateIsFullyLoaded()) // changed? { - if (isFullyLoaded() && isSelf()) + if (isFullyLoaded() && mFirstFullyVisible && isSelf()) { - static bool first_fully_visible = true; - if (first_fully_visible) - { - llinfos << "self isFullyLoaded, first_fully_visible" << llendl; - - first_fully_visible = false; + LL_INFOS("Avatar") << avString() << "self isFullyLoaded, mFirstFullyVisible" << LL_ENDL; + mFirstFullyVisible = FALSE; LLAppearanceMgr::instance().onFirstFullyVisible(); } + if (isFullyLoaded() && mFirstFullyVisible && !isSelf()) + { + LL_INFOS("Avatar") << avString() << "other isFullyLoaded, mFirstFullyVisible" << LL_ENDL; + mFirstFullyVisible = FALSE; } if (isFullyLoaded()) { @@ -2926,43 +3025,43 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last) return; } - BOOL new_name = FALSE; - if (visible_chat != mVisibleChat) - { - mVisibleChat = visible_chat; - new_name = TRUE; - } + BOOL new_name = FALSE; + if (visible_chat != mVisibleChat) + { + mVisibleChat = visible_chat; + new_name = TRUE; + } - if (sRenderGroupTitles != mRenderGroupTitles) - { - mRenderGroupTitles = sRenderGroupTitles; - new_name = TRUE; - } - - // First Calculate Alpha - // If alpha > 0, create mNameText if necessary, otherwise delete it - F32 alpha = 0.f; - if (mAppAngle > 5.f) + if (sRenderGroupTitles != mRenderGroupTitles) { - const F32 START_FADE_TIME = NAME_SHOW_TIME - FADE_DURATION; - if (!visible_chat && sRenderName == RENDER_NAME_FADE && time_visible > START_FADE_TIME) + mRenderGroupTitles = sRenderGroupTitles; + new_name = TRUE; + } + + // First Calculate Alpha + // If alpha > 0, create mNameText if necessary, otherwise delete it + F32 alpha = 0.f; + if (mAppAngle > 5.f) { - alpha = 1.f - (time_visible - START_FADE_TIME) / FADE_DURATION; + const F32 START_FADE_TIME = NAME_SHOW_TIME - FADE_DURATION; + if (!visible_chat && sRenderName == RENDER_NAME_FADE && time_visible > START_FADE_TIME) + { + alpha = 1.f - (time_visible - START_FADE_TIME) / FADE_DURATION; + } + else + { + // ...not fading, full alpha + alpha = 1.f; + } } - else + else if (mAppAngle > 2.f) { - // ...not fading, full alpha - alpha = 1.f; + // far away is faded out also + alpha = (mAppAngle-2.f)/3.f; } - } - else if (mAppAngle > 2.f) - { - // far away is faded out also - alpha = (mAppAngle-2.f)/3.f; - } if (alpha <= 0.f) - { + { if (mNameText) { mNameText->markDead(); @@ -2972,19 +3071,19 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last) return; } - if (!mNameText) - { + if (!mNameText) + { mNameText = static_cast<LLHUDNameTag*>( LLHUDObject::addHUDObject( LLHUDObject::LL_HUD_NAME_TAG) ); //mNameText->setMass(10.f); - mNameText->setSourceObject(this); + mNameText->setSourceObject(this); mNameText->setVertAlignment(LLHUDNameTag::ALIGN_VERT_TOP); - mNameText->setVisibleOffScreen(TRUE); - mNameText->setMaxLines(11); - mNameText->setFadeDistance(CHAT_NORMAL_RADIUS, 5.f); - sNumVisibleChatBubbles++; - new_name = TRUE; - } + mNameText->setVisibleOffScreen(TRUE); + mNameText->setMaxLines(11); + mNameText->setFadeDistance(CHAT_NORMAL_RADIUS, 5.f); + sNumVisibleChatBubbles++; + new_name = TRUE; + } idleUpdateNameTagPosition(root_pos_last); idleUpdateNameTagText(new_name); @@ -3015,208 +3114,202 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name) bool is_friend = LLAvatarTracker::instance().isBuddy(getID()); bool is_cloud = getIsCloud(); - if (gSavedSettings.getBOOL("DebugAvatarRezTime") - && is_appearance != mNameAppearance) + if (is_appearance != mNameAppearance) { - LLSD args; - args["EXISTENCE"] = llformat("%d",(U32)mDebugExistenceTimer.getElapsedTimeF32()); - args["NAME"] = getFullname(); if (is_appearance) { - LLNotificationsUtil::add("AvatarRezEnteredAppearanceNotification",args); - llinfos << "REZTIME: [ " << (U32)mDebugExistenceTimer.getElapsedTimeF32() << "sec ] Avatar '" << getFullname() << "' entered appearance mode." << llendl; + debugAvatarRezTime("AvatarRezEnteredAppearanceNotification","entered appearance mode"); } else { - LLNotificationsUtil::add("AvatarRezLeftAppearanceNotification",args); - llinfos << "REZTIME: [ " << (U32)mDebugExistenceTimer.getElapsedTimeF32() << "sec ] Avatar '" << getFullname() << "' left appearance mode." << llendl; + debugAvatarRezTime("AvatarRezLeftAppearanceNotification","left appearance mode"); } - } - // Rebuild name tag if state change detected - if (mNameString.empty() - || new_name - || (!title && !mTitle.empty()) - || (title && mTitle != title->getString()) - || is_away != mNameAway - || is_busy != mNameBusy - || is_muted != mNameMute - || is_appearance != mNameAppearance - || is_friend != mNameFriend - || is_cloud != mNameCloud) - { - LLColor4 name_tag_color = getNameTagColor(is_friend); + // Rebuild name tag if state change detected + if (mNameString.empty() + || new_name + || (!title && !mTitle.empty()) + || (title && mTitle != title->getString()) + || is_away != mNameAway + || is_busy != mNameBusy + || is_muted != mNameMute + || is_appearance != mNameAppearance + || is_friend != mNameFriend + || is_cloud != mNameCloud) + { + LLColor4 name_tag_color = getNameTagColor(is_friend); - clearNameTag(); + clearNameTag(); - if (is_away || is_muted || is_busy || is_appearance) - { - std::string line; - if (is_away) - { - line += LLTrans::getString("AvatarAway"); - line += ", "; - } - if (is_busy) - { - line += LLTrans::getString("AvatarBusy"); - line += ", "; - } - if (is_muted) - { - line += LLTrans::getString("AvatarMuted"); - line += ", "; - } - if (is_appearance) + if (is_away || is_muted || is_busy || is_appearance) { - line += LLTrans::getString("AvatarEditingAppearance"); - line += ", "; + std::string line; + if (is_away) + { + line += LLTrans::getString("AvatarAway"); + line += ", "; + } + if (is_busy) + { + line += LLTrans::getString("AvatarBusy"); + line += ", "; + } + if (is_muted) + { + line += LLTrans::getString("AvatarMuted"); + line += ", "; + } + if (is_appearance) + { + line += LLTrans::getString("AvatarEditingAppearance"); + line += ", "; + } + if (is_cloud) + { + line += LLTrans::getString("LoadingData"); + line += ", "; + } + // trim last ", " + line.resize( line.length() - 2 ); + addNameTagLine(line, name_tag_color, LLFontGL::NORMAL, + LLFontGL::getFontSansSerifSmall()); } - if (is_cloud) + + if (sRenderGroupTitles + && title && title->getString() && title->getString()[0] != '\0') { - line += LLTrans::getString("LoadingData"); - line += ", "; + std::string title_str = title->getString(); + LLStringFn::replace_ascii_controlchars(title_str,LL_UNKNOWN_CHAR); + addNameTagLine(title_str, name_tag_color, LLFontGL::NORMAL, + LLFontGL::getFontSansSerifSmall()); } - // trim last ", " - line.resize( line.length() - 2 ); - addNameTagLine(line, name_tag_color, LLFontGL::NORMAL, - LLFontGL::getFontSansSerifSmall()); - } - if (sRenderGroupTitles - && title && title->getString() && title->getString()[0] != '\0') - { - std::string title_str = title->getString(); - LLStringFn::replace_ascii_controlchars(title_str,LL_UNKNOWN_CHAR); - addNameTagLine(title_str, name_tag_color, LLFontGL::NORMAL, - LLFontGL::getFontSansSerifSmall()); - } - - static LLUICachedControl<bool> show_display_names("NameTagShowDisplayNames"); - static LLUICachedControl<bool> show_usernames("NameTagShowUsernames"); + static LLUICachedControl<bool> show_display_names("NameTagShowDisplayNames"); + static LLUICachedControl<bool> show_usernames("NameTagShowUsernames"); - if (LLAvatarNameCache::useDisplayNames()) - { - LLAvatarName av_name; - if (!LLAvatarNameCache::get(getID(), &av_name)) + if (LLAvatarNameCache::useDisplayNames()) { - // ...call this function back when the name arrives - // and force a rebuild - LLAvatarNameCache::get(getID(), - boost::bind(&LLVOAvatar::clearNameTag, this)); - } + LLAvatarName av_name; + if (!LLAvatarNameCache::get(getID(), &av_name)) + { + // ...call this function back when the name arrives + // and force a rebuild + LLAvatarNameCache::get(getID(), + boost::bind(&LLVOAvatar::clearNameTag, this)); + } - // Might be blank if name not available yet, that's OK - if (show_display_names) - { - addNameTagLine(av_name.mDisplayName, name_tag_color, LLFontGL::NORMAL, - LLFontGL::getFontSansSerif()); + // Might be blank if name not available yet, that's OK + if (show_display_names) + { + addNameTagLine(av_name.mDisplayName, name_tag_color, LLFontGL::NORMAL, + LLFontGL::getFontSansSerif()); + } + // Suppress SLID display if display name matches exactly (ugh) + if (show_usernames && !av_name.mIsDisplayNameDefault) + { + // *HACK: Desaturate the color + LLColor4 username_color = name_tag_color * 0.83f; + addNameTagLine(av_name.mUsername, username_color, LLFontGL::NORMAL, + LLFontGL::getFontSansSerifSmall()); + } } - // Suppress SLID display if display name matches exactly (ugh) - if (show_usernames && !av_name.mIsDisplayNameDefault) + else { - // *HACK: Desaturate the color - LLColor4 username_color = name_tag_color * 0.83f; - addNameTagLine(av_name.mUsername, username_color, LLFontGL::NORMAL, - LLFontGL::getFontSansSerifSmall()); + const LLFontGL* font = LLFontGL::getFontSansSerif(); + std::string full_name = LLCacheName::buildFullName( firstname->getString(), lastname->getString() ); + addNameTagLine(full_name, name_tag_color, LLFontGL::NORMAL, font); } - } - else - { - const LLFontGL* font = LLFontGL::getFontSansSerif(); - std::string full_name = LLCacheName::buildFullName( firstname->getString(), lastname->getString() ); - addNameTagLine(full_name, name_tag_color, LLFontGL::NORMAL, font); - } - - mNameAway = is_away; - mNameBusy = is_busy; - mNameMute = is_muted; - mNameAppearance = is_appearance; - mNameFriend = is_friend; - mNameCloud = is_cloud; - mTitle = title ? title->getString() : ""; - LLStringFn::replace_ascii_controlchars(mTitle, LL_UNKNOWN_CHAR); - new_name = TRUE; - } - if (mVisibleChat) - { - mNameText->setFont(LLFontGL::getFontSansSerif()); - mNameText->setTextAlignment(LLHUDNameTag::ALIGN_TEXT_LEFT); - mNameText->setFadeDistance(CHAT_NORMAL_RADIUS * 2.f, 5.f); - - char line[MAX_STRING]; /* Flawfinder: ignore */ - line[0] = '\0'; - std::deque<LLChat>::iterator chat_iter = mChats.begin(); - mNameText->clearString(); - - LLColor4 new_chat = LLUIColorTable::instance().getColor( isSelf() ? "UserChatColor" : "AgentChatColor" ); - LLColor4 normal_chat = lerp(new_chat, LLColor4(0.8f, 0.8f, 0.8f, 1.f), 0.7f); - LLColor4 old_chat = lerp(normal_chat, LLColor4(0.6f, 0.6f, 0.6f, 1.f), 0.7f); - if (mTyping && mChats.size() >= MAX_BUBBLE_CHAT_UTTERANCES) - { - ++chat_iter; + mNameAway = is_away; + mNameBusy = is_busy; + mNameMute = is_muted; + mNameAppearance = is_appearance; + mNameFriend = is_friend; + mNameCloud = is_cloud; + mTitle = title ? title->getString() : ""; + LLStringFn::replace_ascii_controlchars(mTitle,LL_UNKNOWN_CHAR); + new_name = TRUE; } - for(; chat_iter != mChats.end(); ++chat_iter) + if (mVisibleChat) { - F32 chat_fade_amt = llclamp((F32)((LLFrameTimer::getElapsedSeconds() - chat_iter->mTime) / CHAT_FADE_TIME), 0.f, 4.f); - LLFontGL::StyleFlags style; - switch(chat_iter->mChatType) - { - case CHAT_TYPE_WHISPER: - style = LLFontGL::ITALIC; - break; - case CHAT_TYPE_SHOUT: - style = LLFontGL::BOLD; - break; - default: - style = LLFontGL::NORMAL; - break; - } - if (chat_fade_amt < 1.f) + mNameText->setFont(LLFontGL::getFontSansSerif()); + mNameText->setTextAlignment(LLHUDNameTag::ALIGN_TEXT_LEFT); + mNameText->setFadeDistance(CHAT_NORMAL_RADIUS * 2.f, 5.f); + + char line[MAX_STRING]; /* Flawfinder: ignore */ + line[0] = '\0'; + std::deque<LLChat>::iterator chat_iter = mChats.begin(); + mNameText->clearString(); + + LLColor4 new_chat = LLUIColorTable::instance().getColor( isSelf() ? "UserChatColor" : "AgentChatColor" ); + LLColor4 normal_chat = lerp(new_chat, LLColor4(0.8f, 0.8f, 0.8f, 1.f), 0.7f); + LLColor4 old_chat = lerp(normal_chat, LLColor4(0.6f, 0.6f, 0.6f, 1.f), 0.7f); + if (mTyping && mChats.size() >= MAX_BUBBLE_CHAT_UTTERANCES) { - F32 u = clamp_rescale(chat_fade_amt, 0.9f, 1.f, 0.f, 1.f); - mNameText->addLine(chat_iter->mText, lerp(new_chat, normal_chat, u), style); + ++chat_iter; } - else if (chat_fade_amt < 2.f) + + for(; chat_iter != mChats.end(); ++chat_iter) { - F32 u = clamp_rescale(chat_fade_amt, 1.9f, 2.f, 0.f, 1.f); - mNameText->addLine(chat_iter->mText, lerp(normal_chat, old_chat, u), style); + F32 chat_fade_amt = llclamp((F32)((LLFrameTimer::getElapsedSeconds() - chat_iter->mTime) / CHAT_FADE_TIME), 0.f, 4.f); + LLFontGL::StyleFlags style; + switch(chat_iter->mChatType) + { + case CHAT_TYPE_WHISPER: + style = LLFontGL::ITALIC; + break; + case CHAT_TYPE_SHOUT: + style = LLFontGL::BOLD; + break; + default: + style = LLFontGL::NORMAL; + break; + } + if (chat_fade_amt < 1.f) + { + F32 u = clamp_rescale(chat_fade_amt, 0.9f, 1.f, 0.f, 1.f); + mNameText->addLine(chat_iter->mText, lerp(new_chat, normal_chat, u), style); + } + else if (chat_fade_amt < 2.f) + { + F32 u = clamp_rescale(chat_fade_amt, 1.9f, 2.f, 0.f, 1.f); + mNameText->addLine(chat_iter->mText, lerp(normal_chat, old_chat, u), style); + } + else if (chat_fade_amt < 3.f) + { + // *NOTE: only remove lines down to minimum number + mNameText->addLine(chat_iter->mText, old_chat, style); + } } - else if (chat_fade_amt < 3.f) + mNameText->setVisibleOffScreen(TRUE); + + if (mTyping) { - // *NOTE: only remove lines down to minimum number - mNameText->addLine(chat_iter->mText, old_chat, style); + S32 dot_count = (llfloor(mTypingTimer.getElapsedTimeF32() * 3.f) + 2) % 3 + 1; + switch(dot_count) + { + case 1: + mNameText->addLine(".", new_chat); + break; + case 2: + mNameText->addLine("..", new_chat); + break; + case 3: + mNameText->addLine("...", new_chat); + break; + } + } } - mNameText->setVisibleOffScreen(TRUE); - - if (mTyping) + else { - S32 dot_count = (llfloor(mTypingTimer.getElapsedTimeF32() * 3.f) + 2) % 3 + 1; - switch(dot_count) - { - case 1: - mNameText->addLine(".", new_chat); - break; - case 2: - mNameText->addLine("..", new_chat); - break; - case 3: - mNameText->addLine("...", new_chat); - break; - } - + // ...not using chat bubbles, just names + mNameText->setTextAlignment(LLHUDNameTag::ALIGN_TEXT_CENTER); + mNameText->setFadeDistance(CHAT_NORMAL_RADIUS, 5.f); + mNameText->setVisibleOffScreen(FALSE); } } - else - { - // ...not using chat bubbles, just names - mNameText->setTextAlignment(LLHUDNameTag::ALIGN_TEXT_CENTER); - mNameText->setFadeDistance(CHAT_NORMAL_RADIUS, 5.f); - mNameText->setVisibleOffScreen(FALSE); - } } void LLVOAvatar::addNameTagLine(const std::string& line, const LLColor4& color, S32 style, const LLFontGL* font) @@ -3341,7 +3434,7 @@ LLColor4 LLVOAvatar::getNameTagColor(bool is_friend) else { color_name = "NameTagMismatch"; - } + } } else { @@ -3434,7 +3527,7 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) { mTimeVisible.reset(); } - + //-------------------------------------------------------------------- // the rest should only be done occasionally for far away avatars //-------------------------------------------------------------------- @@ -3969,7 +4062,7 @@ void LLVOAvatar::updateVisibility() LLNameValue* firstname = getNVPair("FirstName"); if (firstname) { - llinfos << "Avatar " << firstname->getString() << " updating visiblity" << llendl; + LL_DEBUGS("Avatar") << avString() << " updating visibility" << LL_ENDL; } else { @@ -4088,11 +4181,11 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass) { //LOD changed or new mesh created, allocate new vertex buffer if needed if (needs_rebuild || mDirtyMesh >= 2 || mVisibilityRank <= 4) { - updateMeshData(); + updateMeshData(); mDirtyMesh = 0; - mNeedsSkin = TRUE; - mDrawable->clearState(LLDrawable::REBUILD_GEOMETRY); - } + mNeedsSkin = TRUE; + mDrawable->clearState(LLDrawable::REBUILD_GEOMETRY); + } } if (LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) <= 0) @@ -4117,13 +4210,17 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass) mNeedsSkin = FALSE; mLastSkinTime = gFrameTimeSeconds; - LLVertexBuffer* vb = mDrawable->getFace(0)->getVertexBuffer(); + LLFace * face = mDrawable->getFace(0); + if (face) + { + LLVertexBuffer* vb = face->getVertexBuffer(); if (vb) { vb->flush(); } } } + } else { mNeedsSkin = FALSE; @@ -4134,7 +4231,7 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass) LLNameValue* firstname = getNVPair("FirstName"); if (firstname) { - llinfos << "Avatar " << firstname->getString() << " in render" << llendl; + LL_DEBUGS("Avatar") << avString() << " in render" << LL_ENDL; } else { @@ -5753,35 +5850,35 @@ BOOL LLVOAvatar::updateJointLODs() F32 avatar_num_factor = clamp_rescale((F32)sNumVisibleAvatars, 8, 25, 1.f, avatar_num_min_factor); F32 area_scale = 0.16f; - if (isSelf()) - { - if(gAgentCamera.cameraCustomizeAvatar() || gAgentCamera.cameraMouselook()) + if (isSelf()) + { + if(gAgentCamera.cameraCustomizeAvatar() || gAgentCamera.cameraMouselook()) + { + mAdjustedPixelArea = MAX_PIXEL_AREA; + } + else + { + mAdjustedPixelArea = mPixelArea*area_scale; + } + } + else if (mIsDummy) { mAdjustedPixelArea = MAX_PIXEL_AREA; } else { - mAdjustedPixelArea = mPixelArea*area_scale; + // reported avatar pixel area is dependent on avatar render load, based on number of visible avatars + mAdjustedPixelArea = (F32)mPixelArea * area_scale * lod_factor * lod_factor * avatar_num_factor * avatar_num_factor; } - } - else if (mIsDummy) - { - mAdjustedPixelArea = MAX_PIXEL_AREA; - } - else - { - // reported avatar pixel area is dependent on avatar render load, based on number of visible avatars - mAdjustedPixelArea = (F32)mPixelArea * area_scale * lod_factor * lod_factor * avatar_num_factor * avatar_num_factor; - } - // now select meshes to render based on adjusted pixel area - BOOL res = mRoot.updateLOD(mAdjustedPixelArea, TRUE); - if (res) - { - sNumLODChangesThisFrame++; - dirtyMesh(2); - return TRUE; - } + // now select meshes to render based on adjusted pixel area + BOOL res = mRoot.updateLOD(mAdjustedPixelArea, TRUE); + if (res) + { + sNumLODChangesThisFrame++; + dirtyMesh(2); + return TRUE; + } return FALSE; } @@ -6073,20 +6170,20 @@ void LLVOAvatar::cleanupAttachedMesh( LLViewerObject* pVO ) if (pSkinData && pSkinData->mJointNames.size() > 20 // full rig && pSkinData->mAlternateBindMatrix.size() > 0) - { - LLVOAvatar::resetJointPositionsToDefault(); - //Need to handle the repositioning of the cam, updating rig data etc during outfit editing - //This handles the case where we detach a replacement rig. - if ( gAgentCamera.cameraCustomizeAvatar() ) - { - gAgent.unpauseAnimation(); - //Still want to refocus on head bone - gAgentCamera.changeCameraToCustomizeAvatar(); + { + LLVOAvatar::resetJointPositionsToDefault(); + //Need to handle the repositioning of the cam, updating rig data etc during outfit editing + //This handles the case where we detach a replacement rig. + if ( gAgentCamera.cameraCustomizeAvatar() ) + { + gAgent.unpauseAnimation(); + //Still want to refocus on head bone + gAgentCamera.changeCameraToCustomizeAvatar(); + } + } } } } - } -} //----------------------------------------------------------------------------- // detachObject() //----------------------------------------------------------------------------- @@ -6337,10 +6434,10 @@ BOOL LLVOAvatar::isVisible() const } // Determine if we have enough avatar data to render -BOOL LLVOAvatar::getIsCloud() +BOOL LLVOAvatar::getIsCloud() const { // Do we have a shape? - if (visualParamWeightsAreDefault()) + if ((const_cast<LLVOAvatar*>(this))->visualParamWeightsAreDefault()) { return TRUE; } @@ -6359,11 +6456,53 @@ BOOL LLVOAvatar::getIsCloud() return FALSE; } +void LLVOAvatar::updateRezzedStatusTimers() +{ + // State machine for rezzed status. Statuses are 0 = cloud, 1 = gray, 2 = textured. + // Purpose is to collect time data for each period of cloud or cloud+gray. + S32 rez_status = getRezzedStatus(); + if (rez_status != mLastRezzedStatus) + { + LL_DEBUGS("Avatar") << avString() << "rez state change: " << mLastRezzedStatus << " -> " << rez_status << LL_ENDL; + bool is_cloud_or_gray = (rez_status==0 || rez_status==1); + bool was_cloud_or_gray = (mLastRezzedStatus==0 || mLastRezzedStatus==1); + bool is_cloud = (rez_status==0); + bool was_cloud = (mLastRezzedStatus==0); + + // Non-cloud to cloud + if (is_cloud && !was_cloud) + { + // start cloud timer. + getPhases().startPhase("cloud"); + } + else if (was_cloud && !is_cloud) + { + // stop cloud timer, which will capture stats. + getPhases().stopPhase("cloud"); + } + + // Non-cloud-or-gray to cloud-or-gray + if (is_cloud_or_gray && !was_cloud_or_gray) + { + // start cloud-or-gray timer. + getPhases().startPhase("cloud-or-gray"); + } + else if (was_cloud_or_gray && !is_cloud_or_gray) + { + // stop cloud-or-gray timer, which will capture stats. + getPhases().stopPhase("cloud-or-gray"); + } + + mLastRezzedStatus = rez_status; + } +} + // call periodically to keep isFullyLoaded up to date. // returns true if the value has changed. BOOL LLVOAvatar::updateIsFullyLoaded() { const BOOL loading = getIsCloud(); + updateRezzedStatusTimers(); updateRuthTimer(loading); return processFullyLoadedChange(loading); } @@ -6378,27 +6517,19 @@ void LLVOAvatar::updateRuthTimer(bool loading) if (mPreviousFullyLoaded) { mRuthTimer.reset(); - if (gSavedSettings.getBOOL("DebugAvatarRezTime")) - { - llinfos << "REZTIME: [ " << (U32)mDebugExistenceTimer.getElapsedTimeF32() << "sec ] Avatar '" << getFullname() << "' became cloud." << llendl; - LLSD args; - args["EXISTENCE"] = llformat("%d",(U32)mDebugExistenceTimer.getElapsedTimeF32()); - args["TIME"] = llformat("%d",(U32)mRuthDebugTimer.getElapsedTimeF32()); - args["NAME"] = getFullname(); - LLNotificationsUtil::add("AvatarRezCloudNotification",args); - } - mRuthDebugTimer.reset(); + debugAvatarRezTime("AvatarRezCloudNotification","became cloud"); } const F32 LOADING_TIMEOUT__SECONDS = 120.f; if (mRuthTimer.getElapsedTimeF32() > LOADING_TIMEOUT__SECONDS) { - llinfos << "Ruth Timer timeout: Missing texture data for '" << getFullname() << "' " + LL_DEBUGS("Avatar") << avString() + << "Ruth Timer timeout: Missing texture data for '" << getFullname() << "' " << "( Params loaded : " << !visualParamWeightsAreDefault() << " ) " << "( Lower : " << isTextureDefined(TEX_LOWER_BAKED) << " ) " << "( Upper : " << isTextureDefined(TEX_UPPER_BAKED) << " ) " << "( Head : " << isTextureDefined(TEX_HEAD_BAKED) << " )." - << llendl; + << LL_ENDL; LLAvatarPropertiesProcessor::getInstance()->sendAvatarTexturesRequest(getID()); mRuthTimer.reset(); @@ -6415,20 +6546,13 @@ BOOL LLVOAvatar::processFullyLoadedChange(bool loading) mFullyLoaded = (mFullyLoadedTimer.getElapsedTimeF32() > PAUSE); - if (gSavedSettings.getBOOL("DebugAvatarRezTime")) - { if (!mPreviousFullyLoaded && !loading && mFullyLoaded) { - llinfos << "REZTIME: [ " << (U32)mDebugExistenceTimer.getElapsedTimeF32() << "sec ] Avatar '" << getFullname() << "' resolved in " << (U32)mRuthDebugTimer.getElapsedTimeF32() << " seconds." << llendl; - LLSD args; - args["EXISTENCE"] = llformat("%d",(U32)mDebugExistenceTimer.getElapsedTimeF32()); - args["TIME"] = llformat("%d",(U32)mRuthDebugTimer.getElapsedTimeF32()); - args["NAME"] = getFullname(); - LLNotificationsUtil::add("AvatarRezNotification",args); - } + debugAvatarRezTime("AvatarRezNotification","fully loaded"); } // did our loading state "change" from last call? + // runway - why are we updating every 30 calls even if nothing has changed? const S32 UPDATE_RATE = 30; BOOL changed = ((mFullyLoaded != mPreviousFullyLoaded) || // if the value is different from the previous call @@ -6868,7 +6992,7 @@ LLColor4 LLVOAvatar::getDummyColor() void LLVOAvatar::dumpAvatarTEs( const std::string& context ) const { - llinfos << (isSelf() ? "Self: " : "Other: ") << context << llendl; + LL_DEBUGS("Avatar") << avString() << (isSelf() ? "Self: " : "Other: ") << context << LL_ENDL; for (LLVOAvatarDictionary::Textures::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin(); iter != LLVOAvatarDictionary::getInstance()->getTextures().end(); ++iter) @@ -6878,23 +7002,23 @@ void LLVOAvatar::dumpAvatarTEs( const std::string& context ) const const LLViewerTexture* te_image = getImage(iter->first,0); if( !te_image ) { - llinfos << " " << texture_dict->mName << ": null ptr" << llendl; + LL_DEBUGS("Avatar") << avString() << " " << texture_dict->mName << ": null ptr" << LL_ENDL; } else if( te_image->getID().isNull() ) { - llinfos << " " << texture_dict->mName << ": null UUID" << llendl; + LL_DEBUGS("Avatar") << avString() << " " << texture_dict->mName << ": null UUID" << LL_ENDL; } else if( te_image->getID() == IMG_DEFAULT ) { - llinfos << " " << texture_dict->mName << ": IMG_DEFAULT" << llendl; + LL_DEBUGS("Avatar") << avString() << " " << texture_dict->mName << ": IMG_DEFAULT" << LL_ENDL; } else if( te_image->getID() == IMG_DEFAULT_AVATAR ) { - llinfos << " " << texture_dict->mName << ": IMG_DEFAULT_AVATAR" << llendl; + LL_DEBUGS("Avatar") << avString() << " " << texture_dict->mName << ": IMG_DEFAULT_AVATAR" << LL_ENDL; } else { - llinfos << " " << texture_dict->mName << ": " << te_image->getID() << llendl; + LL_DEBUGS("Avatar") << avString() << " " << texture_dict->mName << ": " << te_image->getID() << LL_ENDL; } } } @@ -7021,6 +7145,7 @@ LLBBox LLVOAvatar::getHUDBBox() const //----------------------------------------------------------------------------- void LLVOAvatar::onFirstTEMessageReceived() { + LL_INFOS("Avatar") << avString() << LL_ENDL; if( !mFirstTEMessageReceived ) { mFirstTEMessageReceived = TRUE; @@ -7049,6 +7174,7 @@ void LLVOAvatar::onFirstTEMessageReceived() image->setLoadedCallback( onBakedTextureMasksLoaded, MORPH_MASK_REQUESTED_DISCARD, TRUE, TRUE, new LLTextureMaskData( mID ), src_callback_list, paused); } + LL_DEBUGS("Avatar") << avString() << "layer_baked, setting onInitialBakedTextureLoaded as callback" << LL_ENDL; image->setLoadedCallback( onInitialBakedTextureLoaded, MAX_DISCARD_LEVEL, FALSE, FALSE, new LLUUID( mID ), src_callback_list, paused ); } @@ -7107,14 +7233,16 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) LLMemType mt(LLMemType::MTYPE_AVATAR); -// llinfos << "processAvatarAppearance start " << mID << llendl; BOOL is_first_appearance_message = !mFirstAppearanceMessageReceived; - mFirstAppearanceMessageReceived = TRUE; + LL_INFOS("Avatar") << avString() << "processAvatarAppearance start " << mID + << " first? " << is_first_appearance_message << " self? " << isSelf() << LL_ENDL; + + if( isSelf() ) { - llwarns << "Received AvatarAppearance for self" << llendl; + llwarns << avString() << "Received AvatarAppearance for self" << llendl; if( mFirstTEMessageReceived ) { // llinfos << "processAvatarAppearance end " << mID << llendl; @@ -7145,7 +7273,10 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) } - if( !is_first_appearance_message ) + // runway - was + // if (!is_first_appearance_message ) + // which means it would be called on second appearance message - probably wrong. + if (is_first_appearance_message ) { onFirstTEMessageReceived(); } @@ -7166,6 +7297,7 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) bool drop_visual_params_debug = gSavedSettings.getBOOL("BlockSomeAvatarAppearanceVisualParams") && (ll_rand(2) == 0); // pretend that ~12% of AvatarAppearance messages arrived without a VisualParam block, for testing if( num_blocks > 1 && !drop_visual_params_debug) { + LL_DEBUGS("Avatar") << avString() << " handle visual params, num_blocks " << num_blocks << LL_ENDL; BOOL params_changed = FALSE; BOOL interp_params = FALSE; @@ -7238,6 +7370,7 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) else { // AvatarAppearance message arrived without visual params + LL_DEBUGS("Avatar") << avString() << "no visual params" << LL_ENDL; if (drop_visual_params_debug) { llinfos << "Debug-faked lack of parameters on AvatarAppearance for object: " << getID() << llendl; @@ -7322,7 +7455,7 @@ void LLVOAvatar::onBakedTextureMasksLoaded( BOOL success, LLViewerFetchedTexture } U32 gl_name; - LLImageGL::generateTextures(1, &gl_name ); + LLImageGL::generateTextures(LLTexUnit::TT_TEXTURE, GL_ALPHA8, 1, &gl_name ); stop_glerror(); gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, gl_name); @@ -7359,7 +7492,7 @@ void LLVOAvatar::onBakedTextureMasksLoaded( BOOL success, LLViewerFetchedTexture maskData->mLastDiscardLevel = discard_level; if (self->mBakedTextureDatas[baked_index].mMaskTexName) { - LLImageGL::deleteTextures(1, &(self->mBakedTextureDatas[baked_index].mMaskTexName)); + LLImageGL::deleteTextures(LLTexUnit::TT_TEXTURE, 0, -1, 1, &(self->mBakedTextureDatas[baked_index].mMaskTexName)); } self->mBakedTextureDatas[baked_index].mMaskTexName = gl_name; found_texture_id = true; @@ -7390,9 +7523,16 @@ void LLVOAvatar::onBakedTextureMasksLoaded( BOOL success, LLViewerFetchedTexture // static void LLVOAvatar::onInitialBakedTextureLoaded( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata ) { + + LLUUID *avatar_idp = (LLUUID *)userdata; LLVOAvatar *selfp = (LLVOAvatar *)gObjectList.findObject(*avatar_idp); + if (selfp) + { + LL_DEBUGS("Avatar") << selfp->avString() << "discard_level " << discard_level << " success " << success << " final " << final << LL_ENDL; + } + if (!success && selfp) { selfp->removeMissingBakedTextures(); @@ -7403,13 +7543,20 @@ void LLVOAvatar::onInitialBakedTextureLoaded( BOOL success, LLViewerFetchedTextu } } -void LLVOAvatar::onBakedTextureLoaded(BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata) +// Static +void LLVOAvatar::onBakedTextureLoaded(BOOL success, + LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, + S32 discard_level, BOOL final, void* userdata) { //llinfos << "onBakedTextureLoaded: " << src_vi->getID() << llendl; LLUUID id = src_vi->getID(); LLUUID *avatar_idp = (LLUUID *)userdata; LLVOAvatar *selfp = (LLVOAvatar *)gObjectList.findObject(*avatar_idp); + if (selfp) + { + LL_DEBUGS("Avatar") << selfp->avString() << "discard_level " << discard_level << " success " << success << " final " << final << " id " << src_vi->getID() << LL_ENDL; + } if (selfp && !success) { @@ -7436,6 +7583,7 @@ void LLVOAvatar::useBakedTexture( const LLUUID& id ) LLViewerTexture* image_baked = getImage( mBakedTextureDatas[i].mTextureIndex, 0 ); if (id == image_baked->getID()) { + LL_DEBUGS("Avatar") << avString() << " i " << i << " id " << id << LL_ENDL; mBakedTextureDatas[i].mIsLoaded = true; mBakedTextureDatas[i].mLastTextureIndex = id; mBakedTextureDatas[i].mIsUsed = true; @@ -7610,6 +7758,9 @@ void LLVOAvatar::cullAvatarsByPixelArea() } } + // runway - this doesn't detect gray/grey state. + // think we just need to be checking self av since it's the only + // one with lltexlayer stuff. S32 grey_avatars = 0; if (LLVOAvatar::areAllNearbyInstancesBaked(grey_avatars)) { @@ -8200,7 +8351,7 @@ BOOL LLVOAvatar::updateLOD() BOOL res = updateJointLODs(); LLFace* facep = mDrawable->getFace(0); - if (!facep->getVertexBuffer()) + if (!facep || !facep->getVertexBuffer()) { dirtyMesh(2); } @@ -8413,7 +8564,9 @@ void LLVOAvatar::idleUpdateRenderCost() } } - setDebugText(llformat("%d", cost)); + + std::string viz_string = LLVOAvatar::rezStatusToString(getRezzedStatus()); + setDebugText(llformat("%s %d", viz_string.c_str(), cost)); mVisualComplexity = cost; F32 green = 1.f-llclamp(((F32) cost-(F32)ARC_LIMIT)/(F32)ARC_LIMIT, 0.f, 1.f); F32 red = llmin((F32) cost/(F32)ARC_LIMIT, 1.f); diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 036e282d8e..9a69e15743 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -48,6 +48,7 @@ #include "lltexglobalcolor.h" #include "lldriverparam.h" #include "material_codes.h" // LL_MCODE_END +#include "llviewerstats.h" extern const LLUUID ANIM_AGENT_BODY_NOISE; extern const LLUUID ANIM_AGENT_BREATHE_ROT; @@ -278,14 +279,27 @@ public: public: BOOL isFullyLoaded() const; bool isTooComplex() const; - bool visualParamWeightsAreDefault(); + bool visualParamWeightsAreDefault(); + virtual BOOL getIsCloud() const; + BOOL isFullyTextured() const; + BOOL hasGray() const; + S32 getRezzedStatus() const; // 0 = cloud, 1 = gray, 2 = fully textured. + void updateRezzedStatusTimers(); + + S32 mLastRezzedStatus; + + LLViewerStats::PhaseMap& getPhases() + { + return mPhases; + } + protected: - virtual BOOL getIsCloud(); BOOL updateIsFullyLoaded(); BOOL processFullyLoadedChange(bool loading); void updateRuthTimer(bool loading); F32 calcMorphAmount(); private: + BOOL mFirstFullyVisible; BOOL mFullyLoaded; BOOL mPreviousFullyLoaded; BOOL mFullyLoadedInitialized; @@ -293,6 +307,28 @@ private: S32 mVisualComplexity; LLFrameTimer mFullyLoadedTimer; LLFrameTimer mRuthTimer; + +public: + class ScopedPhaseSetter + { + public: + ScopedPhaseSetter(LLVOAvatar *avatarp, std::string phase_name): + mAvatar(avatarp), mPhaseName(phase_name) + { + if (mAvatar) { mAvatar->getPhases().startPhase(mPhaseName); } + } + ~ScopedPhaseSetter() + { + if (mAvatar) { mAvatar->getPhases().stopPhase(mPhaseName); } + } + private: + std::string mPhaseName; + LLVOAvatar* mAvatar; + }; + +private: + LLViewerStats::PhaseMap mPhases; + protected: LLFrameTimer mInvisibleTimer; @@ -520,9 +556,10 @@ public: virtual BOOL isTextureVisible(LLVOAvatarDefines::ETextureIndex type, U32 index = 0) const; virtual BOOL isTextureVisible(LLVOAvatarDefines::ETextureIndex type, LLWearable *wearable) const; -protected: BOOL isFullyBaked(); static BOOL areAllNearbyInstancesBaked(S32& grey_avatars); + static void getNearbyRezzedStats(std::vector<S32>& counts); + static std::string rezStatusToString(S32 status); //-------------------------------------------------------------------- // Baked textures @@ -883,6 +920,7 @@ private: public: std::string getFullname() const; // Returns "FirstName LastName" + std::string avString() const; // Frequently used string in log messages "Avatar '<full name'" protected: static void getAnimLabels(LLDynamicArray<std::string>* labels); static void getAnimNames(LLDynamicArray<std::string>* names); @@ -984,7 +1022,9 @@ private: // Avatar Rez Metrics //-------------------------------------------------------------------- public: + void debugAvatarRezTime(std::string notification_name, std::string comment = ""); F32 debugGetExistenceTimeElapsedF32() const { return mDebugExistenceTimer.getElapsedTimeF32(); } + protected: LLFrameTimer mRuthDebugTimer; // For tracking how long it takes for av to rez LLFrameTimer mDebugExistenceTimer; // Debugging for how long the avatar has been in memory. diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index f063653cc5..98f7245f8d 100644 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -58,6 +58,8 @@ #include "llappearancemgr.h" #include "llmeshrepository.h" #include "llvovolume.h" +#include "llsdutil.h" +#include "llstartup.h" #if LL_MSVC // disable boost::lexical_cast warning @@ -75,6 +77,39 @@ BOOL isAgentAvatarValid() (!gAgentAvatarp->isDead())); } +void selfStartPhase(const std::string& phase_name) +{ + if (isAgentAvatarValid()) + { + gAgentAvatarp->getPhases().startPhase(phase_name); + } +} + +void selfStopPhase(const std::string& phase_name) +{ + if (isAgentAvatarValid()) + { + gAgentAvatarp->getPhases().stopPhase(phase_name); + } +} + +void selfClearPhases() +{ + if (isAgentAvatarValid()) + { + gAgentAvatarp->getPhases().clearPhases(); + gAgentAvatarp->mLastRezzedStatus = -1; + } +} + +void selfStopAllPhases() +{ + if (isAgentAvatarValid()) + { + gAgentAvatarp->getPhases().stopAllPhases(); + } +} + using namespace LLVOAvatarDefines; /********************************************************************************* @@ -131,7 +166,8 @@ LLVOAvatarSelf::LLVOAvatarSelf(const LLUUID& id, LLVOAvatar(id, pcode, regionp), mScreenp(NULL), mLastRegionHandle(0), - mRegionCrossingCount(0) + mRegionCrossingCount(0), + mInitialBakesLoaded(false) { gAgentWearables.setAvatarObject(this); @@ -164,6 +200,7 @@ void LLVOAvatarSelf::initInstance() { mDebugBakedTextureTimes[i][0] = -1.0f; mDebugBakedTextureTimes[i][1] = -1.0f; + mInitialBakeIDs[i] = LLUUID::null; } status &= buildMenus(); @@ -762,6 +799,41 @@ void LLVOAvatarSelf::stopMotionFromSource(const LLUUID& source_id) } } +//virtual +U32 LLVOAvatarSelf::processUpdateMessage(LLMessageSystem *mesgsys, + void **user_data, + U32 block_num, + const EObjectUpdateType update_type, + LLDataPacker *dp) +{ + U32 retval = LLVOAvatar::processUpdateMessage(mesgsys,user_data,block_num,update_type,dp); + + if (mInitialBakesLoaded == false && retval == 0x0) + { + // call update textures to force the images to be created + updateMeshTextures(); + + // unpack the texture UUIDs to the texture slots + retval = unpackTEMessage(mesgsys, _PREHASH_ObjectData, block_num); + + // need to trigger a few operations to get the avatar to use the new bakes + for (U32 i = 0; i < mBakedTextureDatas.size(); i++) + { + const LLVOAvatarDefines::ETextureIndex te = mBakedTextureDatas[i].mTextureIndex; + LLUUID texture_id = getTEImage(te)->getID(); + setNewBakedTexture(te, texture_id); + mInitialBakeIDs[i] = texture_id; + } + + onFirstTEMessageReceived(); + + mInitialBakesLoaded = true; + } + + return retval; +} + + void LLVOAvatarSelf::setLocalTextureTE(U8 te, LLViewerTexture* image, U32 index) { if (te >= TEX_NUM_INDICES) @@ -1889,7 +1961,7 @@ void LLVOAvatarSelf::dumpTotalLocalTextureByteCount() llinfos << "Total Avatar LocTex GL:" << (gl_bytes/1024) << "KB" << llendl; } -BOOL LLVOAvatarSelf::getIsCloud() +BOOL LLVOAvatarSelf::getIsCloud() const { // do we have our body parts? if (gAgentWearables.getWearableCount(LLWearableType::WT_SHAPE) == 0 || @@ -2055,6 +2127,80 @@ const std::string LLVOAvatarSelf::debugDumpAllLocalTextureDataInfo() const return text; } +// Dump avatar metrics data. +LLSD LLVOAvatarSelf::metricsData() +{ + // runway - add region info + LLSD result; + result["id"] = getID(); + result["rez_status"] = LLVOAvatar::rezStatusToString(getRezzedStatus()); + result["is_self"] = isSelf(); + std::vector<S32> rez_counts; + LLVOAvatar::getNearbyRezzedStats(rez_counts); + result["nearby"] = LLSD::emptyMap(); + for (S32 i=0; i<rez_counts.size(); ++i) + { + std::string rez_status_name = LLVOAvatar::rezStatusToString(i); + result["nearby"][rez_status_name] = rez_counts[i]; + } + result["timers"]["debug_existence"] = mDebugExistenceTimer.getElapsedTimeF32(); + result["timers"]["ruth_debug"] = mRuthDebugTimer.getElapsedTimeF32(); + result["timers"]["ruth"] = mRuthTimer.getElapsedTimeF32(); + result["timers"]["invisible"] = mInvisibleTimer.getElapsedTimeF32(); + result["timers"]["fully_loaded"] = mFullyLoadedTimer.getElapsedTimeF32(); + result["phases"] = getPhases().dumpPhases(); + result["startup"] = LLStartUp::getPhases().dumpPhases(); + + return result; +} + +class ViewerAppearanceChangeMetricsResponder: public LLCurl::Responder +{ +public: + ViewerAppearanceChangeMetricsResponder() + { + } + + virtual void completed(U32 status, + const std::string& reason, + const LLSD& content) + { + if (isGoodStatus(status)) + { + LL_DEBUGS("Avatar") << "OK" << LL_ENDL; + result(content); + } + else + { + LL_WARNS("Avatar") << "Failed " << status << " reason " << reason << LL_ENDL; + error(status,reason); + } + } +}; + +void LLVOAvatarSelf::sendAppearanceChangeMetrics() +{ + // gAgentAvatarp->stopAllPhases(); + + LLSD msg = metricsData(); + msg["message"] = "ViewerAppearanceChangeMetrics"; + + LL_DEBUGS("Avatar") << avString() << "message: " << ll_pretty_print_sd(msg) << LL_ENDL; + std::string caps_url; + if (getRegion()) + { + // runway - change here to activate. + caps_url = getRegion()->getCapability("ViewerMetrics"); + } + if (!caps_url.empty()) + { + LLCurlRequest::headers_t headers; + LLHTTPClient::post(caps_url, + msg, + new ViewerAppearanceChangeMetricsResponder); + } +} + const LLUUID& LLVOAvatarSelf::grabBakedTexture(EBakedTextureIndex baked_index) const { if (canGrabBakedTexture(baked_index)) @@ -2253,11 +2399,25 @@ void LLVOAvatarSelf::setNewBakedTexture( ETextureIndex te, const LLUUID& uuid ) if (isAllLocalTextureDataFinal()) { LLNotificationsUtil::add("AvatarRezSelfBakedDoneNotification",args); + LL_DEBUGS("Avatar") << "REZTIME: [ " << (U32)mDebugExistenceTimer.getElapsedTimeF32() + << "sec ]" + << avString() + << "RuthTimer " << (U32)mRuthDebugTimer.getElapsedTimeF32() + << " SelfLoadTimer " << (U32)mDebugSelfLoadTimer.getElapsedTimeF32() + << " Notification " << "AvatarRezSelfBakedDoneNotification" + << llendl; } else { args["STATUS"] = debugDumpAllLocalTextureDataInfo(); LLNotificationsUtil::add("AvatarRezSelfBakedUpdateNotification",args); + LL_DEBUGS("Avatar") << "REZTIME: [ " << (U32)mDebugExistenceTimer.getElapsedTimeF32() + << "sec ]" + << avString() + << "RuthTimer " << (U32)mRuthDebugTimer.getElapsedTimeF32() + << " SelfLoadTimer " << (U32)mDebugSelfLoadTimer.getElapsedTimeF32() + << " Notification " << "AvatarRezSelfBakedUpdateNotification" + << llendl; } } @@ -2265,7 +2425,7 @@ void LLVOAvatarSelf::setNewBakedTexture( ETextureIndex te, const LLUUID& uuid ) } } -// FIXME: This is never called. Something may be broken. +// FIXME: This is not called consistently. Something may be broken. void LLVOAvatarSelf::outputRezDiagnostics() const { if(!gSavedSettings.getBOOL("DebugAvatarLocalTexLoadedTime")) @@ -2274,11 +2434,11 @@ void LLVOAvatarSelf::outputRezDiagnostics() const } const F32 final_time = mDebugSelfLoadTimer.getElapsedTimeF32(); - llinfos << "REZTIME: Myself rez stats:" << llendl; - llinfos << "\t Time from avatar creation to load wearables: " << (S32)mDebugTimeWearablesLoaded << llendl; - llinfos << "\t Time from avatar creation to de-cloud: " << (S32)mDebugTimeAvatarVisible << llendl; - llinfos << "\t Time from avatar creation to de-cloud for others: " << (S32)final_time << llendl; - llinfos << "\t Load time for each texture: " << llendl; + LL_DEBUGS("Avatar") << "REZTIME: Myself rez stats:" << llendl; + LL_DEBUGS("Avatar") << "\t Time from avatar creation to load wearables: " << (S32)mDebugTimeWearablesLoaded << llendl; + LL_DEBUGS("Avatar") << "\t Time from avatar creation to de-cloud: " << (S32)mDebugTimeAvatarVisible << llendl; + LL_DEBUGS("Avatar") << "\t Time from avatar creation to de-cloud for others: " << (S32)final_time << llendl; + LL_DEBUGS("Avatar") << "\t Load time for each texture: " << llendl; for (U32 i = 0; i < LLVOAvatarDefines::TEX_NUM_INDICES; ++i) { std::stringstream out; @@ -2302,12 +2462,14 @@ void LLVOAvatarSelf::outputRezDiagnostics() const // Don't print out non-existent textures. if (j != 0) - llinfos << out.str() << llendl; + { + LL_DEBUGS("Avatar") << out.str() << LL_ENDL; + } } - llinfos << "\t Time points for each upload (start / finish)" << llendl; + LL_DEBUGS("Avatar") << "\t Time points for each upload (start / finish)" << llendl; for (U32 i = 0; i < LLVOAvatarDefines::BAKED_NUM_INDICES; ++i) { - llinfos << "\t\t (" << i << ") \t" << (S32)mDebugBakedTextureTimes[i][0] << " / " << (S32)mDebugBakedTextureTimes[i][1] << llendl; + LL_DEBUGS("Avatar") << "\t\t (" << i << ") \t" << (S32)mDebugBakedTextureTimes[i][0] << " / " << (S32)mDebugBakedTextureTimes[i][1] << llendl; } for (LLVOAvatarDefines::LLVOAvatarDictionary::BakedTextures::const_iterator baked_iter = LLVOAvatarDefines::LLVOAvatarDictionary::getInstance()->getBakedTextures().begin(); @@ -2319,15 +2481,16 @@ void LLVOAvatarSelf::outputRezDiagnostics() const if (!layerset) continue; const LLTexLayerSetBuffer *layerset_buffer = layerset->getComposite(); if (!layerset_buffer) continue; - llinfos << layerset_buffer->dumpTextureInfo() << llendl; + LL_DEBUGS("Avatar") << layerset_buffer->dumpTextureInfo() << llendl; } } void LLVOAvatarSelf::outputRezTiming(const std::string& msg) const { - LL_DEBUGS("Avatar Rez") + LL_INFOS("Avatar") + << avString() << llformat("%s. Time from avatar creation: %.2f", msg.c_str(), mDebugSelfLoadTimer.getElapsedTimeF32()) - << llendl; + << LL_ENDL; } void LLVOAvatarSelf::reportAvatarRezTime() const @@ -2351,6 +2514,18 @@ void LLVOAvatarSelf::setCachedBakedTexture( ETextureIndex te, const LLUUID& uuid { if ( mBakedTextureDatas[i].mTextureIndex == te && mBakedTextureDatas[i].mTexLayerSet) { + if (mInitialBakeIDs[i] != LLUUID::null) + { + if (mInitialBakeIDs[i] == uuid) + { + llinfos << "baked texture correctly loaded at login! " << i << llendl; + } + else + { + llwarns << "baked texture does not match id loaded at login!" << i << llendl; + } + mInitialBakeIDs[i] = LLUUID::null; + } mBakedTextureDatas[i].mTexLayerSet->cancelUpload(); } } @@ -2478,6 +2653,20 @@ LLTexLayerSet* LLVOAvatarSelf::getLayerSet(ETextureIndex index) const return NULL; } +LLTexLayerSet* LLVOAvatarSelf::getLayerSet(EBakedTextureIndex baked_index) const +{ + /* switch(index) + case TEX_HEAD_BAKED: + case TEX_HEAD_BODYPAINT: + return mHeadLayerSet; */ + if (baked_index >= 0 && baked_index < BAKED_NUM_INDICES) + { + return mBakedTextureDatas[baked_index].mTexLayerSet; + } + return NULL; +} + + // static void LLVOAvatarSelf::onCustomizeStart() { @@ -2558,54 +2747,11 @@ BOOL LLVOAvatarSelf::needsRenderBeam() // static void LLVOAvatarSelf::deleteScratchTextures() { - if(gAuditTexture) - { - S32 total_tex_size = sScratchTexBytes ; - S32 tex_size = SCRATCH_TEX_WIDTH * SCRATCH_TEX_HEIGHT ; - - if( sScratchTexNames.checkData( GL_LUMINANCE ) ) - { - LLImageGL::decTextureCounter(tex_size, 1, LLViewerTexture::AVATAR_SCRATCH_TEX) ; - total_tex_size -= tex_size ; - } - if( sScratchTexNames.checkData( GL_ALPHA ) ) - { - LLImageGL::decTextureCounter(tex_size, 1, LLViewerTexture::AVATAR_SCRATCH_TEX) ; - total_tex_size -= tex_size ; - } - if( sScratchTexNames.checkData( GL_COLOR_INDEX ) ) - { - LLImageGL::decTextureCounter(tex_size, 1, LLViewerTexture::AVATAR_SCRATCH_TEX) ; - total_tex_size -= tex_size ; - } - if( sScratchTexNames.checkData( LLRender::sGLCoreProfile ? GL_RG : GL_LUMINANCE_ALPHA ) ) - { - LLImageGL::decTextureCounter(tex_size, 2, LLViewerTexture::AVATAR_SCRATCH_TEX) ; - total_tex_size -= 2 * tex_size ; - } - if( sScratchTexNames.checkData( GL_RGB ) ) - { - LLImageGL::decTextureCounter(tex_size, 3, LLViewerTexture::AVATAR_SCRATCH_TEX) ; - total_tex_size -= 3 * tex_size ; - } - if( sScratchTexNames.checkData( GL_RGBA ) ) - { - LLImageGL::decTextureCounter(tex_size, 4, LLViewerTexture::AVATAR_SCRATCH_TEX) ; - total_tex_size -= 4 * tex_size ; - } - //others - while(total_tex_size > 0) - { - LLImageGL::decTextureCounter(tex_size, 4, LLViewerTexture::AVATAR_SCRATCH_TEX) ; - total_tex_size -= 4 * tex_size ; - } - } - for( LLGLuint* namep = sScratchTexNames.getFirstData(); namep; namep = sScratchTexNames.getNextData() ) { - LLImageGL::deleteTextures(1, (U32 *)namep ); + LLImageGL::deleteTextures(LLTexUnit::TT_TEXTURE, 0, -1, 1, (U32 *)namep ); stop_glerror(); } diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h index 655fb3a012..543891ca63 100644 --- a/indra/newview/llvoavatarself.h +++ b/indra/newview/llvoavatarself.h @@ -93,15 +93,27 @@ public: /*virtual*/ void updateVisualParams(); /*virtual*/ void idleUpdateAppearanceAnimation(); + /*virtual*/ U32 processUpdateMessage(LLMessageSystem *mesgsys, + void **user_data, + U32 block_num, + const EObjectUpdateType update_type, + LLDataPacker *dp); + private: // helper function. Passed in param is assumed to be in avatar's parameter list. BOOL setParamWeight(LLViewerVisualParam *param, F32 weight, BOOL upload_bake = FALSE ); + /** Initialization ** ** *******************************************************************************/ +private: + LLUUID mInitialBakeIDs[6]; + bool mInitialBakesLoaded; + + /******************************************************************************** ** ** ** STATE @@ -121,7 +133,7 @@ public: // Loading state //-------------------------------------------------------------------- public: - /*virtual*/ BOOL getIsCloud(); + /*virtual*/ BOOL getIsCloud() const; //-------------------------------------------------------------------- // Region state @@ -229,6 +241,7 @@ public: void requestLayerSetUpload(LLVOAvatarDefines::EBakedTextureIndex i); void requestLayerSetUpdate(LLVOAvatarDefines::ETextureIndex i); LLTexLayerSet* getLayerSet(LLVOAvatarDefines::ETextureIndex index) const; + LLTexLayerSet* getLayerSet(LLVOAvatarDefines::EBakedTextureIndex baked_index) const; //-------------------------------------------------------------------- // Composites @@ -369,6 +382,8 @@ public: const LLTexLayerSet* debugGetLayerSet(LLVOAvatarDefines::EBakedTextureIndex index) const { return mBakedTextureDatas[index].mTexLayerSet; } const std::string debugDumpLocalTextureDataInfo(const LLTexLayerSet* layerset) const; // Lists out state of this particular baked texture layer const std::string debugDumpAllLocalTextureDataInfo() const; // Lists out which baked textures are at highest LOD + LLSD metricsData(); + void sendAppearanceChangeMetrics(); // send data associated with completing a change. private: LLFrameTimer mDebugSelfLoadTimer; F32 mDebugTimeWearablesLoaded; @@ -387,4 +402,9 @@ extern LLPointer<LLVOAvatarSelf> gAgentAvatarp; BOOL isAgentAvatarValid(); +void selfStartPhase(const std::string& phase_name); +void selfStopPhase(const std::string& phase_name); +void selfStopAllPhases(); +void selfClearPhases(); + #endif // LL_VO_AVATARSELF_H diff --git a/indra/newview/llvograss.cpp b/indra/newview/llvograss.cpp index 8a79d564d3..44968342bf 100644 --- a/indra/newview/llvograss.cpp +++ b/indra/newview/llvograss.cpp @@ -34,6 +34,7 @@ #include "llagentcamera.h" #include "llnotificationsutil.h" #include "lldrawable.h" +#include "lldrawpoolalpha.h" #include "llface.h" #include "llsky.h" #include "llsurface.h" @@ -380,8 +381,10 @@ BOOL LLVOGrass::updateLOD() { mNumBlades <<= 1; } - - face->setSize(mNumBlades*8, mNumBlades*12); + if (face) + { + face->setSize(mNumBlades*8, mNumBlades*12); + } gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE); } else if (num_blades <= (mNumBlades >> 1)) @@ -391,7 +394,10 @@ BOOL LLVOGrass::updateLOD() mNumBlades >>=1; } - face->setSize(mNumBlades*8, mNumBlades*12); + if (face) + { + face->setSize(mNumBlades*8, mNumBlades*12); + } gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE); return TRUE; } @@ -449,14 +455,16 @@ void LLVOGrass::plantBlades() } LLFace *face = mDrawable->getFace(0); + if (face) + { + face->setTexture(getTEImage(0)); + face->setState(LLFace::GLOBAL); + face->setSize(mNumBlades * 8, mNumBlades * 12); + face->setVertexBuffer(NULL); + face->setTEOffset(0); + face->mCenterLocal = mPosition + mRegionp->getOriginAgent(); + } - face->setTexture(getTEImage(0)); - face->setState(LLFace::GLOBAL); - face->setSize(mNumBlades * 8, mNumBlades * 12); - face->setVertexBuffer(NULL); - face->setTEOffset(0); - face->mCenterLocal = mPosition + mRegionp->getOriginAgent(); - mDepth = (face->mCenterLocal - LLViewerCamera::getInstance()->getOrigin())*LLViewerCamera::getInstance()->getAtAxis(); mDrawable->setPosition(face->mCenterLocal); mDrawable->movePartition(); @@ -486,6 +494,8 @@ void LLVOGrass::getGeometry(S32 idx, LLColor4U color(255,255,255,255); LLFace *face = mDrawable->getFace(idx); + if (!face) + return; F32 width = sSpeciesTable[mSpecies]->mBladeSizeX; F32 height = sSpeciesTable[mSpecies]->mBladeSizeY; @@ -594,6 +604,7 @@ U32 LLVOGrass::getPartitionType() const } LLGrassPartition::LLGrassPartition() +: LLSpatialPartition(LLDrawPoolAlpha::VERTEX_DATA_MASK | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, GL_STREAM_DRAW_ARB) { mDrawableType = LLPipeline::RENDER_TYPE_GRASS; mPartitionType = LLViewerRegion::PARTITION_GRASS; @@ -604,6 +615,143 @@ LLGrassPartition::LLGrassPartition() mBufferUsage = GL_DYNAMIC_DRAW_ARB; } +void LLGrassPartition::addGeometryCount(LLSpatialGroup* group, U32& vertex_count, U32& index_count) +{ + group->mBufferUsage = mBufferUsage; + + mFaceList.clear(); + + LLViewerCamera* camera = LLViewerCamera::getInstance(); + for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i) + { + LLDrawable* drawablep = *i; + + if (drawablep->isDead()) + { + continue; + } + + LLAlphaObject* obj = (LLAlphaObject*) drawablep->getVObj().get(); + obj->mDepth = 0.f; + + if (drawablep->isAnimating()) + { + group->mBufferUsage = GL_STREAM_DRAW_ARB; + } + + U32 count = 0; + for (S32 j = 0; j < drawablep->getNumFaces(); ++j) + { + drawablep->updateFaceSize(j); + + LLFace* facep = drawablep->getFace(j); + if ( !facep || !facep->hasGeometry()) + { + continue; + } + + if ((facep->getGeomCount() + vertex_count) <= 65536) + { + count++; + facep->mDistance = (facep->mCenterLocal - camera->getOrigin()) * camera->getAtAxis(); + obj->mDepth += facep->mDistance; + + mFaceList.push_back(facep); + vertex_count += facep->getGeomCount(); + index_count += facep->getIndicesCount(); + llassert(facep->getIndicesCount() < 65536); + } + else + { + facep->clearVertexBuffer(); + } + } + + obj->mDepth /= count; + } +} + +static LLFastTimer::DeclareTimer FTM_REBUILD_GRASS_VB("Grass VB"); + +void LLGrassPartition::getGeometry(LLSpatialGroup* group) +{ + LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); + LLFastTimer ftm(FTM_REBUILD_GRASS_VB); + + std::sort(mFaceList.begin(), mFaceList.end(), LLFace::CompareDistanceGreater()); + + U32 index_count = 0; + U32 vertex_count = 0; + + group->clearDrawMap(); + + LLVertexBuffer* buffer = group->mVertexBuffer; + + LLStrider<U16> indicesp; + LLStrider<LLVector4a> verticesp; + LLStrider<LLVector3> normalsp; + LLStrider<LLVector2> texcoordsp; + LLStrider<LLColor4U> colorsp; + + buffer->getVertexStrider(verticesp); + buffer->getNormalStrider(normalsp); + buffer->getColorStrider(colorsp); + buffer->getTexCoord0Strider(texcoordsp); + buffer->getIndexStrider(indicesp); + + LLSpatialGroup::drawmap_elem_t& draw_vec = group->mDrawMap[mRenderPass]; + + for (std::vector<LLFace*>::iterator i = mFaceList.begin(); i != mFaceList.end(); ++i) + { + LLFace* facep = *i; + LLAlphaObject* object = (LLAlphaObject*) facep->getViewerObject(); + facep->setGeomIndex(vertex_count); + facep->setIndicesIndex(index_count); + facep->setVertexBuffer(buffer); + facep->setPoolType(LLDrawPool::POOL_ALPHA); + object->getGeometry(facep->getTEOffset(), verticesp, normalsp, texcoordsp, colorsp, indicesp); + + vertex_count += facep->getGeomCount(); + index_count += facep->getIndicesCount(); + + S32 idx = draw_vec.size()-1; + + BOOL fullbright = facep->isState(LLFace::FULLBRIGHT); + F32 vsize = facep->getVirtualSize(); + + if (idx >= 0 && draw_vec[idx]->mEnd == facep->getGeomIndex()-1 && + draw_vec[idx]->mTexture == facep->getTexture() && + (U16) (draw_vec[idx]->mEnd - draw_vec[idx]->mStart + facep->getGeomCount()) <= (U32) gGLManager.mGLMaxVertexRange && + //draw_vec[idx]->mCount + facep->getIndicesCount() <= (U32) gGLManager.mGLMaxIndexRange && + draw_vec[idx]->mEnd - draw_vec[idx]->mStart + facep->getGeomCount() < 4096 && + draw_vec[idx]->mFullbright == fullbright) + { + draw_vec[idx]->mCount += facep->getIndicesCount(); + draw_vec[idx]->mEnd += facep->getGeomCount(); + draw_vec[idx]->mVSize = llmax(draw_vec[idx]->mVSize, vsize); + } + else + { + U32 start = facep->getGeomIndex(); + U32 end = start + facep->getGeomCount()-1; + U32 offset = facep->getIndicesStart(); + U32 count = facep->getIndicesCount(); + LLDrawInfo* info = new LLDrawInfo(start,end,count,offset,facep->getTexture(), + //facep->getTexture(), + buffer, fullbright); + info->mExtents[0] = group->mObjectExtents[0]; + info->mExtents[1] = group->mObjectExtents[1]; + info->mVSize = vsize; + draw_vec.push_back(info); + //for alpha sorting + facep->setDrawInfo(info); + } + } + + buffer->flush(); + mFaceList.clear(); +} + // virtual void LLVOGrass::updateDrawable(BOOL force_damped) { diff --git a/indra/newview/llvoground.cpp b/indra/newview/llvoground.cpp index 0060f81ab5..6da54435e3 100644 --- a/indra/newview/llvoground.cpp +++ b/indra/newview/llvoground.cpp @@ -82,6 +82,7 @@ LLDrawable *LLVOGround::createDrawable(LLPipeline *pipeline) return mDrawable; } +// TO DO - this always returns TRUE, BOOL LLVOGround::updateGeometry(LLDrawable *drawable) { LLStrider<LLVector3> verticesp; @@ -96,6 +97,8 @@ BOOL LLVOGround::updateGeometry(LLDrawable *drawable) if (drawable->getNumFaces() < 1) drawable->addFace(poolp, NULL); face = drawable->getFace(0); + if (!face) + return TRUE; if (!face->getVertexBuffer()) { diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp index df1d3f2955..820d1d73e1 100644 --- a/indra/newview/llvoicevivox.cpp +++ b/indra/newview/llvoicevivox.cpp @@ -27,8 +27,6 @@ #include "llviewerprecompiledheaders.h" #include "llvoicevivox.h" -#include <boost/tokenizer.hpp> - #include "llsdutil.h" // Linden library includes @@ -47,6 +45,7 @@ #include "llbase64.h" #include "llviewercontrol.h" #include "llappviewer.h" // for gDisconnected, gDisableVoice +#include "llprocess.h" // Viewer includes #include "llmutelist.h" // to check for muted avatars @@ -242,59 +241,21 @@ void LLVivoxVoiceClientCapResponder::result(const LLSD& content) } } - - -#if LL_WINDOWS -static HANDLE sGatewayHandle = 0; +static LLProcessPtr sGatewayPtr; static bool isGatewayRunning() { - bool result = false; - if(sGatewayHandle != 0) - { - DWORD waitresult = WaitForSingleObject(sGatewayHandle, 0); - if(waitresult != WAIT_OBJECT_0) - { - result = true; - } - } - return result; -} -static void killGateway() -{ - if(sGatewayHandle != 0) - { - TerminateProcess(sGatewayHandle,0); - } -} - -#else // Mac and linux - -static pid_t sGatewayPID = 0; -static bool isGatewayRunning() -{ - bool result = false; - if(sGatewayPID != 0) - { - // A kill with signal number 0 has no effect, just does error checking. It should return an error if the process no longer exists. - if(kill(sGatewayPID, 0) == 0) - { - result = true; - } - } - return result; + return sGatewayPtr && sGatewayPtr->isRunning(); } static void killGateway() { - if(sGatewayPID != 0) + if (sGatewayPtr) { - kill(sGatewayPID, SIGTERM); + sGatewayPtr->kill(); } } -#endif - /////////////////////////////////////////////////////////////////////////////////////////////// LLVivoxVoiceClient::LLVivoxVoiceClient() : @@ -790,7 +751,7 @@ void LLVivoxVoiceClient::stateMachine() } else if(!isGatewayRunning()) { - if(true) + if (true) // production build, not test { // Launch the voice daemon @@ -809,102 +770,33 @@ void LLVivoxVoiceClient::stateMachine() #endif // See if the vivox executable exists llstat s; - if(!LLFile::stat(exe_path, &s)) + if (!LLFile::stat(exe_path, &s)) { // vivox executable exists. Build the command line and launch the daemon. + LLProcess::Params params; + params.executable = exe_path; // SLIM SDK: these arguments are no longer necessary. // std::string args = " -p tcp -h -c"; - std::string args; - std::string cmd; std::string loglevel = gSavedSettings.getString("VivoxDebugLevel"); - if(loglevel.empty()) { loglevel = "-1"; // turn logging off completely } - - args += " -ll "; - args += loglevel; - - LL_DEBUGS("Voice") << "Args for SLVoice: " << args << LL_ENDL; - -#if LL_WINDOWS - PROCESS_INFORMATION pinfo; - STARTUPINFOA sinfo; - - memset(&sinfo, 0, sizeof(sinfo)); - - std::string exe_dir = gDirUtilp->getAppRODataDir(); - cmd = "SLVoice.exe"; - cmd += args; - - // So retarded. Windows requires that the second parameter to CreateProcessA be writable (non-const) string... - char *args2 = new char[args.size() + 1]; - strcpy(args2, args.c_str()); - if(!CreateProcessA(exe_path.c_str(), args2, NULL, NULL, FALSE, 0, NULL, exe_dir.c_str(), &sinfo, &pinfo)) - { -// DWORD dwErr = GetLastError(); - } - else - { - // foo = pinfo.dwProcessId; // get your pid here if you want to use it later on - // CloseHandle(pinfo.hProcess); // stops leaks - nothing else - sGatewayHandle = pinfo.hProcess; - CloseHandle(pinfo.hThread); // stops leaks - nothing else - } - - delete[] args2; -#else // LL_WINDOWS - // This should be the same for mac and linux - { - std::vector<std::string> arglist; - arglist.push_back(exe_path); - - // Split the argument string into separate strings for each argument - typedef boost::tokenizer<boost::char_separator<char> > tokenizer; - boost::char_separator<char> sep(" "); - tokenizer tokens(args, sep); - tokenizer::iterator token_iter; - for(token_iter = tokens.begin(); token_iter != tokens.end(); ++token_iter) - { - arglist.push_back(*token_iter); - } - - // create an argv vector for the child process - char **fakeargv = new char*[arglist.size() + 1]; - int i; - for(i=0; i < arglist.size(); i++) - fakeargv[i] = const_cast<char*>(arglist[i].c_str()); + params.args.add("-ll"); + params.args.add(loglevel); + params.cwd = gDirUtilp->getAppRODataDir(); + sGatewayPtr = LLProcess::create(params); - fakeargv[i] = NULL; - - fflush(NULL); // flush all buffers before the child inherits them - pid_t id = vfork(); - if(id == 0) - { - // child - execv(exe_path.c_str(), fakeargv); - - // If we reach this point, the exec failed. - // Use _exit() instead of exit() per the vfork man page. - _exit(0); - } - - // parent - delete[] fakeargv; - sGatewayPID = id; - } -#endif // LL_WINDOWS mDaemonHost = LLHost(gSavedSettings.getString("VivoxVoiceHost").c_str(), gSavedSettings.getU32("VivoxVoicePort")); - } + } else { LL_INFOS("Voice") << exe_path << " not found." << LL_ENDL; - } + } } else - { + { // SLIM SDK: port changed from 44124 to 44125. // We can connect to a client gateway running on another host. This is useful for testing. // To do this, launch the gateway on a nearby host like this: diff --git a/indra/newview/llvopartgroup.cpp b/indra/newview/llvopartgroup.cpp index 5c10a80b07..e21358b65a 100644 --- a/indra/newview/llvopartgroup.cpp +++ b/indra/newview/llvopartgroup.cpp @@ -48,6 +48,117 @@ const F32 MAX_PART_LIFETIME = 120.f; extern U64 gFrameTime; +LLPointer<LLVertexBuffer> LLVOPartGroup::sVB = NULL; +S32 LLVOPartGroup::sVBSlotFree[]; +S32* LLVOPartGroup::sVBSlotCursor = NULL; + +//static +void LLVOPartGroup::restoreGL() +{ + for (S32 i = 0; i < LL_MAX_PARTICLE_COUNT; ++i) + { + sVBSlotFree[i] = i; + } + + sVBSlotCursor = sVBSlotFree; + + sVB = new LLVertexBuffer(VERTEX_DATA_MASK, GL_STREAM_DRAW_ARB); + U32 count = LL_MAX_PARTICLE_COUNT; + sVB->allocateBuffer(count*4, count*6, true); + + //indices and texcoords are always the same, set once + LLStrider<U16> indicesp; + + LLStrider<LLVector4a> verticesp; + + sVB->getIndexStrider(indicesp); + sVB->getVertexStrider(verticesp); + + LLVector4a v; + v.set(0,0,0,0); + + + U16 vert_offset = 0; + + for (U32 i = 0; i < LL_MAX_PARTICLE_COUNT; i++) + { + *indicesp++ = vert_offset + 0; + *indicesp++ = vert_offset + 1; + *indicesp++ = vert_offset + 2; + + *indicesp++ = vert_offset + 1; + *indicesp++ = vert_offset + 3; + *indicesp++ = vert_offset + 2; + + *verticesp++ = v; + + vert_offset += 4; + } + + LLStrider<LLVector2> texcoordsp; + sVB->getTexCoord0Strider(texcoordsp); + + for (U32 i = 0; i < LL_MAX_PARTICLE_COUNT; i++) + { + *texcoordsp++ = LLVector2(0.f, 1.f); + *texcoordsp++ = LLVector2(0.f, 0.f); + *texcoordsp++ = LLVector2(1.f, 1.f); + *texcoordsp++ = LLVector2(1.f, 0.f); + } + + sVB->flush(); + +} + +//static +void LLVOPartGroup::destroyGL() +{ + sVB = NULL; +} + +//static +S32 LLVOPartGroup::findAvailableVBSlot() +{ + if (sVBSlotCursor >= sVBSlotFree+LL_MAX_PARTICLE_COUNT) + { //no more available slots + return -1; + } + + S32 ret = *sVBSlotCursor; + sVBSlotCursor++; + + return ret; +} + +bool ll_is_part_idx_allocated(S32 idx, S32* start, S32* end) +{ + while (start < end) + { + if (*start == idx) + { //not allocated (in free list) + return false; + } + ++start; + } + + //allocated (not in free list) + return true; +} + +//static +void LLVOPartGroup::freeVBSlot(S32 idx) +{ + llassert(idx < LL_MAX_PARTICLE_COUNT && idx >= 0); + llassert(sVBSlotCursor > sVBSlotFree); + llassert(ll_is_part_idx_allocated(idx, sVBSlotCursor, sVBSlotFree+LL_MAX_PARTICLE_COUNT)); + + if (sVBSlotCursor > sVBSlotFree) + { + sVBSlotCursor--; + *sVBSlotCursor = idx; + } +} + LLVOPartGroup::LLVOPartGroup(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) : LLAlphaObject(id, pcode, regionp), mViewerPartGroupp(NULL) @@ -62,7 +173,6 @@ LLVOPartGroup::~LLVOPartGroup() { } - BOOL LLVOPartGroup::isActive() const { return FALSE; @@ -287,9 +397,6 @@ void LLVOPartGroup::getGeometry(S32 idx, const LLViewerPart &part = *((LLViewerPart*) (mViewerPartGroupp->mParticles[idx])); - U32 vert_offset = mDrawable->getFace(idx)->getGeomIndex(); - - LLVector4a part_pos_agent; part_pos_agent.load3(part.mPosAgent.mV); LLVector4a camera_agent; @@ -361,33 +468,18 @@ void LLVOPartGroup::getGeometry(S32 idx, verticesp->setAdd(ppamu, right); (*verticesp++).getF32ptr()[3] = 0.f; - //*verticesp++ = part_pos_agent + up - right; - //*verticesp++ = part_pos_agent - up - right; - //*verticesp++ = part_pos_agent + up + right; - //*verticesp++ = part_pos_agent - up + right; - *colorsp++ = part.mColor; *colorsp++ = part.mColor; *colorsp++ = part.mColor; *colorsp++ = part.mColor; - *texcoordsp++ = LLVector2(0.f, 1.f); - *texcoordsp++ = LLVector2(0.f, 0.f); - *texcoordsp++ = LLVector2(1.f, 1.f); - *texcoordsp++ = LLVector2(1.f, 0.f); - - *normalsp++ = normal; - *normalsp++ = normal; - *normalsp++ = normal; - *normalsp++ = normal; - - *indicesp++ = vert_offset + 0; - *indicesp++ = vert_offset + 1; - *indicesp++ = vert_offset + 2; - - *indicesp++ = vert_offset + 1; - *indicesp++ = vert_offset + 3; - *indicesp++ = vert_offset + 2; + if (!(part.mFlags & LLPartData::LL_PART_EMISSIVE_MASK)) + { //not fullbright, needs normal + *normalsp++ = normal; + *normalsp++ = normal; + *normalsp++ = normal; + *normalsp++ = normal; + } } U32 LLVOPartGroup::getPartitionType() const @@ -412,6 +504,49 @@ LLHUDParticlePartition::LLHUDParticlePartition() : mPartitionType = LLViewerRegion::PARTITION_HUD_PARTICLE; } +static LLFastTimer::DeclareTimer FTM_REBUILD_PARTICLE_VBO("Particle VBO"); + +void LLParticlePartition::rebuildGeom(LLSpatialGroup* group) +{ + if (group->isDead() || !group->isState(LLSpatialGroup::GEOM_DIRTY)) + { + return; + } + + if (group->changeLOD()) + { + group->mLastUpdateDistance = group->mDistance; + group->mLastUpdateViewAngle = group->mViewAngle; + } + + LLFastTimer ftm(FTM_REBUILD_PARTICLE_VBO); + + group->clearDrawMap(); + + //get geometry count + U32 index_count = 0; + U32 vertex_count = 0; + + addGeometryCount(group, vertex_count, index_count); + + + if (vertex_count > 0 && index_count > 0) + { + group->mBuilt = 1.f; + //use one vertex buffer for all groups + group->mVertexBuffer = LLVOPartGroup::sVB; + getGeometry(group); + } + else + { + group->mVertexBuffer = NULL; + group->mBufferMap.clear(); + } + + group->mLastUpdateTime = gFrameTimeSeconds; + group->clearState(LLSpatialGroup::GEOM_DIRTY); +} + void LLParticlePartition::addGeometryCount(LLSpatialGroup* group, U32& vertex_count, U32& index_count) { group->mBufferUsage = mBufferUsage; @@ -431,11 +566,6 @@ void LLParticlePartition::addGeometryCount(LLSpatialGroup* group, U32& vertex_co LLAlphaObject* obj = (LLAlphaObject*) drawablep->getVObj().get(); obj->mDepth = 0.f; - if (drawablep->isAnimating()) - { - group->mBufferUsage = GL_STREAM_DRAW_ARB; - } - U32 count = 0; for (S32 j = 0; j < drawablep->getNumFaces(); ++j) { @@ -447,13 +577,14 @@ void LLParticlePartition::addGeometryCount(LLSpatialGroup* group, U32& vertex_co continue; } + vertex_count += facep->getGeomCount(); + index_count += facep->getIndicesCount(); + count++; facep->mDistance = (facep->mCenterLocal - camera->getOrigin()) * camera->getAtAxis(); obj->mDepth += facep->mDistance; mFaceList.push_back(facep); - vertex_count += facep->getGeomCount(); - index_count += facep->getIndicesCount(); llassert(facep->getIndicesCount() < 65536); } @@ -461,15 +592,13 @@ void LLParticlePartition::addGeometryCount(LLSpatialGroup* group, U32& vertex_co } } -static LLFastTimer::DeclareTimer FTM_REBUILD_GRASS_VB("Grass VB"); -static LLFastTimer::DeclareTimer FTM_REBUILD_PARTICLE_VB("Particle VB"); + +static LLFastTimer::DeclareTimer FTM_REBUILD_PARTICLE_GEOM("Particle Geom"); void LLParticlePartition::getGeometry(LLSpatialGroup* group) { LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); - LLFastTimer ftm(mDrawableType == LLPipeline::RENDER_TYPE_GRASS ? - FTM_REBUILD_GRASS_VB : - FTM_REBUILD_PARTICLE_VB); + LLFastTimer ftm(FTM_REBUILD_PARTICLE_GEOM); std::sort(mFaceList.begin(), mFaceList.end(), LLFace::CompareDistanceGreater()); @@ -489,21 +618,44 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group) buffer->getVertexStrider(verticesp); buffer->getNormalStrider(normalsp); buffer->getColorStrider(colorsp); - buffer->getTexCoord0Strider(texcoordsp); - buffer->getIndexStrider(indicesp); - + LLSpatialGroup::drawmap_elem_t& draw_vec = group->mDrawMap[mRenderPass]; for (std::vector<LLFace*>::iterator i = mFaceList.begin(); i != mFaceList.end(); ++i) { LLFace* facep = *i; LLAlphaObject* object = (LLAlphaObject*) facep->getViewerObject(); - facep->setGeomIndex(vertex_count); - facep->setIndicesIndex(index_count); - facep->setVertexBuffer(buffer); - facep->setPoolType(LLDrawPool::POOL_ALPHA); - object->getGeometry(facep->getTEOffset(), verticesp, normalsp, texcoordsp, colorsp, indicesp); + + if (facep->getIndicesStart() == 0xFFFFFFFF) + { //set the indices of this face + S32 idx = LLVOPartGroup::findAvailableVBSlot(); + if (idx >= 0) + { + facep->setGeomIndex(idx*4); + facep->setIndicesIndex(idx*6); + facep->setVertexBuffer(LLVOPartGroup::sVB); + facep->setPoolType(LLDrawPool::POOL_ALPHA); + } + else + { + continue; //out of space in particle buffer + } + } + + S32 geom_idx = (S32) facep->getGeomIndex(); + + LLStrider<U16> cur_idx = indicesp + facep->getIndicesStart(); + LLStrider<LLVector4a> cur_vert = verticesp + geom_idx; + LLStrider<LLVector3> cur_norm = normalsp + geom_idx; + LLStrider<LLVector2> cur_tc = texcoordsp + geom_idx; + LLStrider<LLColor4U> cur_col = colorsp + geom_idx; + + object->getGeometry(facep->getTEOffset(), cur_vert, cur_norm, cur_tc, cur_col, cur_idx); + llassert(facep->getGeomCount() == 4); + llassert(facep->getIndicesCount() == 6); + + vertex_count += facep->getGeomCount(); index_count += facep->getIndicesCount(); @@ -512,18 +664,31 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group) BOOL fullbright = facep->isState(LLFace::FULLBRIGHT); F32 vsize = facep->getVirtualSize(); - if (idx >= 0 && draw_vec[idx]->mEnd == facep->getGeomIndex()-1 && + bool batched = false; + + if (idx >= 0 && draw_vec[idx]->mTexture == facep->getTexture() && - (U16) (draw_vec[idx]->mEnd - draw_vec[idx]->mStart + facep->getGeomCount()) <= (U32) gGLManager.mGLMaxVertexRange && - //draw_vec[idx]->mCount + facep->getIndicesCount() <= (U32) gGLManager.mGLMaxIndexRange && - draw_vec[idx]->mEnd - draw_vec[idx]->mStart + facep->getGeomCount() < 4096 && draw_vec[idx]->mFullbright == fullbright) { - draw_vec[idx]->mCount += facep->getIndicesCount(); - draw_vec[idx]->mEnd += facep->getGeomCount(); - draw_vec[idx]->mVSize = llmax(draw_vec[idx]->mVSize, vsize); + if (draw_vec[idx]->mEnd == facep->getGeomIndex()-1) + { + batched = true; + draw_vec[idx]->mCount += facep->getIndicesCount(); + draw_vec[idx]->mEnd += facep->getGeomCount(); + draw_vec[idx]->mVSize = llmax(draw_vec[idx]->mVSize, vsize); + } + else if (draw_vec[idx]->mStart == facep->getGeomIndex()+facep->getGeomCount()+1) + { + batched = true; + draw_vec[idx]->mCount += facep->getIndicesCount(); + draw_vec[idx]->mStart -= facep->getGeomCount(); + draw_vec[idx]->mOffset = facep->getIndicesStart(); + draw_vec[idx]->mVSize = llmax(draw_vec[idx]->mVSize, vsize); + } } - else + + + if (!batched) { U32 start = facep->getGeomIndex(); U32 end = start + facep->getGeomCount()-1; @@ -541,7 +706,6 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group) } } - buffer->flush(); mFaceList.clear(); } diff --git a/indra/newview/llvopartgroup.h b/indra/newview/llvopartgroup.h index e58fed86d9..6160bceb24 100644 --- a/indra/newview/llvopartgroup.h +++ b/indra/newview/llvopartgroup.h @@ -31,18 +31,32 @@ #include "v3math.h" #include "v3color.h" #include "llframetimer.h" +#include "llviewerpartsim.h" +#include "llvertexbuffer.h" class LLViewerPartGroup; class LLVOPartGroup : public LLAlphaObject { public: + + //vertex buffer for holding all particles + static LLPointer<LLVertexBuffer> sVB; + static S32 sVBSlotFree[LL_MAX_PARTICLE_COUNT]; + static S32* sVBSlotCursor; + + static void restoreGL(); + static void destroyGL(); + static S32 findAvailableVBSlot(); + static void freeVBSlot(S32 idx); + enum { - VERTEX_DATA_MASK = (1 << LLVertexBuffer::TYPE_VERTEX) | - (1 << LLVertexBuffer::TYPE_NORMAL) | - (1 << LLVertexBuffer::TYPE_TEXCOORD0) | - (1 << LLVertexBuffer::TYPE_COLOR) + VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX | + LLVertexBuffer::MAP_NORMAL | + LLVertexBuffer::MAP_TEXCOORD0 | + LLVertexBuffer::MAP_COLOR | + LLVertexBuffer::MAP_TEXTURE_INDEX }; LLVOPartGroup(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp); diff --git a/indra/newview/llvosurfacepatch.cpp b/indra/newview/llvosurfacepatch.cpp index bf6158eeaf..94a3111f4c 100644 --- a/indra/newview/llvosurfacepatch.cpp +++ b/indra/newview/llvosurfacepatch.cpp @@ -296,18 +296,20 @@ void LLVOSurfacePatch::updateFaceSize(S32 idx) } LLFace* facep = mDrawable->getFace(idx); - - S32 num_vertices = 0; - S32 num_indices = 0; - - if (mLastStride) + if (facep) { - getGeomSizesMain(mLastStride, num_vertices, num_indices); - getGeomSizesNorth(mLastStride, mLastNorthStride, num_vertices, num_indices); - getGeomSizesEast(mLastStride, mLastEastStride, num_vertices, num_indices); - } + S32 num_vertices = 0; + S32 num_indices = 0; + + if (mLastStride) + { + getGeomSizesMain(mLastStride, num_vertices, num_indices); + getGeomSizesNorth(mLastStride, mLastNorthStride, num_vertices, num_indices); + getGeomSizesEast(mLastStride, mLastEastStride, num_vertices, num_indices); + } - facep->setSize(num_vertices, num_indices); + facep->setSize(num_vertices, num_indices); + } } BOOL LLVOSurfacePatch::updateLOD() @@ -322,30 +324,32 @@ void LLVOSurfacePatch::getGeometry(LLStrider<LLVector3> &verticesp, LLStrider<U16> &indicesp) { LLFace* facep = mDrawable->getFace(0); + if (facep) + { + U32 index_offset = facep->getGeomIndex(); - U32 index_offset = facep->getGeomIndex(); - - updateMainGeometry(facep, - verticesp, - normalsp, - texCoords0p, - texCoords1p, - indicesp, - index_offset); - updateNorthGeometry(facep, - verticesp, - normalsp, - texCoords0p, - texCoords1p, - indicesp, - index_offset); - updateEastGeometry(facep, + updateMainGeometry(facep, verticesp, normalsp, texCoords0p, texCoords1p, indicesp, index_offset); + updateNorthGeometry(facep, + verticesp, + normalsp, + texCoords0p, + texCoords1p, + indicesp, + index_offset); + updateEastGeometry(facep, + verticesp, + normalsp, + texCoords0p, + texCoords1p, + indicesp, + index_offset); + } } void LLVOSurfacePatch::updateMainGeometry(LLFace *facep, @@ -864,7 +868,11 @@ void LLVOSurfacePatch::dirtyGeom() if (mDrawable) { gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE); - mDrawable->getFace(0)->setVertexBuffer(NULL); + LLFace* facep = mDrawable->getFace(0); + if (facep) + { + facep->setVertexBuffer(NULL); + } mDrawable->movePartition(); } } diff --git a/indra/newview/llvotree.cpp b/indra/newview/llvotree.cpp index 4564207da4..3556bde9a8 100644 --- a/indra/newview/llvotree.cpp +++ b/indra/newview/llvotree.cpp @@ -490,11 +490,16 @@ BOOL LLVOTree::updateGeometry(LLDrawable *drawable) if(mTrunkLOD >= sMAX_NUM_TREE_LOD_LEVELS) //do not display the tree. { mReferenceBuffer = NULL ; - mDrawable->getFace(0)->setVertexBuffer(NULL); + LLFace * facep = drawable->getFace(0); + if (facep) + { + facep->setVertexBuffer(NULL); + } return TRUE ; } - if (mReferenceBuffer.isNull() || !mDrawable->getFace(0)->getVertexBuffer()) + if (mDrawable->getFace(0) && + (mReferenceBuffer.isNull() || !mDrawable->getFace(0)->getVertexBuffer())) { const F32 SRR3 = 0.577350269f; // sqrt(1/3) const F32 SRR2 = 0.707106781f; // sqrt(1/2) @@ -507,6 +512,7 @@ BOOL LLVOTree::updateGeometry(LLDrawable *drawable) S32 lod; LLFace *face = drawable->getFace(0); + if (!face) return TRUE; face->mCenterAgent = getPositionAgent(); face->mCenterLocal = face->mCenterAgent; @@ -879,6 +885,7 @@ void LLVOTree::updateMesh() calcNumVerts(vert_count, index_count, mTrunkLOD, stop_depth, mDepth, mTrunkDepth, mBranches); LLFace* facep = mDrawable->getFace(0); + if (!facep) return; LLVertexBuffer* buff = new LLVertexBuffer(LLDrawPoolTree::VERTEX_DATA_MASK, GL_STATIC_DRAW_ARB); buff->allocateBuffer(vert_count, index_count, TRUE); facep->setVertexBuffer(buff); diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index e7c35d8220..5ea13ee0a6 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -520,6 +520,7 @@ void LLVOVolume::animateTextures() for (S32 i = start; i <= end; i++) { LLFace* facep = mDrawable->getFace(i); + if (!facep) continue; if(facep->getVirtualSize() <= MIN_TEX_ANIM_SIZE && facep->mTextureMatrix) continue; const LLTextureEntry* te = facep->getTextureEntry(); @@ -638,7 +639,7 @@ BOOL LLVOVolume::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) { LLViewerObject::idleUpdate(agent, world, time); - static LLFastTimer::DeclareTimer ftm("Volume"); + static LLFastTimer::DeclareTimer ftm("Volume Idle"); LLFastTimer t(ftm); if (mDead || mDrawable.isNull()) @@ -682,7 +683,21 @@ void LLVOVolume::updateTextures() const F32 TEXTURE_AREA_REFRESH_TIME = 5.f; // seconds if (mTextureUpdateTimer.getElapsedTimeF32() > TEXTURE_AREA_REFRESH_TIME) { - updateTextureVirtualSize(); + updateTextureVirtualSize(); + + if (mDrawable.notNull() && !isVisible() && !mDrawable->isActive()) + { //delete vertex buffer to free up some VRAM + LLSpatialGroup* group = mDrawable->getSpatialGroup(); + if (group) + { + group->destroyGL(true); + + //flag the group as having changed geometry so it gets a rebuild next time + //it becomes visible + group->setState(LLSpatialGroup::GEOM_DIRTY | LLSpatialGroup::MESH_DIRTY | LLSpatialGroup::NEW_DRAWINFO); + } + } + } } @@ -715,7 +730,18 @@ void LLVOVolume::updateTextureVirtualSize(bool forced) if(!forced) { if(!isVisible()) - { + { //don't load textures for non-visible faces + const S32 num_faces = mDrawable->getNumFaces(); + for (S32 i = 0; i < num_faces; i++) + { + LLFace* face = mDrawable->getFace(i); + if (face) + { + face->setPixelArea(0.f); + face->setVirtualSize(0.f); + } + } + return ; } @@ -743,6 +769,7 @@ void LLVOVolume::updateTextureVirtualSize(bool forced) for (S32 i = 0; i < num_faces; i++) { LLFace* face = mDrawable->getFace(i); + if (!face) continue; const LLTextureEntry *te = face->getTextureEntry(); LLViewerTexture *imagep = face->getTexture(); if (!imagep || !te || @@ -1062,9 +1089,33 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms_in, const S32 detail, bo } } + + static LLCachedControl<bool> use_transform_feedback(gSavedSettings, "RenderUseTransformFeedback"); + + bool cache_in_vram = use_transform_feedback && gTransformPositionProgram.mProgramObject && + (!mVolumeImpl || !mVolumeImpl->isVolumeUnique()); + + if (cache_in_vram) + { //this volume might be used as source data for a transform object, put it in vram + LLVolume* volume = getVolume(); + for (S32 i = 0; i < volume->getNumFaces(); ++i) + { + const LLVolumeFace& face = volume->getVolumeFace(i); + if (face.mVertexBuffer.notNull()) + { //already cached + break; + } + volume->genBinormals(i); + LLFace::cacheFaceInVRAM(face); + } + } + + return TRUE; } + + return FALSE; } @@ -1246,7 +1297,8 @@ BOOL LLVOVolume::calcLOD() llround(radius, 0.01f)); - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_LOD_INFO)) + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_LOD_INFO) && + mDrawable->getFace(0)) { //setDebugText(llformat("%.2f:%.2f, %d", debug_distance, radius, cur_detail)); @@ -1325,25 +1377,23 @@ void LLVOVolume::updateFaceFlags() for (S32 i = 0; i < getVolume()->getNumFaces(); i++) { LLFace *face = mDrawable->getFace(i); - if (!face) + if (face) { - return; - } + BOOL fullbright = getTE(i)->getFullbright(); + face->clearState(LLFace::FULLBRIGHT | LLFace::HUD_RENDER | LLFace::LIGHT); - BOOL fullbright = getTE(i)->getFullbright(); - face->clearState(LLFace::FULLBRIGHT | LLFace::HUD_RENDER | LLFace::LIGHT); - - if (fullbright || (mMaterial == LL_MCODE_LIGHT)) - { - face->setState(LLFace::FULLBRIGHT); - } - if (mDrawable->isLight()) - { - face->setState(LLFace::LIGHT); - } - if (isHUDAttachment()) - { - face->setState(LLFace::HUD_RENDER); + if (fullbright || (mMaterial == LL_MCODE_LIGHT)) + { + face->setState(LLFace::FULLBRIGHT); + } + if (mDrawable->isLight()) + { + face->setState(LLFace::LIGHT); + } + if (isHUDAttachment()) + { + face->setState(LLFace::HUD_RENDER); + } } } } @@ -1380,6 +1430,8 @@ void LLVOVolume::regenFaces() for (S32 i = 0; i < mNumFaces; i++) { LLFace* facep = count_changed ? addFace(i) : mDrawable->getFace(i); + if (!facep) continue; + facep->setTEOffset(i); facep->setTexture(getTEImage(i)); facep->setViewerObject(this); @@ -1416,7 +1468,7 @@ BOOL LLVOVolume::genBBoxes(BOOL force_global) BOOL rebuild = mDrawable->isState(LLDrawable::REBUILD_VOLUME | LLDrawable::REBUILD_POSITION | LLDrawable::REBUILD_RIGGED); -// bool rigged = false; + // bool rigged = false; LLVolume* volume = mRiggedVolume; if (!volume) { @@ -1471,11 +1523,11 @@ void LLVOVolume::preRebuild() } } -void LLVOVolume::updateRelativeXform() +void LLVOVolume::updateRelativeXform(bool force_identity) { if (mVolumeImpl) { - mVolumeImpl->updateRelativeXform(); + mVolumeImpl->updateRelativeXform(force_identity); return; } @@ -1495,15 +1547,16 @@ void LLVOVolume::updateRelativeXform() mRelativeXform.invert(); mRelativeXformInvTrans.transpose(); } - else if (drawable->isActive()) + else if (drawable->isActive() || force_identity) { // setup relative transforms LLQuaternion delta_rot; LLVector3 delta_pos, delta_scale; //matrix from local space to parent relative/global space - delta_rot = drawable->isSpatialRoot() ? LLQuaternion() : mDrawable->getRotation(); - delta_pos = drawable->isSpatialRoot() ? LLVector3(0,0,0) : mDrawable->getPosition(); + bool use_identity = force_identity || drawable->isSpatialRoot(); + delta_rot = use_identity ? LLQuaternion() : mDrawable->getRotation(); + delta_pos = use_identity ? LLVector3(0,0,0) : mDrawable->getPosition(); delta_scale = mDrawable->getScale(); // Vertex transform (4x4) @@ -1604,7 +1657,11 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable) return res; } - dirtySpatialGroup(drawable->isState(LLDrawable::IN_REBUILD_Q1)); + LLSpatialGroup* group = drawable->getSpatialGroup(); + if (group) + { + group->dirtyMesh(); + } BOOL compiled = FALSE; @@ -1617,6 +1674,8 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable) if (mVolumeChanged || mFaceMappingChanged ) { + dirtySpatialGroup(drawable->isState(LLDrawable::IN_REBUILD_Q1)); + compiled = TRUE; if (mVolumeChanged) @@ -1635,6 +1694,8 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable) } else if ((mLODChanged) || (mSculptChanged)) { + dirtySpatialGroup(drawable->isState(LLDrawable::IN_REBUILD_Q1)); + LLVolume *old_volumep, *new_volumep; F32 old_lod, new_lod; S32 old_num_faces, new_num_faces ; @@ -1716,16 +1777,19 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable) void LLVOVolume::updateFaceSize(S32 idx) { LLFace* facep = mDrawable->getFace(idx); - if (idx >= getVolume()->getNumVolumeFaces()) - { - facep->setSize(0,0, true); - } - else + if (facep) { - const LLVolumeFace& vol_face = getVolume()->getVolumeFace(idx); - facep->setSize(vol_face.mNumVertices, vol_face.mNumIndices, - true); // <--- volume faces should be padded for 16-byte alignment + if (idx >= getVolume()->getNumVolumeFaces()) + { + facep->setSize(0,0, true); + } + else + { + const LLVolumeFace& vol_face = getVolume()->getVolumeFace(idx); + facep->setSize(vol_face.mNumVertices, vol_face.mNumIndices, + true); // <--- volume faces should be padded for 16-byte alignment + } } } @@ -1815,9 +1879,13 @@ S32 LLVOVolume::setTEColor(const U8 te, const LLColor4& color) } else if (color != tep->getColor()) { - if (color.mV[3] != tep->getColor().mV[3]) + F32 old_alpha = tep->getColor().mV[3]; + if (color.mV[3] != old_alpha) { gPipeline.markTextured(mDrawable); + //treat this alpha change as an LoD update since render batches may need to get rebuilt + mLODChanged = TRUE; + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, FALSE); } retval = LLPrimitive::setTEColor(te, color); if (mDrawable.notNull() && retval) @@ -3098,6 +3166,7 @@ U32 LLVOVolume::getRenderCost(texture_cost_t &textures) const for (S32 i = 0; i < num_faces; ++i) { const LLFace* face = drawablep->getFace(i); + if (!face) continue; const LLTextureEntry* te = face->getTextureEntry(); const LLViewerTexture* img = face->getTexture(); @@ -3369,6 +3438,7 @@ F32 LLVOVolume::getBinRadius() for (S32 i = 0; i < mDrawable->getNumFaces(); i++) { LLFace* face = mDrawable->getFace(i); + if (!face) continue; if (face->getPoolType() == LLDrawPool::POOL_ALPHA && !face->canRenderAsMask()) { @@ -3450,9 +3520,12 @@ LLVector3 LLVOVolume::agentPositionToVolume(const LLVector3& pos) const { LLVector3 ret = pos - getRenderPosition(); ret = ret * ~getRenderRotation(); - LLVector3 objScale = isVolumeGlobal() ? LLVector3(1,1,1) : getScale(); - LLVector3 invObjScale(1.f / objScale.mV[VX], 1.f / objScale.mV[VY], 1.f / objScale.mV[VZ]); - ret.scaleVec(invObjScale); + if (!isVolumeGlobal()) + { + LLVector3 objScale = getScale(); + LLVector3 invObjScale(1.f / objScale.mV[VX], 1.f / objScale.mV[VY], 1.f / objScale.mV[VZ]); + ret.scaleVec(invObjScale); + } return ret; } @@ -3470,8 +3543,12 @@ LLVector3 LLVOVolume::agentDirectionToVolume(const LLVector3& dir) const LLVector3 LLVOVolume::volumePositionToAgent(const LLVector3& dir) const { LLVector3 ret = dir; - LLVector3 objScale = isVolumeGlobal() ? LLVector3(1,1,1) : getScale(); - ret.scaleVec(objScale); + if (!isVolumeGlobal()) + { + LLVector3 objScale = getScale(); + ret.scaleVec(objScale); + } + ret = ret * getRenderRotation(); ret += getRenderPosition(); @@ -3592,7 +3669,8 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& e { LLFace* face = mDrawable->getFace(face_hit); - if (pick_transparent || !face->getTexture() || !face->getTexture()->hasGLTexture() || face->getTexture()->getMask(face->surfaceToTexture(tc, p, n))) + if (face && + (pick_transparent || !face->getTexture() || !face->getTexture()->hasGLTexture() || face->getTexture()->getMask(face->surfaceToTexture(tc, p, n)))) { v_end = p; if (face_hitp != NULL) @@ -3902,8 +3980,11 @@ bool can_batch_texture(LLFace* facep) return true; } +static LLFastTimer::DeclareTimer FTM_REGISTER_FACE("Register Face"); + void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, U32 type) { + LLFastTimer t(FTM_REGISTER_FACE); LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); if (facep->getViewerObject()->isSelected() && LLSelectMgr::getInstance()->mHideSelectedObjects) @@ -3935,9 +4016,14 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, const LLMatrix4* model_mat = NULL; LLDrawable* drawable = facep->getDrawable(); - if (drawable->isActive()) + + if (drawable->isState(LLDrawable::ANIMATED_CHILD)) + { + model_mat = &drawable->getWorldMatrix(); + } + else if (drawable->isActive()) { - model_mat = &(drawable->getRenderMatrix()); + model_mat = &drawable->getRenderMatrix(); } else { @@ -3948,6 +4034,8 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, } } + //drawable->getVObj()->setDebugText(llformat("%d", drawable->isState(LLDrawable::ANIMATED_CHILD))); + U8 bump = (type == LLRenderPass::PASS_BUMP || type == LLRenderPass::PASS_POST_BUMP) ? facep->getTextureEntry()->getBumpmap() : 0; LLViewerTexture* tex = facep->getTexture(); @@ -4041,8 +4129,9 @@ void LLVolumeGeometryManager::getGeometry(LLSpatialGroup* group) } -static LLFastTimer::DeclareTimer FTM_REBUILD_VOLUME_VB("Volume"); -static LLFastTimer::DeclareTimer FTM_REBUILD_VBO("VBO Rebuilt"); +static LLFastTimer::DeclareTimer FTM_REBUILD_VOLUME_VB("Volume VB"); +static LLFastTimer::DeclareTimer FTM_REBUILD_VOLUME_FACE_LIST("Build Face List"); +static LLFastTimer::DeclareTimer FTM_REBUILD_VOLUME_GEN_DRAW_INFO("Gen Draw Info"); static LLDrawPoolAvatar* get_avatar_drawpool(LLViewerObject* vobj) { @@ -4073,6 +4162,8 @@ static LLDrawPoolAvatar* get_avatar_drawpool(LLViewerObject* vobj) void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) { + + if (group->changeLOD()) { group->mLastUpdateDistance = group->mDistance; @@ -4084,19 +4175,15 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) { if (group->isState(LLSpatialGroup::MESH_DIRTY) && !LLPipeline::sDelayVBUpdate) { - LLFastTimer ftm(FTM_REBUILD_VBO); - LLFastTimer ftm2(FTM_REBUILD_VOLUME_VB); - rebuildMesh(group); } return; } - group->mBuilt = 1.f; - LLFastTimer ftm(FTM_REBUILD_VBO); - - LLFastTimer ftm2(FTM_REBUILD_VOLUME_VB); + LLFastTimer ftm(FTM_REBUILD_VOLUME_VB); + group->mBuilt = 1.f; + LLVOAvatar* pAvatarVO = NULL; LLSpatialBridge* bridge = group->mSpatialPartition->asBridge(); @@ -4123,6 +4210,9 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) group->mGeometryBytes = 0; group->mSurfaceArea = 0; + //cache object box size since it might be used for determining visibility + group->mObjectBoxSize = group->mObjectBounds[1].getLength3().getF32(); + group->clearDrawMap(); mFaceList.clear(); @@ -4142,359 +4232,375 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) bool emissive = false; - //get all the faces into a list - for (LLSpatialGroup::element_iter drawable_iter = group->getData().begin(); drawable_iter != group->getData().end(); ++drawable_iter) { - LLDrawable* drawablep = *drawable_iter; - - if (drawablep->isDead() || drawablep->isState(LLDrawable::FORCE_INVISIBLE) ) + LLFastTimer t(FTM_REBUILD_VOLUME_FACE_LIST); + + //get all the faces into a list + for (LLSpatialGroup::element_iter drawable_iter = group->getData().begin(); drawable_iter != group->getData().end(); ++drawable_iter) { - continue; - } + LLDrawable* drawablep = *drawable_iter; + + if (drawablep->isDead() || drawablep->isState(LLDrawable::FORCE_INVISIBLE) ) + { + continue; + } - if (drawablep->isAnimating()) - { //fall back to stream draw for animating verts - useage = GL_STREAM_DRAW_ARB; - } + if (drawablep->isAnimating()) + { //fall back to stream draw for animating verts + useage = GL_STREAM_DRAW_ARB; + } - LLVOVolume* vobj = drawablep->getVOVolume(); + LLVOVolume* vobj = drawablep->getVOVolume(); - if (!vobj) - { - continue; - } + if (!vobj) + { + continue; + } - if (vobj->isMesh() && - (vobj->getVolume() && !vobj->getVolume()->isMeshAssetLoaded() || !gMeshRepo.meshRezEnabled())) - { - continue; - } + if (vobj->isMesh() && + (vobj->getVolume() && !vobj->getVolume()->isMeshAssetLoaded() || !gMeshRepo.meshRezEnabled())) + { + continue; + } - LLVolume* volume = vobj->getVolume(); - if (volume) - { - const LLVector3& scale = vobj->getScale(); - group->mSurfaceArea += volume->getSurfaceArea() * llmax(llmax(scale.mV[0], scale.mV[1]), scale.mV[2]); - } + LLVolume* volume = vobj->getVolume(); + if (volume) + { + const LLVector3& scale = vobj->getScale(); + group->mSurfaceArea += volume->getSurfaceArea() * llmax(llmax(scale.mV[0], scale.mV[1]), scale.mV[2]); + } - llassert_always(vobj); - vobj->updateTextureVirtualSize(true); - vobj->preRebuild(); + llassert_always(vobj); + vobj->updateTextureVirtualSize(true); + vobj->preRebuild(); - drawablep->clearState(LLDrawable::HAS_ALPHA); + drawablep->clearState(LLDrawable::HAS_ALPHA); - bool rigged = vobj->isAttachment() && - vobj->isMesh() && - gMeshRepo.getSkinInfo(vobj->getVolume()->getParams().getSculptID(), vobj); + bool rigged = vobj->isAttachment() && + vobj->isMesh() && + gMeshRepo.getSkinInfo(vobj->getVolume()->getParams().getSculptID(), vobj); - bool bake_sunlight = LLPipeline::sBakeSunlight && drawablep->isStatic(); + bool bake_sunlight = LLPipeline::sBakeSunlight && drawablep->isStatic(); - bool is_rigged = false; + bool is_rigged = false; - //for each face - for (S32 i = 0; i < drawablep->getNumFaces(); i++) - { - LLFace* facep = drawablep->getFace(i); + //for each face + for (S32 i = 0; i < drawablep->getNumFaces(); i++) + { + LLFace* facep = drawablep->getFace(i); + if (!facep) + { + continue; + } - //ALWAYS null out vertex buffer on rebuild -- if the face lands in a render - // batch, it will recover its vertex buffer reference from the spatial group - facep->setVertexBuffer(NULL); + //ALWAYS null out vertex buffer on rebuild -- if the face lands in a render + // batch, it will recover its vertex buffer reference from the spatial group + facep->setVertexBuffer(NULL); - //sum up face verts and indices - drawablep->updateFaceSize(i); + //sum up face verts and indices + drawablep->updateFaceSize(i); - if (rigged) - { - if (!facep->isState(LLFace::RIGGED)) - { //completely reset vertex buffer - facep->clearVertexBuffer(); - } + if (rigged) + { + if (!facep->isState(LLFace::RIGGED)) + { //completely reset vertex buffer + facep->clearVertexBuffer(); + } - facep->setState(LLFace::RIGGED); - is_rigged = true; + facep->setState(LLFace::RIGGED); + is_rigged = true; - //get drawpool of avatar with rigged face - LLDrawPoolAvatar* pool = get_avatar_drawpool(vobj); + //get drawpool of avatar with rigged face + LLDrawPoolAvatar* pool = get_avatar_drawpool(vobj); - //Determine if we've received skininfo that contains an - //alternate bind matrix - if it does then apply the translational component - //to the joints of the avatar. - bool pelvisGotSet = false; + //Determine if we've received skininfo that contains an + //alternate bind matrix - if it does then apply the translational component + //to the joints of the avatar. + bool pelvisGotSet = false; - if ( pAvatarVO ) - { - LLUUID currentId = vobj->getVolume()->getParams().getSculptID(); - const LLMeshSkinInfo* pSkinData = gMeshRepo.getSkinInfo( currentId, vobj ); - - if ( pSkinData ) + if ( pAvatarVO ) { - const int bindCnt = pSkinData->mAlternateBindMatrix.size(); - if ( bindCnt > 0 ) - { - const int jointCnt = pSkinData->mJointNames.size(); - const F32 pelvisZOffset = pSkinData->mPelvisOffset; - bool fullRig = (jointCnt>=20) ? true : false; - if ( fullRig ) - { - for ( int i=0; i<jointCnt; ++i ) + LLUUID currentId = vobj->getVolume()->getParams().getSculptID(); + const LLMeshSkinInfo* pSkinData = gMeshRepo.getSkinInfo( currentId, vobj ); + + if ( pSkinData ) + { + const int bindCnt = pSkinData->mAlternateBindMatrix.size(); + if ( bindCnt > 0 ) + { + const int jointCnt = pSkinData->mJointNames.size(); + const F32 pelvisZOffset = pSkinData->mPelvisOffset; + bool fullRig = (jointCnt>=20) ? true : false; + if ( fullRig ) { - std::string lookingForJoint = pSkinData->mJointNames[i].c_str(); - //llinfos<<"joint name "<<lookingForJoint.c_str()<<llendl; - LLJoint* pJoint = pAvatarVO->getJoint( lookingForJoint ); - if ( pJoint && pJoint->getId() != currentId ) - { - pJoint->setId( currentId ); - const LLVector3& jointPos = pSkinData->mAlternateBindMatrix[i].getTranslation(); - //Set the joint position - pJoint->storeCurrentXform( jointPos ); - //If joint is a pelvis then handle old/new pelvis to foot values - if ( lookingForJoint == "mPelvis" ) - { + for ( int i=0; i<jointCnt; ++i ) + { + std::string lookingForJoint = pSkinData->mJointNames[i].c_str(); + //llinfos<<"joint name "<<lookingForJoint.c_str()<<llendl; + LLJoint* pJoint = pAvatarVO->getJoint( lookingForJoint ); + if ( pJoint && pJoint->getId() != currentId ) + { + pJoint->setId( currentId ); + const LLVector3& jointPos = pSkinData->mAlternateBindMatrix[i].getTranslation(); + //Set the joint position pJoint->storeCurrentXform( jointPos ); - if ( !pAvatarVO->hasPelvisOffset() ) - { - pAvatarVO->setPelvisOffset( true, jointPos, pelvisZOffset ); - //Trigger to rebuild viewer AV - pelvisGotSet = true; + //If joint is a pelvis then handle old/new pelvis to foot values + if ( lookingForJoint == "mPelvis" ) + { + pJoint->storeCurrentXform( jointPos ); + if ( !pAvatarVO->hasPelvisOffset() ) + { + pAvatarVO->setPelvisOffset( true, jointPos, pelvisZOffset ); + //Trigger to rebuild viewer AV + pelvisGotSet = true; + } } - } + } } - } - } + } + } } } - } - //If we've set the pelvis to a new position we need to also rebuild some information that the - //viewer does at launch (e.g. body size etc.) - if ( pelvisGotSet ) - { - pAvatarVO->postPelvisSetRecalc(); - } - - if (pool) - { - const LLTextureEntry* te = facep->getTextureEntry(); - - //remove face from old pool if it exists - LLDrawPool* old_pool = facep->getPool(); - if (old_pool && old_pool->getType() == LLDrawPool::POOL_AVATAR) + //If we've set the pelvis to a new position we need to also rebuild some information that the + //viewer does at launch (e.g. body size etc.) + if ( pelvisGotSet ) { - ((LLDrawPoolAvatar*) old_pool)->removeRiggedFace(facep); + pAvatarVO->postPelvisSetRecalc(); } - //add face to new pool - LLViewerTexture* tex = facep->getTexture(); - U32 type = gPipeline.getPoolTypeFromTE(te, tex); - - if (type == LLDrawPool::POOL_ALPHA) + if (pool) { - if (te->getColor().mV[3] > 0.f) + const LLTextureEntry* te = facep->getTextureEntry(); + + //remove face from old pool if it exists + LLDrawPool* old_pool = facep->getPool(); + if (old_pool && old_pool->getType() == LLDrawPool::POOL_AVATAR) + { + ((LLDrawPoolAvatar*) old_pool)->removeRiggedFace(facep); + } + + //add face to new pool + LLViewerTexture* tex = facep->getTexture(); + U32 type = gPipeline.getPoolTypeFromTE(te, tex); + + if (type == LLDrawPool::POOL_ALPHA) + { + if (te->getColor().mV[3] > 0.f) + { + if (te->getFullbright()) + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT_ALPHA); + } + else + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_ALPHA); + } + } + } + else if (te->getShiny()) { if (te->getFullbright()) { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT_ALPHA); + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT_SHINY); } else { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_ALPHA); + if (LLPipeline::sRenderDeferred) + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SIMPLE); + } + else + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SHINY); + } } } - } - else if (te->getShiny()) - { - if (te->getFullbright()) - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT_SHINY); - } else { - if (LLPipeline::sRenderDeferred) + if (te->getFullbright()) { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SIMPLE); + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT); } else { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SHINY); + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SIMPLE); } } - } - else - { - if (te->getFullbright()) - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT); - } - else + + if (te->getGlow()) { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SIMPLE); + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_GLOW); } - } - if (te->getGlow()) - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_GLOW); - } - - if (LLPipeline::sRenderDeferred) - { - if (type != LLDrawPool::POOL_ALPHA && !te->getFullbright()) + if (LLPipeline::sRenderDeferred) { - if (te->getBumpmap()) - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_DEFERRED_BUMP); - } - else + if (type != LLDrawPool::POOL_ALPHA && !te->getFullbright()) { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_DEFERRED_SIMPLE); + if (te->getBumpmap()) + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_DEFERRED_BUMP); + } + else + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_DEFERRED_SIMPLE); + } } } } - } - continue; - } - else - { - if (facep->isState(LLFace::RIGGED)) - { //face is not rigged but used to be, remove from rigged face pool - LLDrawPoolAvatar* pool = (LLDrawPoolAvatar*) facep->getPool(); - if (pool) - { - pool->removeRiggedFace(facep); + continue; + } + else + { + if (facep->isState(LLFace::RIGGED)) + { //face is not rigged but used to be, remove from rigged face pool + LLDrawPoolAvatar* pool = (LLDrawPoolAvatar*) facep->getPool(); + if (pool) + { + pool->removeRiggedFace(facep); + } + facep->clearState(LLFace::RIGGED); } - facep->clearState(LLFace::RIGGED); } - } - if (cur_total > max_total || facep->getIndicesCount() <= 0 || facep->getGeomCount() <= 0) - { - facep->clearVertexBuffer(); - continue; - } - - cur_total += facep->getGeomCount(); - - if (facep->hasGeometry() && facep->getPixelArea() > FORCE_CULL_AREA) - { - const LLTextureEntry* te = facep->getTextureEntry(); - LLViewerTexture* tex = facep->getTexture(); - - if (te->getGlow() >= 1.f/255.f) + if (cur_total > max_total || facep->getIndicesCount() <= 0 || facep->getGeomCount() <= 0) { - emissive = true; + facep->clearVertexBuffer(); + continue; } - if (facep->isState(LLFace::TEXTURE_ANIM)) - { - if (!vobj->mTexAnimMode) - { - facep->clearState(LLFace::TEXTURE_ANIM); - } - } + cur_total += facep->getGeomCount(); - BOOL force_simple = (facep->getPixelArea() < FORCE_SIMPLE_RENDER_AREA); - U32 type = gPipeline.getPoolTypeFromTE(te, tex); - if (type != LLDrawPool::POOL_ALPHA && force_simple) + if (facep->hasGeometry() && facep->getPixelArea() > FORCE_CULL_AREA) { - type = LLDrawPool::POOL_SIMPLE; - } - facep->setPoolType(type); + const LLTextureEntry* te = facep->getTextureEntry(); + LLViewerTexture* tex = facep->getTexture(); - if (vobj->isHUDAttachment()) - { - facep->setState(LLFace::FULLBRIGHT); - } + if (te->getGlow() >= 1.f/255.f) + { + emissive = true; + } - if (vobj->mTextureAnimp && vobj->mTexAnimMode) - { - if (vobj->mTextureAnimp->mFace <= -1) + if (facep->isState(LLFace::TEXTURE_ANIM)) { - S32 face; - for (face = 0; face < vobj->getNumTEs(); face++) + if (!vobj->mTexAnimMode) { - drawablep->getFace(face)->setState(LLFace::TEXTURE_ANIM); + facep->clearState(LLFace::TEXTURE_ANIM); } } - else if (vobj->mTextureAnimp->mFace < vobj->getNumTEs()) + + BOOL force_simple = (facep->getPixelArea() < FORCE_SIMPLE_RENDER_AREA); + U32 type = gPipeline.getPoolTypeFromTE(te, tex); + if (type != LLDrawPool::POOL_ALPHA && force_simple) { - drawablep->getFace(vobj->mTextureAnimp->mFace)->setState(LLFace::TEXTURE_ANIM); + type = LLDrawPool::POOL_SIMPLE; } - } + facep->setPoolType(type); - if (type == LLDrawPool::POOL_ALPHA) - { - if (facep->canRenderAsMask()) - { //can be treated as alpha mask - simple_faces.push_back(facep); - } - else + if (vobj->isHUDAttachment()) { - if (te->getColor().mV[3] > 0.f) - { //only treat as alpha in the pipeline if < 100% transparent - drawablep->setState(LLDrawable::HAS_ALPHA); - } - alpha_faces.push_back(facep); + facep->setState(LLFace::FULLBRIGHT); } - } - else - { - if (drawablep->isState(LLDrawable::REBUILD_VOLUME)) + + if (vobj->mTextureAnimp && vobj->mTexAnimMode) { - facep->mLastUpdateTime = gFrameTimeSeconds; + if (vobj->mTextureAnimp->mFace <= -1) + { + S32 face; + for (face = 0; face < vobj->getNumTEs(); face++) + { + LLFace * facep = drawablep->getFace(face); + if (facep) + { + facep->setState(LLFace::TEXTURE_ANIM); + } + } + } + else if (vobj->mTextureAnimp->mFace < vobj->getNumTEs()) + { + LLFace * facep = drawablep->getFace(vobj->mTextureAnimp->mFace); + if (facep) + { + facep->setState(LLFace::TEXTURE_ANIM); + } + } } - if (gPipeline.canUseWindLightShadersOnObjects() - && LLPipeline::sRenderBump) + if (type == LLDrawPool::POOL_ALPHA) { - if (te->getBumpmap()) - { //needs normal + binormal - bump_faces.push_back(facep); - } - else if (te->getShiny() || !te->getFullbright()) - { //needs normal + if (facep->canRenderAsMask()) + { //can be treated as alpha mask simple_faces.push_back(facep); } - else - { //doesn't need normal - facep->setState(LLFace::FULLBRIGHT); - fullbright_faces.push_back(facep); + else + { + if (te->getColor().mV[3] > 0.f) + { //only treat as alpha in the pipeline if < 100% transparent + drawablep->setState(LLDrawable::HAS_ALPHA); + } + alpha_faces.push_back(facep); } } else { - if (te->getBumpmap() && LLPipeline::sRenderBump) - { //needs normal + binormal - bump_faces.push_back(facep); + if (drawablep->isState(LLDrawable::REBUILD_VOLUME)) + { + facep->mLastUpdateTime = gFrameTimeSeconds; } - else if ((te->getShiny() && LLPipeline::sRenderBump) || - !(te->getFullbright() || bake_sunlight)) - { //needs normal - simple_faces.push_back(facep); + + if (gPipeline.canUseWindLightShadersOnObjects() + && LLPipeline::sRenderBump) + { + if (te->getBumpmap()) + { //needs normal + binormal + bump_faces.push_back(facep); + } + else if (te->getShiny() || !te->getFullbright()) + { //needs normal + simple_faces.push_back(facep); + } + else + { //doesn't need normal + facep->setState(LLFace::FULLBRIGHT); + fullbright_faces.push_back(facep); + } } - else - { //doesn't need normal - facep->setState(LLFace::FULLBRIGHT); - fullbright_faces.push_back(facep); + else + { + if (te->getBumpmap() && LLPipeline::sRenderBump) + { //needs normal + binormal + bump_faces.push_back(facep); + } + else if ((te->getShiny() && LLPipeline::sRenderBump) || + !(te->getFullbright() || bake_sunlight)) + { //needs normal + simple_faces.push_back(facep); + } + else + { //doesn't need normal + facep->setState(LLFace::FULLBRIGHT); + fullbright_faces.push_back(facep); + } } } } + else + { //face has no renderable geometry + facep->clearVertexBuffer(); + } } - else - { //face has no renderable geometry - facep->clearVertexBuffer(); - } - } - if (is_rigged) - { - drawablep->setState(LLDrawable::RIGGED); - } - else - { - drawablep->clearState(LLDrawable::RIGGED); + if (is_rigged) + { + drawablep->setState(LLDrawable::RIGGED); + } + else + { + drawablep->clearState(LLDrawable::RIGGED); + } } } @@ -4561,15 +4667,15 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) } } -static LLFastTimer::DeclareTimer FTM_VOLUME_GEOM("Volume Geometry"); -static LLFastTimer::DeclareTimer FTM_VOLUME_GEOM_PARTIAL("Terse Rebuild"); void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group) { llassert(group); if (group && group->isState(LLSpatialGroup::MESH_DIRTY) && !group->isState(LLSpatialGroup::GEOM_DIRTY)) { - LLFastTimer tm(FTM_VOLUME_GEOM); + LLFastTimer ftm(FTM_REBUILD_VOLUME_VB); + LLFastTimer t(FTM_REBUILD_VOLUME_GEN_DRAW_INFO); //make sure getgeometryvolume shows up in the right place in timers + S32 num_mapped_veretx_buffer = LLVertexBuffer::sMappedCount ; group->mBuilt = 1.f; @@ -4578,14 +4684,18 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group) for (LLSpatialGroup::element_iter drawable_iter = group->getData().begin(); drawable_iter != group->getData().end(); ++drawable_iter) { - LLFastTimer t(FTM_VOLUME_GEOM_PARTIAL); LLDrawable* drawablep = *drawable_iter; - if (!drawablep->isDead() && drawablep->isState(LLDrawable::REBUILD_ALL) ) + if (!drawablep->isDead() && drawablep->isState(LLDrawable::REBUILD_ALL) && !drawablep->isState(LLDrawable::RIGGED) ) { LLVOVolume* vobj = drawablep->getVOVolume(); vobj->preRebuild(); + if (drawablep->isState(LLDrawable::ANIMATED_CHILD)) + { + vobj->updateRelativeXform(true); + } + LLVolume* volume = vobj->getVolume(); for (S32 i = 0; i < drawablep->getNumFaces(); ++i) { @@ -4595,6 +4705,7 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group) LLVertexBuffer* buff = face->getVertexBuffer(); if (buff) { + llassert(!face->isState(LLFace::RIGGED)); face->getGeometryVolume(*volume, face->getTEOffset(), vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), face->getGeomIndex()); @@ -4605,6 +4716,12 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group) } } } + + if (drawablep->isState(LLDrawable::ANIMATED_CHILD)) + { + vobj->updateRelativeXform(); + } + drawablep->clearState(LLDrawable::REBUILD_ALL); } @@ -4633,10 +4750,13 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group) for (S32 i = 0; i < drawablep->getNumFaces(); ++i) { LLFace* face = drawablep->getFace(i); - LLVertexBuffer* buff = face->getVertexBuffer(); - if (face && buff && buff->isLocked()) + if (face) { - buff->flush(); + LLVertexBuffer* buff = face->getVertexBuffer(); + if (buff && buff->isLocked()) + { + buff->flush(); + } } } } @@ -4645,7 +4765,7 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group) group->clearState(LLSpatialGroup::MESH_DIRTY | LLSpatialGroup::NEW_DRAWINFO); } - llassert(!group || !group->isState(LLSpatialGroup::NEW_DRAWINFO)); +// llassert(!group || !group->isState(LLSpatialGroup::NEW_DRAWINFO)); } struct CompareBatchBreakerModified @@ -4671,8 +4791,20 @@ struct CompareBatchBreakerModified } }; +static LLFastTimer::DeclareTimer FTM_GEN_DRAW_INFO_SORT("Draw Info Face Sort"); +static LLFastTimer::DeclareTimer FTM_GEN_DRAW_INFO_FACE_SIZE("Face Sizing"); +static LLFastTimer::DeclareTimer FTM_GEN_DRAW_INFO_ALLOCATE("Allocate VB"); +static LLFastTimer::DeclareTimer FTM_GEN_DRAW_INFO_FIND_VB("Find VB"); +static LLFastTimer::DeclareTimer FTM_GEN_DRAW_INFO_RESIZE_VB("Resize VB"); + + + + + void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::vector<LLFace*>& faces, BOOL distance_sort, BOOL batch_textures) { + LLFastTimer t(FTM_REBUILD_VOLUME_GEN_DRAW_INFO); + U32 buffer_usage = group->mBufferUsage; #if LL_DARWIN @@ -4690,15 +4822,18 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: U32 max_vertices = (gSavedSettings.getS32("RenderMaxVBOSize")*1024)/LLVertexBuffer::calcVertexSize(group->mSpatialPartition->mVertexDataMask); max_vertices = llmin(max_vertices, (U32) 65535); - if (!distance_sort) - { - //sort faces by things that break batches - std::sort(faces.begin(), faces.end(), CompareBatchBreakerModified()); - } - else { - //sort faces by distance - std::sort(faces.begin(), faces.end(), LLFace::CompareDistanceGreater()); + LLFastTimer t(FTM_GEN_DRAW_INFO_SORT); + if (!distance_sort) + { + //sort faces by things that break batches + std::sort(faces.begin(), faces.end(), CompareBatchBreakerModified()); + } + else + { + //sort faces by distance + std::sort(faces.begin(), faces.end(), LLFace::CompareDistanceGreater()); + } } bool hud_group = group->isHUDGroup() ; @@ -4763,57 +4898,86 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: std::vector<LLViewerTexture*> texture_list; - if (batch_textures) { - U8 cur_tex = 0; - facep->setTextureIndex(cur_tex); - texture_list.push_back(tex); - - //if (can_batch_texture(facep)) + LLFastTimer t(FTM_GEN_DRAW_INFO_FACE_SIZE); + if (batch_textures) { - while (i != faces.end()) + U8 cur_tex = 0; + facep->setTextureIndex(cur_tex); + texture_list.push_back(tex); + + //if (can_batch_texture(facep)) { - facep = *i; - if (facep->getTexture() != tex) + while (i != faces.end()) { - if (distance_sort) - { //textures might be out of order, see if texture exists in current batch - bool found = false; - for (U32 tex_idx = 0; tex_idx < texture_list.size(); ++tex_idx) - { - if (facep->getTexture() == texture_list[tex_idx]) + facep = *i; + if (facep->getTexture() != tex) + { + if (distance_sort) + { //textures might be out of order, see if texture exists in current batch + bool found = false; + for (U32 tex_idx = 0; tex_idx < texture_list.size(); ++tex_idx) { - cur_tex = tex_idx; - found = true; - break; + if (facep->getTexture() == texture_list[tex_idx]) + { + cur_tex = tex_idx; + found = true; + break; + } } - } - if (!found) + if (!found) + { + cur_tex = texture_list.size(); + } + } + else { - cur_tex = texture_list.size(); + cur_tex++; } - } - else - { - cur_tex++; - } - if (!can_batch_texture(facep)) - { //face is bump mapped or has an animated texture matrix -- can't - //batch more than 1 texture at a time - break; + if (!can_batch_texture(facep)) + { //face is bump mapped or has an animated texture matrix -- can't + //batch more than 1 texture at a time + break; + } + + if (cur_tex >= texture_index_channels) + { //cut batches when index channels are depleted + break; + } + + tex = facep->getTexture(); + + texture_list.push_back(tex); } - if (cur_tex >= texture_index_channels) - { //cut batches when index channels are depleted + if (geom_count + facep->getGeomCount() > max_vertices) + { //cut batches on geom count too big break; } - tex = facep->getTexture(); + ++i; + index_count += facep->getIndicesCount(); + geom_count += facep->getGeomCount(); - texture_list.push_back(tex); + facep->setTextureIndex(cur_tex); } + } + + tex = texture_list[0]; + } + else + { + while (i != faces.end() && + (LLPipeline::sTextureBindTest || (distance_sort || (*i)->getTexture() == tex))) + { + facep = *i; + + + //face has no texture index + facep->mDrawInfo = NULL; + facep->setTextureIndex(255); if (geom_count + facep->getGeomCount() > max_vertices) { //cut batches on geom count too big @@ -4823,69 +4987,18 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: ++i; index_count += facep->getIndicesCount(); geom_count += facep->getGeomCount(); - - facep->setTextureIndex(cur_tex); } } - - tex = texture_list[0]; } - else - { - while (i != faces.end() && - (LLPipeline::sTextureBindTest || (distance_sort || (*i)->getTexture() == tex))) - { - facep = *i; - - //face has no texture index - facep->mDrawInfo = NULL; - facep->setTextureIndex(255); - - if (geom_count + facep->getGeomCount() > max_vertices) - { //cut batches on geom count too big - break; - } - - ++i; - index_count += facep->getIndicesCount(); - geom_count += facep->getGeomCount(); - } - } - - //create/delete/resize vertex buffer if needed + //create vertex buffer LLVertexBuffer* buffer = NULL; - { //try to find a buffer to reuse - LLSpatialGroup::buffer_texture_map_t::iterator found_iter = group->mBufferMap[mask].find(*face_iter); - - if (found_iter != group->mBufferMap[mask].end()) - { - if ((U32) buffer_index < found_iter->second.size()) - { - buffer = found_iter->second[buffer_index]; - } - } - } - - if (!buffer || !buffer->isWriteable()) - { //create new buffer if needed + { + LLFastTimer t(FTM_GEN_DRAW_INFO_ALLOCATE); buffer = createVertexBuffer(mask, buffer_usage); buffer->allocateBuffer(geom_count, index_count, TRUE); } - else - { //resize pre-existing buffer - if (LLVertexBuffer::sEnableVBOs && buffer->getUsage() != buffer_usage || - buffer->getTypeMask() != mask) - { - buffer = createVertexBuffer(mask, buffer_usage); - buffer->allocateBuffer(geom_count, index_count, TRUE); - } - else - { - buffer->resizeBuffer(geom_count, index_count); - } - } group->mGeometryBytes += buffer->getSize() + buffer->getIndicesSize(); @@ -4919,10 +5032,22 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: LLVOVolume* vobj = drawablep->getVOVolume(); LLVolume* volume = vobj->getVolume(); + if (drawablep->isState(LLDrawable::ANIMATED_CHILD)) + { + vobj->updateRelativeXform(true); + } + U32 te_idx = facep->getTEOffset(); + llassert(!facep->isState(LLFace::RIGGED)); + facep->getGeometryVolume(*volume, te_idx, - vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), index_offset); + vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), index_offset,true); + + if (drawablep->isState(LLDrawable::ANIMATED_CHILD)) + { + vobj->updateRelativeXform(false); + } } } @@ -5086,6 +5211,7 @@ void LLGeometryManager::addGeometryCount(LLSpatialGroup* group, U32 &vertex_coun mFaceList.clear(); //for each drawable + for (LLSpatialGroup::element_iter drawable_iter = group->getData().begin(); drawable_iter != group->getData().end(); ++drawable_iter) { LLDrawable* drawablep = *drawable_iter; @@ -5106,17 +5232,21 @@ void LLGeometryManager::addGeometryCount(LLSpatialGroup* group, U32 &vertex_coun //sum up face verts and indices drawablep->updateFaceSize(i); LLFace* facep = drawablep->getFace(i); - if (facep->hasGeometry() && facep->getPixelArea() > FORCE_CULL_AREA) + if (facep) { - vertex_count += facep->getGeomCount(); - index_count += facep->getIndicesCount(); - llassert(facep->getIndicesCount() < 65536); - //remember face (for sorting) - mFaceList.push_back(facep); - } - else - { - facep->clearVertexBuffer(); + if (facep->hasGeometry() && facep->getPixelArea() > FORCE_CULL_AREA && + facep->getGeomCount() + vertex_count <= 65536) + { + vertex_count += facep->getGeomCount(); + index_count += facep->getIndicesCount(); + + //remember face (for sorting) + mFaceList.push_back(facep); + } + else + { + facep->clearVertexBuffer(); + } } } } diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index 3cf434dc26..29e782e9dd 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -79,7 +79,7 @@ public: virtual bool isVolumeGlobal() const = 0; // Are we in global space? virtual bool isActive() const = 0; // Is this object currently active? virtual const LLMatrix4& getWorldMatrix(LLXformMatrix* xform) const = 0; - virtual void updateRelativeXform() = 0; + virtual void updateRelativeXform(bool force_identity = false) = 0; virtual U32 getID() const = 0; virtual void preRebuild() = 0; }; @@ -203,7 +203,7 @@ public: LLAssetType::EType type, void* user_data, S32 status, LLExtStat ext_status); - void updateRelativeXform(); + void updateRelativeXform(bool force_identity = false); /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); /*virtual*/ void updateFaceSize(S32 idx); /*virtual*/ BOOL updateLOD(); @@ -340,7 +340,8 @@ public: U8 mTexAnimMode; private: friend class LLDrawable; - + friend class LLFace; + BOOL mFaceMappingChanged; LLFrameTimer mTextureUpdateTimer; S32 mLOD; diff --git a/indra/newview/llvowater.cpp b/indra/newview/llvowater.cpp index cd78157944..942eff6171 100644 --- a/indra/newview/llvowater.cpp +++ b/indra/newview/llvowater.cpp @@ -146,6 +146,10 @@ BOOL LLVOWater::updateGeometry(LLDrawable *drawable) drawable->addFace(poolp, NULL); } face = drawable->getFace(0); + if (!face) + { + return TRUE; + } // LLVector2 uvs[4]; // LLVector3 vtx[4]; diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp index 3d971e738e..b061c90d98 100644 --- a/indra/newview/llworld.cpp +++ b/indra/newview/llworld.cpp @@ -839,7 +839,6 @@ void LLWorld::updateWaterObjects() // Now, get a list of the holes S32 x, y; - F32 water_height = gAgent.getRegion()->getWaterHeight() + 256.f; for (x = min_x; x <= max_x; x += rwidth) { for (y = min_y; y <= max_y; y += rwidth) @@ -851,7 +850,7 @@ void LLWorld::updateWaterObjects() waterp->setUseTexture(FALSE); waterp->setPositionGlobal(LLVector3d(x + rwidth/2, y + rwidth/2, - water_height)); + 256.f+DEFAULT_WATER_HEIGHT)); waterp->setScale(LLVector3((F32)rwidth, (F32)rwidth, 512.f)); gPipeline.createObject(waterp); mHoleWaterObjects.push_back(waterp); @@ -908,7 +907,7 @@ void LLWorld::updateWaterObjects() } waterp->setRegion(gAgent.getRegion()); - LLVector3d water_pos(water_center_x, water_center_y, water_height) ; + LLVector3d water_pos(water_center_x, water_center_y, 256.f+DEFAULT_WATER_HEIGHT) ; LLVector3 water_scale((F32) dim[0], (F32) dim[1], 512.f); //stretch out to horizon diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 72455e4cd8..7c744f3c3f 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -51,6 +51,10 @@ // newview includes #include "llagent.h" #include "llagentcamera.h" +#include "llappviewer.h" +#include "lltexturecache.h" +#include "lltexturefetch.h" +#include "llimageworker.h" #include "lldrawable.h" #include "lldrawpoolalpha.h" #include "lldrawpoolavatar.h" @@ -187,6 +191,7 @@ F32 LLPipeline::RenderShadowFOVCutoff; BOOL LLPipeline::CameraOffset; F32 LLPipeline::CameraMaxCoF; F32 LLPipeline::CameraDoFResScale; +F32 LLPipeline::RenderAutoHideSurfaceAreaLimit; const F32 BACKLIGHT_DAY_MAGNITUDE_AVATAR = 0.2f; const F32 BACKLIGHT_NIGHT_MAGNITUDE_AVATAR = 0.1f; @@ -263,6 +268,7 @@ std::string gPoolNames[] = void drawBox(const LLVector3& c, const LLVector3& r); void drawBoxOutline(const LLVector3& pos, const LLVector3& size); U32 nhpo2(U32 v); +LLVertexBuffer* ll_create_cube_vb(U32 type_mask, U32 usage); glh::matrix4f glh_copy_matrix(F32* src) { @@ -402,9 +408,11 @@ LLPipeline::LLPipeline() : mInitialized(FALSE), mVertexShadersEnabled(FALSE), mVertexShadersLoaded(0), + mTransformFeedbackPrimitives(0), mRenderDebugFeatureMask(0), mRenderDebugMask(0), mOldRenderDebugMask(0), + mMeshDirtyQueryObject(0), mGroupQ1Locked(false), mGroupQ2Locked(false), mResetVertexBuffers(false), @@ -503,6 +511,11 @@ void LLPipeline::init() mSpotLightFade[i] = 1.f; } + if (mCubeVB.isNull()) + { + mCubeVB = ll_create_cube_vb(LLVertexBuffer::MAP_VERTEX, GL_STATIC_DRAW_ARB); + } + mDeferredVB = new LLVertexBuffer(DEFERRED_VB_MASK, 0); mDeferredVB->allocateBuffer(8, 0, true); setLightingDetail(-1); @@ -592,6 +605,7 @@ void LLPipeline::init() gSavedSettings.getControl("CameraOffset")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); gSavedSettings.getControl("CameraMaxCoF")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); gSavedSettings.getControl("CameraDoFResScale")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); + gSavedSettings.getControl("RenderAutoHideSurfaceAreaLimit")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); } LLPipeline::~LLPipeline() @@ -691,6 +705,12 @@ void LLPipeline::destroyGL() { LLVertexBuffer::sEnableVBOs = FALSE; } + + if (mMeshDirtyQueryObject) + { + glDeleteQueriesARB(1, &mMeshDirtyQueryObject); + mMeshDirtyQueryObject = 0; + } } static LLFastTimer::DeclareTimer FTM_RESIZE_SCREEN_TEXTURE("Resize Screen Texture"); @@ -846,9 +866,10 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples) if (shadow_detail > 0) { //allocate 4 sun shadow maps + U32 sun_shadow_map_width = ((U32(resX*scale)+1)&~1); // must be even to avoid a stripe in the horizontal shadow blur for (U32 i = 0; i < 4; i++) { - if (!mShadow[i].allocate(U32(resX*scale),U32(resY*scale), 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE)) return false; + if (!mShadow[i].allocate(sun_shadow_map_width,U32(resY*scale), 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE)) return false; } } else @@ -864,9 +885,10 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples) if (shadow_detail > 1) { //allocate two spot shadow maps + U32 spot_shadow_map_width = width; for (U32 i = 4; i < 6; i++) { - if (!mShadow[i].allocate(width, height, 0, TRUE, FALSE)) return false; + if (!mShadow[i].allocate(spot_shadow_map_width, height, 0, TRUE, FALSE)) return false; } } else @@ -938,6 +960,7 @@ void LLPipeline::refreshCachedSettings() LLPipeline::sUseOcclusion = (!gUseWireframe + && LLGLSLShader::sNoFixedFunction && LLFeatureManager::getInstance()->isFeatureAvailable("UseOcclusion") && gSavedSettings.getBOOL("UseOcclusion") && gGLManager.mHasOcclusionQuery) ? 2 : 0; @@ -1015,6 +1038,7 @@ void LLPipeline::refreshCachedSettings() CameraOffset = gSavedSettings.getBOOL("CameraOffset"); CameraMaxCoF = gSavedSettings.getF32("CameraMaxCoF"); CameraDoFResScale = gSavedSettings.getF32("CameraDoFResScale"); + RenderAutoHideSurfaceAreaLimit = gSavedSettings.getF32("RenderAutoHideSurfaceAreaLimit"); updateRenderDeferred(); } @@ -1025,13 +1049,13 @@ void LLPipeline::releaseGLBuffers() if (mNoiseMap) { - LLImageGL::deleteTextures(1, &mNoiseMap); + LLImageGL::deleteTextures(LLTexUnit::TT_TEXTURE, GL_RGB16F_ARB, 0, 1, &mNoiseMap); mNoiseMap = 0; } if (mTrueNoiseMap) { - LLImageGL::deleteTextures(1, &mTrueNoiseMap); + LLImageGL::deleteTextures(LLTexUnit::TT_TEXTURE, GL_RGB16F_ARB, 0, 1, &mTrueNoiseMap); mTrueNoiseMap = 0; } @@ -1055,7 +1079,7 @@ void LLPipeline::releaseLUTBuffers() { if (mLightFunc) { - LLImageGL::deleteTextures(1, &mLightFunc); + LLImageGL::deleteTextures(LLTexUnit::TT_TEXTURE, GL_R8, 0, 1, &mLightFunc); mLightFunc = 0; } } @@ -1133,10 +1157,10 @@ void LLPipeline::createGLBuffers() noise[i].mV[2] = ll_frand()*scaler+1.f-scaler/2.f; } - LLImageGL::generateTextures(1, &mNoiseMap); + LLImageGL::generateTextures(LLTexUnit::TT_TEXTURE, GL_RGB16F_ARB, 1, &mNoiseMap); gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mNoiseMap); - LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGB16F_ARB, noiseRes, noiseRes, GL_RGB, GL_FLOAT, noise); + LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGB16F_ARB, noiseRes, noiseRes, GL_RGB, GL_FLOAT, noise, false); gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); } @@ -1149,9 +1173,9 @@ void LLPipeline::createGLBuffers() noise[i] = ll_frand()*2.0-1.0; } - LLImageGL::generateTextures(1, &mTrueNoiseMap); + LLImageGL::generateTextures(LLTexUnit::TT_TEXTURE, GL_RGB16F_ARB, 1, &mTrueNoiseMap); gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mTrueNoiseMap); - LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGB16F_ARB, noiseRes, noiseRes, GL_RGB,GL_FLOAT, noise); + LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGB16F_ARB, noiseRes, noiseRes, GL_RGB,GL_FLOAT, noise, false); gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); } @@ -1205,9 +1229,9 @@ void LLPipeline::createLUTBuffers() } } - LLImageGL::generateTextures(1, &mLightFunc); + LLImageGL::generateTextures(LLTexUnit::TT_TEXTURE, GL_R8, 1, &mLightFunc); gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mLightFunc); - LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_R8, lightResX, lightResY, GL_RED, GL_UNSIGNED_BYTE, ls); + LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_R8, lightResX, lightResY, GL_RED, GL_UNSIGNED_BYTE, ls, false); gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_TRILINEAR); @@ -1815,6 +1839,16 @@ void LLPipeline::updateMovedList(LLDrawable::drawable_vector_t& moved_list) if (done) { drawablep->clearState(LLDrawable::ON_MOVE_LIST); + if (drawablep->isState(LLDrawable::ANIMATED_CHILD)) + { //will likely not receive any future world matrix updates + // -- this keeps attachments from getting stuck in space and falling off your avatar + drawablep->clearState(LLDrawable::ANIMATED_CHILD); + markRebuild(drawablep, LLDrawable::REBUILD_VOLUME, TRUE); + if (drawablep->getVObj()) + { + drawablep->getVObj()->dirtySpatialGroup(TRUE); + } + } iter = moved_list.erase(curiter); } } @@ -2209,8 +2243,6 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl gGLLastMatrix = NULL; gGL.loadMatrix(gGLLastModelView); - - LLVertexBuffer::unbind(); LLGLDisable blend(GL_BLEND); LLGLDisable test(GL_ALPHA_TEST); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); @@ -2254,7 +2286,16 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl { //if no shader is currently bound, use the occlusion shader instead of fixed function if we can // (shadow render uses a special shader that clamps to clip planes) bound_shader = true; - gOcclusionProgram.bind(); + gOcclusionCubeProgram.bind(); + } + + if (sUseOcclusion > 1) + { + if (mCubeVB.isNull()) + { //cube VB will be used for issuing occlusion queries + mCubeVB = ll_create_cube_vb(LLVertexBuffer::MAP_VERTEX, GL_STATIC_DRAW_ARB); + } + mCubeVB->setBuffer(LLVertexBuffer::MAP_VERTEX); } for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); @@ -2286,7 +2327,7 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl if (bound_shader) { - gOcclusionProgram.unbind(); + gOcclusionCubeProgram.unbind(); } camera.disableUserClipPlane(); @@ -2419,14 +2460,20 @@ void LLPipeline::doOcclusion(LLCamera& camera) { if (LLPipeline::sShadowRender) { - gDeferredShadowProgram.bind(); + gDeferredShadowCubeProgram.bind(); } else { - gOcclusionProgram.bind(); + gOcclusionCubeProgram.bind(); } } + if (mCubeVB.isNull()) + { //cube VB will be used for issuing occlusion queries + mCubeVB = ll_create_cube_vb(LLVertexBuffer::MAP_VERTEX, GL_STATIC_DRAW_ARB); + } + mCubeVB->setBuffer(LLVertexBuffer::MAP_VERTEX); + for (LLCullResult::sg_list_t::iterator iter = sCull->beginOcclusionGroups(); iter != sCull->endOcclusionGroups(); ++iter) { LLSpatialGroup* group = *iter; @@ -2438,11 +2485,11 @@ void LLPipeline::doOcclusion(LLCamera& camera) { if (LLPipeline::sShadowRender) { - gDeferredShadowProgram.unbind(); + gDeferredShadowCubeProgram.unbind(); } else { - gOcclusionProgram.unbind(); + gOcclusionCubeProgram.unbind(); } } @@ -2461,6 +2508,8 @@ BOOL LLPipeline::updateDrawableGeom(LLDrawable* drawablep, BOOL priority) return update_complete; } +static LLFastTimer::DeclareTimer FTM_SEED_VBO_POOLS("Seed VBO Pool"); + void LLPipeline::updateGL() { while (!LLGLUpdate::sGLQ.empty()) @@ -2470,6 +2519,11 @@ void LLPipeline::updateGL() glu->mInQ = FALSE; LLGLUpdate::sGLQ.pop_front(); } + + { //seed VBO Pools + LLFastTimer t(FTM_SEED_VBO_POOLS); + LLVertexBuffer::seedPools(); + } } void LLPipeline::rebuildPriorityGroups() @@ -2833,6 +2887,11 @@ void LLPipeline::processPartitionQ() mPartitionQ.clear(); } +void LLPipeline::markMeshDirty(LLSpatialGroup* group) +{ + mMeshDirtyGroup.push_back(group); +} + void LLPipeline::markRebuild(LLSpatialGroup* group, BOOL priority) { LLMemType mt(LLMemType::MTYPE_PIPELINE); @@ -3184,7 +3243,11 @@ void renderScriptedBeacons(LLDrawable* drawablep) S32 count = drawablep->getNumFaces(); for (face_id = 0; face_id < count; face_id++) { - gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) ); + LLFace * facep = drawablep->getFace(face_id); + if (facep) + { + gPipeline.mHighlightFaces.push_back(facep); + } } } } @@ -3210,7 +3273,11 @@ void renderScriptedTouchBeacons(LLDrawable* drawablep) S32 count = drawablep->getNumFaces(); for (face_id = 0; face_id < count; face_id++) { - gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) ); + LLFace * facep = drawablep->getFace(face_id); + if (facep) + { + gPipeline.mHighlightFaces.push_back(facep); + } } } } @@ -3235,7 +3302,11 @@ void renderPhysicalBeacons(LLDrawable* drawablep) S32 count = drawablep->getNumFaces(); for (face_id = 0; face_id < count; face_id++) { - gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) ); + LLFace * facep = drawablep->getFace(face_id); + if (facep) + { + gPipeline.mHighlightFaces.push_back(facep); + } } } } @@ -3271,7 +3342,11 @@ void renderMOAPBeacons(LLDrawable* drawablep) S32 count = drawablep->getNumFaces(); for (face_id = 0; face_id < count; face_id++) { - gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) ); + LLFace * facep = drawablep->getFace(face_id); + if (facep) + { + gPipeline.mHighlightFaces.push_back(facep); + } } } } @@ -3296,7 +3371,11 @@ void renderParticleBeacons(LLDrawable* drawablep) S32 count = drawablep->getNumFaces(); for (face_id = 0; face_id < count; face_id++) { - gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) ); + LLFace * facep = drawablep->getFace(face_id); + if (facep) + { + gPipeline.mHighlightFaces.push_back(facep); + } } } } @@ -3314,7 +3393,11 @@ void renderSoundHighlights(LLDrawable* drawablep) S32 count = drawablep->getNumFaces(); for (face_id = 0; face_id < count; face_id++) { - gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) ); + LLFace * facep = drawablep->getFace(face_id); + if (facep) + { + gPipeline.mHighlightFaces.push_back(facep); + } } } } @@ -3345,27 +3428,15 @@ void LLPipeline::postSort(LLCamera& camera) rebuildPriorityGroups(); llpushcallstacks ; - const S32 bin_count = 1024*8; - - static LLCullResult::drawinfo_list_t alpha_bins[bin_count]; - static U32 bin_size[bin_count]; - - //clear one bin per frame to avoid memory bloat - static S32 clear_idx = 0; - clear_idx = (1+clear_idx)%bin_count; - alpha_bins[clear_idx].clear(); - - for (U32 j = 0; j < bin_count; j++) - { - bin_size[j] = 0; - } - + //build render map for (LLCullResult::sg_list_t::iterator i = sCull->beginVisibleGroups(); i != sCull->endVisibleGroups(); ++i) { LLSpatialGroup* group = *i; if (sUseOcclusion && - group->isOcclusionState(LLSpatialGroup::OCCLUDED)) + group->isOcclusionState(LLSpatialGroup::OCCLUDED) || + (RenderAutoHideSurfaceAreaLimit > 0.f && + group->mSurfaceArea > RenderAutoHideSurfaceAreaLimit*llmax(group->mObjectBoxSize, 10.f))) { continue; } @@ -3429,11 +3500,43 @@ void LLPipeline::postSort(LLCamera& camera) } } } + + //flush particle VB + LLVOPartGroup::sVB->flush(); + + /*bool use_transform_feedback = gTransformPositionProgram.mProgramObject && !mMeshDirtyGroup.empty(); + + if (use_transform_feedback) + { //place a query around potential transform feedback code for synchronization + mTransformFeedbackPrimitives = 0; + + if (!mMeshDirtyQueryObject) + { + glGenQueriesARB(1, &mMeshDirtyQueryObject); + } + + glBeginQueryARB(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, mMeshDirtyQueryObject); + }*/ + + //pack vertex buffers for groups that chose to delay their updates + for (LLSpatialGroup::sg_vector_t::iterator iter = mMeshDirtyGroup.begin(); iter != mMeshDirtyGroup.end(); ++iter) + { + (*iter)->rebuildMesh(); + } + + /*if (use_transform_feedback) + { + glEndQueryARB(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN); + }*/ + + mMeshDirtyGroup.clear(); + if (!sShadowRender) { std::sort(sCull->beginAlphaGroups(), sCull->endAlphaGroups(), LLSpatialGroup::CompareDepthGreater()); } + llpushcallstacks ; // only render if the flag is set. The flag is only set if we are in edit mode or the toggle is set in the menus if (LLFloaterReg::instanceVisible("beacons") && !sShadowRender) @@ -3507,7 +3610,11 @@ void LLPipeline::postSort(LLCamera& camera) { if (object->mDrawable) { - gPipeline.mSelectedFaces.push_back(object->mDrawable->getFace(te)); + LLFace * facep = object->mDrawable->getFace(te); + if (facep) + { + gPipeline.mSelectedFaces.push_back(facep); + } } return true; } @@ -3516,6 +3623,33 @@ void LLPipeline::postSort(LLCamera& camera) } } + /*static LLFastTimer::DeclareTimer FTM_TRANSFORM_WAIT("Transform Fence"); + static LLFastTimer::DeclareTimer FTM_TRANSFORM_DO_WORK("Transform Work"); + if (use_transform_feedback) + { //using transform feedback, wait for transform feedback to complete + LLFastTimer t(FTM_TRANSFORM_WAIT); + + S32 done = 0; + //glGetQueryivARB(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, GL_CURRENT_QUERY, &count); + + glGetQueryObjectivARB(mMeshDirtyQueryObject, GL_QUERY_RESULT_AVAILABLE, &done); + + while (!done) + { + { + LLFastTimer t(FTM_TRANSFORM_DO_WORK); + F32 max_time = llmin(gFrameIntervalSeconds*10.f, 1.f); + //do some useful work while we wait + LLAppViewer::getTextureCache()->update(max_time); // unpauses the texture cache thread + LLAppViewer::getImageDecodeThread()->update(max_time); // unpauses the image thread + LLAppViewer::getTextureFetch()->update(max_time); // unpauses the texture fetch thread + } + glGetQueryObjectivARB(mMeshDirtyQueryObject, GL_QUERY_RESULT_AVAILABLE, &done); + } + + mTransformFeedbackPrimitives = 0; + }*/ + //LLSpatialGroup::sNoDelete = FALSE; llpushcallstacks ; } @@ -6207,7 +6341,10 @@ void LLPipeline::resetVertexBuffers(LLDrawable* drawable) for (S32 i = 0; i < drawable->getNumFaces(); i++) { LLFace* facep = drawable->getFace(i); - facep->clearVertexBuffer(); + if (facep) + { + facep->clearVertexBuffer(); + } } } @@ -6225,6 +6362,8 @@ void LLPipeline::doResetVertexBuffers() mResetVertexBuffers = false; + mCubeVB = NULL; + for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); iter != LLWorld::getInstance()->getRegionList().end(); ++iter) { @@ -6243,11 +6382,15 @@ void LLPipeline::doResetVertexBuffers() gSky.resetVertexBuffers(); + LLVOPartGroup::destroyGL(); + LLVertexBuffer::cleanupClass(); //delete all name pool caches LLGLNamePool::cleanupPools(); + + if (LLVertexBuffer::sGLCount > 0) { llwarns << "VBO wipe failed -- " << LLVertexBuffer::sGLCount << " buffers remaining." << llendl; @@ -6267,6 +6410,8 @@ void LLPipeline::doResetVertexBuffers() LLPipeline::sTextureBindTest = gSavedSettings.getBOOL("RenderDebugTextureBind"); LLVertexBuffer::initClass(LLVertexBuffer::sEnableVBOs, LLVertexBuffer::sDisableVBOMapping); + + LLVOPartGroup::restoreGL(); } void LLPipeline::renderObjects(U32 type, U32 mask, BOOL texture, BOOL batch_texture) @@ -7454,12 +7599,17 @@ void LLPipeline::renderDeferredLighting() std::list<LLVector4> light_colors; LLVertexBuffer::unbind(); - LLVector4a* v = (LLVector4a*) vert.get(); { bindDeferredShader(gDeferredLightProgram); - mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX); + + if (mCubeVB.isNull()) + { + mCubeVB = ll_create_cube_vb(LLVertexBuffer::MAP_VERTEX, GL_STATIC_DRAW_ARB); + } + mCubeVB->setBuffer(LLVertexBuffer::MAP_VERTEX); + LLGLDepthTest depth(GL_TRUE, GL_FALSE); for (LLDrawable::drawable_set_t::iterator iter = mLights.begin(); iter != mLights.end(); ++iter) { @@ -7505,25 +7655,7 @@ void LLPipeline::renderDeferredLighting() } sVisibleLightCount++; - - glh::vec3f tc(c); - mat.mult_matrix_vec(tc); - - //vertex positions are encoded so the 3 bits of their vertex index - //correspond to their axis facing, with bit position 3,2,1 matching - //axis facing x,y,z, bit set meaning positive facing, bit clear - //meaning negative facing - mDeferredVB->getVertexStrider(vert); - v[0].set(c[0]-s,c[1]-s,c[2]-s); // 0 - 0000 - v[1].set(c[0]-s,c[1]-s,c[2]+s); // 1 - 0001 - v[2].set(c[0]-s,c[1]+s,c[2]-s); // 2 - 0010 - v[3].set(c[0]-s,c[1]+s,c[2]+s); // 3 - 0011 - - v[4].set(c[0]+s,c[1]-s,c[2]-s); // 4 - 0100 - v[5].set(c[0]+s,c[1]-s,c[2]+s); // 5 - 0101 - v[6].set(c[0]+s,c[1]+s,c[2]-s); // 6 - 0110 - v[7].set(c[0]+s,c[1]+s,c[2]+s); // 7 - 0111 - + if (camera->getOrigin().mV[0] > c[0] + s + 0.2f || camera->getOrigin().mV[0] < c[0] - s - 0.2f || camera->getOrigin().mV[1] > c[1] + s + 0.2f || @@ -7541,16 +7673,13 @@ void LLPipeline::renderDeferredLighting() } LLFastTimer ftm(FTM_LOCAL_LIGHTS); - //glTexCoord4f(tc.v[0], tc.v[1], tc.v[2], s*s); - gDeferredLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, tc.v); + gDeferredLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, c); gDeferredLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s*s); gDeferredLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV); gDeferredLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff()*0.5f); - //gGL.diffuseColor4f(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff()*0.5f); gGL.syncMatrices(); - mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX); - glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8, - GL_UNSIGNED_SHORT, get_box_fan_indices_ptr(camera, center)); + + mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, center)); stop_glerror(); } } @@ -7563,6 +7692,9 @@ void LLPipeline::renderDeferredLighting() continue; } + glh::vec3f tc(c); + mat.mult_matrix_vec(tc); + fullscreen_lights.push_back(LLVector4(tc.v[0], tc.v[1], tc.v[2], s*s)); light_colors.push_back(LLVector4(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff()*0.5f)); } @@ -7575,7 +7707,7 @@ void LLPipeline::renderDeferredLighting() LLGLDepthTest depth(GL_TRUE, GL_FALSE); bindDeferredShader(gDeferredSpotLightProgram); - mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX); + mCubeVB->setBuffer(LLVertexBuffer::MAP_VERTEX); gDeferredSpotLightProgram.enableTexture(LLShaderMgr::DEFERRED_PROJECTION); @@ -7593,36 +7725,17 @@ void LLPipeline::renderDeferredLighting() sVisibleLightCount++; - glh::vec3f tc(c); - mat.mult_matrix_vec(tc); - setupSpotLight(gDeferredSpotLightProgram, drawablep); LLColor3 col = volume->getLightColor(); - //vertex positions are encoded so the 3 bits of their vertex index - //correspond to their axis facing, with bit position 3,2,1 matching - //axis facing x,y,z, bit set meaning positive facing, bit clear - //meaning negative facing - mDeferredVB->getVertexStrider(vert); - v[0].set(c[0]-s,c[1]-s,c[2]-s); // 0 - 0000 - v[1].set(c[0]-s,c[1]-s,c[2]+s); // 1 - 0001 - v[2].set(c[0]-s,c[1]+s,c[2]-s); // 2 - 0010 - v[3].set(c[0]-s,c[1]+s,c[2]+s); // 3 - 0011 - - v[4].set(c[0]+s,c[1]-s,c[2]-s); // 4 - 0100 - v[5].set(c[0]+s,c[1]-s,c[2]+s); // 5 - 0101 - v[6].set(c[0]+s,c[1]+s,c[2]-s); // 6 - 0110 - v[7].set(c[0]+s,c[1]+s,c[2]+s); // 7 - 0111 - - gDeferredSpotLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, tc.v); + gDeferredSpotLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, c); gDeferredSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s*s); gDeferredSpotLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV); gDeferredSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff()*0.5f); gGL.syncMatrices(); - mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX); - glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8, - GL_UNSIGNED_SHORT, get_box_fan_indices_ptr(camera, center)); + + mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, center)); } gDeferredSpotLightProgram.disableTexture(LLShaderMgr::DEFERRED_PROJECTION); unbindDeferredShader(gDeferredSpotLightProgram); @@ -7654,8 +7767,6 @@ void LLPipeline::renderDeferredLighting() LLVector4 light[max_count]; LLVector4 col[max_count]; -// glVertexPointer(2, GL_FLOAT, 0, vert); - F32 far_z = 0.f; while (!fullscreen_lights.empty()) @@ -8288,7 +8399,7 @@ static LLFastTimer::DeclareTimer FTM_SHADOW_RENDER("Render Shadows"); static LLFastTimer::DeclareTimer FTM_SHADOW_ALPHA("Alpha Shadow"); static LLFastTimer::DeclareTimer FTM_SHADOW_SIMPLE("Simple Shadow"); -void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera& shadow_cam, LLCullResult &result, BOOL use_shader, BOOL use_occlusion) +void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera& shadow_cam, LLCullResult &result, BOOL use_shader, BOOL use_occlusion, U32 target_width) { LLFastTimer t(FTM_SHADOW_RENDER); @@ -8312,7 +8423,7 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera if (use_shader) { - gDeferredShadowProgram.bind(); + gDeferredShadowCubeProgram.bind(); } updateCull(shadow_cam, result); @@ -8329,17 +8440,10 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera stop_glerror(); gGLLastMatrix = NULL; - { - //LLGLDepthTest depth(GL_TRUE); - //glClear(GL_DEPTH_BUFFER_BIT); - } - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); stop_glerror(); - //glCullFace(GL_FRONT); - LLVertexBuffer::unbind(); { @@ -8347,6 +8451,10 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera { //occlusion program is general purpose depth-only no-textures gOcclusionProgram.bind(); } + else + { + gDeferredShadowProgram.bind(); + } gGL.diffuseColor4f(1,1,1,1); gGL.setColorMask(false, false); @@ -8379,7 +8487,8 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera LLFastTimer ftm(FTM_SHADOW_ALPHA); gDeferredShadowAlphaMaskProgram.bind(); gDeferredShadowAlphaMaskProgram.setMinimumAlpha(0.598f); - + gDeferredShadowAlphaMaskProgram.uniform1f(LLShaderMgr::DEFERRED_SHADOW_TARGET_WIDTH, (float)target_width); + U32 mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR | @@ -8395,7 +8504,7 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera //glCullFace(GL_BACK); - gDeferredShadowProgram.bind(); + gDeferredShadowCubeProgram.bind(); gGLLastMatrix = NULL; gGL.loadMatrix(gGLModelView); doOcclusion(shadow_cam); @@ -9232,11 +9341,13 @@ void LLPipeline::generateSunShadow(LLCamera& camera) mShadow[j].getViewport(gGLViewport); mShadow[j].clear(); + U32 target_width = mShadow[j].getWidth(); + { static LLCullResult result[4]; //LLGLEnable enable(GL_DEPTH_CLAMP_NV); - renderShadow(view[j], proj[j], shadow_cam, result[j], TRUE); + renderShadow(view[j], proj[j], shadow_cam, result[j], TRUE, TRUE, target_width); } mShadow[j].flush(); @@ -9375,11 +9486,13 @@ void LLPipeline::generateSunShadow(LLCamera& camera) mShadow[i+4].getViewport(gGLViewport); mShadow[i+4].clear(); + U32 target_width = mShadow[i+4].getWidth(); + static LLCullResult result[2]; LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_SHADOW0+i+4; - renderShadow(view[i+4], proj[i+4], shadow_cam, result[i], FALSE, FALSE); + renderShadow(view[i+4], proj[i+4], shadow_cam, result[i], FALSE, FALSE, target_width); mShadow[i+4].flush(); } diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index b8b4f164fe..6ae482fa06 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -163,6 +163,7 @@ public: void markRebuild(LLSpatialGroup* group, BOOL priority = FALSE); void markRebuild(LLDrawable *drawablep, LLDrawable::EDrawableFlags flag = LLDrawable::REBUILD_ALL, BOOL priority = FALSE); void markPartitionMove(LLDrawable* drawablep); + void markMeshDirty(LLSpatialGroup* group); //get the object between start and end that's closest to start. LLViewerObject* lineSegmentIntersectInWorld(const LLVector3& start, const LLVector3& end, @@ -264,7 +265,7 @@ public: void setHighlightObject(LLDrawable* obj) { mHighlightObject = obj; } - void renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera& camera, LLCullResult& result, BOOL use_shader = TRUE, BOOL use_occlusion = TRUE); + void renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera& camera, LLCullResult& result, BOOL use_shader, BOOL use_occlusion, U32 target_width); void renderHighlights(); void renderDebug(); void renderPhysicsDisplay(); @@ -464,6 +465,7 @@ public: RENDER_DEBUG_LOD_INFO = 0x04000000, RENDER_DEBUG_RENDER_COMPLEXITY = 0x08000000, RENDER_DEBUG_ATTACHMENT_BYTES = 0x10000000, + RENDER_DEBUG_TEXEL_DENSITY = 0x20000000 }; public: @@ -543,6 +545,9 @@ public: //utility buffer for rendering post effects, gets abused by renderDeferredLighting LLPointer<LLVertexBuffer> mDeferredVB; + //utility buffer for rendering cubes, 8 vertices are corners of a cube [-1, 1] + LLPointer<LLVertexBuffer> mCubeVB; + //sun shadow map LLRenderTarget mShadow[6]; std::vector<LLVector3> mShadowFrustPoints[4]; @@ -594,6 +599,7 @@ public: BOOL mVertexShadersEnabled; S32 mVertexShadersLoaded; // 0 = no, 1 = yes, -1 = failed + U32 mTransformFeedbackPrimitives; //number of primitives expected to be generated by transform feedback protected: BOOL mRenderTypeEnabled[NUM_RENDER_TYPES]; std::stack<std::string> mRenderTypeEnableStack; @@ -651,6 +657,9 @@ protected: LLSpatialGroup::sg_vector_t mGroupQ1; //priority LLSpatialGroup::sg_vector_t mGroupQ2; // non-priority + LLSpatialGroup::sg_vector_t mMeshDirtyGroup; //groups that need rebuildMesh called + U32 mMeshDirtyQueryObject; + LLDrawable::drawable_list_t mPartitionQ; //drawables that need to update their spatial partition radius bool mGroupQ2Locked; @@ -851,6 +860,7 @@ public: static BOOL CameraOffset; static F32 CameraMaxCoF; static F32 CameraDoFResScale; + static F32 RenderAutoHideSurfaceAreaLimit; }; void render_bbox(const LLVector3 &min, const LLVector3 &max); diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index ce9474d5e5..0404fdae48 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -54,6 +54,8 @@ with the same filename but different name <texture name="Arrow_Down" file_name="widgets/Arrow_Down.png" preload="true" /> <texture name="Arrow_Up" file_name="widgets/Arrow_Up.png" preload="true" /> + <texture name="Arrow_Left" file_name="widgets/Arrow_Left.png" preload="true" /> + <texture name="Arrow_Right" file_name="widgets/Arrow_Right.png" preload="true" /> <texture name="AudioMute_Off" file_name="icons/AudioMute_Off.png" preload="false" /> <texture name="AudioMute_Over" file_name="icons/AudioMute_Over.png" preload="false" /> diff --git a/indra/newview/skins/default/textures/widgets/Arrow_Left.png b/indra/newview/skins/default/textures/widgets/Arrow_Left.png Binary files differnew file mode 100644 index 0000000000..a424282839 --- /dev/null +++ b/indra/newview/skins/default/textures/widgets/Arrow_Left.png diff --git a/indra/newview/skins/default/textures/widgets/Arrow_Right.png b/indra/newview/skins/default/textures/widgets/Arrow_Right.png Binary files differnew file mode 100644 index 0000000000..e32bee8f34 --- /dev/null +++ b/indra/newview/skins/default/textures/widgets/Arrow_Right.png diff --git a/indra/newview/skins/default/xui/da/floater_model_wizard.xml b/indra/newview/skins/default/xui/da/floater_model_wizard.xml deleted file mode 100644 index 8ad443581a..0000000000 --- a/indra/newview/skins/default/xui/da/floater_model_wizard.xml +++ /dev/null @@ -1,241 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Model Wizard" title="UPLOAD MODEL WIZARD"> - <button label="5. Upload" name="upload_btn"/> - <button label="4. Review" name="review_btn"/> - <button label="3. Physics" name="physics2_btn"/> - <button label="3. Physics" name="physics_btn"/> - <button label="2. Optimize" name="optimize_btn"/> - <button label="1. Choose File" name="choose_file_btn"/> - <panel name="choose_file_panel"> - <panel name="header_panel"> - <text name="header_text"> - Upload Model - </text> - </panel> - <text name="description"> - This wizard will help you import mesh models to Second Life. First specify a file containing the model you wish to import. Second Life supports COLLADA (.dae) files. - </text> - <panel name="content"> - <text name="Cache location"> - Filename: - </text> - <button label="Browse..." label_selected="Browse..." name="browse"/> - <text name="dimensions"> - X: Y: Z: - </text> - <text name="dimension_dividers"> - | | - </text> - </panel> - </panel> - <panel name="optimize_panel"> - <panel name="header_panel"> - <text name="header_text"> - Optimize - </text> - </panel> - <text name="description"> - This wizard has optimized your model to improve performance. You may adjust the results of the optimization process bellow or click Next to continue. - </text> - <panel name="content"> - <text name="high_detail_text"> - Generate Level of Detail: High - </text> - <text name="medium_detail_text"> - Generate Level of Detail: Medium - </text> - <text name="low_detail_text"> - Generate Level of Detail: Low - </text> - <text name="lowest_detail_text"> - Generate Level of Detail: Lowest - </text> - </panel> - <panel name="content2"> - <text name="lod_label"> - Model Preview: - </text> - <combo_box name="preview_lod_combo2" tool_tip="LOD to view in preview render"> - <combo_item name="high"> - High - </combo_item> - <combo_item name="medium"> - Medium - </combo_item> - <combo_item name="low"> - Low - </combo_item> - <combo_item name="lowest"> - Lowest - </combo_item> - </combo_box> - <text name="streaming cost"> - Resource Cost: [COST] - </text> - <text name="dimensions"> - X: Y: Z: - </text> - <text name="dimension_dividers"> - | | - </text> - </panel> - </panel> - <panel name="physics_panel"> - <panel name="header_panel"> - <text name="header_text"> - Physics - </text> - </panel> - <text name="description"> - The wizard will create a physical shape, which determines how the object interacts with other objects and avatars. Set the slider to the detail level most appropriate for how your object will be used: - </text> - <panel name="content"> - <text name="streaming cost"> - Resource Cost: [COST] - </text> - </panel> - </panel> - <panel name="physics2_panel"> - <panel name="header_panel"> - <text name="header_text"> - Physics - </text> - </panel> - <text name="description"> - Preview the physics shape below then click Next to continue. To modify the physics shape, click the Back button. - </text> - <panel name="content"> - <text name="lod_label"> - Model Preview: - </text> - <combo_box name="preview_lod_combo3" tool_tip="LOD to view in preview render"> - <combo_item name="high"> - High - </combo_item> - <combo_item name="medium"> - Medium - </combo_item> - <combo_item name="low"> - Low - </combo_item> - <combo_item name="lowest"> - Lowest - </combo_item> - </combo_box> - <text name="dimensions"> - X: Y: Z: - </text> - <text name="dimension_dividers"> - | | - </text> - <text name="streaming cost"> - Resource Cost: [COST] - </text> - </panel> - </panel> - <panel name="review_panel"> - <panel name="header_panel"> - <text name="header_text"> - Review - </text> - </panel> - <text name="description"> - Review the details below then click. Upload to upload your model. Your L$ balance will be charged when you click Upload. - </text> - <panel name="content"> - <text name="lod_label"> - Model Preview: - </text> - <combo_box name="preview_lod_combo" tool_tip="LOD to view in preview render"> - <combo_item name="high"> - High - </combo_item> - <combo_item name="medium"> - Medium - </combo_item> - <combo_item name="low"> - Low - </combo_item> - <combo_item name="lowest"> - Lowest - </combo_item> - </combo_box> - <text name="dimensions"> - X: Y: Z: - </text> - <text name="dimension_dividers"> - | | - </text> - </panel> - <text name="streaming cost"> - Resource Cost: [COST] - </text> - <text name="physics cost"> - Physics Cost: [COST] - </text> - </panel> - <panel name="upload_panel"> - <panel name="header_panel"> - <text name="header_text"> - Upload Complete! - </text> - </panel> - <text name="description"> - Congratulations! Your model has been sucessfully uploaded. You will find the model in the Objects folder in your inventory. - </text> - </panel> - <button label="<< Back" name="back"/> - <button label="Next >>" name="next"/> - <button label="Upload" name="upload" tool_tip="Upload to simulator"/> - <button label="Cancel" name="cancel"/> - <button label="Close" name="close"/> - <spinner name="import_scale" value="1.0"/> - <string name="status_idle"> - Idle - </string> - <string name="status_reading_file"> - Loading... - </string> - <string name="status_generating_meshes"> - Generating Meshes... - </string> - <string name="status_vertex_number_overflow"> - Error: Vertex number is more than 65534, aborted! - </string> - <string name="high"> - High - </string> - <string name="medium"> - Medium - </string> - <string name="low"> - Low - </string> - <string name="lowest"> - Lowest - </string> - <string name="mesh_status_good"> - Ship it! - </string> - <string name="mesh_status_na"> - N/A - </string> - <string name="mesh_status_none"> - None - </string> - <string name="mesh_status_submesh_mismatch"> - Levels of detail have a different number of textureable faces. - </string> - <string name="mesh_status_mesh_mismatch"> - Levels of detail have a different number of mesh instances. - </string> - <string name="mesh_status_too_many_vertices"> - Level of detail has too many vertices. - </string> - <string name="mesh_status_missing_lod"> - Missing required level of detail. - </string> - <string name="layer_all"> - All - </string> -</floater> diff --git a/indra/newview/skins/default/xui/de/floater_model_wizard.xml b/indra/newview/skins/default/xui/de/floater_model_wizard.xml deleted file mode 100644 index ee26d51d32..0000000000 --- a/indra/newview/skins/default/xui/de/floater_model_wizard.xml +++ /dev/null @@ -1,208 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Model Wizard" title="ASSISTENT ZUM HOCHLADEN VON MODELLEN"> - <button label="5. Hochladen" name="upload_btn"/> - <button label="4. Überprüfen" name="review_btn"/> - <button label="3. Physik" name="physics_btn"/> - <button label="2. Optimieren" name="optimize_btn"/> - <button label="1. Datei auswählen" name="choose_file_btn"/> - <panel name="choose_file_panel"> - <panel name="choose_file_header_panel"> - <text name="choose_file_header_text"> - Modelldatei auswählen - </text> - </panel> - <panel name="choose_file_content"> - <text name="advanced_users_text"> - Fortgeschrittene Benutzer: Wenn Sie bereits mit Tools zur Erstellung von 3D-Inhalten vertraut sind, können Sie den erweiterten Uploader verwenden. - </text> - <button label="Auf Erweitert wechseln" name="switch_to_advanced"/> - <text name="Cache location"> - Hochzuladende Modelldatei auswählen - </text> - <button label="Durchsuchen..." label_selected="Durchsuchen..." name="browse"/> - <text name="Model types"> - Second Life unterstützt COLLADA-Dateien (.dae). - </text> - <text name="dimensions"> - X Y Z - </text> - <text name="warning_label"> - ACHTUNG: - </text> - <text name="warning_text"> - Sie können den letzten Schritt nicht abschließen (Modell auf Second Life-Server hochladen). [secondlife:///app/floater/learn_more Weitere Infos], wie Sie Ihr Konto zum Hochladen von Netzmodellen einrichten. - </text> - </panel> - </panel> - <panel name="optimize_panel"> - <panel name="optimize_header_panel"> - <text name="optimize_header_text"> - Modell optimieren - </text> - </panel> - <text name="optimize_description"> - Wir haben das Modell auf Leistung optimiert. Sie können es bei Bedarf weiter anpassen. - </text> - <panel name="optimize_content"> - <text name="high_detail_text"> - Detailstufe generieren: hoch - </text> - <text name="medium_detail_text"> - Detailstufe generieren: mittel - </text> - <text name="low_detail_text"> - Detailstufe generieren: niedrig - </text> - <text name="lowest_detail_text"> - Detailstufe generieren: niedrigste - </text> - </panel> - <panel name="content2"> - <button label="Geometrie neu berechnen" name="recalculate_geometry_btn"/> - <text name="lod_label"> - Geometrievorschau - </text> - <combo_box name="preview_lod_combo" tool_tip="Detailstufe zur Anzeige in Vorschaudarstellung"> - <combo_item name="high"> - Viel Details - </combo_item> - <combo_item name="medium"> - Mittlere Details - </combo_item> - <combo_item name="low"> - Wenig Details - </combo_item> - <combo_item name="lowest"> - Wenigste Details - </combo_item> - </combo_box> - </panel> - </panel> - <panel name="physics_panel"> - <panel name="physics_header_panel"> - <text name="physics_header_text"> - Physik anpassen - </text> - </panel> - <text name="physics_description"> - Wir erstellen eine Form für die Außenhülle des Modells. Passen Sie die Detailstufe der Form wie für den beabsichtigten Zweck erforderlich an. - </text> - <panel name="physics_content"> - <button label="Physik neu berechnen" name="recalculate_physics_btn"/> - <button label="Neu berechnen..." name="recalculating_physics_btn"/> - <text name="lod_label"> - Physikvorschau - </text> - <combo_box name="preview_lod_combo2" tool_tip="Detailstufe zur Anzeige in Vorschaudarstellung"> - <combo_item name="high"> - Viel Details - </combo_item> - <combo_item name="medium"> - Mittlere Details - </combo_item> - <combo_item name="low"> - Wenig Details - </combo_item> - <combo_item name="lowest"> - Wenigste Details - </combo_item> - </combo_box> - </panel> - </panel> - <panel name="review_panel"> - <panel name="review_header_panel"> - <text name="review_header_text"> - Überprüfen - </text> - </panel> - <panel name="review_content"> - <text name="review_prim_equiv"> - Auswirkung auf Parzelle/Region: Prim-Äquivalenzwert [EQUIV] - </text> - <text name="review_fee"> - Die für das Hochladen anfallende Gebühr in Höhe von L$ [FEE] wird von Ihrem Konto abgebucht. - </text> - <text name="review_confirmation"> - Durch Klicken auf „Hochladen“ bestätigen Sie, dass Sie die erforderlichen Rechte für das im Modell enthaltene Material besitzen. - </text> - </panel> - </panel> - <panel name="upload_panel"> - <panel name="upload_header_panel"> - <text name="upload_header_text"> - Upload abgeschlossen - </text> - </panel> - <text name="model_uploaded_text"> - Ihr Modell wurde hochgeladen. - </text> - <text name="inventory_text"> - Sie finden das Modell im Objektordner Ihres Inventars. - </text> - <text name="charged_fee"> - Von Ihrem Konto wurden [FEE] L$ abgebucht. - </text> - </panel> - <button label="<< Zurück" name="back"/> - <button label="Weiter >>" name="next"/> - <button label="Gewichte und Gebühr berechnen >>" name="calculate"/> - <button label="Berechnen..." name="calculating"/> - <button label="Hochladen" name="upload" tool_tip="An Simulator hochladen"/> - <button label="Abbrechen" name="cancel"/> - <button label="Schließen" name="close"/> - <spinner name="import_scale" value="1,0"/> - <string name="status_idle"> - Inaktiv - </string> - <string name="status_parse_error"> - DAE-Parsing-Fehler. Details siehe Protokoll. - </string> - <string name="status_reading_file"> - Laden... - </string> - <string name="status_generating_meshes"> - Netze werden generiert... - </string> - <string name="status_vertex_number_overflow"> - Fehler: Anzahl von Vertices überschreitet 65534. Operation abgebrochen. - </string> - <string name="bad_element"> - Fehler: ungültiges Element. - </string> - <string name="high"> - Hoch - </string> - <string name="medium"> - Mittel - </string> - <string name="low"> - Niedrig - </string> - <string name="lowest"> - Niedrigste - </string> - <string name="mesh_status_good"> - Ausliefern - </string> - <string name="mesh_status_na"> - -- - </string> - <string name="mesh_status_none"> - Keine - </string> - <string name="mesh_status_submesh_mismatch"> - Detailstufen haben unterschiedliche Anzahl texturfähiger Flächen. - </string> - <string name="mesh_status_mesh_mismatch"> - Detailstufen haben unterschiedliche Anzahl von Netzinstanzen. - </string> - <string name="mesh_status_too_many_vertices"> - Detailstufe hat zu viele Vertices. - </string> - <string name="mesh_status_missing_lod"> - Erforderliche Detailstufe fehlt. - </string> - <string name="layer_all"> - Alle - </string> -</floater> diff --git a/indra/newview/skins/default/xui/en/floater_about.xml b/indra/newview/skins/default/xui/en/floater_about.xml index 060d889003..63eb87f27a 100644 --- a/indra/newview/skins/default/xui/en/floater_about.xml +++ b/indra/newview/skins/default/xui/en/floater_about.xml @@ -196,27 +196,26 @@ Dummy Name replaced at run time top="5" width="435" word_wrap="true"> - 3Dconnexion SDK Copyright (C) 1992-2007 3Dconnexion - APR Copyright (C) 2000-2004 The Apache Software Foundation - Collada DOM Copyright 2005 Sony Computer Entertainment Inc. - cURL Copyright (C) 1996-2002, Daniel Stenberg, (daniel@haxx.se) + 3Dconnexion SDK Copyright (C) 1992-2009 3Dconnexion + APR Copyright (C) 2011 The Apache Software Foundation + Collada DOM Copyright 2006 Sony Computer Entertainment Inc. + cURL Copyright (C) 1996-2010, Daniel Stenberg, (daniel@haxx.se) DBus/dbus-glib Copyright (C) 2002, 2003 CodeFactory AB / Copyright (C) 2003, 2004 Red Hat, Inc. expat Copyright (C) 1998, 1999, 2000 Thai Open Source Software Center Ltd. - FreeType Copyright (C) 1996-2002, The FreeType Project (www.freetype.org). + FreeType Copyright (C) 1996-2002, 2006 David Turner, Robert Wilhelm, and Werner Lemberg. GL Copyright (C) 1999-2004 Brian Paul. GLOD Copyright (C) 2003-04 Jonathan Cohen, Nat Duca, Chris Niski, Johns Hopkins University and David Luebke, Brenden Schubert, University of Virginia. google-perftools Copyright (c) 2005, Google Inc. Havok.com(TM) Copyright (C) 1999-2001, Telekinesys Research Limited. jpeg2000 Copyright (C) 2001, David Taubman, The University of New South Wales (UNSW) jpeglib Copyright (C) 1991-1998, Thomas G. Lane. - ogg/vorbis Copyright (C) 2001, Xiphophorus - OpenSSL Copyright (C) 1998-2002 The OpenSSL Project. - PCRE Copyright (c) 1997-2008 University of Cambridge + ogg/vorbis Copyright (C) 2002, Xiphophorus + OpenSSL Copyright (C) 1998-2008 The OpenSSL Project. + PCRE Copyright (c) 1997-2012 University of Cambridge SDL Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga SSLeay Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) xmlrpc-epi Copyright (C) 2000 Epinions, Inc. - zlib Copyright (C) 1995-2002 Jean-loup Gailly and Mark Adler. - google-perftools Copyright (c) 2005, Google Inc. + zlib Copyright (C) 1995-2012 Jean-loup Gailly and Mark Adler. Second Life Viewer uses Havok (TM) Physics. (c)Copyright 1999-2010 Havok.com Inc. (and its Licensors). All Rights Reserved. See www.havok.com for details. diff --git a/indra/newview/skins/default/xui/en/floater_about_land.xml b/indra/newview/skins/default/xui/en/floater_about_land.xml index fb123ec4d1..793a6e6fa1 100644 --- a/indra/newview/skins/default/xui/en/floater_about_land.xml +++ b/indra/newview/skins/default/xui/en/floater_about_land.xml @@ -1354,79 +1354,13 @@ Only large parcels can be listed in search. top="150" width="430" /> <combo_box - enabled="false" - height="23" - layout="topleft" - left="20" - top="194" - name="land category with adult" - visible="false" - width="140"> - <combo_box.item - label="Any Category" - name="item0" - value="any" /> - <combo_box.item - label="Linden Location" - name="item1" - value="linden" /> - <combo_box.item - label="Adult" - name="item2" - value="adult" /> - <combo_box.item - label="Arts & Culture" - name="item3" - value="arts" /> - <combo_box.item - label="Business" - name="item4" - value="store" /> - <combo_box.item - label="Educational" - name="item5" - value="educational" /> - <combo_box.item - label="Gaming" - name="item6" - value="game" /> - <combo_box.item - label="Hangout" - name="item7" - value="gather" /> - <combo_box.item - label="Newcomer Friendly" - name="item8" - value="newcomer" /> - <combo_box.item - label="Parks & Nature" - name="item9" - value="park" /> - <combo_box.item - label="Residential" - name="item10" - value="home" /> - <combo_box.item - label="Shopping" - name="item11" - value="shopping" /> - <combo_box.item - label="Rental" - name="item13" - value="rental" /> - <combo_box.item - label="Other" - name="item12" - value="other" /> - </combo_box> - <combo_box - enabled="false" + enabled="true" height="23" layout="topleft" left="20" top="194" name="land category" - visible="false" + visible="true" width="140"> <combo_box.item label="Any Category" @@ -1989,11 +1923,11 @@ Only large parcels can be listed in search. <check_box follows="top|left" height="16" - label="Have been age-verified [ESTATE_AGE_LIMIT]" + label="Are age 18 or older [ESTATE_AGE_LIMIT]" layout="topleft" left_delta="0" name="limit_age_verified" - tool_tip="Residents must be age verified to access this parcel. See the [SUPPORT_SITE] for more information." + tool_tip="Residents must be age 18 or older to access this parcel. See the [SUPPORT_SITE] for more information." top_pad="4" width="278" /> <check_box diff --git a/indra/newview/skins/default/xui/en/floater_autoreplace.xml b/indra/newview/skins/default/xui/en/floater_autoreplace.xml new file mode 100644 index 0000000000..0bfefc8abe --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_autoreplace.xml @@ -0,0 +1,289 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<floater + border="true" + can_close="true" + can_minimize="true" + can_resize="false" + help_topic="autoreplace_settings" + save_rect="true" + height="455" + width="490" + name="autoreplace_floater" + title="Auto-Replace Settings"> + <check_box + bottom_delta="30" + left_delta="15" + height="16" + width="100" + follows="left|top" + label="Enable Auto-Replace" + name="autoreplace_enable" + tool_tip="As you enter chat text, replace any of the keywords entered with the corresponding replacement"/> + <view_border + top_pad="15" + left="2" + height="0" + width="491" + follows="left|top" + bevel_style="none" + border_thickness="1" + mouse_opaque="false" + name="divisor1"/> + <button + top_pad="10" + left="10" + height="22" + width="110" + enabled="true" + follows="left|top" + mouse_opaque="true" + halign="center" + scale_image="true" + name="autoreplace_import_list" + label="Import List..." + tool_tip="Load a previously exported list from a file."/> + <button + top_delta="0" + left_pad="10" + height="22" + width="110" + enabled="true" + follows="left|top" + mouse_opaque="true" + halign="center" + scale_image="true" + name="autoreplace_export_list" + label="Export List..." + tool_tip="Save the selected list to a file so you can share it."/> + <button + top_delta="0" + left_pad="10" + height="22" + width="110" + enabled="true" + follows="left|top" + mouse_opaque="true" + halign="center" + scale_image="true" + name="autoreplace_new_list" + label="New List..." + tool_tip="Create a new list."/> + <button + top_delta="0" + left_pad="10" + height="22" + width="110" + enabled="true" + follows="left|top" + mouse_opaque="true" + halign="center" + scale_image="true" + name="autoreplace_delete_list" + label="Delete List" + tool_tip="Delete the selected list."/> + <scroll_list + top_pad="10" + left="10" + height="100" + width="370" + follows="left|top" + column_padding="0" + draw_heading="false" + multi_select="false" + name="autoreplace_list_name" + search_column="0"> + </scroll_list> + <button + top_delta="23" + left_pad="10" + height="22" + width="90" + enabled="true" + follows="left|top" + mouse_opaque="true" + halign="center" + scale_image="true" + name="autoreplace_list_up" + image_overlay="Arrow_Up" + tool_tip="Move this list up in priority."/> + <button + top_pad="10" + left_delta="0" + height="22" + width="90" + enabled="true" + follows="left|top" + mouse_opaque="true" + halign="center" + scale_image="true" + name="autoreplace_list_down" + image_overlay="Arrow_Down" + tool_tip="Move this list down in priority."/> + <view_border + top_pad="36" + left="2" + height="0" + width="491" + follows="left|top" + bevel_style="none" + border_thickness="1" + mouse_opaque="false" + name="divisor2"/> + <scroll_list + top_pad="10" + left="10" + height="120" + width="370" + follows="left|top" + column_padding="0" + draw_heading="true" + multi_select="true" + name="autoreplace_list_replacements" + search_column="0"> + <scroll_list.columns + label="Keyword" + name="keyword" + relative_width="0.30" /> + <scroll_list.columns + label="Replacement" + name="replacement" + relative_width="0.70" /> + </scroll_list> + <button + top_delta="41" + left_pad="10" + height="22" + width="90" + enabled="true" + follows="left|top" + mouse_opaque="true" + halign="center" + scale_image="true" + name="autoreplace_add_entry" + label="Add..."/> + <button + top_pad="10" + left_delta="0" + height="22" + width="90" + enabled="true" + follows="left|top" + mouse_opaque="true" + halign="center" + scale_image="true" + name="autoreplace_delete_entry" + label="Remove"/> + <view_border + top_pad="38" + left="2" + height="0" + width="491" + follows="left|top" + bevel_style="none" + border_thickness="1" + mouse_opaque="false" + name="divisor3"/> + <text + type="string" + follows="left|top" + height="16" + layout="topleft" + left="10" + top_pad="13" + width="50"> + Keyword: + </text> + <line_editor + name="autoreplace_keyword" + follows="left|top" + height="23" + layout="topleft" + left="100" + max_length_bytes="255" + top_delta="-5" + width="150" + /> + <text + type="string" + follows="left|top" + height="16" + layout="topleft" + left="10" + right="90" + top_pad="10" + > + Replacement: + </text> + <line_editor + name="autoreplace_replacement" + follows="left|top" + height="23" + layout="topleft" + left="100" + max_length_bytes="255" + top_delta="-5" + width="280" + /> + <button + top_delta="0" + right="-10" + height="22" + width="90" + enabled="false" + follows="left|top" + mouse_opaque="true" + halign="center" + scale_image="true" + name="autoreplace_save_entry" + label="Save Entry" + tool_tip="Save this entry."/> + <view_border + top_pad="10" + left="2" + height="0" + width="491" + follows="left|top" + bevel_style="none" + border_thickness="1" + mouse_opaque="false" + name="divisor4"/> + <button + top_pad="10" + right="380" + height="22" + width="90" + enabled="true" + follows="left|top" + mouse_opaque="true" + halign="center" + scale_image="true" + name="autoreplace_save_changes" + label="Save Changes" + tool_tip="Save all changes."/> + <button + top_delta="0" + right="480" + height="22" + width="90" + enabled="true" + follows="left|top" + mouse_opaque="true" + halign="center" + scale_image="true" + name="autoreplace_cancel" + label="Cancel" + tool_tip="Discard all changes."/> +</floater> +<!-- + <text + top_pad="10" + left="10" + height="16" + width="260" + follows="left|top" + halign="center" + mouse_opaque="true" + name="autoreplace_text2"> + Entries + </text> +--> diff --git a/indra/newview/skins/default/xui/en/floater_hardware_settings.xml b/indra/newview/skins/default/xui/en/floater_hardware_settings.xml index 66bb9d3cea..9deb0d2030 100644 --- a/indra/newview/skins/default/xui/en/floater_hardware_settings.xml +++ b/indra/newview/skins/default/xui/en/floater_hardware_settings.xml @@ -132,6 +132,28 @@ name="vbo" tool_tip="Enabling this on modern hardware gives a performance gain. However, older hardware often has poor implementations of VBOs and you may get crashes when this is enabled." width="315" /> + <text + type="string" + length="1" + follows="left|top" + height="16" + layout="topleft" + left="10" + name="tc label" + top_pad="10" + width="188"> + Enable S3TC: + </text> + <check_box + control_name="RenderCompressTextures" + height="16" + initial_value="true" + label="Enable Texture Compression (requires restart)" + layout="topleft" + left_pad="10" + name="texture compression" + tool_tip="Compresses textures in video memory, allowing for higher resolution textures to be loaded at the cost of some color quality." + width="315" /> <slider control_name="TextureMemory" decimal_digits="0" diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index 95f6708e96..09c1510004 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -148,14 +148,14 @@ follows="all" height="310" ignore_online_status="true" - layout="topleft" + layout="topleft" name="speakers_list" opaque="false" show_info_btn="true" show_profile_btn="false" show_speaking_indicator="false" width="150" /> - </layout_panel> + </layout_panel> <layout_panel default_tab_group="3" left="0" @@ -213,7 +213,7 @@ <layout_panel height="248" width="234" - layout="topleft" + layout="topleft" follows="all" left_delta="0" top_delta="0" @@ -222,33 +222,34 @@ user_resize="true" auto_resize="true" name="chat_holder"> - <chat_history - font="SansSerifSmall" + <chat_history + font="SansSerifSmall" follows="all" visible="true" height="240" - name="chat_history" - parse_highlights="true" - parse_urls="true" - left="1" + name="chat_history" + parse_highlights="true" + parse_urls="true" + left="1" width="229"> - </chat_history> + </chat_history> </layout_panel> </layout_stack> </panel> <chat_editor - bottom="0" + bottom="0" expand_lines_count="5" - follows="left|right|bottom" - font="SansSerifSmall" + follows="left|right|bottom" + font="SansSerifSmall" visible="true" - height="20" + height="20" is_expandable="true" - label="To" - layout="bottomleft" - name="chat_editor" + label="To" + layout="bottomleft" + name="chat_editor" max_length="1023" - tab_group="3" + spellcheck="true" + tab_group="3" width="240" wrap="true"> </chat_editor> diff --git a/indra/newview/skins/default/xui/en/floater_model_preview.xml b/indra/newview/skins/default/xui/en/floater_model_preview.xml index 0e211551e6..5e92a12251 100644 --- a/indra/newview/skins/default/xui/en/floater_model_preview.xml +++ b/indra/newview/skins/default/xui/en/floater_model_preview.xml @@ -1,8 +1,16 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater can_close="true" can_drag_on_left="false" can_minimize="false" - can_resize="false" height="480" min_height="480" min_width="940" - name="Model Preview" title="UPLOAD MODEL" width="940" - help_topic="upload_model" > +<floater + can_close="true" + can_drag_on_left="false" + can_minimize="false" + can_resize="false" + height="480" + min_height="480" + width="980" + min_width="980" + name="Model Preview" + title="UPLOAD MODEL" + help_topic="upload_model" > <string name="status_idle"></string> <string name="status_parse_error">Error: Dae parsing issue - see log for details.</string> @@ -98,7 +106,7 @@ top_pad="15" left="0" height="300" - width="625" + width="635" name="import_tab" tab_position="top"> <!-- LOD PANEL --> @@ -116,13 +124,13 @@ left="3" name="lod_tab_border" top_pad="0" - width="619" /> + width="629" /> <text follows="left|top" height="18" initial_value="Source" layout="topleft" - left="75" + left="85" name="source" text_color="ModelUploaderLabels" top="15" @@ -165,7 +173,7 @@ top_pad="10" valign="top" value="High" - width="65" /> + width="75" /> <combo_box follows="top|left" height="20" @@ -175,10 +183,10 @@ top_delta="-3" width="135"> <item - id="Load from file" + name="Load from file" value="Load from file" /> <item - id="Generate" + name="Generate" value="Generate" /> </combo_box> <line_editor @@ -210,10 +218,10 @@ visible="false" width="135"> <item - id="Triangle Limit" + name="Triangle Limit" value="Triangle Limit" /> <item - id="Error Threshold" + name="Error Threshold" value="Error Threshold" /> </combo_box> <spinner @@ -290,7 +298,7 @@ top_pad="15" valign="top" value="Medium" - width="65" /> + width="75" /> <combo_box follows="top|left" height="20" @@ -300,13 +308,13 @@ top_delta="-3" width="135"> <item - id="Load from file" + name="Load from file" value="Load from file" /> <item - id="Generate" + name="Generate" value="Generate" /> <item - id="Use LoD above" + name="Use LoD above" value="Use LoD above" /> </combo_box> <line_editor @@ -339,10 +347,10 @@ top_delta="0" width="135"> <item - id="Triangle Limit" + name="Triangle Limit" value="Triangle Limit" /> <item - id="Error Threshold" + name="Error Threshold" value="Error Threshold" /> </combo_box> <spinner @@ -418,7 +426,7 @@ top_pad="15" valign="top" value="Low" - width="65" /> + width="75" /> <combo_box follows="top|left" height="20" @@ -428,13 +436,13 @@ top_delta="-3" width="135"> <item - id="Load from file" + name="Load from file" value="Load from file" /> <item - id="Generate" + name="Generate" value="Generate" /> <item - id="Use LoD above" + name="Use LoD above" value="Use LoD above" /> </combo_box> <line_editor @@ -467,10 +475,10 @@ top_delta="0" width="135"> <item - id="Triangle Limit" + name="Triangle Limit" value="Triangle Limit" /> <item - id="Error Threshold" + name="Error Threshold" value="Error Threshold" /> </combo_box> <spinner @@ -546,7 +554,7 @@ top_pad="15" valign="top" value="Lowest" - width="65" /> + width="75" /> <combo_box follows="top|left" height="20" @@ -556,13 +564,13 @@ top_delta="-3" width="135"> <item - id="Load from file" + name="Load from file" value="Load from file" /> <item - id="Generate" + name="Generate" value="Generate" /> <item - id="Use LoD above" + name="Use LoD above" value="Use LoD above" /> </combo_box> <line_editor @@ -595,10 +603,10 @@ top_delta="0" width="135"> <item - id="Triangle Limit" + name="Triangle Limit" value="Triangle Limit" /> <item - id="Error Threshold" + name="Error Threshold" value="Error Threshold" /> </combo_box> <spinner @@ -1201,7 +1209,7 @@ name="calculate_btn" top="3" height="20" - width="150" + width="165" tool_tip="Calculate weights &fee"/> <button follows="top|left" @@ -1234,7 +1242,7 @@ right="-2" top="3" height="20" - width="155"/> + width="275"/> <!-- ========== WEIGHTS ==========--> <text follows="top|left" @@ -1343,7 +1351,7 @@ layout="topleft" name="right_panel" top_pad="5" - width="290"> + width="340"> <combo_box top_pad="3" follows="left|top" diff --git a/indra/newview/skins/default/xui/en/floater_model_wizard.xml b/indra/newview/skins/default/xui/en/floater_model_wizard.xml deleted file mode 100644 index 62b8c5f96e..0000000000 --- a/indra/newview/skins/default/xui/en/floater_model_wizard.xml +++ /dev/null @@ -1,841 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater - legacy_header_height="18" - layout="topleft" - name="Model Wizard" - help_topic="model_wizard" - bg_opaque_image_overlay="0.5 0.5 0.5 1" - height="480" - save_rect="true" - title="UPLOAD MODEL WIZARD" - width="535"> - <button - top="32" - tab_stop="false" - left="410" - height="32" - name="upload_btn" - enabled="false" - label="5. Upload" - border="false" - image_unselected="BreadCrumbBtn_Right_Off" - image_selected="BreadCrumbBtn_Right_Press" - image_hover_unselected="BreadCrumbBtn_Right_Over" - image_disabled="BreadCrumbBtn_Right_Disabled" - image_disabled_selected="BreadCrumbBtn_Right_Disabled" - width="110"> - <button.commit_callback - function="Wizard.Upload"/> - </button> - <button - top="32" - left="310" - height="32" - tab_stop="false" - name="review_btn" - label="4. Review" - enabled="false" - border="false" - image_unselected="BreadCrumbBtn_Middle_Off" - image_selected="BreadCrumbBtn_Middle_Press" - image_hover_unselected="BreadCrumbBtn_Middle_Over" - image_disabled="BreadCrumbBtn_Middle_Disabled" - image_disabled_selected="BreadCrumbBtn_Middle_Disabled" - width="110"> - <button.commit_callback - function="Wizard.Review"/> - </button> - <button - top="32" - left="210" - height="32" - name="physics_btn" - label="3. Physics" - tab_stop="false" - enabled="false" - border="false" - image_unselected="BreadCrumbBtn_Middle_Off" - image_selected="BreadCrumbBtn_Middle_Press" - image_hover_unselected="BreadCrumbBtn_Middle_Over" - image_disabled="BreadCrumbBtn_Middle_Disabled" - image_disabled_selected="BreadCrumbBtn_Middle_Disabled" - width="110"> - <button.commit_callback - function="Wizard.Physics"/> - </button> - <button - top="32" - left="115" - name="optimize_btn" - label="2. Optimize" - tab_stop="false" - height="32" - border="false" - image_unselected="BreadCrumbBtn_Middle_Off" - image_selected="BreadCrumbBtn_Middle_Press" - image_hover_unselected="BreadCrumbBtn_Middle_Over" - image_disabled="BreadCrumbBtn_Middle_Disabled" - image_disabled_selected="BreadCrumbBtn_Middle_Disabled" - width="110"> - <button.commit_callback - function="Wizard.Optimize"/> - </button> - <button - top="32" - left="15" - name="choose_file_btn" - tab_stop="false" - enabled="false" - label="1. Choose File" - height="32" - image_unselected="BreadCrumbBtn_Left_Off" - image_selected="BreadCrumbBtn_Left_Press" - image_hover_unselected="BreadCrumbBtn_Left_Over" - image_disabled="BreadCrumbBtn_Left_Disabled" - image_disabled_selected="BreadCrumbBtn_Left_Disabled" - width="110"> - <button.commit_callback - function="Wizard.Choose"/> - </button> - <panel - height="388" - top_pad="0" - name="choose_file_panel" - visible="false" - width="535" - left="0"> - <panel - height="22" - top_pad="15" - width="505" - name="choose_file_header_panel" - bg_opaque_color="DkGray2" - background_visible="true" - background_opaque="true" - left="15"> - <text - width="200" - left="10" - top="3" - name="choose_file_header_text" - text_color="White" - height="10" - font="SansSerifBig" - layout="topleft"> - Choose model file - </text> - </panel> - <panel - top_pad="14" - left="15" - height="310" - width="505" - name="choose_file_content" - bg_opaque_color="DkGray2" - background_visible="true" - background_opaque="true"> - <text - height="32" - left="10" - name="advanced_users_text" - text_color="White" - top="15" - width="320" - word_wrap="true"> - Advanced users: If you are familiar with 3D content creation tools you may wish to use the Advanced Uploader. - </text> - <button - follows="left|top" - height="20" - label="Switch to Advanced" - layout="topleft" - left_delta="0" - name="switch_to_advanced" - top_pad="5" - width="130"> - </button> - <text - type="string" - length="1" - text_color="White" - follows="left|top" - top_pad="30" - height="10" - layout="topleft" - left_delta="0" - name="Cache location" - width="320"> - Choose model file to upload - </text> - <line_editor - border_style="line" - border_thickness="1" - follows="left|top" - font="SansSerifSmall" - height="20" - layout="topleft" - left_delta="0" - max_length="4096" - name="lod_file" - top_pad="5" - width="230" /> - <button - follows="left|top" - height="23" - label="Browse..." - label_selected="Browse..." - layout="topleft" - left_pad="5" - name="browse" - top_delta="-1" - width="85"> - </button> - <text - type="string" - length="1" - text_color="White" - follows="left|top" - top_pad="5" - height="10" - layout="topleft" - left="10" - name="Model types" - width="320"> - Second Life supports COLLADA (.dae) files - </text> - <!-- Placeholder panel for 3D preview render --> - <panel - top="30" - right="-10" - name="choose_file_preview_panel" - bevel_style="none" - highlight_light_color="0.09 0.09 0.09 1" - border="true" - border_style="line" - height="150" - follows="all" - width="150"> - </panel> - <text - top_pad="10" - width="130" - height="14" - left_delta="0" - text_color="White" - word_wrap="true"> - Dimensions (meters): - </text> - <text - top_pad="0" - width="160" - height="15" - font="SansSerifSmallBold" - text_color="White" - name="dimensions" - left_delta="0"> - X Y Z - </text> - <text - top_delta="0" - width="160" - height="15" - name="dimension_x" - left="356"/> - <text - top_delta="0" - width="160" - height="15" - name="dimension_y" - left="403"/> - <text - top_delta="0" - width="160" - height="15" - name="dimension_z" - left="450"/> - <text - height="16" - left="10" - name="warning_label" - text_color="Yellow" - top="200" - visible="false" - width="320"> - WARNING: - </text> - <text - height="50" - left="10" - name="warning_text" - top_pad="0" - visible="false" - width="320" - word_wrap="true"> - You will not be able to complete the final step of uploading this model to the Second Life servers. [secondlife:///app/floater/learn_more Find out how] to set up your account for mesh model uploads. - </text> - </panel> - </panel> - - - <panel - height="388" - top_delta="0" - name="optimize_panel" - visible="true" - width="535" - left="0"> - <panel - height="22" - top_pad="15" - name="optimize_header_panel" - width="505" - bg_opaque_color="DkGray2" - background_visible="true" - background_opaque="true" - left="15"> - <text - width="200" - left="10" - name="optimize_header_text" - top="3" - text_color="White" - height="10" - font="SansSerifBig" - layout="topleft"> - Optimize model - </text> - </panel> - <text - top_pad="14" - width="460" - height="20" - font="SansSerifSmall" - layout="topleft" - name="optimize_description" - word_wrap="true" - left_delta="5"> - We have optimized the model for performance. Adjust it further if you wish. - </text> - <panel - top_delta="40" - visible="false" - left="15" - height="270" - width="505" - name="optimize_content" - bg_opaque_color="DkGray2" - background_visible="true" - background_opaque="true"> - <text - top="20" - width="300" - height="12" - font="SansSerifBold" - left="112">Generating Level of Detail</text> - <progress_bar - name="optimize_progress_bar" - image_fill="model_wizard\progress_light.png" - color_bg="1 1 1 1" - color_bar="1 1 1 0.96" - follows="left|right|top" - width="260" - height="16" - image_bar="model_wizard\progress_bar_bg.png" - top_pad="14" - left="110"/> - <icon - top_pad="10" - left_delta="0" - width="13" - height="12" - image_name="model_wizard\check_mark.png"/> - <text - top_delta="0" - left_delta="18" - name="high_detail_text" - width="200" - height="14">Generate Level of Detail: High</text> - <icon - top_pad="10" - left_delta="-18" - width="13" - height="12" - image_name="model_wizard\check_mark.png"/> - <text - top_delta="0" - left_delta="18" - name="medium_detail_text" - width="200" - height="14">Generate Level of Detail: Medium</text> - <icon - top_pad="10" - left_delta="-18" - width="13" - height="12" - image_name="model_wizard\check_mark.png"/> - <text - top_delta="0" - left_delta="18" - name="low_detail_text" - width="200" - height="14">Generate Level of Detail: Low</text> - <icon - top_pad="10" - left_delta="-18" - width="13" - height="12" - image_name="model_wizard\check_mark.png"/> - <text - top_delta="0" - left_delta="18" - name="lowest_detail_text" - width="200" - height="14">Generate Level of Detail: Lowest</text> - </panel> - <panel - top_delta="0" - left_delta="0" - height="270" - width="505" - name="content2" - bg_opaque_color="DkGray2" - background_visible="true" - background_opaque="true"> - <text top="69" left="10" text_color="White" font="SansSerifSmallBold" width="120" height="16" wrap="true">Performance</text> - <text top="85" left="10" width="120" word_wrap="true" font="SansSerifSmall" height="40">Faster rendering -Less detail -Lower prim weight</text> - <text top="69" left="184" text_color="White" font="SansSerifSmallBold" width="120" height="16" wrap="true">Accuracy</text> - <text top="85" left="184" width="120" word_wrap="true" font="SansSerifSmall" height="40">Slower rendering -More detail -Higher prim weight</text> - - <slider - follows="left|top" - height="20" - increment="1" - layout="topleft" - left="10" - max_val="2" - initial_value="1" - min_val="0" - name="accuracy_slider" - show_text="false" - top="130" - width="290" /> - <text - font="SansSerifSmall" - top_pad="0" - width="5" - left_delta="6" - height="4">' - </text> - <text - font="SansSerifSmall" - top_delta="0" - width="5" - left_delta="137" - height="4">' - </text> - <text - font="SansSerifSmall" - top_delta="0" - width="5" - left_delta="137" - height="4">' - </text> - <button - follows="left|top" - height="20" - label="Recalculate Geometry" - layout="topleft" - left="80" - name="recalculate_geometry_btn" - top_pad="15" - width="150"> - </button> - <text top="10" right="-10" width="185" text_color="White" follows="left|top" height="15" name="lod_label"> - Geometry preview - </text> - <panel - right="-10" - top="32" - name="optimize_preview_panel" - bevel_style="none" - highlight_light_color="0.09 0.09 0.09 1" - border_style="line" - border="true" - height="185" - follows="all" - width="185"> - </panel> - <combo_box left_delta="75" top_pad="10" follows="left|top" list_position="below" height="22" - name="preview_lod_combo" width="110" tool_tip="LOD to view in preview render"> - <combo_item name="high"> - High detail - </combo_item> - <combo_item name="medium"> - Medium detail - </combo_item> - <combo_item name="low"> - Low detail - </combo_item> - <combo_item name="lowest"> - Lowest detail - </combo_item> - </combo_box> - </panel> - </panel> - - <panel - height="388" - top_delta="0" - name="physics_panel" - visible="false" - width="535" - left="0"> - <panel - height="22" - top_pad="15" - name="physics_header_panel" - width="505" - bg_opaque_color="DkGray2" - background_visible="true" - background_opaque="true" - left="15"> - <text - width="200" - left="10" - name="physics_header_text" - top="3" - height="10" - font="SansSerifBig" - text_color="White" - layout="topleft"> - Adjust physics - </text> - </panel> - <text - top_pad="10" - width="474" - height="50" - font="SansSerifSmall" - layout="topleft" - name="physics_description" - word_wrap="true" - left_delta="5"> - We will create a shape for the outer hull of the model. Adjust the shape's detail level as needed for the intended purpose of your model. - </text> - <panel - top_delta="44" - left="15" - height="270" - width="505" - name="physics_content" - bg_opaque_color="DkGray2" - background_visible="true" - background_opaque="true"> - <text top="10" left="10" text_color="White" font="SansSerifSmallBold" width="120" halign="right" height="16" wrap="true">Performance</text> - <text top="26" left="10" width="120" word_wrap="true" font="SansSerifSmall" halign="right" height="40">Faster rendering -Less detail -Lower prim weight</text> - <text top="174" left="10" text_color="White" font="SansSerifSmallBold" width="120" halign="right" height="16" wrap="true">Accuracy</text> - <text top="190" left="10" width="120" word_wrap="true" font="SansSerifSmall" halign="right" height="40">Slower rendering -More detail -Higher prim weight</text> - - <slider - follows="left|top" - height="190" - increment=".1" - layout="topleft" - left="140" - max_val="1" - initial_value="0.5" - min_val="0" - name="physics_slider" - orientation="vertical" - show_text="false" - top="25" - width="22" /> - <text top="10" width="120" word_wrap="true" left_pad="10" height="50">Examples: -Moving objects -Flying objects -Vehicles</text> - <text top="95" width="120" word_wrap="true" left_delta="0" height="50">Examples: -Small static objects -Less detailed objects -Simple furniture</text> - <text top="180" width="120" word_wrap="true" left_delta="0" height="50">Examples: -Static objects -Detailed objects -Buildings</text> - <button - follows="left|top" - height="20" - label="Recalculate physics" - layout="topleft" - left="80" - name="recalculate_physics_btn" - top_pad="10" - width="150"> - </button> - <button - enabled="false" - follows="left|top" - height="20" - label="Recalculating..." - layout="topleft" - left_delta="0" - name="recalculating_physics_btn" - top_delta="0" - visible="false" - width="150"> - </button> - <text top="10" right="-10" width="185" text_color="White" follows="left|top" height="15" name="lod_label"> - Physics preview - </text> - <panel - right="-10" - top="32" - name="physics_preview_panel" - bevel_style="none" - highlight_light_color="0.09 0.09 0.09 1" - border_style="line" - border="true" - height="185" - follows="all" - width="185"> - </panel> - <combo_box left_delta="75" top_pad="10" follows="left|top" list_position="below" height="22" - name="preview_lod_combo2" width="110" tool_tip="LOD to view in preview render"> - <combo_item name="high"> - High detail - </combo_item> - <combo_item name="medium"> - Medium detail - </combo_item> - <combo_item name="low"> - Low detail - </combo_item> - <combo_item name="lowest"> - Lowest detail - </combo_item> - </combo_box> - </panel> - </panel> - - <panel - height="388" - top_delta="0" - name="review_panel" - visible="false" - width="535" - left="0"> - <panel - height="22" - top_pad="15" - name="review_header_panel" - width="505" - bg_opaque_color="DkGray2" - background_visible="true" - background_opaque="true" - left="15"> - <text - width="200" - left="10" - name="review_header_text" - text_color="White" - top="3" - height="10" - font="SansSerifBig" - layout="topleft"> - Review - </text> - </panel> - <panel - top_pad="14" - left="15" - height="310" - width="505" - name="review_content" - bg_opaque_color="DkGray2" - background_visible="true" - background_opaque="true"> - <text - top="20" - width="485" - font="SansSerifMedium" - text_color="White" - left="10" - name="review_prim_equiv" - height="16">Impact to parcel/region: [EQUIV] prim equivalents - </text> - <text - top_pad="20" - width="485" - font="SansSerifMedium" - text_color="White" - left="10" - name="review_fee" - height="16">Your account will be charged an upload fee of L$ [FEE]. - </text> - <text - top_pad="20" - width="485" - font="SansSerifMedium" - text_color="White" - left="10" - name="review_confirmation" - height="32" - word_wrap="true">By clicking the upload button, you confirm that you have the appropriate rights to the material contained in the model. - </text> - </panel> - </panel> - - - - - <panel - height="388" - top_delta="0" - name="upload_panel" - visible="false" - width="535" - left="0"> - <panel - height="22" - top_pad="15" - name="upload_header_panel" - width="505" - bg_opaque_color="DkGray2" - background_visible="true" - background_opaque="true" - left="15"> - <text - width="200" - left="10" - name="upload_header_text" - top="3" - text_color="White" - height="10" - font="SansSerifBig" - layout="topleft"> - Upload complete - </text> - </panel> - <text - top_pad="14" - width="495" - height="16" - font="SansSerifMedium" - layout="topleft" - name="model_uploaded_text" - text_color="White" - word_wrap="true" - left="25"> - Your model has been uploaded. - </text> - <text - top_pad="5" - width="495" - height="16" - font="SansSerifMedium" - layout="topleft" - name="inventory_text" - text_color="White" - word_wrap="true" - left="25"> - You will find it in the Objects folder in your inventory. - </text> - <text - top_pad="20" - width="495" - font="SansSerifMedium" - text_color="White" - left="25" - name="charged_fee" - height="16">Your account has been charged L$ [FEE]. - </text> - </panel> - - - - <button - top="440" - right="-285" - width="90" - height="22" - name="back" - label="<< Back" /> - <button - top_delta="0" - right="-190" - width="90" - height="22" - name="next" - label="Next >> " /> - <button - top_delta="0" - left_delta="0" - width="160" - height="22" - name="calculate" - label="Calculate weights & fee >> " /> - <button - enabled="false" - visible="false" - top_delta="0" - left_delta="0" - width="160" - height="22" - name="calculating" - label="Calculating... " /> - <button - enabled="false" - top_delta="0" - right="-150" - width="90" - height="22" - visible="false" - name="upload" - tool_tip="Upload to simulator" - label="Upload" /> - <button - top_delta="0" - right="-15" - width="90" - height="22" - name="cancel" - label="Cancel" /> - <button - top_delta="0" - right="-15" - width="90" - height="22" - name="close" - visible="false" - label="Close" /> - <spinner visible="false" left="10" height="20" follows="top|left" width="80" top_pad="-50" value="1.0" min_val="0.01" max_val="64.0" name="import_scale"/> - - <string name="status_idle">Idle</string> - <string name="status_parse_error">Dae parsing issue - see log for details.</string> - <string name="status_reading_file">Loading...</string> - <string name="status_generating_meshes">Generating Meshes...</string> - <string name="status_vertex_number_overflow">Error: Vertex number is more than 65534, aborted!</string> - <string name="bad_element">Error: element is invalid</string> - <string name="high">High</string> - <string name="medium">Medium</string> - <string name="low">Low</string> - <string name="lowest">Lowest</string> - <string name="mesh_status_good">Ship it!</string> - <string name="mesh_status_na">N/A</string> - <string name="mesh_status_none">None</string> - <string name="mesh_status_submesh_mismatch">Levels of detail have a different number of textureable faces.</string> - <string name="mesh_status_mesh_mismatch">Levels of detail have a different number of mesh instances.</string> - <string name="mesh_status_too_many_vertices">Level of detail has too many vertices.</string> - <string name="mesh_status_missing_lod">Missing required level of detail.</string> - <string name="layer_all">All</string> - <!-- Text to display in physics layer combo box for "all layers" --> - -</floater> diff --git a/indra/newview/skins/default/xui/en/floater_my_inventory.xml b/indra/newview/skins/default/xui/en/floater_my_inventory.xml index 184f296255..ea44fd493e 100644 --- a/indra/newview/skins/default/xui/en/floater_my_inventory.xml +++ b/indra/newview/skins/default/xui/en/floater_my_inventory.xml @@ -6,7 +6,7 @@ height="570" help_topic="sidebar_inventory" min_width="333" - min_height="440" + min_height="560" name="floater_my_inventory" save_rect="true" save_visibility="true" diff --git a/indra/newview/skins/default/xui/en/floater_preview_notecard.xml b/indra/newview/skins/default/xui/en/floater_preview_notecard.xml index be3b2d179d..2e1c8ce670 100644 --- a/indra/newview/skins/default/xui/en/floater_preview_notecard.xml +++ b/indra/newview/skins/default/xui/en/floater_preview_notecard.xml @@ -70,6 +70,7 @@ max_length="65536" name="Notecard Editor" parse_urls="false" + spellcheck="true" tab_group="1" top="46" width="392" diff --git a/indra/newview/skins/default/xui/en/floater_report_abuse.xml b/indra/newview/skins/default/xui/en/floater_report_abuse.xml index e6d749a3f0..9561f67941 100644 --- a/indra/newview/skins/default/xui/en/floater_report_abuse.xml +++ b/indra/newview/skins/default/xui/en/floater_report_abuse.xml @@ -155,6 +155,7 @@ name="object_name" top_delta="0" translate="false" + parse_urls="false" use_ellipses="true" width="185"> Consetetur Sadipscing diff --git a/indra/newview/skins/default/xui/en/floater_spellcheck.xml b/indra/newview/skins/default/xui/en/floater_spellcheck.xml new file mode 100644 index 0000000000..76a350dd29 --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_spellcheck.xml @@ -0,0 +1,160 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<floater + border="true" + can_close="true" + can_minimize="true" + save_rect="true" + help_topic="spelling_settings" + can_resize="false" + height="315" + width="490" + name="spellcheck_floater" + title="Spell Checker Settings"> + <check_box + bottom_delta="30" + control_name="SpellCheck" + left_delta="15" + height="16" + width="100" + follows="left|top" + label="Enable spell checker" + name="spellcheck_enable" /> + <view_border + top_pad="10" + left="2" + height="0" + width="491" + follows="left|top" + bevel_style="none" + border_thickness="1" + mouse_opaque="false" + name="divisor1"/> + <text + enabled_control="SpellCheck" + follows="top|left" + height="10" + layout="topleft" + left="38" + mouse_opaque="false" + name="spellcheck_main" + top_pad="15" + type="string" + width="90" + > + Main dictionary : + </text> + <combo_box + enabled_control="SpellCheck" + follows="top|left" + height="23" + layout="topleft" + left_pad="10" + name="spellcheck_main_combo" + top_pad="-15" + width="175" + /> + <text + enabled_control="SpellCheck" + follows="top|left" + height="10" + label="Logs:" + layout="topleft" + left="38" + mouse_opaque="false" + name="spellcheck_additional" + top_pad="15" + type="string" + width="190" + > + Additional dictionaries : + </text> + <text + follows="top|left" + height="12" + layout="topleft" + left="55" + length="1" + name="spellcheck_available" + top_pad="10" + type="string" + width="175"> + Available + </text> + <text + follows="top|left" + height="12" + type="string" + left_pad="45" + length="1" + layout="topleft" + name="spellcheck_active" + width="175"> + Active + </text> + <scroll_list + enabled_control="SpellCheck" + follows="top|left" + height="155" + layout="topleft" + left="55" + multi_select="true" + name="spellcheck_available_list" + sort_column="0" + sort_ascending="true" + width="175" /> + <button + enabled_control="SpellCheck" + follows="top|left" + height="26" + image_overlay="Arrow_Right" + hover_glow_amount="0.15" + layout="topleft" + left_pad="10" + name="spellcheck_moveright_btn" + top_delta="50" + width="25"> + </button> + <button + enabled_control="SpellCheck" + follows="top|left" + height="26" + image_overlay="Arrow_Left" + hover_glow_amount="0.15" + layout="topleft" + name="spellcheck_moveleft_btn" + top_delta="30" + width="25"> + </button> + <scroll_list + enabled_control="SpellCheck" + follows="top|left" + height="155" + layout="topleft" + left_pad="10" + multi_select="true" + name="spellcheck_active_list" + sort_column="0" + sort_ascending="true" + top_pad="-105" + width="175" + /> + <button + enabled="false" + follows="left|top" + height="23" + label="Remove" + layout="topleft" + left="55" + name="spellcheck_remove_btn" + top_pad="5" + width="80" /> + <button + follows="left|top" + height="23" + label="Import..." + layout="topleft" + left_pad="15" + name="spellcheck_import_btn" + top_delta="0" + width="80" /> +</floater> diff --git a/indra/newview/skins/default/xui/en/floater_spellcheck_import.xml b/indra/newview/skins/default/xui/en/floater_spellcheck_import.xml new file mode 100644 index 0000000000..b54090015d --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_spellcheck_import.xml @@ -0,0 +1,116 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<floater + border="true" + can_close="true" + can_minimize="true" + bottom="275" + left="300" + can_resize="false" + height="140" + width="400" + name="spellcheck_import" + title="Import Dictionary"> + <text + follows="top|left" + height="16" + layout="topleft" + left="25" + top="15" + type="string" + width="65"> + Dictionary: + </text> + <line_editor + enabled="false" + follows="left|top" + height="23" + layout="topleft" + left_pad="10" + max_length_bytes="255" + name="dictionary_path" + top_delta="-5" + width="200" /> + <button + follows="left|top" + height="23" + label="Browse" + label_selected="Browse" + layout="topleft" + left_pad="5" + name="dictionary_path_browse" + top_delta="0" + width="75" /> + <text + follows="top|left" + height="16" + layout="topleft" + left="25" + top_pad="8" + type="string" + width="65"> + Name: + </text> + <line_editor + enabled="false" + follows="left|top" + height="23" + layout="topleft" + left_pad="10" + max_length_bytes="255" + name="dictionary_name" + top_delta="-5" + width="200" /> + <text + follows="top|left" + height="16" + layout="topleft" + left="25" + top_pad="8" + type="string" + width="65"> + Language: + </text> + <line_editor + follows="left|top" + height="23" + layout="topleft" + left_pad="10" + max_length_bytes="255" + name="dictionary_language" + top_delta="-5" + width="200" /> + <view_border + top_pad="10" + left="2" + height="0" + width="396" + follows="left|top" + bevel_style="none" + border_thickness="1" + mouse_opaque="false" + name="divisor"/> + <button + top_pad="10" + right="280" + height="22" + width="90" + enabled="true" + follows="left|top" + mouse_opaque="true" + halign="center" + scale_image="true" + name="ok_btn" + label="Import" /> + <button + top_delta="0" + right="380" + height="22" + width="90" + enabled="true" + follows="left|top" + mouse_opaque="true" + halign="center" + scale_image="true" + name="cancel_btn" + label="Cancel" /> +</floater> diff --git a/indra/newview/skins/default/xui/en/floater_stats.xml b/indra/newview/skins/default/xui/en/floater_stats.xml index 2fd932786b..9400f7b94f 100644 --- a/indra/newview/skins/default/xui/en/floater_stats.xml +++ b/indra/newview/skins/default/xui/en/floater_stats.xml @@ -149,13 +149,52 @@ show_per_sec="true" show_bar="false"> </stat_bar> + <stat_bar + name="object_cache_hits" + label="Object Cache Hit Rate" + stat="object_cache_hits" + bar_min="0" + bar_max="100" + unit_label="%" + tick_spacing="20" + label_spacing="20" + show_history="true" + show_per_sec="false" + show_bar="false"> + </stat_bar> </stat_view> <!--Texture Stats--> <stat_view name="texture" label="Texture" show_label="true"> - <stat_bar + <stat_bar + name="texture_cache_hits" + label="Cache Hit Rate" + stat="texture_cache_hits" + bar_min="0.f" + bar_max="100.f" + unit_label="%" + tick_spacing="20" + label_spacing="20" + show_history="true" + show_per_sec="false" + show_bar="false"> + </stat_bar> + <stat_bar + name="texture_cache_read_latency" + label="Cache Read Latency" + unit_label="msec" + stat="texture_cache_read_latency" + bar_min="0.f" + bar_max="1000.f" + tick_spacing="100" + label_spacing="200" + show_history="true" + show_per_sec="false" + show_bar="false"> + </stat_bar> + <stat_bar name="numimagesstat" label="Count" stat="numimagesstat" diff --git a/indra/newview/skins/default/xui/en/floater_texture_ctrl.xml b/indra/newview/skins/default/xui/en/floater_texture_ctrl.xml index ffb8b842f0..6021ba0a5a 100644 --- a/indra/newview/skins/default/xui/en/floater_texture_ctrl.xml +++ b/indra/newview/skins/default/xui/en/floater_texture_ctrl.xml @@ -134,6 +134,16 @@ top_delta="-25" name="Pipette" width="28" /> + <text + follows="left|bottom" + height="20" + layout="topleft" + left="8" + name="preview_disabled" + top="266" + value="Preview Disabled" + visible="false" + width="120" /> <filter_editor follows="left|top|right" height="23" diff --git a/indra/newview/skins/default/xui/en/floater_texture_fetch_debugger.xml b/indra/newview/skins/default/xui/en/floater_texture_fetch_debugger.xml new file mode 100644 index 0000000000..f3f8d4ddca --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_texture_fetch_debugger.xml @@ -0,0 +1,341 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<floater + legacy_header_height="18" + can_minimize="false" + height="550" + layout="topleft" + name="TexFetchDebugger" + help_topic="texfetchdebugger" + title="Texture Fetching Debugger" + width="540"> + <text + type="string" + length="1" + follows="left|top" + height="25" + layout="topleft" + left="10" + name="total_num_fetched_label" + top="30" + width="400"> + 1, Total number of fetched textures: [NUM] + </text> + <text + type="string" + length="1" + follows="left|top" + height="25" + layout="topleft" + left_delta="0" + name="total_num_fetching_requests_label" + top_delta="25" + width="400"> + 2, Total number of fetching requests: [NUM] + </text> + <text + type="string" + length="1" + follows="left|top" + height="25" + layout="topleft" + left_delta="0" + name="total_num_cache_hits_label" + top_delta="25" + width="400"> + 3, Total number of cache hits: [NUM] + </text> + <text + type="string" + length="1" + follows="left|top" + height="25" + layout="topleft" + left_delta="0" + name="total_num_visible_tex_label" + top_delta="25" + width="400"> + 4, Total number of visible textures: [NUM] + </text> + <text + type="string" + length="1" + follows="left|top" + height="25" + layout="topleft" + left_delta="0" + name="total_num_visible_tex_fetch_req_label" + top_delta="25" + width="450"> + 5, Total number of visible texture fetching requests: [NUM] + </text> + <text + type="string" + length="1" + follows="left|top" + height="25" + layout="topleft" + left_delta="0" + name="total_fetched_data_label" + top_delta="25" + width="530"> + 6, Total number of fetched data: [SIZE1]KB, Decoded Data: [SIZE2]KB, [PIXEL]MPixels + </text> + <text + type="string" + length="1" + follows="left|top" + height="25" + layout="topleft" + left_delta="0" + name="total_fetched_vis_data_label" + top_delta="25" + width="480"> + 7, Total number of visible data: [SIZE1]KB, Decoded Data: [SIZE2]KB + </text> + <text + type="string" + length="1" + follows="left|top" + height="25" + layout="topleft" + left_delta="0" + name="total_fetched_rendered_data_label" + top_delta="25" + width="530"> + 8, Total number of rendered data: [SIZE1]KB, Decoded Data: [SIZE2]KB, [PIXEL]MPixels + </text> + <text + type="string" + length="1" + follows="left|top" + height="25" + layout="topleft" + left_delta="0" + name="total_time_cache_read_label" + top_delta="25" + width="400"> + 9, Total time on cache readings: [TIME] seconds + </text> + <text + type="string" + length="1" + follows="left|top" + height="25" + layout="topleft" + left_delta="0" + name="total_time_cache_write_label" + top_delta="25" + width="400"> + 10, Total time on cache writings: [TIME] seconds + </text> + <text + type="string" + length="1" + follows="left|top" + height="25" + layout="topleft" + left_delta="0" + name="total_time_decode_label" + top_delta="25" + width="400"> + 11, Total time on decodings: [TIME] seconds + </text> + <text + type="string" + length="1" + follows="left|top" + height="25" + layout="topleft" + left_delta="0" + name="total_time_gl_label" + top_delta="25" + width="400"> + 12, Total time on gl texture creation: [TIME] seconds + </text> + <text + type="string" + length="1" + follows="left|top" + height="25" + layout="topleft" + left_delta="0" + name="total_time_http_label" + top_delta="25" + width="400"> + 13, Total time on HTTP fetching: [TIME] seconds + </text> + <text + type="string" + length="1" + follows="left|top" + height="25" + layout="topleft" + left_delta="0" + name="total_time_fetch_label" + top_delta="25" + width="400"> + 14, Total time on entire fetching: [TIME] seconds + </text> + <text + type="string" + length="1" + follows="left|top" + height="25" + layout="topleft" + left_delta="0" + name="total_time_refetch_vis_cache_label" + top_delta="25" + width="540"> + 15, Refetching visibles from cache, Time: [TIME] seconds, Fetched: [SIZE]KB, [PIXEL]MPixels + </text> + <text + type="string" + length="1" + follows="left|top" + height="25" + layout="topleft" + left_delta="0" + name="total_time_refetch_vis_http_label" + top_delta="25" + width="540"> + 16, Refetching visibles from HTTP, Time: [TIME] seconds, Fetched: [SIZE]KB, [PIXEL]MPixels + </text> + <spinner + decimal_digits="2" + follows="left|top" + height="20" + increment="0.01" + initial_value="1.0" + label="17, Ratio of Texel/Pixel:" + label_width="130" + layout="topleft" + left_delta="0" + max_val="10.0" + min_val="0.01" + name="texel_pixel_ratio" + top_delta="30" + width="200"> + <spinner.commit_callback + function="TexFetchDebugger.ChangeTexelPixelRatio" /> + </spinner> + <button + follows="left|top" + height="20" + label="Start" + layout="topleft" + left_delta="0" + name="start_btn" + top_delta="30" + width="70"> + <button.commit_callback + function="TexFetchDebugger.Start" /> + </button> + <button + follows="left|top" + height="20" + label="Reset" + layout="topleft" + left_pad="7" + name="clear_btn" + top_delta="0" + width="70"> + <button.commit_callback + function="TexFetchDebugger.Clear" /> + </button> + <button + follows="left|top" + height="20" + label="Close" + layout="topleft" + left_pad="7" + name="close_btn" + top_delta="0" + width="70"> + <button.commit_callback + function="TexFetchDebugger.Close" /> + </button> + <button + follows="left|top" + height="20" + label="Cache Read" + layout="topleft" + left="10" + name="cacheread_btn" + top_delta="30" + width="80"> + <button.commit_callback + function="TexFetchDebugger.CacheRead" /> + </button> + <button + follows="left|top" + height="20" + label="Cache Write" + layout="topleft" + left_pad="7" + name="cachewrite_btn" + top_delta="0" + width="80"> + <button.commit_callback + function="TexFetchDebugger.CacheWrite" /> + </button> + <button + follows="left|top" + height="20" + label="HTTP" + layout="topleft" + left_pad="7" + name="http_btn" + top_delta="0" + width="70"> + <button.commit_callback + function="TexFetchDebugger.HTTPLoad" /> + </button> + <button + follows="left|top" + height="20" + label="Decode" + layout="topleft" + left_pad="7" + name="decode_btn" + top_delta="0" + width="70"> + <button.commit_callback + function="TexFetchDebugger.Decode" /> + </button> + <button + follows="left|top" + height="20" + label="GL Texture" + layout="topleft" + left_pad="7" + name="gl_btn" + top_delta="0" + width="70"> + <button.commit_callback + function="TexFetchDebugger.GLTexture" /> + </button> + <button + follows="left|top" + height="20" + label="Refetch Vis Cache" + layout="topleft" + left="10" + name="refetchviscache_btn" + top_delta="30" + width="120"> + <button.commit_callback + function="TexFetchDebugger.RefetchVisCache" /> + </button> + <button + follows="left|top" + height="20" + label="Refetch Vis HTTP" + layout="topleft" + left_pad="7" + name="refetchvishttp_btn" + top_delta="0" + width="120"> + <button.commit_callback + function="TexFetchDebugger.RefetchVisHTTP" /> + </button> +</floater> diff --git a/indra/newview/skins/default/xui/en/menu_text_editor.xml b/indra/newview/skins/default/xui/en/menu_text_editor.xml index fe8489166b..70b40dd89b 100644 --- a/indra/newview/skins/default/xui/en/menu_text_editor.xml +++ b/indra/newview/skins/default/xui/en/menu_text_editor.xml @@ -2,6 +2,85 @@ <context_menu name="Text editor context menu"> <menu_item_call + label="(unknown)" + layout="topleft" + name="Suggestion 1"> + <menu_item_call.on_click + function="SpellCheck.ReplaceWithSuggestion" + parameter="0" /> + <menu_item_call.on_visible + function="SpellCheck.VisibleSuggestion" + parameter="0" /> + </menu_item_call> + <menu_item_call + label="(unknown)" + layout="topleft" + name="Suggestion 2"> + <menu_item_call.on_click + function="SpellCheck.ReplaceWithSuggestion" + parameter="1" /> + <menu_item_call.on_visible + function="SpellCheck.VisibleSuggestion" + parameter="1" /> + </menu_item_call> + <menu_item_call + label="(unknown)" + layout="topleft" + name="Suggestion 3"> + <menu_item_call.on_click + function="SpellCheck.ReplaceWithSuggestion" + parameter="2" /> + <menu_item_call.on_visible + function="SpellCheck.VisibleSuggestion" + parameter="2" /> + </menu_item_call> + <menu_item_call + label="(unknown)" + layout="topleft" + name="Suggestion 4"> + <menu_item_call.on_click + function="SpellCheck.ReplaceWithSuggestion" + parameter="3" /> + <menu_item_call.on_visible + function="SpellCheck.VisibleSuggestion" + parameter="3" /> + </menu_item_call> + <menu_item_call + label="(unknown)" + layout="topleft" + name="Suggestion 5"> + <menu_item_call.on_click + function="SpellCheck.ReplaceWithSuggestion" + parameter="4" /> + <menu_item_call.on_visible + function="SpellCheck.VisibleSuggestion" + parameter="4" /> + </menu_item_call> + <menu_item_separator + layout="topleft" + name="Suggestion Separator" /> + <menu_item_call + label="Add to Dictionary" + layout="topleft" + name="Add to Dictionary"> + <menu_item_call.on_click + function="SpellCheck.AddToDictionary" /> + <menu_item_call.on_enable + function="SpellCheck.EnableAddToDictionary" /> + </menu_item_call> + <menu_item_call + label="Add to Ignore" + layout="topleft" + name="Add to Ignore"> + <menu_item_call.on_click + function="SpellCheck.AddToIgnore" /> + <menu_item_call.on_enable + function="SpellCheck.EnableAddToIgnore" /> + </menu_item_call> + <menu_item_separator + layout="topleft" + name="Spellcheck Separator" /> + <menu_item_call label="Cut" layout="topleft" name="Cut"> diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 5ba566b175..6bcdc615c3 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -193,6 +193,15 @@ <menu_item_call.on_click function="View.ToggleUI" /> </menu_item_call> + <menu_item_check + label="Show HUD Attachments" + name="Show HUD Attachments" + shortcut="alt|shift|H"> + <menu_item_check.on_check + function="View.CheckHUDAttachments" /> + <menu_item_check.on_click + function="View.ShowHUDAttachments" /> + </menu_item_check> <menu_item_separator/> @@ -291,6 +300,12 @@ function="SideTray.PanelPeopleTab" parameter="nearby_panel" /> </menu_item_call> + <menu_item_call + label="Block List" + name="Block List"> + <menu_item_call.on_click + function="Communicate.BlockList" /> + </menu_item_call> </menu> <menu create_jump_keys="true" @@ -1374,15 +1389,6 @@ function="View.HighlightTransparent" /> </menu_item_check> <menu_item_check - label="Show HUD Attachments" - name="Show HUD Attachments" - shortcut="alt|shift|H"> - <menu_item_check.on_check - function="View.CheckHUDAttachments" /> - <menu_item_check.on_click - function="View.ShowHUDAttachments" /> - </menu_item_check> - <menu_item_check label="Show Mouselook Crosshairs" name="ShowCrosshairs"> <menu_item_check.on_check @@ -1876,7 +1882,7 @@ <menu_item_check.on_click function="Advanced.ToggleConsole" parameter="texture" /> - </menu_item_check> + </menu_item_check> <menu_item_check label="Debug Console" name="Debug Console" @@ -1898,28 +1904,6 @@ parameter="notifications_console" /> </menu_item_call> <menu_item_check - label="Texture Size Console" - name="Texture Size" - shortcut="control|shift|6"> - <menu_item_check.on_check - function="Advanced.CheckConsole" - parameter="texture size" /> - <menu_item_check.on_click - function="Advanced.ToggleConsole" - parameter="texture size" /> - </menu_item_check> - <menu_item_check - label="Texture Category Console" - name="Texture Category" - shortcut="control|shift|7"> - <menu_item_check.on_check - function="Advanced.CheckConsole" - parameter="texture category" /> - <menu_item_check.on_click - function="Advanced.ToggleConsole" - parameter="texture category" /> - </menu_item_check> - <menu_item_check label="Fast Timers" name="Fast Timers" shortcut="control|shift|9" @@ -1953,7 +1937,20 @@ function="Advanced.ToggleConsole" parameter="scene view" /> </menu_item_check> - + <menu_item_call + enabled="false" + visible="false" + label="Texture Fetch Debug Console" + name="Texture Fetch Debug Console"> + <menu_item_call.on_click + function="Floater.Show" + parameter="tex_fetch_debugger" /> + <on_enable + function="Develop.SetTexFetchDebugger" /> + <on_visible + function="Develop.SetTexFetchDebugger" /> + </menu_item_call> + <menu_item_separator/> <menu_item_call @@ -2439,6 +2436,52 @@ function="Advanced.ToggleInfoDisplay" parameter="sculpt" /> </menu_item_check> + <menu + create_jump_keys="true" + label="Texture Density" + name="Texture Density" + tear_off="true"> + <menu_item_check + label="None" + name="None"> + <menu_item_check.on_check + function="Advanced.CheckDisplayTextureDensity" + parameter="none" /> + <menu_item_check.on_click + function="Advanced.SetDisplayTextureDensity" + parameter="none" /> + </menu_item_check> + <menu_item_check + label="Current" + name="Current"> + <menu_item_check.on_check + function="Advanced.CheckDisplayTextureDensity" + parameter="current" /> + <menu_item_check.on_click + function="Advanced.SetDisplayTextureDensity" + parameter="current" /> + </menu_item_check> + <menu_item_check + label="Desired" + name="Desired"> + <menu_item_check.on_check + function="Advanced.CheckDisplayTextureDensity" + parameter="desired" /> + <menu_item_check.on_click + function="Advanced.SetDisplayTextureDensity" + parameter="desired" /> + </menu_item_check> + <menu_item_check + label="Full" + name="Full"> + <menu_item_check.on_check + function="Advanced.CheckDisplayTextureDensity" + parameter="full" /> + <menu_item_check.on_click + function="Advanced.SetDisplayTextureDensity" + parameter="full" /> + </menu_item_check> + </menu> </menu> <menu create_jump_keys="true" @@ -2606,16 +2649,6 @@ parameter="TextureLoadFullRes" /> </menu_item_check> <menu_item_check - label="Audit Textures" - name="Audit Textures"> - <menu_item_check.on_check - function="CheckControl" - parameter="AuditTexture" /> - <menu_item_check.on_click - function="ToggleControl" - parameter="AuditTexture" /> - </menu_item_check> - <menu_item_check label="Texture Atlas (experimental)" name="Texture Atlas"> <menu_item_check.on_check @@ -3098,12 +3131,6 @@ <menu_item_call.on_click function="Advanced.TestFemale" /> </menu_item_call> - <menu_item_call - label="Toggle PG" - name="Toggle PG"> - <menu_item_call.on_click - function="Advanced.TogglePG" /> - </menu_item_call> <menu_item_check label="Allow Select Avatar" name="Allow Select Avatar"> diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 8f8f4ae7ff..3d057fa8f5 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -1245,6 +1245,25 @@ Visit [_URL] for more information? <notification icon="alertmodal.tga" + name="IntelOldDriver" + type="alertmodal"> + There is likely a newer driver for your graphics chip. Updating graphics drivers can substantially improve performance. + + Visit [_URL] to check for driver updates? + <tag>confirm</tag> + <url option="0" name="url"> + http://www.intel.com/p/en_US/support/detect/graphics + </url> + <usetemplate + ignoretext="My graphics driver is out of date" + name="okcancelignore" + notext="No" + yestext="Yes"/> + <tag>fail</tag> + </notification> + + <notification + icon="alertmodal.tga" name="UnknownGPU" type="alertmodal"> Your system contains a graphics card that [APP_NAME] doesn't recognize. @@ -2340,6 +2359,93 @@ Would you be my friend? </notification> <notification + icon="alertmodal.tga" + label="Add Auto-Replace List" + name="AddAutoReplaceList" + type="alertmodal"> + <tag>addlist</tag> + Name for the new list: + <tag>confirm</tag> + <form name="form"> + <input name="listname" type="text"/> + <button + default="true" + index="0" + name="SetName" + text="OK"/> + </form> + </notification> + + <notification + icon="alertmodal.tga" + label="Rename Auto-Replace List" + name="RenameAutoReplaceList" + type="alertmodal"> + The name '[DUPNAME]' is in use + Enter a new unique name: + <tag>confirm</tag> + <form name="form"> + <input name="listname" type="text"/> + <button + default="false" + index="0" + name="ReplaceList" + text="Replace Current List"/> + <button + default="true" + index="1" + name="SetName" + text="Use New Name"/> + </form> + </notification> + + <notification + icon="alertmodal.tga" + name="InvalidAutoReplaceEntry" + type="alertmodal"> + The keyword must be a single word, and the replacement may not be empty. + <tag>fail</tag> + </notification> + + <notification + icon="alertmodal.tga" + name="InvalidAutoReplaceList" + type="alertmodal"> + That replacement list is not valid. + <tag>fail</tag> + </notification> + + <notification + icon="alertmodal.tga" + name="SpellingDictImportRequired" + type="alertmodal"> + You must specify a file, a name, and a language. + <tag>fail</tag> + </notification> + + <notification + icon="alertmodal.tga" + name="SpellingDictIsSecondary" + type="alertmodal"> +The dictionary [DIC_NAME] does not appear to have an "aff" file; this means that it is a "secondary" dictionary. +It can be used as an additional dictionary, but not as your Main dictionary. + +See https://wiki.secondlife.com/wiki/Adding_Spelling_Dictionaries + <tag>confirm</tag> + </notification> + + <notification + icon="alertmodal.tga" + name="SpellingDictImportFailed" + type="alertmodal"> + Unable to copy + [FROM_NAME] + to + [TO_NAME] + <tag>fail</tag> + </notification> + + <notification icon="alertmodal.tga" label="Save Outfit" name="SaveOutfitAs" @@ -4072,9 +4178,7 @@ Are you sure you want to change the Estate Covenant? name="RegionEntryAccessBlocked" type="alertmodal"> <tag>fail</tag> -You are not allowed in that Region due to your maturity Rating. This may be a result of a lack of information validating your age. - -Please verify you have the latest Viewer installed, and go to the Knowledge Base for details on accessing areas with this maturity rating. + The region you're trying to visit contains content exceeding your current preferences. You can change your preferences using Me > Preferences > General. <usetemplate name="okbutton" yestext="OK"/> @@ -4082,13 +4186,11 @@ Please verify you have the latest Viewer installed, and go to the Knowledge Base <notification icon="alertmodal.tga" - name="RegionEntryAccessBlocked_KB" + name="RegionEntryAccessBlocked_AdultsOnlyContent" type="alertmodal"> <tag>fail</tag> <tag>confirm</tag> -You are not allowed in that region due to your maturity Rating. - -Go to the Knowledge Base for more information about maturity Ratings? + The region you're trying to visit contains [REGIONMATURITY] content, which is accessible to adults only. <url option="0" name="url"> http://wiki.secondlife.com/wiki/Linden_Lab_Official:Maturity_ratings:_an_overview </url> @@ -4096,7 +4198,7 @@ Go to the Knowledge Base for more information about maturity Ratings? name="okcancelignore" yestext="Go to Knowledge Base" notext="Close" - ignoretext="I can't enter this Region, due to restrictions of the maturity Rating"/> + ignoretext="Region crossing: The region you're trying to visit contains content which is accessible to adults only."/> </notification> <notification @@ -4104,47 +4206,156 @@ Go to the Knowledge Base for more information about maturity Ratings? name="RegionEntryAccessBlocked_Notify" type="notifytip"> <tag>fail</tag> -You are not allowed in that region due to your maturity Rating. +The region you're trying to visit contains [REGIONMATURITY] content, but your current preferences are set to exclude [REGIONMATURITY] content. + </notification> + + <notification + icon="notifytip.tga" + name="RegionEntryAccessBlocked_NotifyAdultsOnly" + type="notifytip"> + <tag>fail</tag> + The region you're trying to visit contains [REGIONMATURITY] content, which is accessible to adults only. </notification> <notification icon="alertmodal.tga" name="RegionEntryAccessBlocked_Change" type="alertmodal"> - <tag>fail</tag> + <tag>fail</tag> <tag>confirm</tag> -You are not allowed in that Region due to your maturity Rating preference. - -To enter the desired region, please change your maturity Rating preference. This will allow you to search for and access [REGIONMATURITY] content. To undo any changes, go to Me > Preferences > General. - <form name="form"> +The region you're trying to visit contains [REGIONMATURITY] content, but your current preferences are set to exclude [REGIONMATURITY] content. We can change your preferences, or you can cancel. After your preferences are changed, you may attempt to enter the region again. + <form name="form"> <button index="0" name="OK" - text="Change Preference"/> - <button + text="Change preferences"/> + <button default="true" index="1" name="Cancel" - text="Close"/> - <ignore name="ignore" text="My chosen Rating preference prevents me from entering a Region"/> + text="Cancel"/> + <ignore name="ignore" text="Region crossing: The region you're trying to visit contains content excluded by your preferences."/> </form> </notification> <notification + icon="alertmodal.tga" + name="RegionEntryAccessBlocked_PreferencesOutOfSync" + type="alertmodal"> + <tag>fail</tag> + We are having technical difficulties with your teleport because your preferences are out of sync with the server. + <usetemplate + name="okbutton" + yestext="OK"/> + </notification> + + <notification + icon="alertmodal.tga" + name="TeleportEntryAccessBlocked" + type="alertmodal"> + <tag>fail</tag> + The region you're trying to visit contains content exceeding your current preferences. You can change your preferences using Me > Preferences > General. + <usetemplate + name="okbutton" + yestext="OK"/> + </notification> + + <notification + icon="alertmodal.tga" + name="TeleportEntryAccessBlocked_AdultsOnlyContent" + type="alertmodal"> + <unique> + <context>REGIONMATURITY</context> + </unique> + <tag>fail</tag> + <tag>confirm</tag> + The region you're trying to visit contains [REGIONMATURITY] content, which is accessible to adults only. + <url option="0" name="url"> + http://wiki.secondlife.com/wiki/Linden_Lab_Official:Maturity_ratings:_an_overview + </url> + <usetemplate + name="okcancelignore" + yestext="Go to Knowledge Base" + notext="Close" + ignoretext="Teleport: The region you're trying to visit contains content which is accessible to adults only."/> + </notification> + + <notification icon="notifytip.tga" - name="PreferredMaturityChanged" + name="TeleportEntryAccessBlocked_Notify" type="notifytip"> -Your maturity Rating preference is now [RATING]. + <unique> + <context>REGIONMATURITY</context> + </unique> + <tag>fail</tag> + The region you're trying to visit contains [REGIONMATURITY] content, but your current preferences are set to exclude [REGIONMATURITY] content. + </notification> + + <notification + icon="notifytip.tga" + name="TeleportEntryAccessBlocked_NotifyAdultsOnly" + type="notifytip"> + <unique> + <context>REGIONMATURITY</context> + </unique> + <tag>fail</tag> + The region you're trying to visit contains [REGIONMATURITY] content, which is accessible to adults only. </notification> <notification icon="alertmodal.tga" - name="LandClaimAccessBlocked" + name="TeleportEntryAccessBlocked_ChangeAndReTeleport" type="alertmodal"> -You cannot claim this land due to your maturity Rating. This may be a result of a lack of information validating your age. + <unique> + <context>REGIONMATURITY</context> + </unique> + <tag>fail</tag> + <tag>confirm</tag> + The region you're trying to visit contains [REGIONMATURITY] content, but your current preferences are set to exclude [REGIONMATURITY] content. We can change your preferences and continue with the teleport, or you can cancel this teleport. + <form name="form"> + <button + index="0" + name="OK" + text="Change and continue"/> + <button + default="true" + index="1" + name="Cancel" + text="Cancel"/> + <ignore name="ignore" text="Teleport (restartable): The region you're trying to visit contains content excluded by your preferences."/> + </form> + </notification> -Please verify you have the latest Viewer installed, and go to the Knowledge Base for details on accessing areas with this maturity rating. - <tag>fail</tag> + <notification + icon="alertmodal.tga" + name="TeleportEntryAccessBlocked_Change" + type="alertmodal"> + <unique> + <context>REGIONMATURITY</context> + </unique> + <tag>fail</tag> + <tag>confirm</tag> + The region you're trying to visit contains [REGIONMATURITY] content, but your current preferences are set to exclude [REGIONMATURITY] content. We can change your preferences, or you can cancel the teleport. After your preferences are changed, you will need to attempt the teleport again. + <form name="form"> + <button + index="0" + name="OK" + text="Change preferences"/> + <button + default="true" + index="1" + name="Cancel" + text="Cancel"/> + <ignore name="ignore" text="Teleport (non-restartable): The region you're trying to visit contains content excluded by your preferences."/> + </form> + </notification> + + <notification + icon="alertmodal.tga" + name="TeleportEntryAccessBlocked_PreferencesOutOfSync" + type="alertmodal"> + <tag>fail</tag> + We are having technical difficulties with your teleport because your preferences are out of sync with the server. <usetemplate name="okbutton" yestext="OK"/> @@ -4152,12 +4363,43 @@ Please verify you have the latest Viewer installed, and go to the Knowledge Base <notification icon="alertmodal.tga" - name="LandClaimAccessBlocked_KB" + name="PreferredMaturityChanged" type="alertmodal"> -You cannot claim this land due to your maturity Rating. +You won't receive any more notifications that you're about to visit a region with [RATING] content. You may change your content preferences in the future by using Me > Preferences > General from the menu bar. + <tag>confirm</tag> + <usetemplate + name="okbutton" + yestext="OK"/> + </notification> -Go to the Knowledge Base for more information about maturity Ratings? - <tag>fail</tag> + <notification + icon="alertmodal.tga" + name="MaturityChangeError" + type="alertmodal"> + We were unable to change your preferences to view [PREFERRED_MATURITY] content at this time. Your preferences have been reset to view [ACTUAL_MATURITY] content. You may attempt to change your preferences again by using Me > Preferences > General from the menu bar. + <tag>confirm</tag> + <usetemplate + name="okbutton" + yestext="OK"/> + </notification> + + <notification + icon="alertmodal.tga" + name="LandClaimAccessBlocked" + type="alertmodal"> + The land you're trying to claim has a maturity rating exceeding your current preferences. You can change your preferences using Me > Preferences > General. + <tag>fail</tag> + <usetemplate + name="okbutton" + yestext="OK"/> + </notification> + + <notification + icon="alertmodal.tga" + name="LandClaimAccessBlocked_AdultsOnlyContent" + type="alertmodal"> + Only adults can claim this land. + <tag>fail</tag> <tag>confirm</tag> <url option="0" name="url"> http://wiki.secondlife.com/wiki/Linden_Lab_Official:Maturity_ratings:_an_overview @@ -4166,41 +4408,52 @@ Go to the Knowledge Base for more information about maturity Ratings? name="okcancelignore" yestext="Go to Knowledge Base" notext="Close" - ignoretext="I can't claim this Land, due to restrictions of the maturity Rating"/> + ignoretext="Only adults can claim this land."/> </notification> <notification icon="notifytip.tga" name="LandClaimAccessBlocked_Notify" type="notifytip"> -You cannot claim this land due to your maturity Rating. - <tag>fail</tag> + The land you're trying to claim contains [REGIONMATURITY] content, but your current preferences are set to exclude [REGIONMATURITY] content. + <tag>fail</tag> + </notification> + + <notification + icon="notifytip.tga" + name="LandClaimAccessBlocked_NotifyAdultsOnly" + type="notifytip"> + <tag>fail</tag> + The land you're trying to claim contains [REGIONMATURITY] content, which is accessible to adults only. </notification> <notification icon="alertmodal.tga" name="LandClaimAccessBlocked_Change" type="alertmodal"> -You cannot claim this land due to your maturity Rating preference. - -You can click 'Change Preference' to raise your maturity Rating preference now and allow you to enter. You will be able to search and access [REGIONMATURITY] content from now on. If you later want to change this setting back, go to Me > Preferences > General. + The land you're trying to claim contains [REGIONMATURITY] content, but your current preferences are set to exclude [REGIONMATURITY] content. We can change your preferences, then you can try claiming the land again. <tag>fail</tag> <tag>confirm</tag> - <usetemplate - name="okcancelignore" - yestext="Change Preference" - notext="Close" - ignoretext="My chosen Rating preference prevents me from claiming Land"/> + <form name="form"> + <button + index="0" + name="OK" + text="Change preferences"/> + <button + default="true" + index="1" + name="Cancel" + text="Cancel"/> + <ignore name="ignore" text="The land you're trying to claim contains content excluded by your preferences."/> + </form> </notification> <notification icon="alertmodal.tga" name="LandBuyAccessBlocked" type="alertmodal"> -You cannot buy this land due to your maturity Rating. This may be a result of a lack of information validating your age. - -Please verify you have the latest Viewer installed, and go to the Knowledge Base for details on accessing areas with this maturity rating. - <tag>fail</tag> + The land you're trying to buy has a maturity rating exceeding your current preferences. You can change your preferences using Me > Preferences > General. + <tag>fail</tag> <usetemplate name="okbutton" yestext="OK"/> @@ -4208,11 +4461,9 @@ Please verify you have the latest Viewer installed, and go to the Knowledge Base <notification icon="alertmodal.tga" - name="LandBuyAccessBlocked_KB" + name="LandBuyAccessBlocked_AdultsOnlyContent" type="alertmodal"> -You cannot buy this land due to your maturity Rating. - -Go to the Knowledge Base for more information about maturity Ratings? + Only adults can buy this land. <tag>confirm</tag> <tag>fail</tag> <url option="0" name="url"> @@ -4222,31 +4473,44 @@ Go to the Knowledge Base for more information about maturity Ratings? name="okcancelignore" yestext="Go to Knowledge Base" notext="Close" - ignoretext="I can't buy this Land, due to restrictions of the maturity Rating"/> + ignoretext="Only adults can buy this land."/> </notification> <notification icon="notifytip.tga" name="LandBuyAccessBlocked_Notify" type="notifytip"> -You cannot buy this land due to your maturity Rating. - <tag>fail</tag> + The land you're trying to buy contains [REGIONMATURITY] content, but your current preferences are set to exclude [REGIONMATURITY] content. + <tag>fail</tag> + </notification> + + <notification + icon="notifytip.tga" + name="LandBuyAccessBlocked_NotifyAdultsOnly" + type="notifytip"> + <tag>fail</tag> + The land you're trying to buy contains [REGIONMATURITY] content, which is accessible to adults only. </notification> <notification icon="alertmodal.tga" name="LandBuyAccessBlocked_Change" type="alertmodal"> -You cannot buy this land due to your maturity Rating preference. - -You can click 'Change Preference' to raise your maturity Rating preference now and allow you to enter. You will be able to search and access [REGIONMATURITY] content from now on. If you later want to change this setting back, go to Me > Preferences > General. + The land you're trying to buy contains [REGIONMATURITY] content, but your current preferences are set to exclude [REGIONMATURITY] content. We can change your preferences, then you can try buying the land again. <tag>confirm</tag> <tag>fail</tag> - <usetemplate - name="okcancelignore" - yestext="Change Preference" - notext="Close" - ignoretext="My chosen Rating preference prevents me from buying Land"/> + <form name="form"> + <button + index="0" + name="OK" + text="Change preferences"/> + <button + default="true" + index="1" + name="Cancel" + text="Cancel"/> + <ignore name="ignore" text="The land you're trying to buy contains content excluded by your preferences."/> + </form> </notification> <notification @@ -4401,10 +4665,11 @@ Type a short announcement which will be sent to everyone in this region. label="Changed Region Maturity" name="RegionMaturityChange" type="alertmodal"> -The maturity rating for this region has been updated. -It may take some time for the change to be reflected on the map. - -To enter Adult regions, Residents must be Account Verified, either by age-verification or payment-verification. +The maturity rating for this region has been changed. +It may take some time for this change to be reflected on the map. + <usetemplate + name="okbutton" + yestext="OK"/> </notification> <notification @@ -5110,20 +5375,20 @@ Would you like to automatically wear the clothing you are about to create? icon="alertmodal.tga" name="NotAgeVerified" type="alertmodal"> - <tag>fail</tag> -To access adult content and areas in Second Life you must be at least 18 years old. Please visit our age verification page to confirm you are over 18. -Note this will launch your web browser. - -[_URL] - <tag>confirm</tag> - <url option="0" name="url"> - https://secondlife.com/my/account/verification.php - </url> + The location you're trying to visit is restricted to residents age 18 and over. + <tag>fail</tag> <usetemplate - ignoretext="I have not verified my age" - name="okcancelignore" - notext="Cancel" - yestext="Go to Age Verification"/> + ignoretext="I am not old enough to visit age restricted areas." + name="okignore" + yestext="OK"/> + </notification> + + <notification + icon="notifytip.tga" + name="NotAgeVerified_Notify" + type="notifytip"> + Location restricted to age 18 and over. + <tag>fail</tag> </notification> <notification @@ -5268,7 +5533,7 @@ Terrain.raw downloaded icon="notifytip.tga" name="GestureMissing" type="notifytip"> -Hmm. Gesture [NAME] is missing from the database. +Gesture [NAME] is missing from the database. <tag>fail</tag> </notification> @@ -5813,9 +6078,7 @@ You can only claim public land in the Region you're in. persist="true" type="notify"> <tag>fail</tag> -You aren't allowed in that Region due to your maturity Rating. You may need to validate your age and/or install the latest Viewer. - -Please go to the Knowledge Base for details on accessing areas with this maturity Rating. + The region you're trying to visit contains content exceeding your current preferences. You can change your preferences using Me > Preferences > General. </notification> <notification @@ -5847,11 +6110,11 @@ You do not have proper payment status to enter this region. <notification icon="notify.tga" - name="MustGetAgeRgion" + name="MustGetAgeRegion" persist="true" type="notify"> <tag>fail</tag> -You must be age-verified to enter this region. +You must be age 18 or over to enter this region. </notification> <notification @@ -5860,7 +6123,7 @@ You must be age-verified to enter this region. persist="true" type="notify"> <tag>fail</tag> -You must be age-verified to enter this parcel. + You must be age 18 or over to enter this parcel. </notification> <notification @@ -6137,7 +6400,8 @@ Your object named <nolink>[OBJECTFROMNAME]</nolink> has given you th type="offer"> [NAME_SLURL] has offered to teleport you to their location: -[MESSAGE] - [MATURITY_STR] <icon>[MATURITY_ICON]</icon> +“[MESSAGE]” +<icon>[MATURITY_ICON]</icon> - [MATURITY_STR] <tag>confirm</tag> <form name="form"> <button @@ -6153,6 +6417,42 @@ Your object named <nolink>[OBJECTFROMNAME]</nolink> has given you th <notification icon="notify.tga" + name="TeleportOffered_MaturityExceeded" + type="offer"> +[NAME_SLURL] has offered to teleport you to their location: + +“[MESSAGE]” +<icon>[MATURITY_ICON]</icon> - [MATURITY_STR] + +This region contains [REGION_CONTENT_MATURITY] content, but your current preferences are set to exclude [REGION_CONTENT_MATURITY] content. We can change your preferences and continue with the teleport, or you can cancel this teleport. + <tag>confirm</tag> + <form name="form"> + <button + index="0" + name="Teleport" + text="Change and Continue"/> + <button + index="1" + name="Cancel" + text="Cancel"/> + </form> + </notification> + + <notification + icon="notify.tga" + name="TeleportOffered_MaturityBlocked" + type="notifytip"> +[NAME_SLURL] has offered to teleport you to their location: + +“[MESSAGE]” +<icon>[MATURITY_ICON]</icon> - [MATURITY_STR] + +However, this region contains content accessible to adults only. + <tag>fail</tag> + </notification> + + <notification + icon="notify.tga" name="TeleportOfferSent" log_to_im="true" show_toast="false" @@ -6393,31 +6693,28 @@ Is this OK? <notification icon="notify.tga" name="ScriptQuestionCaution" - priority="high" + priority="critical" persist="true" type="notify"> -An object named '<nolink>[OBJECTNAME]</nolink>', owned by '[NAME]' would like to: - -[QUESTIONS] -If you do not trust this object and its creator, you should deny the request. +Warning: The object '<nolink>[OBJECTNAME]</nolink>' wants total access to your Linden Dollars account. If you allow access, it can remove funds from your account at any time, or empty your account completely, on an ongoing basis with no additional warnings. + +It is rare that such a request is legitimate. Do not allow access if you do not fully understand why it wants access to your account. -Grant this request? <tag>confirm</tag> <form name="form"> <button index="0" name="Grant" - text="Grant"/> + text="Allow total access"/> <button default="true" index="1" name="Deny" text="Deny"/> - <button - index="2" - name="Details" - text="Details..."/> </form> + <footer> +[FOOTERTEXT] + </footer> </notification> <notification @@ -7201,6 +7498,18 @@ You locally updated a [RESOLUTION] baked texture for '[BODYREGION]' after [TIME] <notification icon="alertmodal.tga" + name="LivePreviewUnavailable" + type="alert"> + +We cannot display a preview of this texture because it is no-copy and/or no-transfer. + <usetemplate + ignoretext="Warn me that Live Preview mode is not available for no-copy and/or no-transfer textures" + name="okignore" + yestext="OK"/> + </notification> + + <notification + icon="alertmodal.tga" name="ConfirmLeaveCall" type="alert"> Are you sure you want to leave this call? diff --git a/indra/newview/skins/default/xui/en/panel_edit_pick.xml b/indra/newview/skins/default/xui/en/panel_edit_pick.xml index 0faa1598b1..553c112e6f 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_pick.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_pick.xml @@ -134,6 +134,7 @@ top_pad="2" max_length="1023" name="pick_desc" + spellcheck="true" text_color="black" word_wrap="true" /> <text diff --git a/indra/newview/skins/default/xui/en/panel_group_notices.xml b/indra/newview/skins/default/xui/en/panel_group_notices.xml index 607e1bb213..6d5fb51e85 100644 --- a/indra/newview/skins/default/xui/en/panel_group_notices.xml +++ b/indra/newview/skins/default/xui/en/panel_group_notices.xml @@ -141,6 +141,7 @@ Maximum 200 per group daily max_length_bytes="63" name="create_subject" prevalidate_callback="ascii" + spellcheck="true" width="218" /> <text follows="left|top" @@ -161,6 +162,7 @@ Maximum 200 per group daily left_pad="3" max_length="511" name="create_message" + spellcheck="true" top_delta="0" width="218" word_wrap="true" /> @@ -309,6 +311,7 @@ Maximum 200 per group daily left_pad="3" max_length_bytes="63" name="view_subject" + spellcheck="true" top_delta="-1" visible="false" width="200" /> @@ -333,6 +336,7 @@ Maximum 200 per group daily right="-1" max_length="511" name="view_message" + spellcheck="true" top_delta="-40" width="313" word_wrap="true" /> diff --git a/indra/newview/skins/default/xui/en/panel_nearby_chat_bar.xml b/indra/newview/skins/default/xui/en/panel_nearby_chat_bar.xml index 21c627cdfb..6bc9c48729 100644 --- a/indra/newview/skins/default/xui/en/panel_nearby_chat_bar.xml +++ b/indra/newview/skins/default/xui/en/panel_nearby_chat_bar.xml @@ -19,6 +19,7 @@ left="0" max_length_bytes="1023" name="chat_box" + spellcheck="true" text_pad_left="5" text_pad_right="25" tool_tip="Press Enter to say, Ctrl+Enter to shout" diff --git a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml index d7a7f7d735..c76a3cfaaf 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml @@ -149,13 +149,36 @@ <button follows="left|top" height="23" - label="Chat Translation Settings" + label="Translation..." layout="topleft" left="30" name="ok_btn" - top="-40" + top="-50" width="170"> <button.commit_callback function="Pref.TranslationSettings" /> </button> -</panel>
\ No newline at end of file + <button + follows="top|left" + height="23" + layout="topleft" + top_pad="-23" + left_pad="5" + name="autoreplace_showgui" + commit_callback.function="Pref.AutoReplace" + label="Auto-Replace..." + width="150"> + </button> + <button + follows="top|left" + height="23" + layout="topleft" + top_pad="-23" + left_pad="5" + name="spellcheck_showgui" + commit_callback.function="Pref.SpellChecker" + label="Spell Checking..." + width="150"> + </button> + +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_region_estate.xml b/indra/newview/skins/default/xui/en/panel_region_estate.xml index bfd796a62b..76a82212ae 100644 --- a/indra/newview/skins/default/xui/en/panel_region_estate.xml +++ b/indra/newview/skins/default/xui/en/panel_region_estate.xml @@ -149,11 +149,11 @@ <check_box follows="top|left" height="16" - label="Have been age-verified" + label="Are age 18 or older" layout="topleft" left_delta="0" name="limit_age_verified" - tool_tip="Residents must be age verified to access this estate. See the [SUPPORT_SITE] for more information." + tool_tip="Residents must be age 18 or older to access this estate. See the [SUPPORT_SITE] for more information." top_pad="2" width="278" /> diff --git a/indra/newview/skins/default/xui/en/panel_script_question_toast.xml b/indra/newview/skins/default/xui/en/panel_script_question_toast.xml new file mode 100644 index 0000000000..b0436bb6dc --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_script_question_toast.xml @@ -0,0 +1,55 @@ +<?xml version="1.0" encoding="UTF-8"?> +<panel + background_opaque="false" + border_visible="false" + background_visible="true" + bg_alpha_color="PanelNotificationBackground" + bg_opaque_color="PanelNotificationBackground" + chrome="true" + height="270" + label="script_question_panel" + layout="topleft" + left="0" + name="panel_script_question_toast" + top="0" + width="305"> + <text + follows="left|right|top" + font="SansSerifBold" + height="160" + layout="topleft" + left="10" + mouse_opaque="false" + name="top_info_message" + parse_highlights="true" + parse_urls="true" + text_color="NotifyCautionBoxColor" + top="10" + value="" + width="285" + wrap="true"/> + <panel + background_visible="false" + follows="left|right|top" + height="30" + label="buttons_panel" + layout="topleft" + name="buttons_panel" + top_pad="10" + width="285"> + </panel> + <text + follows="all" + font="SansSerifBold" + height="55" + layout="topleft" + mouse_opaque="false" + name="bottom_info_message" + parse_highlights="true" + parse_urls="true" + text_color="NotifyCautionBoxColor" + top_pad="5" + value="" + width="285" + wrap="true"/> +</panel> diff --git a/indra/newview/skins/default/xui/en/sidepanel_inventory.xml b/indra/newview/skins/default/xui/en/sidepanel_inventory.xml index 6ecb57b41d..14bd349480 100644 --- a/indra/newview/skins/default/xui/en/sidepanel_inventory.xml +++ b/indra/newview/skins/default/xui/en/sidepanel_inventory.xml @@ -48,7 +48,7 @@ height="300" width="330" /> </layout_panel> - <layout_panel + <layout_panel width="330" layout="topleft" auto_resize="false" diff --git a/indra/newview/skins/default/xui/en/sidepanel_task_info.xml b/indra/newview/skins/default/xui/en/sidepanel_task_info.xml index 6600339ad7..bf2e6bc2d9 100644 --- a/indra/newview/skins/default/xui/en/sidepanel_task_info.xml +++ b/indra/newview/skins/default/xui/en/sidepanel_task_info.xml @@ -267,19 +267,19 @@ <combo_box.item label="Touch (default)" name="Touch/grab(default)" - value="Touch/grab (default)" /> + value="Touch" /> <combo_box.item label="Sit on object" name="Sitonobject" - value="Sit on object" /> + value="Sit" /> <combo_box.item label="Buy object" name="Buyobject" - value="Buy object" /> + value="Buy" /> <combo_box.item label="Pay object" name="Payobject" - value="Pay object" /> + value="Pay" /> <combo_box.item label="Open" name="Open" diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index fff892af68..9ccd6b5cbe 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -393,6 +393,7 @@ Please try logging in again in a minute.</string> <string name="reconnect_nearby">You will now be reconnected to Nearby Voice Chat</string> <string name="ScriptQuestionCautionChatGranted">'[OBJECTNAME]', an object owned by '[OWNERNAME]', located in [REGIONNAME] at [REGIONPOS], has been granted permission to: [PERMISSIONS].</string> <string name="ScriptQuestionCautionChatDenied">'[OBJECTNAME]', an object owned by '[OWNERNAME]', located in [REGIONNAME] at [REGIONPOS], has been denied permission to: [PERMISSIONS].</string> + <string name="AdditionalPermissionsRequestHeader">If you allow access to your account, you will also be allowing the object to:</string> <string name="ScriptTakeMoney">Take Linden dollars (L$) from you</string> <string name="ActOnControlInputs">Act on your control inputs</string> <string name="RemapControlInputs">Remap your control inputs</string> @@ -441,6 +442,7 @@ Please try logging in again in a minute.</string> <string name="load_files">Load Files</string> <string name="choose_the_directory">Choose Directory</string> <string name="script_files">Scripts</string> + <string name="dictionary_files">Dictionaries</string> <!-- LSL Usage Hover Tips --> <!-- NOTE: For now these are set as translate="false", until DEV-40761 is implemented (to internationalize the rest of tooltips in the same window). @@ -3759,4 +3761,9 @@ Try enclosing path to the editor with double quotes. <string name="snapshot_quality_high">High</string> <string name="snapshot_quality_very_high">Very High</string> + <string name="TeleportMaturityExceeded">The Resident cannot visit this region.</string> + + <!-- Spell check settings floater --> + <string name="UserDictionary">[User]</string> + </strings> diff --git a/indra/newview/skins/default/xui/en/teleport_strings.xml b/indra/newview/skins/default/xui/en/teleport_strings.xml index dce6b8dd6d..fdf41991cd 100644 --- a/indra/newview/skins/default/xui/en/teleport_strings.xml +++ b/indra/newview/skins/default/xui/en/teleport_strings.xml @@ -45,6 +45,9 @@ Go to 'Welcome Island Public' to repeat the tutorial. <message name="no_inventory_host"> The inventory system is currently unavailable. </message> + <message name="MustGetAgeRegion"> + You must be age 18 or over to enter this region. + </message> </message_set> <message_set name="progress"> <message name="sending_dest"> @@ -80,5 +83,8 @@ Go to 'Welcome Island Public' to repeat the tutorial. <message name="requesting"> Requesting Teleport... </message> - </message_set> + <message name="pending"> + Pending Teleport... + </message> + </message_set> </teleport_messages> diff --git a/indra/newview/skins/default/xui/es/floater_model_wizard.xml b/indra/newview/skins/default/xui/es/floater_model_wizard.xml deleted file mode 100644 index 5bd6b5e0e5..0000000000 --- a/indra/newview/skins/default/xui/es/floater_model_wizard.xml +++ /dev/null @@ -1,208 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Model Wizard" title="CARGAR ASISTENTE DE MODELO"> - <button label="5. Subir" name="upload_btn"/> - <button label="4. Revisar" name="review_btn"/> - <button label="3. Física" name="physics_btn"/> - <button label="2. Optimizar" name="optimize_btn"/> - <button label="1. Seleccionar archivo" name="choose_file_btn"/> - <panel name="choose_file_panel"> - <panel name="choose_file_header_panel"> - <text name="choose_file_header_text"> - Elige el archivo de modelo - </text> - </panel> - <panel name="choose_file_content"> - <text name="advanced_users_text"> - Usuarios avanzados: si tienes experiencia con las herramientas de creación de contenidos 3D, quizá te interese utilizar la función de subida avanzada. - </text> - <button label="Cambiar al modo Avanzado" name="switch_to_advanced"/> - <text name="Cache location"> - Elige el archivo de modelo que deseas subir - </text> - <button label="Examinar..." label_selected="Examinar..." name="browse"/> - <text name="Model types"> - Second Life admite los archivos COLLADA (.dae) - </text> - <text name="dimensions"> - X Y Z - </text> - <text name="warning_label"> - ATENCIÓN: - </text> - <text name="warning_text"> - No podrás completar el paso final de la subida de este modelo a los servidores de Second Life. [secondlife:///app/floater/learn_more Averigua cómo] configurar tu cuenta para subir modelos de malla. - </text> - </panel> - </panel> - <panel name="optimize_panel"> - <panel name="optimize_header_panel"> - <text name="optimize_header_text"> - Optimizar el modelo - </text> - </panel> - <text name="optimize_description"> - Hemos optimizado el rendimiento del modelo, pero puedes ajustarlo más si lo deseas. - </text> - <panel name="optimize_content"> - <text name="high_detail_text"> - Generar el nivel de detalle: Alto - </text> - <text name="medium_detail_text"> - Generar el nivel de detalle: Medio - </text> - <text name="low_detail_text"> - Generar el nivel de detalle: Bajo - </text> - <text name="lowest_detail_text"> - Generar el nivel de detalle: Mínimo - </text> - </panel> - <panel name="content2"> - <button label="Recalcular la geometría" name="recalculate_geometry_btn"/> - <text name="lod_label"> - Vista previa de geometría - </text> - <combo_box name="preview_lod_combo" tool_tip="LOD para ver en renderizado de prueba"> - <combo_item name="high"> - Detalle alto - </combo_item> - <combo_item name="medium"> - Detalles medios - </combo_item> - <combo_item name="low"> - Detalle bajo - </combo_item> - <combo_item name="lowest"> - Detalles mínimos - </combo_item> - </combo_box> - </panel> - </panel> - <panel name="physics_panel"> - <panel name="physics_header_panel"> - <text name="physics_header_text"> - Ajustar la física - </text> - </panel> - <text name="physics_description"> - Crearemos una forma para la apariencia exterior del modelo. Ajusta el nivel de detalle de la forma según se necesite para el propósito proyectado del modelo. - </text> - <panel name="physics_content"> - <button label="Recalcular física" name="recalculate_physics_btn"/> - <button label="Recalculando..." name="recalculating_physics_btn"/> - <text name="lod_label"> - Prueba de física - </text> - <combo_box name="preview_lod_combo2" tool_tip="LOD para ver en renderizado de prueba"> - <combo_item name="high"> - Detalle alto - </combo_item> - <combo_item name="medium"> - Detalles medios - </combo_item> - <combo_item name="low"> - Detalle bajo - </combo_item> - <combo_item name="lowest"> - Detalles mínimos - </combo_item> - </combo_box> - </panel> - </panel> - <panel name="review_panel"> - <panel name="review_header_panel"> - <text name="review_header_text"> - Revisar - </text> - </panel> - <panel name="review_content"> - <text name="review_prim_equiv"> - Impacto en la parcela/región: [EQUIV] equivalentes en prim - </text> - <text name="review_fee"> - Cargaremos en tu cuenta el precio de subida de L$ [FEE]. - </text> - <text name="review_confirmation"> - Al pulsar en el botón de subida, confirmas que posees los derechos necesarios sobre el material que contiene el modelo. - </text> - </panel> - </panel> - <panel name="upload_panel"> - <panel name="upload_header_panel"> - <text name="upload_header_text"> - Subida finalizada - </text> - </panel> - <text name="model_uploaded_text"> - Se ha subido tu modelo. - </text> - <text name="inventory_text"> - Puedes buscar la carpeta Objetos en tu inventario. - </text> - <text name="charged_fee"> - Se han cargado [FEE] L$ en tu cuenta. - </text> - </panel> - <button label="<< Atrás" name="back"/> - <button label="Siguiente >>" name="next"/> - <button label="Calcular pesos y precio >>" name="calculate"/> - <button label="Calculando..." name="calculating"/> - <button label="Subir" name="upload" tool_tip="Cargar al simulador"/> - <button label="Cancelar" name="cancel"/> - <button label="Cerrar" name="close"/> - <spinner name="import_scale" value="1.0"/> - <string name="status_idle"> - Inactivo - </string> - <string name="status_parse_error"> - Problema de análisis de DAE - consulta los datos en el registro. - </string> - <string name="status_reading_file"> - Cargando... - </string> - <string name="status_generating_meshes"> - Generando redes... - </string> - <string name="status_vertex_number_overflow"> - Error: El número de intersección es superior a 65534. Cancelado. - </string> - <string name="bad_element"> - Error: el elemento no es válido - </string> - <string name="high"> - Alto - </string> - <string name="medium"> - Media - </string> - <string name="low"> - Bajo - </string> - <string name="lowest"> - Mínimo - </string> - <string name="mesh_status_good"> - Factúralo. - </string> - <string name="mesh_status_na"> - N/A - </string> - <string name="mesh_status_none"> - Ninguno - </string> - <string name="mesh_status_submesh_mismatch"> - Los niveles de detalle poseen un número distinto de caras a las que se pueden aplicar texturas. - </string> - <string name="mesh_status_mesh_mismatch"> - Los niveles de detalle poseen un número distinto de ejemplos de red. - </string> - <string name="mesh_status_too_many_vertices"> - El nivel de detalle posee demasiadas intersecciones. - </string> - <string name="mesh_status_missing_lod"> - Falta un nivel de detalle requerido. - </string> - <string name="layer_all"> - Todo - </string> -</floater> diff --git a/indra/newview/skins/default/xui/fr/floater_about_land.xml b/indra/newview/skins/default/xui/fr/floater_about_land.xml index 6f8885487a..49af1a87e1 100644 --- a/indra/newview/skins/default/xui/fr/floater_about_land.xml +++ b/indra/newview/skins/default/xui/fr/floater_about_land.xml @@ -439,7 +439,7 @@ musique : <text name="Sound:"> Son : </text> - <check_box label="Limiter les gestes et sons d'objet à cette parcelle" name="check sound local"/> + <check_box label="Limiter les sons des gestes et des objets à cette parcelle" name="check sound local"/> <text name="Avatar Sounds:"> Sons d'avatar : </text> diff --git a/indra/newview/skins/default/xui/fr/floater_model_preview.xml b/indra/newview/skins/default/xui/fr/floater_model_preview.xml index a3b50351ae..0f272891c7 100644 --- a/indra/newview/skins/default/xui/fr/floater_model_preview.xml +++ b/indra/newview/skins/default/xui/fr/floater_model_preview.xml @@ -214,7 +214,7 @@ </panel> </tab_container> <panel name="weights_and_warning_panel"> - <button label="Calculer les poids et les frais." name="calculate_btn" tool_tip="Calculer les poids et les frais."/> + <button label="Calculer les poids et les frais" name="calculate_btn" tool_tip="Calculer les poids et les frais."/> <button label="Annuler" name="cancel_btn"/> <button label="Charger le modèle" name="ok_btn" tool_tip="Charger dans le simulateur"/> <button label="Effacer les paramètres et réinitialiser le formulaire" name="reset_btn"/> diff --git a/indra/newview/skins/default/xui/fr/floater_model_wizard.xml b/indra/newview/skins/default/xui/fr/floater_model_wizard.xml deleted file mode 100644 index 128b9d6fa4..0000000000 --- a/indra/newview/skins/default/xui/fr/floater_model_wizard.xml +++ /dev/null @@ -1,208 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Model Wizard" title="ASSISTANT DE CHARGEMENT DE MODÈLE"> - <button label="5. Chargement" name="upload_btn"/> - <button label="4. Vérification" name="review_btn"/> - <button label="3. Propriétés physiques" name="physics_btn"/> - <button label="2. Optimisation" name="optimize_btn"/> - <button label="1. Sélection du fichier" name="choose_file_btn"/> - <panel name="choose_file_panel"> - <panel name="choose_file_header_panel"> - <text name="choose_file_header_text"> - Choisir un fichier de modèle - </text> - </panel> - <panel name="choose_file_content"> - <text name="advanced_users_text"> - Utilisateurs expérimentés : si vous êtes habitué à utiliser des outils de création de contenu en 3D, l'outil de chargement avancé est mis à votre disposition. - </text> - <button label="Passer à Avancé" name="switch_to_advanced"/> - <text name="Cache location"> - Choisir un fichier de modèle à charger - </text> - <button label="Parcourir..." label_selected="Parcourir..." name="browse"/> - <text name="Model types"> - Second Life prend en charge les fichiers COLLADA (.dae). - </text> - <text name="dimensions"> - X Y Z - </text> - <text name="warning_label"> - AVERTISSEMENT : - </text> - <text name="warning_text"> - Vous ne pourrez pas effectuer l'étape de chargement finale du modèle sur les serveurs Second Life. [secondlife:///app/floater/learn_more Découvrez comment] configurer votre compte pour le chargement de modèles de maillage. - </text> - </panel> - </panel> - <panel name="optimize_panel"> - <panel name="optimize_header_panel"> - <text name="optimize_header_text"> - Optimiser le modèle - </text> - </panel> - <text name="optimize_description"> - Le modèle a été optimisé en termes de performances. Vous pouvez l'ajuster si vous le souhaitez. - </text> - <panel name="optimize_content"> - <text name="high_detail_text"> - Générer le niveau de détail : Élevé - </text> - <text name="medium_detail_text"> - Générer le niveau de détail : Moyen - </text> - <text name="low_detail_text"> - Générer le niveau de détail : Faible - </text> - <text name="lowest_detail_text"> - Générer le niveau de détail : Le plus faible - </text> - </panel> - <panel name="content2"> - <button label="Recalcul géométrique" name="recalculate_geometry_btn"/> - <text name="lod_label"> - Aperçu de la géométrie - </text> - <combo_box name="preview_lod_combo" tool_tip="Niveau de détail à afficher en rendu d'aperçu."> - <combo_item name="high"> - Niveau de détail élevé - </combo_item> - <combo_item name="medium"> - Niveau de détail moyen - </combo_item> - <combo_item name="low"> - Niveau de détail faible - </combo_item> - <combo_item name="lowest"> - Niveau de détail le plus faible - </combo_item> - </combo_box> - </panel> - </panel> - <panel name="physics_panel"> - <panel name="physics_header_panel"> - <text name="physics_header_text"> - Ajuster les propriétés physiques - </text> - </panel> - <text name="physics_description"> - Une forme va être créée pour l'enveloppe externe du modèle. Ajustez le niveau de détail de la forme en fonction de l'objectif souhaité pour votre modèle. - </text> - <panel name="physics_content"> - <button label="Recalcul physique" name="recalculate_physics_btn"/> - <button label="Recalcul en cours..." name="recalculating_physics_btn"/> - <text name="lod_label"> - Aperçu des propriétés physiques - </text> - <combo_box name="preview_lod_combo2" tool_tip="Niveau de détail à afficher en rendu d'aperçu."> - <combo_item name="high"> - Niveau de détail élevé - </combo_item> - <combo_item name="medium"> - Niveau de détail moyen - </combo_item> - <combo_item name="low"> - Niveau de détail faible - </combo_item> - <combo_item name="lowest"> - Niveau de détail le plus faible - </combo_item> - </combo_box> - </panel> - </panel> - <panel name="review_panel"> - <panel name="review_header_panel"> - <text name="review_header_text"> - Vérification - </text> - </panel> - <panel name="review_content"> - <text name="review_prim_equiv"> - Impact sur la parcelle/région : équivalent à [EQUIV] prims - </text> - <text name="review_fee"> - Votre compte sera débité de [FEE] L$ de frais de chargement. - </text> - <text name="review_confirmation"> - En cliquant sur le bouton de chargement, vous confirmez que vous disposez des droits appropriés sur le contenu du modèle. - </text> - </panel> - </panel> - <panel name="upload_panel"> - <panel name="upload_header_panel"> - <text name="upload_header_text"> - Chargement terminé - </text> - </panel> - <text name="model_uploaded_text"> - Votre modèle a été chargé. - </text> - <text name="inventory_text"> - Vous le trouverez dans le dossier Objets de votre inventaire. - </text> - <text name="charged_fee"> - Votre compte a été débité de [FEE] L$. - </text> - </panel> - <button label="<< Préc." name="back"/> - <button label="Suiv. >>" name="next"/> - <button label="Calculer les poids et les frais >>" name="calculate"/> - <button label="Calcul en cours..." name="calculating"/> - <button label="Charger" name="upload" tool_tip="Charger dans le simulateur."/> - <button label="Annuler" name="cancel"/> - <button label="Fermer" name="close"/> - <spinner name="import_scale" value="1.0"/> - <string name="status_idle"> - Inactif - </string> - <string name="status_parse_error"> - Problème d'analyse de fichier .dae ; reportez-vous au journal pour plus de détails. - </string> - <string name="status_reading_file"> - Chargement... - </string> - <string name="status_generating_meshes"> - Génération des maillages... - </string> - <string name="status_vertex_number_overflow"> - Erreur : valeur de sommet supérieure à 65534. Opération abandonnée. - </string> - <string name="bad_element"> - Erreur : élément non valide - </string> - <string name="high"> - Élevé - </string> - <string name="medium"> - Moyen - </string> - <string name="low"> - Faible - </string> - <string name="lowest"> - Le plus faible - </string> - <string name="mesh_status_good"> - Bon à publier ! - </string> - <string name="mesh_status_na"> - N/A - </string> - <string name="mesh_status_none"> - Aucun - </string> - <string name="mesh_status_submesh_mismatch"> - Un nombre différent de faces d'application de texture est associé aux niveaux de détail. - </string> - <string name="mesh_status_mesh_mismatch"> - Un nombre différent d'instances de maillage est associé aux niveaux de détail. - </string> - <string name="mesh_status_too_many_vertices"> - Trop de sommets pour le niveau de détail. - </string> - <string name="mesh_status_missing_lod"> - Niveau de détail requis manquant. - </string> - <string name="layer_all"> - Tout - </string> -</floater> diff --git a/indra/newview/skins/default/xui/fr/strings.xml b/indra/newview/skins/default/xui/fr/strings.xml index 3eebed450f..8b410128da 100644 --- a/indra/newview/skins/default/xui/fr/strings.xml +++ b/indra/newview/skins/default/xui/fr/strings.xml @@ -4509,7 +4509,7 @@ Essayez avec le chemin d'accès à l'éditeur entre guillemets doubles Backsp </string> <string name="Shift"> - Shift + Maj </string> <string name="Ctrl"> Ctrl diff --git a/indra/newview/skins/default/xui/it/floater_model_wizard.xml b/indra/newview/skins/default/xui/it/floater_model_wizard.xml deleted file mode 100644 index ab5fdb29e4..0000000000 --- a/indra/newview/skins/default/xui/it/floater_model_wizard.xml +++ /dev/null @@ -1,208 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Model Wizard" title="PROCEDURA GUIDATA CARICA MODELLO"> - <button label="5. Carica sul server" name="upload_btn"/> - <button label="4. Rivedi" name="review_btn"/> - <button label="3. Fisica" name="physics_btn"/> - <button label="2. Ottimizza" name="optimize_btn"/> - <button label="1. Seleziona file" name="choose_file_btn"/> - <panel name="choose_file_panel"> - <panel name="choose_file_header_panel"> - <text name="choose_file_header_text"> - Seleziona file modello - </text> - </panel> - <panel name="choose_file_content"> - <text name="advanced_users_text"> - Utenti avanzati: Gli utenti che hanno dimestichezza con gli strumenti di creazione 3D possono usare le opzioni di caricamento avanzate. - </text> - <button label="Passa a modalità avanzata" name="switch_to_advanced"/> - <text name="Cache location"> - Scegli il file del modello da caricare - </text> - <button label="Sfoglia..." label_selected="Sfoglia..." name="browse"/> - <text name="Model types"> - Second Life supporta file COLLADA (.dae) - </text> - <text name="dimensions"> - X Y Z - </text> - <text name="warning_label"> - ATTENZIONE: - </text> - <text name="warning_text"> - Non sarà possibile completare il passaggio finale per il caricamento finale di questo modello sui server di Second Life. [secondlife:///app/floater/learn_more Scopri come] impostare l'account per il caricamento di modelli con reticolo. - </text> - </panel> - </panel> - <panel name="optimize_panel"> - <panel name="optimize_header_panel"> - <text name="optimize_header_text"> - Ottimizza modello - </text> - </panel> - <text name="optimize_description"> - Abbiamo ottimizzato il modello per migliorare le prestazioni. Se necessario, può essere regolato ulteriormente. - </text> - <panel name="optimize_content"> - <text name="high_detail_text"> - Genera livello di dettaglio: Alto - </text> - <text name="medium_detail_text"> - Genera livello di dettaglio: Medio - </text> - <text name="low_detail_text"> - Genera livello di dettaglio: Basso - </text> - <text name="lowest_detail_text"> - Genera livello di dettaglio: Bassissimo - </text> - </panel> - <panel name="content2"> - <button label="Ricalcola geometria" name="recalculate_geometry_btn"/> - <text name="lod_label"> - Anteprima geometria - </text> - <combo_box name="preview_lod_combo" tool_tip="Livello di dettaglio per anteprima rendering"> - <combo_item name="high"> - Molti dettagli - </combo_item> - <combo_item name="medium"> - Dettagli medi - </combo_item> - <combo_item name="low"> - Meno dettagli - </combo_item> - <combo_item name="lowest"> - Dettaglio minimo - </combo_item> - </combo_box> - </panel> - </panel> - <panel name="physics_panel"> - <panel name="physics_header_panel"> - <text name="physics_header_text"> - Modifica fisica - </text> - </panel> - <text name="physics_description"> - Verrà creata una forma per lo scafo esterno del modello. Regola il livello di dettaglio della forma in base al fine desiderato del modello. - </text> - <panel name="physics_content"> - <button label="Ricalcola fisica" name="recalculate_physics_btn"/> - <button label="Ricalcolo in corso..." name="recalculating_physics_btn"/> - <text name="lod_label"> - Anteprima fisica - </text> - <combo_box name="preview_lod_combo2" tool_tip="Livello di dettaglio per anteprima rendering"> - <combo_item name="high"> - Molti dettagli - </combo_item> - <combo_item name="medium"> - Dettagli medi - </combo_item> - <combo_item name="low"> - Meno dettagli - </combo_item> - <combo_item name="lowest"> - Dettaglio minimo - </combo_item> - </combo_box> - </panel> - </panel> - <panel name="review_panel"> - <panel name="review_header_panel"> - <text name="review_header_text"> - Rivedi - </text> - </panel> - <panel name="review_content"> - <text name="review_prim_equiv"> - Impatto sul lotto o sulla regione: [EQUIV] prim equivalenti - </text> - <text name="review_fee"> - All'account verrà accreditata una tariffa di caricamento pari a L$ [FEE]. - </text> - <text name="review_confirmation"> - Facendo clic sul pulsante Carica, confermi di possedere i diritti relativi ai materiali contenuti nel modello. - </text> - </panel> - </panel> - <panel name="upload_panel"> - <panel name="upload_header_panel"> - <text name="upload_header_text"> - Caricamento completato - </text> - </panel> - <text name="model_uploaded_text"> - Il modello è stato caricato. - </text> - <text name="inventory_text"> - Puoi trovarlo nella cartella Oggetti nel tuo inventario. - </text> - <text name="charged_fee"> - La somma di L$ [FEE] è stata addebitata sul tuo account. - </text> - </panel> - <button label="<< Indietro" name="back"/> - <button label="Avanti >>" name="next"/> - <button label="Calcolare pesi e tariffa >>" name="calculate"/> - <button label="Calcolo in corso..." name="calculating"/> - <button label="Carica" name="upload" tool_tip="Carica al simulatore"/> - <button label="Annulla" name="cancel"/> - <button label="Chiudi" name="close"/> - <spinner name="import_scale" value="1.0"/> - <string name="status_idle"> - Pausa - </string> - <string name="status_parse_error"> - Problema nell'elaborazione DAE - vedi il registro per informazioni al riguardo. - </string> - <string name="status_reading_file"> - Caricamento in corso... - </string> - <string name="status_generating_meshes"> - Generazione reticoli... - </string> - <string name="status_vertex_number_overflow"> - Errore: numero di vertici maggiore di 65534, annullato. - </string> - <string name="bad_element"> - Errore: elemento non valido - </string> - <string name="high"> - Alto - </string> - <string name="medium"> - Medio - </string> - <string name="low"> - Basso - </string> - <string name="lowest"> - Bassissimo - </string> - <string name="mesh_status_good"> - Invia! - </string> - <string name="mesh_status_na"> - N/D - </string> - <string name="mesh_status_none"> - Nessuno - </string> - <string name="mesh_status_submesh_mismatch"> - Ai vari livelli del dettaglio corrispondono numeri diversi di faccette con texture. - </string> - <string name="mesh_status_mesh_mismatch"> - Ai vari livelli del dettaglio corrispondono numeri diversi istanze di reticoli. - </string> - <string name="mesh_status_too_many_vertices"> - Troppi vertici per il livello di dettaglio. - </string> - <string name="mesh_status_missing_lod"> - Livello di dettaglio minimo mancante. - </string> - <string name="layer_all"> - Tutto - </string> -</floater> diff --git a/indra/newview/skins/default/xui/ja/floater_model_wizard.xml b/indra/newview/skins/default/xui/ja/floater_model_wizard.xml deleted file mode 100644 index 746bd8553c..0000000000 --- a/indra/newview/skins/default/xui/ja/floater_model_wizard.xml +++ /dev/null @@ -1,208 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Model Wizard" title="モデルウィザードをアップロード"> - <button label="5. アップロード" name="upload_btn"/> - <button label="4. 確認" name="review_btn"/> - <button label="3. 物理効果" name="physics_btn"/> - <button label="2. 最適化" name="optimize_btn"/> - <button label="1. ファイルを選択" name="choose_file_btn"/> - <panel name="choose_file_panel"> - <panel name="choose_file_header_panel"> - <text name="choose_file_header_text"> - モデルファイルを選択 - </text> - </panel> - <panel name="choose_file_content"> - <text name="advanced_users_text"> - 上級ユーザーの場合:3D コンテンツ制作ツールの使用に慣れている方は、高度なアップローダーもお試しください。 - </text> - <button label="アドバンスモードに切り替える" name="switch_to_advanced"/> - <text name="Cache location"> - アップロードするモデルファイルを選択 - </text> - <button label="参照..." label_selected="参照..." name="browse"/> - <text name="Model types"> - Second Life は COLLADA (.dae) ファイルをサポートします。 - </text> - <text name="dimensions"> - X Y Z - </text> - <text name="warning_label"> - 警告: - </text> - <text name="warning_text"> - このモデルを Second Life サーバーにアップロードするための最終手順を実行できません。[secondlife:///app/floater/learn_more こちらを参照して]、メッシュモデルをアップロードできるようにアカウントを設定してください。 - </text> - </panel> - </panel> - <panel name="optimize_panel"> - <panel name="optimize_header_panel"> - <text name="optimize_header_text"> - モデルを最適化 - </text> - </panel> - <text name="optimize_description"> - モデルはパフォーマンスを重視して最適化されています。必要に応じて調整してください。 - </text> - <panel name="optimize_content"> - <text name="high_detail_text"> - 次の描画詳細度を作成:高 - </text> - <text name="medium_detail_text"> - 次の描画詳細度を作成:中 - </text> - <text name="low_detail_text"> - 次の描画詳細度を作成:低 - </text> - <text name="lowest_detail_text"> - 次の描画詳細度を作成:最低 - </text> - </panel> - <panel name="content2"> - <button label="ジオメトリを再計算" name="recalculate_geometry_btn"/> - <text name="lod_label"> - ジオメトリのプレビュー - </text> - <combo_box name="preview_lod_combo" tool_tip="プレビュー表示の LOD 設定"> - <combo_item name="high"> - 高い詳細度 - </combo_item> - <combo_item name="medium"> - 中の詳細度 - </combo_item> - <combo_item name="low"> - 低い詳細度 - </combo_item> - <combo_item name="lowest"> - 最低の詳細度 - </combo_item> - </combo_box> - </panel> - </panel> - <panel name="physics_panel"> - <panel name="physics_header_panel"> - <text name="physics_header_text"> - 物理作用の調整 - </text> - </panel> - <text name="physics_description"> - モデルの外殻構造のシェイプは弊社が作成します。モデルの目的に応じてシェイプの詳細度を調整してください。 - </text> - <panel name="physics_content"> - <button label="物理作用を再計算" name="recalculate_physics_btn"/> - <button label="再計算中..." name="recalculating_physics_btn"/> - <text name="lod_label"> - 物理作用のプレビュー - </text> - <combo_box name="preview_lod_combo2" tool_tip="プレビュー表示の LOD 設定"> - <combo_item name="high"> - 高い詳細度 - </combo_item> - <combo_item name="medium"> - 中の詳細度 - </combo_item> - <combo_item name="low"> - 低い詳細度 - </combo_item> - <combo_item name="lowest"> - 最低の詳細度 - </combo_item> - </combo_box> - </panel> - </panel> - <panel name="review_panel"> - <panel name="review_header_panel"> - <text name="review_header_text"> - 確認 - </text> - </panel> - <panel name="review_content"> - <text name="review_prim_equiv"> - 区画/リージョンへの負荷:[EQUIV] プリム換算値 - </text> - <text name="review_fee"> - L$ [FEE] のアップロード料金があなたのアカウントに請求されます。 - </text> - <text name="review_confirmation"> - アップロードボタンをクリックすることにより、モデルに含まれるマテリアルの所有権や使用許可の所持を認めたことになります。 - </text> - </panel> - </panel> - <panel name="upload_panel"> - <panel name="upload_header_panel"> - <text name="upload_header_text"> - アップロード完了 - </text> - </panel> - <text name="model_uploaded_text"> - モデルがアップロードされました。 - </text> - <text name="inventory_text"> - それはインベントリの「オブジェクト」フォルダにあります。 - </text> - <text name="charged_fee"> - あなたのアカウントに L$ [FEE] が請求されました。 - </text> - </panel> - <button label="<< 戻る" name="back"/> - <button label="次へ>>" name="next"/> - <button label="ウェイトと料金の計算 >>" name="calculate"/> - <button label="計算中..." name="calculating"/> - <button label="アップロード" name="upload" tool_tip="シミュレーターにアップロード"/> - <button label="取り消し" name="cancel"/> - <button label="閉じる" name="close"/> - <spinner name="import_scale" value="1.0"/> - <string name="status_idle"> - 待機状態 - </string> - <string name="status_parse_error"> - Dae に問題が見つかりました - 詳細についてはログをご参照ください。 - </string> - <string name="status_reading_file"> - ローディング... - </string> - <string name="status_generating_meshes"> - メッシュを作成中 - </string> - <string name="status_vertex_number_overflow"> - エラー:頂点の数が65534を超過したので中止されました。 - </string> - <string name="bad_element"> - エラー:要素が無効です - </string> - <string name="high"> - 高 - </string> - <string name="medium"> - 中 - </string> - <string name="low"> - 低 - </string> - <string name="lowest"> - 最低 - </string> - <string name="mesh_status_good"> - 発送 - </string> - <string name="mesh_status_na"> - 該当なし - </string> - <string name="mesh_status_none"> - なし - </string> - <string name="mesh_status_submesh_mismatch"> - テクスチャ編集可能な面の数は描画詳細度に応じて異なります。 - </string> - <string name="mesh_status_mesh_mismatch"> - メッシュインスタンスの数は描画詳細度に応じて異なります。 - </string> - <string name="mesh_status_too_many_vertices"> - 描画詳細度に対して頂点の数が多すぎます。 - </string> - <string name="mesh_status_missing_lod"> - 必要な描画詳細度が見つかりません。 - </string> - <string name="layer_all"> - 全て - </string> -</floater> diff --git a/indra/newview/skins/default/xui/ja/notifications.xml b/indra/newview/skins/default/xui/ja/notifications.xml index 54031ccf12..7bf8a7b8be 100644 --- a/indra/newview/skins/default/xui/ja/notifications.xml +++ b/indra/newview/skins/default/xui/ja/notifications.xml @@ -2895,6 +2895,18 @@ M キーを押して変更します。 [RESIDENTS] <usetemplate name="okcancelbuttons" notext="取り消し" yestext="Ok"/> </notification> + <notification name="ShareFolderConfirmation"> + フォルダは一度に 1 つしか共有できません。 + +次のアイテムを共有しますか? + +<nolink>[ITEMS]</nolink> + +次の住人と共有: + +[RESIDENTS] + <usetemplate name="okcancelbuttons" notext="取り消し" yestext="Ok"/> + </notification> <notification name="ItemsShared"> アイテムが共有されました。 </notification> diff --git a/indra/newview/skins/default/xui/pt/floater_model_wizard.xml b/indra/newview/skins/default/xui/pt/floater_model_wizard.xml deleted file mode 100644 index 0d07303c91..0000000000 --- a/indra/newview/skins/default/xui/pt/floater_model_wizard.xml +++ /dev/null @@ -1,208 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Model Wizard" title="CARREGAR ASSISTENTE DE MODELAGEM"> - <button label="5. Carregar" name="upload_btn"/> - <button label="4. Revisar" name="review_btn"/> - <button label="3. Física" name="physics_btn"/> - <button label="2. Otimizar" name="optimize_btn"/> - <button label="1. Selecionra arquivo" name="choose_file_btn"/> - <panel name="choose_file_panel"> - <panel name="choose_file_header_panel"> - <text name="choose_file_header_text"> - Escolher arquivo de modelo - </text> - </panel> - <panel name="choose_file_content"> - <text name="advanced_users_text"> - Usuários avançados: se você estiver familiarizado com ferramentas de criação de conteúdo 3D, use o Advanced Uploader. - </text> - <button label="Trocar para avançado" name="switch_to_advanced"/> - <text name="Cache location"> - Escolha o arquivo de modelo para upload - </text> - <button label="Procurar..." label_selected="Procurar..." name="browse"/> - <text name="Model types"> - O Second Life oferece suporte a arquivos COLLADA (.dae) - </text> - <text name="dimensions"> - X Y Z - </text> - <text name="warning_label"> - AVISO: - </text> - <text name="warning_text"> - Não será possível concluir a etapa final do upload desse modelo para os servidores do Second Life. [secondlife:///app/floater/learn_more Saiba como] configurar sua conta para uploads de modelos mesh. - </text> - </panel> - </panel> - <panel name="optimize_panel"> - <panel name="optimize_header_panel"> - <text name="optimize_header_text"> - Otimizar modelo - </text> - </panel> - <text name="optimize_description"> - O modelo foi ajustado para desempenho. Faça novos ajustes, se desejar. - </text> - <panel name="optimize_content"> - <text name="high_detail_text"> - Gerar nível de detalhes: Alto - </text> - <text name="medium_detail_text"> - Gerar nível de detalhes: Médio - </text> - <text name="low_detail_text"> - Gerar nível de detalhes: Baixo - </text> - <text name="lowest_detail_text"> - Gerar nível de detalhes: Mais baixo - </text> - </panel> - <panel name="content2"> - <button label="Recalcular geometria" name="recalculate_geometry_btn"/> - <text name="lod_label"> - Visualização da geometria - </text> - <combo_box name="preview_lod_combo" tool_tip="LOD para exibir na renderização de visualização"> - <combo_item name="high"> - Máximo de detalhes - </combo_item> - <combo_item name="medium"> - Detalhes médios - </combo_item> - <combo_item name="low"> - Poucos detalhes - </combo_item> - <combo_item name="lowest"> - Mínimo de detalhes - </combo_item> - </combo_box> - </panel> - </panel> - <panel name="physics_panel"> - <panel name="physics_header_panel"> - <text name="physics_header_text"> - Ajustar físico - </text> - </panel> - <text name="physics_description"> - Criaremos uma forma para o corpo externo do modelo. Ajuste o nível de detalhes como necessário para a finalidade desejada de seu modelo. - </text> - <panel name="physics_content"> - <button label="Recalcular físico" name="recalculate_physics_btn"/> - <button label="Recalculando..." name="recalculating_physics_btn"/> - <text name="lod_label"> - Visualização do físico - </text> - <combo_box name="preview_lod_combo2" tool_tip="LOD para exibir na renderização de visualização"> - <combo_item name="high"> - Máximo de detalhes - </combo_item> - <combo_item name="medium"> - Detalhes médios - </combo_item> - <combo_item name="low"> - Poucos detalhes - </combo_item> - <combo_item name="lowest"> - Mínimo de detalhes - </combo_item> - </combo_box> - </panel> - </panel> - <panel name="review_panel"> - <panel name="review_header_panel"> - <text name="review_header_text"> - Revisar - </text> - </panel> - <panel name="review_content"> - <text name="review_prim_equiv"> - Impacto no lote/região: [EQUIV] equivalentes de prim - </text> - <text name="review_fee"> - Uma tarifa de upload de L$ [FEE] será debitada da sua conta. - </text> - <text name="review_confirmation"> - Ao clicar no botão de upload, você confirma que detém os direitos apropriados sobre o material contido no modelo. - </text> - </panel> - </panel> - <panel name="upload_panel"> - <panel name="upload_header_panel"> - <text name="upload_header_text"> - Upload concluído - </text> - </panel> - <text name="model_uploaded_text"> - Seu modelo foi carregado. - </text> - <text name="inventory_text"> - Disponível na pasta Objetos do seu inventário. - </text> - <text name="charged_fee"> - L$ [FEE] foram debitados da sua conta. - </text> - </panel> - <button label="<< Voltar" name="back"/> - <button label="Próximo >>" name="next"/> - <button label="Calcular pesos e tarifa >>" name="calculate"/> - <button label="Calculando..." name="calculating"/> - <button label="Carregar" name="upload" tool_tip="Carregar no simulador"/> - <button label="Cancelar" name="cancel"/> - <button label="Fechar" name="close"/> - <spinner name="import_scale" value="1.0"/> - <string name="status_idle"> - Inativo - </string> - <string name="status_parse_error"> - Dae parsing - erro, detalhes no log. - </string> - <string name="status_reading_file"> - Carregando... - </string> - <string name="status_generating_meshes"> - Gerando meshes... - </string> - <string name="status_vertex_number_overflow"> - Erro: Número de Vertex acima de 65534. Abortado. - </string> - <string name="bad_element"> - Erro: elemento inválido - </string> - <string name="high"> - Alto - </string> - <string name="medium"> - Médio - </string> - <string name="low"> - Baixo - </string> - <string name="lowest"> - Mais baixo - </string> - <string name="mesh_status_good"> - Entregar! - </string> - <string name="mesh_status_na"> - N/D - </string> - <string name="mesh_status_none"> - Nenhum - </string> - <string name="mesh_status_submesh_mismatch"> - Cada nível de detalhamento têm um número de faces para textura. - </string> - <string name="mesh_status_mesh_mismatch"> - Cada nível de detalhamento têm um número de faces para textura. - </string> - <string name="mesh_status_too_many_vertices"> - O nível de detalhamento possui vértices demais. - </string> - <string name="mesh_status_missing_lod"> - Falta o nível de detalhamento necessário. - </string> - <string name="layer_all"> - Tudo - </string> -</floater> diff --git a/indra/newview/skins/default/xui/pt/menu_viewer.xml b/indra/newview/skins/default/xui/pt/menu_viewer.xml index d7d5d59a33..fd973bf3c2 100644 --- a/indra/newview/skins/default/xui/pt/menu_viewer.xml +++ b/indra/newview/skins/default/xui/pt/menu_viewer.xml @@ -118,7 +118,7 @@ <menu_item_call label="Devolver objeto" name="Return Object back to Owner"/> </menu> <menu label="Scripts" name="Scripts"> - <menu_item_call label="Recompilar scripts (LSL)" name="Mono"/> + <menu_item_call label="Recompilar scripts (Mono)" name="Mono"/> <menu_item_call label="Recompilar scripts (LSL)" name="LSL"/> <menu_item_call label="Resetar scripts" name="Reset Scripts"/> <menu_item_call label="Scripts em modo execução" name="Set Scripts to Running"/> @@ -163,7 +163,7 @@ <menu_item_check label="Limitar distância da seleção" name="Limit Select Distance"/> <menu_item_check label="Disable Camera Constraints" name="Disable Camera Distance"/> <menu_item_check label="Foto de alta resolução" name="HighResSnapshot"/> - <menu_item_check label="Compactar fotos para HD" name="QuietSnapshotsToDisk"/> + <menu_item_check label="Fotos sem barulho para HD" name="QuietSnapshotsToDisk"/> <menu label="Ferramentas de desempenho" name="Performance Tools"> <menu_item_call label="Medidor de lag" name="Lag Meter"/> <menu_item_check label="Barra de estatísticas" name="Statistics Bar"/> diff --git a/indra/newview/skins/default/xui/ru/floater_model_wizard.xml b/indra/newview/skins/default/xui/ru/floater_model_wizard.xml deleted file mode 100644 index c1a63bf7da..0000000000 --- a/indra/newview/skins/default/xui/ru/floater_model_wizard.xml +++ /dev/null @@ -1,208 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Model Wizard" title="ПЕРЕДАТЬ МАСТЕР МОДЕЛИРОВАНИЯ"> - <button label="5. Передать" name="upload_btn"/> - <button label="4. Просмотр" name="review_btn"/> - <button label="3. Физика" name="physics_btn"/> - <button label="2. Оптимизировать" name="optimize_btn"/> - <button label="1. Выбрать файл" name="choose_file_btn"/> - <panel name="choose_file_panel"> - <panel name="choose_file_header_panel"> - <text name="choose_file_header_text"> - Выберите файл модели - </text> - </panel> - <panel name="choose_file_content"> - <text name="advanced_users_text"> - Пользователям, работающим в расширенном режиме: если вы умеете создавать трехмерные графические объекты, то, возможно, захотите воспользоваться средством Advanced Uploader, которое предоставляет расширенные возможности передачи объектов. - </text> - <button label="Перейти в расширенный режим" name="switch_to_advanced"/> - <text name="Cache location"> - Выберите файл модели для передачи - </text> - <button label="Обзор..." label_selected="Обзор..." name="browse"/> - <text name="Model types"> - В Second Life поддерживаются файлы COLLADA (.dae) - </text> - <text name="dimensions"> - X Y Z - </text> - <text name="warning_label"> - ВНИМАНИЕ! - </text> - <text name="warning_text"> - Вы не сможете завершить передачу этой модели на серверы Second Life. [secondlife:///app/floater/learn_more Узнайте, как] настроить в вашем аккаунте передачу сеточных моделей. - </text> - </panel> - </panel> - <panel name="optimize_panel"> - <panel name="optimize_header_panel"> - <text name="optimize_header_text"> - Оптимизировать модель - </text> - </panel> - <text name="optimize_description"> - Мы оптимизировали модель для повышения быстродействия. По желанию можно выполнить дополнительную настройку. - </text> - <panel name="optimize_content"> - <text name="high_detail_text"> - Создать уровень детализации: Высокий - </text> - <text name="medium_detail_text"> - Создать уровень детализации: Средний - </text> - <text name="low_detail_text"> - Создать уровень детализации: Низкий - </text> - <text name="lowest_detail_text"> - Создать уровень детализации: Самый низкий - </text> - </panel> - <panel name="content2"> - <button label="Пересчитать геометрию" name="recalculate_geometry_btn"/> - <text name="lod_label"> - Просмотр геометрии - </text> - <combo_box name="preview_lod_combo" tool_tip="Детализация при предварительном просмотре"> - <combo_item name="high"> - Детально - </combo_item> - <combo_item name="medium"> - Средняя детализация - </combo_item> - <combo_item name="low"> - Мало деталей - </combo_item> - <combo_item name="lowest"> - Минимум деталей - </combo_item> - </combo_box> - </panel> - </panel> - <panel name="physics_panel"> - <panel name="physics_header_panel"> - <text name="physics_header_text"> - Настроить физические параметры - </text> - </panel> - <text name="physics_description"> - Мы создадим форму для внешнего каркаса модели. Настройте уровень детализации формы в соответствии с целями, для которых предназначена модель. - </text> - <panel name="physics_content"> - <button label="Пересчитать физические данные" name="recalculate_physics_btn"/> - <button label="Пересчет..." name="recalculating_physics_btn"/> - <text name="lod_label"> - Просмотр физических данных - </text> - <combo_box name="preview_lod_combo2" tool_tip="Уровень детализации при предварительном просмотре"> - <combo_item name="high"> - Детально - </combo_item> - <combo_item name="medium"> - Средняя детализация - </combo_item> - <combo_item name="low"> - Мало деталей - </combo_item> - <combo_item name="lowest"> - Минимум деталей - </combo_item> - </combo_box> - </panel> - </panel> - <panel name="review_panel"> - <panel name="review_header_panel"> - <text name="review_header_text"> - Просмотр - </text> - </panel> - <panel name="review_content"> - <text name="review_prim_equiv"> - Воздействие на участок/регион: эквивалент в примитивах: [EQUIV] - </text> - <text name="review_fee"> - За передачу с вашего счета будет снята плата в размере L$[FEE]. - </text> - <text name="review_confirmation"> - Нажав кнопку «Передать», вы подтверждаете, что у вас есть надлежащие права на все составляющие модели. - </text> - </panel> - </panel> - <panel name="upload_panel"> - <panel name="upload_header_panel"> - <text name="upload_header_text"> - Передача завершена - </text> - </panel> - <text name="model_uploaded_text"> - Ваша модель передана. - </text> - <text name="inventory_text"> - Находится в папке «Объекты» вашего инвентаря. - </text> - <text name="charged_fee"> - С вашего счета снято: L$[FEE]. - </text> - </panel> - <button label="<< Назад" name="back"/> - <button label="Далее >>" name="next"/> - <button label="Рассчитать вес и плату >>" name="calculate"/> - <button label="Расчет..." name="calculating"/> - <button label="Передать" name="upload" tool_tip="Передать в симулятор"/> - <button label="Отмена" name="cancel"/> - <button label="Закрыть" name="close"/> - <spinner name="import_scale" value="1.0"/> - <string name="status_idle"> - Неактивно - </string> - <string name="status_parse_error"> - Проблема при анализе файла DAE – см. подробности в журнале. - </string> - <string name="status_reading_file"> - Загрузка... - </string> - <string name="status_generating_meshes"> - Создаются меши... - </string> - <string name="status_vertex_number_overflow"> - Ошибка. Число вершин превышает 65534. Прервано. - </string> - <string name="bad_element"> - Ошибка: недопустимый элемент - </string> - <string name="high"> - высокий - </string> - <string name="medium"> - средний - </string> - <string name="low"> - низкий - </string> - <string name="lowest"> - самый низкий - </string> - <string name="mesh_status_good"> - Доставлено! - </string> - <string name="mesh_status_na"> - Н/Д - </string> - <string name="mesh_status_none"> - Нет - </string> - <string name="mesh_status_submesh_mismatch"> - Отличается число текстурируемых граней на уровнях детализации. - </string> - <string name="mesh_status_mesh_mismatch"> - Отличается число экземпляров меша на уровнях детализации. - </string> - <string name="mesh_status_too_many_vertices"> - Слишком много вершин на уровне детализации. - </string> - <string name="mesh_status_missing_lod"> - Отсутствует необходимый уровень детализации. - </string> - <string name="layer_all"> - Все - </string> -</floater> diff --git a/indra/newview/skins/default/xui/tr/floater_model_wizard.xml b/indra/newview/skins/default/xui/tr/floater_model_wizard.xml deleted file mode 100644 index 9d8b982c24..0000000000 --- a/indra/newview/skins/default/xui/tr/floater_model_wizard.xml +++ /dev/null @@ -1,208 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Model Wizard" title="KARŞIYA MODEL YÜKLEME SİHİRBAZI"> - <button label="5. Karşıya Yükle" name="upload_btn"/> - <button label="4. İncele" name="review_btn"/> - <button label="3. Fizik" name="physics_btn"/> - <button label="2. Optimize et" name="optimize_btn"/> - <button label="1. Dosya Seç" name="choose_file_btn"/> - <panel name="choose_file_panel"> - <panel name="choose_file_header_panel"> - <text name="choose_file_header_text"> - Model dosyasını seçin - </text> - </panel> - <panel name="choose_file_content"> - <text name="advanced_users_text"> - Gelişmiş kullanıcılar: Eğer 3B içerik oluşturma araçlarını kullanmayı biliyorsanız, Gelişmiş Karşıya Yükleyiciyi kullanmak isteyebilirsiniz. - </text> - <button label="Gelişmişe geç" name="switch_to_advanced"/> - <text name="Cache location"> - Karşıya yüklenecek model dosyasını seçin - </text> - <button label="Gözat..." label_selected="Gözat..." name="browse"/> - <text name="Model types"> - Second Life, COLLADA (.dae) dosyalarını destekler - </text> - <text name="dimensions"> - X Y Z - </text> - <text name="warning_label"> - UYARI: - </text> - <text name="warning_text"> - Bu modelin Second Life sunucularına nihai karşıya yükleme adımını tamamlayamayacaksınız. Hesabınızı örgü modellerinin karşıya yüklenmesi için ayarlamanın [secondlife:///app/floater/learn_more nasıl yapılacağını öğrenin]. - </text> - </panel> - </panel> - <panel name="optimize_panel"> - <panel name="optimize_header_panel"> - <text name="optimize_header_text"> - Modeli optimize et - </text> - </panel> - <text name="optimize_description"> - Modeli performans için optimize ettik. İstiyorsanız daha da ayarlayabilirsiniz. - </text> - <panel name="optimize_content"> - <text name="high_detail_text"> - Ayrıntı Seviyesi Oluştur: Yüksek - </text> - <text name="medium_detail_text"> - Ayrıntı Seviyesi Oluştur: Orta - </text> - <text name="low_detail_text"> - Ayrıntı Seviyesi Oluştur: Düşük - </text> - <text name="lowest_detail_text"> - Ayrıntı Seviyesi Oluştur: En Düşük - </text> - </panel> - <panel name="content2"> - <button label="Geometri hesaplarını tekrar yap" name="recalculate_geometry_btn"/> - <text name="lod_label"> - Geometri önizleme - </text> - <combo_box name="preview_lod_combo" tool_tip="Önizleme işlemesinde görülecek ayrıntı seviyesi"> - <combo_item name="high"> - Çok ayrıntı - </combo_item> - <combo_item name="medium"> - Orta düzey ayrıntı - </combo_item> - <combo_item name="low"> - Az ayrıntı - </combo_item> - <combo_item name="lowest"> - En az ayrıntı - </combo_item> - </combo_box> - </panel> - </panel> - <panel name="physics_panel"> - <panel name="physics_header_panel"> - <text name="physics_header_text"> - Fizik ayarlarını yap - </text> - </panel> - <text name="physics_description"> - Modelin dış gövdesi için bir şekil oluşturacağız. Modelinizin amacına uygun olarak şeklin ayrıntı seviyesini belirleyin. - </text> - <panel name="physics_content"> - <button label="Fizik hesaplarını tekrar yap" name="recalculate_physics_btn"/> - <button label="Tekrar hesaplanıyor..." name="recalculating_physics_btn"/> - <text name="lod_label"> - Fizik önizleme - </text> - <combo_box name="preview_lod_combo2" tool_tip="Önizleme işlemesinde görülecek ayrıntı seviyesi"> - <combo_item name="high"> - Çok ayrıntı - </combo_item> - <combo_item name="medium"> - Orta düzey ayrıntı - </combo_item> - <combo_item name="low"> - Az ayrıntı - </combo_item> - <combo_item name="lowest"> - En az ayrıntı - </combo_item> - </combo_box> - </panel> - </panel> - <panel name="review_panel"> - <panel name="review_header_panel"> - <text name="review_header_text"> - İncele - </text> - </panel> - <panel name="review_content"> - <text name="review_prim_equiv"> - Parsele/bölgeye etkisi: [EQUIV] prim eşdeğerleri - </text> - <text name="review_fee"> - Hesabınızdan L$ [FEE] karşıya yükleme ücreti düşülecektir. - </text> - <text name="review_confirmation"> - Karşıya yükleme düğmesine tıkladığınızda, modelde yer alan malzeme için ilgili haklara sahip olduğunuzu teyid edersiniz. - </text> - </panel> - </panel> - <panel name="upload_panel"> - <panel name="upload_header_panel"> - <text name="upload_header_text"> - Karşıya yükleme bitti - </text> - </panel> - <text name="model_uploaded_text"> - Modeliniz karşıya yüklendi. - </text> - <text name="inventory_text"> - Bunu, envanterinizdeki Nesneler klasöründe bulacaksınız. - </text> - <text name="charged_fee"> - Hesabınızdan L$ [FEE] düşüldü. - </text> - </panel> - <button label="<< Geri" name="back"/> - <button label="Sonraki >>" name="next"/> - <button label="Ağırlıkları ve ücreti hesapla >>" name="calculate"/> - <button label="Hesaplanıyor..." name="calculating"/> - <button label="Karşıya Yükle" name="upload" tool_tip="Simülatöre karşıya yükle"/> - <button label="İptal" name="cancel"/> - <button label="Kapat" name="close"/> - <spinner name="import_scale" value="1.0"/> - <string name="status_idle"> - Boşta - </string> - <string name="status_parse_error"> - Dae ayrıştırma sorunu - ayrıntılar için günlüğe bakın. - </string> - <string name="status_reading_file"> - Yükleniyor... - </string> - <string name="status_generating_meshes"> - Örgüler Oluşturuluyor... - </string> - <string name="status_vertex_number_overflow"> - Hata: Köşe numarası 65534'ten fazla, işlem durduruldu! - </string> - <string name="bad_element"> - Hata: Öğe geçersiz - </string> - <string name="high"> - Yüksek - </string> - <string name="medium"> - Orta - </string> - <string name="low"> - Düşük - </string> - <string name="lowest"> - En Düşük - </string> - <string name="mesh_status_good"> - Uygula! - </string> - <string name="mesh_status_na"> - G/D - </string> - <string name="mesh_status_none"> - Hiçbiri - </string> - <string name="mesh_status_submesh_mismatch"> - Ayrıntı seviyelerinde farklı sayıda dokulanabilir yüz var. - </string> - <string name="mesh_status_mesh_mismatch"> - Ayrıntı seviyelerinde farklı sayıda örgü örneği var. - </string> - <string name="mesh_status_too_many_vertices"> - Ayrıntı seviyesinde fazla sayıda köşe var. - </string> - <string name="mesh_status_missing_lod"> - Gereken ayrıntı seviyesi eksik. - </string> - <string name="layer_all"> - Tümü - </string> -</floater> diff --git a/indra/newview/tests/llagentaccess_test.cpp b/indra/newview/tests/llagentaccess_test.cpp index c970d79975..0141a219c5 100644 --- a/indra/newview/tests/llagentaccess_test.cpp +++ b/indra/newview/tests/llagentaccess_test.cpp @@ -111,18 +111,6 @@ namespace tut ensure("1 isMature", !aa.isMature()); ensure("1 isAdult", !aa.isAdult()); - // this is kinda bad -- setting this forces maturity to MATURE but !teen != Mature anymore - aa.setTeen(false); - ensure("2 isTeen", !aa.isTeen()); - ensure("2 isMature", aa.isMature()); - ensure("2 isAdult", !aa.isAdult()); - - // have to flip it back and make sure it still works - aa.setTeen(true); - ensure("3 isTeen", aa.isTeen()); - ensure("3 isMature", !aa.isMature()); - ensure("3 isAdult", !aa.isAdult()); - // check the conversion routine ensure_equals("1 conversion", SIM_ACCESS_PG, aa.convertTextToMaturity('P')); ensure_equals("2 conversion", SIM_ACCESS_MATURE, aa.convertTextToMaturity('M')); @@ -131,21 +119,21 @@ namespace tut // now try the other method of setting it - PG aa.setMaturity('P'); - ensure("4 isTeen", aa.isTeen()); - ensure("4 isMature", !aa.isMature()); - ensure("4 isAdult", !aa.isAdult()); + ensure("2 isTeen", aa.isTeen()); + ensure("2 isMature", !aa.isMature()); + ensure("2 isAdult", !aa.isAdult()); // Mature aa.setMaturity('M'); - ensure("5 isTeen", !aa.isTeen()); - ensure("5 isMature", aa.isMature()); - ensure("5 isAdult", !aa.isAdult()); + ensure("3 isTeen", !aa.isTeen()); + ensure("3 isMature", aa.isMature()); + ensure("3 isAdult", !aa.isAdult()); // Adult aa.setMaturity('A'); - ensure("6 isTeen", !aa.isTeen()); - ensure("6 isMature", aa.isMature()); - ensure("6 isAdult", aa.isAdult()); + ensure("4 isTeen", !aa.isTeen()); + ensure("4 isMature", aa.isMature()); + ensure("4 isAdult", aa.isAdult()); } @@ -239,18 +227,6 @@ namespace tut cgr.declareU32("PreferredMaturity", SIM_ACCESS_PG, "declared_for_test", FALSE); LLAgentAccess aa(cgr); - ensure("1 transition starts false", !aa.isInTransition()); - aa.setTransition(); - ensure("2 transition now true", aa.isInTransition()); - } - - template<> template<> - void agentaccess_object_t::test<6>() - { - LLControlGroup cgr("test"); - cgr.declareU32("PreferredMaturity", SIM_ACCESS_PG, "declared_for_test", FALSE); - LLAgentAccess aa(cgr); - cgr.setU32("PreferredMaturity", SIM_ACCESS_ADULT); aa.setMaturity('M'); ensure("1 preferred maturity pegged to M when maturity is M", cgr.getU32("PreferredMaturity") == SIM_ACCESS_MATURE); diff --git a/indra/newview/tests/llviewerassetstats_test.cpp b/indra/newview/tests/llviewerassetstats_test.cpp index 3faddc13c1..f8923b9868 100644 --- a/indra/newview/tests/llviewerassetstats_test.cpp +++ b/indra/newview/tests/llviewerassetstats_test.cpp @@ -35,6 +35,31 @@ #include "lluuid.h" #include "llsdutil.h" #include "llregionhandle.h" +#include "../llvoavatar.h" + +void LLVOAvatar::getNearbyRezzedStats(std::vector<S32>& counts) +{ + counts.resize(3); + counts[0] = 0; + counts[1] = 0; + counts[2] = 1; +} + +// static +std::string LLVOAvatar::rezStatusToString(S32 rez_status) +{ + if (rez_status==0) return "cloud"; + if (rez_status==1) return "gray"; + if (rez_status==2) return "textured"; + return "unknown"; +} + +// static +LLViewerStats::StatsAccumulator& LLViewerStats::PhaseMap::getPhaseStats(const std::string& phase_name) +{ + static LLViewerStats::StatsAccumulator junk; + return junk; +} static const char * all_keys[] = { @@ -104,18 +129,25 @@ is_single_key_map(const LLSD & sd, const std::string & key) { return sd.isMap() && 1 == sd.size() && sd.has(key); } -#endif static bool is_double_key_map(const LLSD & sd, const std::string & key1, const std::string & key2) { return sd.isMap() && 2 == sd.size() && sd.has(key1) && sd.has(key2); } +#endif + +static bool +is_triple_key_map(const LLSD & sd, const std::string & key1, const std::string & key2, const std::string& key3) +{ + return sd.isMap() && 3 == sd.size() && sd.has(key1) && sd.has(key2) && sd.has(key3); +} + static bool is_no_stats_map(const LLSD & sd) { - return is_double_key_map(sd, "duration", "regions"); + return is_triple_key_map(sd, "duration", "regions", "avatar"); } static bool @@ -226,7 +258,7 @@ namespace tut // Once the region is set, we will get a response even with no data collection it->setRegion(region1_handle); sd_full = it->asLLSD(false); - ensure("Correct single-key LLSD map root", is_double_key_map(sd_full, "duration", "regions")); + ensure("Correct single-key LLSD map root", is_triple_key_map(sd_full, "duration", "regions", "avatar")); ensure("Correct single-slot LLSD array regions", is_single_slot_array(sd_full["regions"], region1_handle)); LLSD sd = sd_full["regions"][0]; @@ -267,7 +299,7 @@ namespace tut it->setRegion(region1_handle); LLSD sd = it->asLLSD(false); - ensure("Correct single-key LLSD map root", is_double_key_map(sd, "regions", "duration")); + ensure("Correct single-key LLSD map root", is_triple_key_map(sd, "regions", "duration", "avatar")); ensure("Correct single-slot LLSD array regions", is_single_slot_array(sd["regions"], region1_handle)); sd = sd[0]; @@ -292,7 +324,7 @@ namespace tut LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_BODYPART, false, false); LLSD sd = gViewerAssetStatsMain->asLLSD(false); - ensure("Correct single-key LLSD map root", is_double_key_map(sd, "regions", "duration")); + ensure("Correct single-key LLSD map root", is_triple_key_map(sd, "regions", "duration", "avatar")); ensure("Correct single-slot LLSD array regions", is_single_slot_array(sd["regions"], region1_handle)); sd = sd["regions"][0]; @@ -332,7 +364,7 @@ namespace tut LLSD sd = gViewerAssetStatsThread1->asLLSD(false); ensure("Other collector is empty", is_no_stats_map(sd)); sd = gViewerAssetStatsMain->asLLSD(false); - ensure("Correct single-key LLSD map root", is_double_key_map(sd, "regions", "duration")); + ensure("Correct single-key LLSD map root", is_triple_key_map(sd, "regions", "duration", "avatar")); ensure("Correct single-slot LLSD array regions", is_single_slot_array(sd["regions"], region1_handle)); sd = sd["regions"][0]; @@ -382,7 +414,7 @@ namespace tut // std::cout << sd << std::endl; - ensure("Correct double-key LLSD map root", is_double_key_map(sd, "duration", "regions")); + ensure("Correct double-key LLSD map root", is_triple_key_map(sd, "duration", "regions", "avatar")); ensure("Correct double-slot LLSD array regions", is_double_slot_array(sd["regions"], region1_handle, region2_handle)); LLSD sd1 = get_region(sd, region1_handle); LLSD sd2 = get_region(sd, region2_handle); @@ -405,7 +437,7 @@ namespace tut // Reset leaves current region in place gViewerAssetStatsMain->reset(); sd = gViewerAssetStatsMain->asLLSD(false); - ensure("Correct single-key LLSD map root", is_double_key_map(sd, "regions", "duration")); + ensure("Correct single-key LLSD map root", is_triple_key_map(sd, "regions", "duration", "avatar")); ensure("Correct single-slot LLSD array regions (p2)", is_single_slot_array(sd["regions"], region2_handle)); sd2 = sd["regions"][0]; @@ -454,7 +486,7 @@ namespace tut LLSD sd = gViewerAssetStatsMain->asLLSD(false); - ensure("Correct double-key LLSD map root", is_double_key_map(sd, "duration", "regions")); + ensure("Correct double-key LLSD map root", is_triple_key_map(sd, "duration", "regions", "avatar")); ensure("Correct double-slot LLSD array regions", is_double_slot_array(sd["regions"], region1_handle, region2_handle)); LLSD sd1 = get_region(sd, region1_handle); LLSD sd2 = get_region(sd, region2_handle); @@ -477,7 +509,7 @@ namespace tut // Reset leaves current region in place gViewerAssetStatsMain->reset(); sd = gViewerAssetStatsMain->asLLSD(false); - ensure("Correct single-key LLSD map root", is_double_key_map(sd, "duration", "regions")); + ensure("Correct single-key LLSD map root", is_triple_key_map(sd, "duration", "regions", "avatar")); ensure("Correct single-slot LLSD array regions (p2)", is_single_slot_array(sd["regions"], region2_handle)); sd2 = get_region(sd, region2_handle); ensure("Region2 is present in results", sd2.isMap()); @@ -523,7 +555,7 @@ namespace tut LLSD sd = gViewerAssetStatsThread1->asLLSD(false); ensure("Other collector is empty", is_no_stats_map(sd)); sd = gViewerAssetStatsMain->asLLSD(false); - ensure("Correct single-key LLSD map root", is_double_key_map(sd, "regions", "duration")); + ensure("Correct single-key LLSD map root", is_triple_key_map(sd, "regions", "duration", "avatar")); ensure("Correct single-slot LLSD array regions", is_single_slot_array(sd["regions"], region1_handle)); sd = get_region(sd, region1_handle); ensure("Region1 is present in results", sd.isMap()); diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 9bf755c8f8..7c6b5403e1 100644 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -91,6 +91,13 @@ class ViewerManifest(LLManifest): # ... and the entire windlight directory self.path("windlight") + + # ... and the included spell checking dictionaries + pkgdir = os.path.join(self.args['build'], os.pardir, 'packages') + if self.prefix(src=pkgdir,dst=""): + self.path("dictionaries") + self.end_prefix(pkgdir) + self.end_prefix("app_settings") if self.prefix(src="character"): @@ -393,6 +400,9 @@ class WindowsManifest(ViewerManifest): self.path("ssleay32.dll") self.path("libeay32.dll") + # Hunspell + self.path("libhunspell.dll") + # For google-perftools tcmalloc allocator. try: if self.args['configuration'].lower() == 'debug': @@ -659,6 +669,7 @@ class DarwinManifest(ViewerManifest): # copy additional libs in <bundle>/Contents/MacOS/ self.path("../packages/lib/release/libndofdev.dylib", dst="Resources/libndofdev.dylib") + self.path("../packages/lib/release/libhunspell-1.3.0.dylib", dst="Resources/libhunspell-1.3.0.dylib") self.path("../viewer_components/updater/scripts/darwin/update_install", "MacOS/update_install") @@ -1025,45 +1036,51 @@ class Linux_i686Manifest(LinuxManifest): super(Linux_i686Manifest, self).construct() if self.prefix("../packages/lib/release", dst="lib"): - self.path("libapr-1.so") - self.path("libapr-1.so.0") - self.path("libapr-1.so.0.4.2") - self.path("libaprutil-1.so") - self.path("libaprutil-1.so.0") - self.path("libaprutil-1.so.0.3.10") - self.path("libbreakpad_client.so.0.0.0") - self.path("libbreakpad_client.so.0") - self.path("libbreakpad_client.so") + self.path("libapr-1.so*") + self.path("libaprutil-1.so*") + self.path("libbreakpad_client.so*") self.path("libcollada14dom.so") - self.path("libdb-5.1.so") - self.path("libdb-5.so") - self.path("libdb.so") - self.path("libcrypto.so.1.0.0") - self.path("libexpat.so.1.5.2") + self.path("libdb*.so") + self.path("libcrypto.so.*") + self.path("libexpat.so.*") self.path("libssl.so.1.0.0") self.path("libglod.so") self.path("libminizip.so") - self.path("libuuid.so") - self.path("libuuid.so.16") - self.path("libuuid.so.16.0.22") - self.path("libSDL-1.2.so.0.11.3") - self.path("libSDL-1.2.so.0") - self.path("libdirectfb-1.4.so.5.0.4") + self.path("libuuid.so*") + self.path("libSDL-1.2.so.*") + self.path("libdirectfb-1.*.so.*") + self.path("libfusion-1.*.so.*") + self.path("libdirect-1.*.so.*") + self.path("libopenjpeg.so*") self.path("libdirectfb-1.4.so.5") - self.path("libfusion-1.4.so.5.0.4") self.path("libfusion-1.4.so.5") self.path("libdirect-1.4.so.5.0.4") self.path("libdirect-1.4.so.5") - self.path("libopenjpeg.so.1.4.0") - self.path("libopenjpeg.so.1") - self.path("libopenjpeg.so") + self.path("libhunspell-1.3.so") + self.path("libhunspell-1.3.so.0") + self.path("libhunspell-1.3.so.0.0.0") self.path("libalut.so") self.path("libopenal.so", "libopenal.so.1") self.path("libopenal.so", "libvivoxoal.so.1") # vivox's sdk expects this soname - self.path("libfontconfig.so.1.4.4") - self.path("libtcmalloc.so", "libtcmalloc.so") #formerly called google perf tools - self.path("libtcmalloc.so.0", "libtcmalloc.so.0") #formerly called google perf tools - self.path("libtcmalloc.so.0.1.0", "libtcmalloc.so.0.1.0") #formerly called google perf tools + # KLUDGE: As of 2012-04-11, the 'fontconfig' package installs + # libfontconfig.so.1.4.4, along with symlinks libfontconfig.so.1 + # and libfontconfig.so. Before we added support for library-file + # wildcards, though, this self.path() call specifically named + # libfontconfig.so.1.4.4 WITHOUT also copying the symlinks. When I + # (nat) changed the call to self.path("libfontconfig.so.*"), we + # ended up with the libfontconfig.so.1 symlink in the target + # directory as well. But guess what! At least on Ubuntu 10.04, + # certain viewer fonts look terrible with libfontconfig.so.1 + # present in the target directory. Removing that symlink suffices + # to improve them. I suspect that means we actually do better when + # the viewer fails to find our packaged libfontconfig.so*, falling + # back on the system one instead -- but diagnosing and fixing that + # is a bit out of scope for the present project. Meanwhile, this + # particular wildcard specification gets us exactly what the + # previous call did, without having to explicitly state the + # version number. + self.path("libfontconfig.so.*.*") + self.path("libtcmalloc.so*") #formerly called google perf tools try: self.path("libfmod-3.75.so") pass |