diff options
361 files changed, 22151 insertions, 7433 deletions
@@ -25,6 +25,7 @@ indra/lib/mono/indra/*.exe indra/lib/mono/indra/*.pdb indra/lib/python/eventlet/ indra/llwindow/glh/glh_linear.h +indra/newview/app_settings/dictionaries indra/newview/app_settings/mozilla indra/newview/app_settings/mozilla-runtime-* indra/newview/app_settings/mozilla_debug @@ -150,6 +150,7 @@ a9abb9633a266c8d2fe62411cfd1c86d32da72bf 2.7.1-release 09984bfa6cae17e0f72d02b75c1b7393c65eecfc 2.7.5-beta1 e1ed60913230dd64269a7f7fc52cbc6004f6d52c 2.8.0-start 502f6a5deca9365ddae57db4f1e30172668e171e 2.8.1-start +888768f162d2c0a8de1dcc5fb9a08bd8bd120a6b DRTVWR-175 2a3965b3ad202df7ea25d2be689291bb14a1280e DRTVWR-155 6866d9df6efbd441c66451debd376d21211de39c DRTVWR-68_2.7.5-release 6866d9df6efbd441c66451debd376d21211de39c 2.7.5-release @@ -264,6 +265,7 @@ c6175c955a19e9b9353d242889ec1779b5762522 3.2.5-release 16f8e2915f3f2e4d732fb3125daf229cb0fd1875 DRTVWR-114_3.2.8-beta1 37dd400ad721e2a89ee820ffc1e7e433c68f3ca2 3.2.9-start 16f8e2915f3f2e4d732fb3125daf229cb0fd1875 3.2.8-beta1 +089e5c84b2dece68f2b016c842ef9b5de4786842 DRTVWR-161 987425b1acf4752379b2e1eb20944b4b35d67a85 DRTVWR-115_3.2.8-beta2 987425b1acf4752379b2e1eb20944b4b35d67a85 3.2.8-beta2 51b2fd52e36aab8f670e0874e7e1472434ec4b4a DRTVWR-113_3.2.8-release @@ -286,6 +288,9 @@ d5f263687f43f278107363365938f0a214920a4b 3.3.0-beta1 28b95a6a28dca3338d9a1f4f204b96678df9f6a5 viewer-beta-candidate b43cd25be49e3984ff5361cefad020e069131d98 3.3.1-start 3e2fca4ed1a0dc9fe6d8a6664e71098bb035a367 DRTVWR-125 +dffd0457ee0745de65bf95f0642a5c9e46b8e2f0 viewer-beta-candidate +3e2fca4ed1a0dc9fe6d8a6664e71098bb035a367 viewer-beta-candidate +3e2fca4ed1a0dc9fe6d8a6664e71098bb035a367 viewer-beta-candidate 3e2fca4ed1a0dc9fe6d8a6664e71098bb035a367 3.3.1-start 28b95a6a28dca3338d9a1f4f204b96678df9f6a5 3.3.1-beta1 1dc545e44617975da2a4a32fe303386c687a6ca1 viewer-beta-candidate @@ -300,7 +305,13 @@ c623bbc854b6f7ee1b33a3718f76715046aa2937 viewer-release-candidate 675668bd24d3bea570814f71762a2a806f7e1b8d viewer-release-candidate 675668bd24d3bea570814f71762a2a806f7e1b8d 3.3.2-release 675668bd24d3bea570814f71762a2a806f7e1b8d viewer-release-candidate +050e48759337249130f684b4a21080b683f61732 DRTVWR-168 +b9d0170b62eb1c7c3adaa37a0b13a833e5e659f9 DRTVWR-171 +c08e2ac17a99973b2a94477659220b99b8847ae2 DRTVWR-163 +600f3b3920d94de805ac6dc8bb6def9c069dd360 DRTVWR-162 600f3b3920d94de805ac6dc8bb6def9c069dd360 DRTVWR-162 +9a78ac13f047056f788c4734dd91aebfe30970e3 DRTVWR-157 +a716684aa7c07c440b1de5815b8a1f3dd3fd8bfb DRTVWR-159 24a7281bef42bd4430ceb25db8b195449c2c7de3 DRTVWR-153 15e90b52dc0297921b022b90d10d797436b8a1bd viewer-release-candidate 6414ecdabc5d89515b08d1f872cf923ed3a5523a DRTVWR-148 @@ -317,3 +328,22 @@ fdcc08a4f20ae9bb060f4693c8980d216534efdf 3.3.3-beta2 af5f3e43e6e4424b1da19d9e16f6b853a7b822ed DRTVWR-169 4b3c68199a86cabaa5d9466d7b0f7e141e901d7a 3.3.3-beta3 6428242e124b523813bfaf4c45b3d422f0298c81 3.3.3-release +57d221de3df94f90b55204313c2cef044a3c0ae2 DRTVWR-176 +09ef7fd1b0781f33b8a3a9af6236b7bcb4831910 DRTVWR-170 +005dfe5c4c377207d065fb27858d2eb0b53b143a DRTVWR-167 +f87bfbe0b62d26f451d02a47c80ebef6b9168fc2 3.3.4-beta1 +f87bfbe0b62d26f451d02a47c80ebef6b9168fc2 DRTVWR-158 +f87bfbe0b62d26f451d02a47c80ebef6b9168fc2 3.3.4-beta1 +cbea6356ce9cb0c313b6777f10c5c14783264fcc DRTVWR-174 +bce218b2b45b730b22cc51e4807aa8b571cadef3 DRTVWR-173 +f91d003091a61937a044652c4c674447f7dcbb7a 3.3.4-beta1 +82b5330bc8b17d0d4b598832e9c5a92e90075682 3.3.4-beta2 +eb539c65e6ee26eea2bf373af2d0f4b52dc91289 DRTVWR-177 +4ad8a3afe40e0200309e3ada68932c4295ac2795 DRTVWR-179 +a8057e1b9a1246b434a27405be35e030f7d28b0c 3.3.4-beta3 +4281aa899fb2cedb7a9ca7ce91c5c29d4aa69594 DRTVWR-180 +9cd174d3a54d93d409a7c346a15b8bfb40fc58f4 DRTVWR-184 +5c08e1d8edd871807153603b690e3ee9dbb548aa DRTVWR-183 +6c75f220b103db1420919c8b635fe53e2177f318 3.3.4-beta4 +ab2ffc547c8a8950ff187c4f6c95e5334fab597b 3.3.4-beta5 +28e100d0379a2b0710c57647a28fc5239d3d7b99 3.3.4-release diff --git a/BuildParams b/BuildParams index b3a9391f92..f7a676f345 100644 --- a/BuildParams +++ b/BuildParams @@ -36,6 +36,26 @@ viewer-development.build_debug_release_separately = true # <username>_<reponame>.email = <email-address> +# ================================================================= +# Canonical viewer integration builds - Oz Linden +# ================================================================= +integration_viewer-development.viewer_channel = "Second Life Development" +integration_viewer-development.login_channel = "Second Life Development" +integration_viewer-development.build_viewer_update_version_manager = false +integration_viewer-development.email = viewer-development-builds@lists.secondlife.com +integration_viewer-development.build_enforce_coding_policy = true +integration_viewer-development.codeticket_add_context = true + +viewer-beta.viewer_channel = "Second Life Beta Viewer" +viewer-beta.login_channel = "Second Life Beta Viewer" +viewer-beta.build_debug_release_separately = true +viewer-beta.build_viewer_update_version_manager = true + +viewer-release.viewer_channel = "Second Life Release" +viewer-release.login_channel = "Second Life Release" +viewer-release.build_debug_release_separately = true +viewer-release.build_viewer_update_version_manager = true + # ======================================== # mesh-development # ======================================== @@ -93,6 +113,17 @@ viewer-mesh.viewer_grid = aditi viewer-mesh.email = shining@lists.lindenlab.com # ======================================== +# viewer-adult-check +# ======================================== + +viewer-adult-check.viewer_channel = "Project Viewer - AdultCheck" +viewer-adult-check.login_channel = "Project Viewer - AdultCheck" +viewer-adult-check.viewer_grid = agni +viewer-adult-check.build_debug_release_separately = true +viewer-adult-check.build_CYGWIN_Debug = false +viewer-adult-check.build_viewer_update_version_manager = false + +# ======================================== # viewer-pathfinding # ======================================== @@ -103,6 +134,36 @@ viewer-pathfinding.build_debug_release_separately = true viewer-pathfinding.build_CYGWIN_Debug = false viewer-pathfinding.build_viewer_update_version_manager = false +# ================ +# oz +# ================ + +Snowstorm_viewer-project-review.build_debug_release_separately = true +Snowstorm_viewer-project-review.codeticket_add_context = true +Snowstorm_viewer-project-review.viewer_channel = "Project Viewer - Snowstorm Team" +Snowstorm_viewer-project-review.login_channel = "Project Viewer - Snowstorm Team" +Snowstorm_viewer-project-review.codeticket_add_context = true + +oz_viewer-devreview.build_debug_release_separately = true +oz_viewer-devreview.codeticket_add_context = false +oz_viewer-devreview.build_enforce_coding_policy = true +oz_viewer-devreview.email = oz@lindenlab.com + +oz_viewer-trial.build_debug_release_separately = true +oz_viewer-trial.codeticket_add_context = false +oz_viewer-trial.build_enforce_coding_policy = true +oz_viewer-trial.email = oz@lindenlab.com + +oz_viewer-beta-review.build_debug_release_separately = true +oz_viewer-beta-review.codeticket_add_context = false +oz_viewer-beta-review.viewer_channel = "Second Life Beta Viewer" +oz_viewer-beta-review.login_channel = "Second Life Beta Viewer" +oz_viewer-beta-review.email = oz@lindenlab.com + +oz_project-7.build_debug_release_separately = true +oz_project-7.codeticket_add_context = false +oz_project-7.email = "sldev@catznip.com oz@lindenlab.com" + # ================================================================= # asset delivery 2010 projects # ================================================================= diff --git a/autobuild.xml b/autobuild.xml index a25056ac87..7d5dbb4dcf 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -363,6 +363,54 @@ </map> </map> </map> + <key>dictionaries</key> + <map> + <key>license</key> + <string>various open</string> + <key>license_file</key> + <string>LICENSES/dictionaries.txt</string> + <key>name</key> + <string>dictionaries</string> + <key>platforms</key> + <map> + <key>darwin</key> + <map> + <key>archive</key> + <map> + <key>hash</key> + <string>06a6c49eb1873e95623d3d2d07aee903</string> + <key>url</key> + <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-dictionaries/rev/259873/arch/Darwin/installer/dictionaries-1-darwin-20120616.tar.bz2</string> + </map> + <key>name</key> + <string>darwin</string> + </map> + <key>linux</key> + <map> + <key>archive</key> + <map> + <key>hash</key> + <string>4f0ca21d27e0cd0b002149062b0a4b25</string> + <key>url</key> + <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-dictionaries/rev/259873/arch/Linux/installer/dictionaries-1-linux-20120616.tar.bz2</string> + </map> + <key>name</key> + <string>linux</string> + </map> + <key>windows</key> + <map> + <key>archive</key> + <map> + <key>hash</key> + <string>7520d75f6af325328322201c888191d4</string> + <key>url</key> + <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-dictionaries/rev/259873/arch/CYGWIN/installer/dictionaries-1-windows-20120616.tar.bz2</string> + </map> + <key>name</key> + <string>windows</string> + </map> + </map> + </map> <key>elfio</key> <map> <key>license</key> @@ -1047,6 +1095,54 @@ </map> </map> </map> + <key>libhunspell</key> + <map> + <key>license</key> + <string>libhunspell</string> + <key>license_file</key> + <string>LICENSES/hunspell.txt</string> + <key>name</key> + <string>libhunspell</string> + <key>platforms</key> + <map> + <key>darwin</key> + <map> + <key>archive</key> + <map> + <key>hash</key> + <string>6f5db0ef258df6e5c93c843ec559db6d</string> + <key>url</key> + <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-hunspell/rev/259874/arch/Darwin/installer/libhunspell-1.3.2-darwin-20120616.tar.bz2</string> + </map> + <key>name</key> + <string>darwin</string> + </map> + <key>linux</key> + <map> + <key>archive</key> + <map> + <key>hash</key> + <string>0c432d2626aea2e91a56335879c92965</string> + <key>url</key> + <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-hunspell/rev/259874/arch/Linux/installer/libhunspell-1.3.2-linux-20120616.tar.bz2</string> + </map> + <key>name</key> + <string>linux</string> + </map> + <key>windows</key> + <map> + <key>archive</key> + <map> + <key>hash</key> + <string>6a140e5620826aa5e587b4157f57b389</string> + <key>url</key> + <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-hunspell/rev/259874/arch/CYGWIN/installer/libhunspell-1.3.2-windows-20120616.tar.bz2</string> + </map> + <key>name</key> + <string>windows</string> + </map> + </map> + </map> <key>libpng</key> <map> <key>license</key> @@ -1818,8 +1914,12 @@ </map> <key>package_description</key> <map> + <key>description</key> + <string>Spell checking dictionaries</string> + <key>license</key> + <string>various open</string> <key>name</key> - <string>viewer_development</string> + <string>dictionaries</string> <key>platforms</key> <map> <key>common</key> @@ -2529,6 +2629,8 @@ <string>windows</string> </map> </map> + <key>version</key> + <string>1.0</string> </map> <key>type</key> <string>autobuild</string> @@ -15,6 +15,12 @@ # * The basic convention is that the build name can be mapped onto a mercurial URL, # which is also used as the "branch" name. +check_for() +{ + if [ -e "$2" ]; then found_dict='FOUND'; else found_dict='MISSING'; fi + echo "$1 ${found_dict} '$2' " 1>&2 +} + build_dir_Darwin() { echo build-darwin-i386 @@ -59,6 +65,8 @@ pre_build() && [ -r "$master_message_template_checkout/message_template.msg" ] \ && template_verifier_master_url="-DTEMPLATE_VERIFIER_MASTER_URL=file://$master_message_template_checkout/message_template.msg" + check_for "Before 'autobuild configure'" ${build_dir}/packages/dictionaries + "$AUTOBUILD" configure -c $variant -- \ -DPACKAGE:BOOL=ON \ -DRELEASE_CRASH_REPORTING:BOOL=ON \ @@ -67,7 +75,10 @@ pre_build() -DGRID:STRING="\"$viewer_grid\"" \ -DLL_TESTS:BOOL="$run_tests" \ -DTEMPLATE_VERIFIER_OPTIONS:STRING="$template_verifier_options" $template_verifier_master_url - end_section "Pre$variant" + + check_for "After 'autobuild configure'" ${build_dir}/packages/dictionaries + + end_section "Pre$variant" } package_llphysicsextensions_tpv() @@ -99,6 +110,8 @@ build() if $build_viewer then begin_section "Viewer$variant" + check_for "Before 'autobuild build'" ${build_dir}/packages/dictionaries + "$AUTOBUILD" build --no-configure -c $variant viewer_build_ok=$? end_section "Viewer$variant" @@ -110,6 +123,8 @@ build() else echo false >"$build_dir"/build_ok fi + check_for "After 'autobuild configure'" ${build_dir}/packages/dictionaries + fi } @@ -199,7 +214,10 @@ eval "$("$AUTOBUILD" source_environment)" # dump environment variables for debugging env|sort +check_for "Before 'autobuild install'" ${build_dir}/packages/dictionaries + +check_for "After 'autobuild install'" ${build_dir}/packages/dictionaries # Now run the build succeeded=true build_processes= diff --git a/doc/contributions.txt b/doc/contributions.txt index 18df538d2a..df504e4a8a 100644 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -297,6 +297,8 @@ Cherry Cheevers ChickyBabes Zuzu Christopher Organiser Ciaran Laval +Cinder Roxley + STORM-1703 Clara Young Coaldust Numbers VWR-1095 @@ -471,6 +473,7 @@ Hiro Sommambulist VWR-143 Hitomi Tiponi STORM-1741 + STORM-1862 Holger Gilruth Horatio Freund Hoze Menges @@ -623,12 +626,22 @@ Jonathan Yap STORM-1799 STORM-1796 STORM-1807 + STORM-1812 + STORM-1820 + STORM-1839 + STORM-1842 STORM-1808 STORM-637 STORM-1822 STORM-1809 STORM-1793 STORM-1810 + STORM-1860 + STORM-1852 + STORM-1870 + STORM-1872 + STORM-1858 + STORM-1862 Kadah Coba STORM-1060 Jondan Lundquist @@ -725,6 +738,8 @@ Marc2 Sands Marianne McCann Marine Kelley STORM-281 +MartinRJ Fayray + STORM-1845 Matthew Anthony Matthew Dowd VWR-1344 @@ -1052,6 +1067,8 @@ Simon Nolan Sini Nubalo Sitearm Madonna SLB Wirefly +Slee Mayo + SEC-1075 snowy Sidran SpacedOut Frye VWR-34 @@ -1287,6 +1304,7 @@ Zi Ree VWR-24017 VWR-25588 STORM-1790 + STORM-1842 Zipherius Turas VWR-76 VWR-77 diff --git a/indra/cmake/00-Common.cmake b/indra/cmake/00-Common.cmake index 98eeed09b3..00baf626d2 100644 --- a/indra/cmake/00-Common.cmake +++ b/indra/cmake/00-Common.cmake @@ -69,6 +69,7 @@ if (WINDOWS) /Oy- /Zc:wchar_t- /arch:SSE2 + /fp:fast ) # Are we using the crummy Visual Studio KDU build workaround? diff --git a/indra/cmake/CMakeLists.txt b/indra/cmake/CMakeLists.txt index 7fccf3327f..569034a6fb 100644 --- a/indra/cmake/CMakeLists.txt +++ b/indra/cmake/CMakeLists.txt @@ -37,6 +37,7 @@ set(cmake_SOURCE_FILES GLOD.cmake GStreamer010Plugin.cmake GooglePerfTools.cmake + Hunspell.cmake JPEG.cmake LLAddBuildTest.cmake LLAudio.cmake diff --git a/indra/cmake/Copy3rdPartyLibs.cmake b/indra/cmake/Copy3rdPartyLibs.cmake index 394db362b1..9f05c4cff2 100644 --- a/indra/cmake/Copy3rdPartyLibs.cmake +++ b/indra/cmake/Copy3rdPartyLibs.cmake @@ -41,6 +41,7 @@ if(WINDOWS) libeay32.dll libcollada14dom22-d.dll glod.dll + libhunspell.dll ) set(release_src_dir "${ARCH_PREBUILT_DIRS_RELEASE}") @@ -53,12 +54,13 @@ if(WINDOWS) libeay32.dll libcollada14dom22.dll glod.dll + libhunspell.dll ) - if(USE_GOOGLE_PERFTOOLS) + if(USE_TCMALLOC) set(debug_files ${debug_files} libtcmalloc_minimal-debug.dll) set(release_files ${release_files} libtcmalloc_minimal.dll) - endif(USE_GOOGLE_PERFTOOLS) + endif(USE_TCMALLOC) if (FMOD) set(debug_files ${debug_files} fmod.dll) @@ -212,11 +214,12 @@ elseif(DARWIN) libexpat.1.5.2.dylib libexpat.dylib libGLOD.dylib - libllqtwebkit.dylib - libminizip.a + libllqtwebkit.dylib + libminizip.a libndofdev.dylib + libhunspell-1.3.0.dylib libexception_handler.dylib - libcollada14dom.dylib + libcollada14dom.dylib ) # fmod is statically linked on darwin @@ -257,24 +260,28 @@ elseif(LINUX) libdb-5.1.so libexpat.so libexpat.so.1 - libglod.so + libglod.so libgmock_main.so libgmock.so.0 libgmodule-2.0.so libgobject-2.0.so libgtest_main.so libgtest.so.0 - libminizip.so + libhunspell-1.3.so.0.0.0 + libminizip.so libopenal.so libopenjpeg.so libssl.so - libtcmalloc_minimal.so libuuid.so.16 libuuid.so.16.0.22 libssl.so.1.0.0 libfontconfig.so.1.4.4 ) + if (USE_TCMALLOC) + set(release_files ${release_files} "libtcmalloc_minimal.so") + endif (USE_TCMALLOC) + if (FMOD) set(release_files ${release_files} "libfmod-3.75.so") endif (FMOD) diff --git a/indra/cmake/FindHUNSPELL.cmake b/indra/cmake/FindHUNSPELL.cmake new file mode 100644 index 0000000000..6faf22959c --- /dev/null +++ b/indra/cmake/FindHUNSPELL.cmake @@ -0,0 +1,38 @@ +# -*- cmake -*- + +# - Find HUNSPELL +# This module defines +# HUNSPELL_INCLUDE_DIR, where to find libhunspell.h, etc. +# HUNSPELL_LIBRARY, the library needed to use HUNSPELL. +# HUNSPELL_FOUND, If false, do not try to use HUNSPELL. + +find_path(HUNSPELL_INCLUDE_DIR hunspell.h + PATH_SUFFIXES hunspell + ) + +set(HUNSPELL_NAMES ${HUNSPELL_NAMES} libhunspell-1.3.0 libhunspell) +find_library(HUNSPELL_LIBRARY + NAMES ${HUNSPELL_NAMES} + ) + +if (HUNSPELL_LIBRARY AND HUNSPELL_INCLUDE_DIR) + set(HUNSPELL_FOUND "YES") +else (HUNSPELL_LIBRARY AND HUNSPELL_INCLUDE_DIR) + set(HUNSPELL_FOUND "NO") +endif (HUNSPELL_LIBRARY AND HUNSPELL_INCLUDE_DIR) + + +if (HUNSPELL_FOUND) + if (NOT HUNSPELL_FIND_QUIETLY) + message(STATUS "Found Hunspell: Library in '${HUNSPELL_LIBRARY}' and header in '${HUNSPELL_INCLUDE_DIR}' ") + endif (NOT HUNSPELL_FIND_QUIETLY) +else (HUNSPELL_FOUND) + if (HUNSPELL_FIND_REQUIRED) + message(FATAL_ERROR " * * *\nCould not find HUNSPELL library! * * *") + endif (HUNSPELL_FIND_REQUIRED) +endif (HUNSPELL_FOUND) + +mark_as_advanced( + HUNSPELL_LIBRARY + HUNSPELL_INCLUDE_DIR + ) diff --git a/indra/cmake/GooglePerfTools.cmake b/indra/cmake/GooglePerfTools.cmake index d9f91193be..09501e0406 100644 --- a/indra/cmake/GooglePerfTools.cmake +++ b/indra/cmake/GooglePerfTools.cmake @@ -1,20 +1,34 @@ # -*- cmake -*- include(Prebuilt) +# If you want to enable or disable TCMALLOC in viewer builds, this is the place. +# set ON or OFF as desired. +set (USE_TCMALLOC ON) + if (STANDALONE) include(FindGooglePerfTools) else (STANDALONE) if (WINDOWS) - use_prebuilt_binary(tcmalloc) - set(TCMALLOC_LIBRARIES - debug libtcmalloc_minimal-debug - optimized libtcmalloc_minimal) + if (USE_TCMALLOC) + use_prebuilt_binary(tcmalloc) + set(TCMALLOC_LIBRARIES + debug libtcmalloc_minimal-debug + optimized libtcmalloc_minimal) + set(TCMALLOC_LINK_FLAGS "/INCLUDE:__tcmalloc") + else (USE_TCMALLOC) + set(TCMALLOC_LIBRARIES) + set(TCMALLOC_LINK_FLAGS) + endif (USE_TCMALLOC) set(GOOGLE_PERFTOOLS_FOUND "YES") endif (WINDOWS) if (LINUX) - use_prebuilt_binary(tcmalloc) - set(TCMALLOC_LIBRARIES - tcmalloc) + if (USE_TCMALLOC) + use_prebuilt_binary(tcmalloc) + set(TCMALLOC_LIBRARIES + tcmalloc) + else (USE_TCMALLOC) + set(TCMALLOC_LIBRARIES) + endif (USE_TCMALLOC) set(PROFILER_LIBRARIES profiler) set(GOOGLE_PERFTOOLS_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include) @@ -29,13 +43,19 @@ if (GOOGLE_PERFTOOLS_FOUND) endif (GOOGLE_PERFTOOLS_FOUND) if (WINDOWS) - set(USE_GOOGLE_PERFTOOLS ON) + set(USE_GOOGLE_PERFTOOLS ON) endif (WINDOWS) if (USE_GOOGLE_PERFTOOLS) - set(TCMALLOC_FLAG -ULL_USE_TCMALLOC=1) + if (USE_TCMALLOC) + set(TCMALLOC_FLAG -DLL_USE_TCMALLOC=1) + else (USE_TCMALLOC) + set(TCMALLOC_FLAG -ULL_USE_TCMALLOC) + endif (USE_TCMALLOC) +endif (USE_GOOGLE_PERFTOOLS) + +if (USE_GOOGLE_PERFTOOLS) include_directories(${GOOGLE_PERFTOOLS_INCLUDE_DIR}) set(GOOGLE_PERFTOOLS_LIBRARIES ${TCMALLOC_LIBRARIES} ${STACKTRACE_LIBRARIES} ${PROFILER_LIBRARIES}) else (USE_GOOGLE_PERFTOOLS) - set(TCMALLOC_FLAG -ULL_USE_TCMALLOC) endif (USE_GOOGLE_PERFTOOLS) diff --git a/indra/cmake/Hunspell.cmake b/indra/cmake/Hunspell.cmake new file mode 100644 index 0000000000..0c9cf93316 --- /dev/null +++ b/indra/cmake/Hunspell.cmake @@ -0,0 +1,22 @@ +# -*- cmake -*- +include(Prebuilt) + +set(HUNSPELL_FIND_QUIETLY ON) +set(HUNSPELL_FIND_REQUIRED ON) + +if (STANDALONE) + include(FindHUNSPELL) +else (STANDALONE) + use_prebuilt_binary(libhunspell) + if (WINDOWS) + set(HUNSPELL_LIBRARY libhunspell) + elseif(DARWIN) + set(HUNSPELL_LIBRARY hunspell-1.3.0) + elseif(LINUX) + set(HUNSPELL_LIBRARY hunspell-1.3) + else() + message(FATAL_ERROR "Invalid platform") + endif() + set(HUNSPELL_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include/hunspell) + use_prebuilt_binary(dictionaries) +endif (STANDALONE) diff --git a/indra/cmake/LLAddBuildTest.cmake b/indra/cmake/LLAddBuildTest.cmake index 08feab6e36..a6f69a09e9 100644 --- a/indra/cmake/LLAddBuildTest.cmake +++ b/indra/cmake/LLAddBuildTest.cmake @@ -205,6 +205,15 @@ FUNCTION(LL_ADD_INTEGRATION_TEST SET_TARGET_PROPERTIES(INTEGRATION_TEST_${testname} PROPERTIES COMPILE_FLAGS -I"${TUT_INCLUDE_DIR}") endif(STANDALONE) + if (WINDOWS) + SET_TARGET_PROPERTIES(INTEGRATION_TEST_${testname} + PROPERTIES + LINK_FLAGS "/debug /NODEFAULTLIB:LIBCMT /SUBSYSTEM:WINDOWS ${TCMALLOC_LINK_FLAGS}" + LINK_FLAGS_DEBUG "/NODEFAULTLIB:\"LIBCMT;LIBCMTD;MSVCRT\" /INCREMENTAL:NO" + LINK_FLAGS_RELEASE "" + ) + endif (WINDOWS) + # Add link deps to the executable if(TEST_DEBUG) message(STATUS "TARGET_LINK_LIBRARIES(INTEGRATION_TEST_${testname} ${libraries})") diff --git a/indra/cmake/ViewerMiscLibs.cmake b/indra/cmake/ViewerMiscLibs.cmake index cec7c28733..5b00c989a4 100644 --- a/indra/cmake/ViewerMiscLibs.cmake +++ b/indra/cmake/ViewerMiscLibs.cmake @@ -2,6 +2,7 @@ include(Prebuilt) if (NOT STANDALONE) + use_prebuilt_binary(libhunspell) use_prebuilt_binary(libuuid) use_prebuilt_binary(slvoice) use_prebuilt_binary(fontconfig) diff --git a/indra/integration_tests/llui_libtest/CMakeLists.txt b/indra/integration_tests/llui_libtest/CMakeLists.txt index 633ad84159..91c9f20c10 100644 --- a/indra/integration_tests/llui_libtest/CMakeLists.txt +++ b/indra/integration_tests/llui_libtest/CMakeLists.txt @@ -18,6 +18,7 @@ include(LLWindow) include(LLUI) include(LLVFS) # ugh, needed for LLDir include(LLXML) +include(Hunspell) include(Linking) # include(Tut) @@ -31,6 +32,7 @@ include_directories( ${LLVFS_INCLUDE_DIRS} ${LLWINDOW_INCLUDE_DIRS} ${LLXML_INCLUDE_DIRS} + ${LIBS_PREBUILD_DIR}/include/hunspell ) set(llui_libtest_SOURCE_FILES @@ -78,6 +80,7 @@ target_link_libraries(llui_libtest ${LLIMAGEJ2COJ_LIBRARIES} ${OS_LIBRARIES} ${GOOGLE_PERFTOOLS_LIBRARIES} + ${HUNSPELL_LIBRARY} ) if (WINDOWS) diff --git a/indra/llcharacter/llcharacter.cpp b/indra/llcharacter/llcharacter.cpp index c9fb8534f1..0a6a8f9fa6 100644 --- a/indra/llcharacter/llcharacter.cpp +++ b/indra/llcharacter/llcharacter.cpp @@ -189,6 +189,7 @@ void LLCharacter::requestStopMotion( LLMotion* motion) //----------------------------------------------------------------------------- static LLFastTimer::DeclareTimer FTM_UPDATE_ANIMATION("Update Animation"); static LLFastTimer::DeclareTimer FTM_UPDATE_HIDDEN_ANIMATION("Update Hidden Anim"); +static LLFastTimer::DeclareTimer FTM_UPDATE_MOTIONS("Update Motions"); void LLCharacter::updateMotions(e_update_t update_type) { @@ -206,7 +207,10 @@ void LLCharacter::updateMotions(e_update_t update_type) mMotionController.unpauseAllMotions(); } bool force_update = (update_type == FORCE_UPDATE); - mMotionController.updateMotions(force_update); + { + LLFastTimer t(FTM_UPDATE_MOTIONS); + mMotionController.updateMotions(force_update); + } } } diff --git a/indra/llcharacter/llmotioncontroller.cpp b/indra/llcharacter/llmotioncontroller.cpp index bb892f4a7f..4f6351709e 100644 --- a/indra/llcharacter/llmotioncontroller.cpp +++ b/indra/llcharacter/llmotioncontroller.cpp @@ -542,6 +542,8 @@ void LLMotionController::updateIdleActiveMotions() //----------------------------------------------------------------------------- // updateMotionsByType() //----------------------------------------------------------------------------- +static LLFastTimer::DeclareTimer FTM_MOTION_ON_UPDATE("Motion onUpdate"); + void LLMotionController::updateMotionsByType(LLMotion::LLMotionBlendType anim_type) { BOOL update_result = TRUE; @@ -699,7 +701,10 @@ void LLMotionController::updateMotionsByType(LLMotion::LLMotionBlendType anim_ty } // perform motion update - update_result = motionp->onUpdate(mAnimTime - motionp->mActivationTimestamp, last_joint_signature); + { + LLFastTimer t(FTM_MOTION_ON_UPDATE); + update_result = motionp->onUpdate(mAnimTime - motionp->mActivationTimestamp, last_joint_signature); + } } //********************** @@ -810,7 +815,7 @@ void LLMotionController::updateMotions(bool force_update) // Always cap the number of loaded motions purgeExcessMotions(); - + // Update timing info for this time step. if (!mPaused) { @@ -832,6 +837,7 @@ void LLMotionController::updateMotions(bool force_update) } updateLoadingMotions(); + return; } @@ -850,7 +856,7 @@ void LLMotionController::updateMotions(bool force_update) } updateLoadingMotions(); - + resetJointSignatures(); if (mPaused && !force_update) @@ -861,11 +867,12 @@ void LLMotionController::updateMotions(bool force_update) { // update additive motions updateAdditiveMotions(); + resetJointSignatures(); - + // update all regular motions updateRegularMotions(); - + if (use_quantum) { mPoseBlender.blendAndCache(TRUE); diff --git a/indra/llcommon/llallocator.cpp b/indra/llcommon/llallocator.cpp index 6f6abefc67..87654b5b97 100644 --- a/indra/llcommon/llallocator.cpp +++ b/indra/llcommon/llallocator.cpp @@ -27,7 +27,7 @@ #include "linden_common.h" #include "llallocator.h" -#if LL_USE_TCMALLOC +#if (LL_USE_TCMALLOC && LL_USE_HEAP_PROFILER) #include "google/heap-profiler.h" #include "google/commandlineflags_public.h" diff --git a/indra/llcommon/llmemory.cpp b/indra/llcommon/llmemory.cpp index 3b9758f996..afaf366668 100644 --- a/indra/llcommon/llmemory.cpp +++ b/indra/llcommon/llmemory.cpp @@ -61,6 +61,18 @@ BOOL LLMemory::sEnableMemoryFailurePrevention = FALSE; LLPrivateMemoryPoolManager::mem_allocation_info_t LLPrivateMemoryPoolManager::sMemAllocationTracker; #endif +void ll_assert_aligned_func(uintptr_t ptr,U32 alignment) +{ +#ifdef SHOW_ASSERT + // Redundant, place to set breakpoints. + if (ptr%alignment!=0) + { + llwarns << "alignment check failed" << llendl; + } + llassert(ptr%alignment==0); +#endif +} + //static void LLMemory::initClass() { diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h index bbbdaa6497..9dd776ff57 100644 --- a/indra/llcommon/llmemory.h +++ b/indra/llcommon/llmemory.h @@ -27,7 +27,6 @@ #define LLMEMORY_H #include "llmemtype.h" -#if LL_DEBUG inline void* ll_aligned_malloc( size_t size, int align ) { void* mem = malloc( size + (align - 1) + sizeof(void*) ); @@ -43,10 +42,11 @@ inline void ll_aligned_free( void* ptr ) free( ((void**)ptr)[-1] ); } +#if !LL_USE_TCMALLOC inline void* ll_aligned_malloc_16(size_t size) // returned hunk MUST be freed with ll_aligned_free_16(). { #if defined(LL_WINDOWS) - return _mm_malloc(size, 16); + return _aligned_malloc(size, 16); #elif defined(LL_DARWIN) return malloc(size); // default osx malloc is 16 byte aligned. #else @@ -58,21 +58,38 @@ inline void* ll_aligned_malloc_16(size_t size) // returned hunk MUST be freed wi #endif } +inline void* ll_aligned_realloc_16(void* ptr, size_t size) // returned hunk MUST be freed with ll_aligned_free_16(). +{ +#if defined(LL_WINDOWS) + return _aligned_realloc(ptr, size, 16); +#elif defined(LL_DARWIN) + return realloc(ptr,size); // default osx malloc is 16 byte aligned. +#else + return realloc(ptr,size); // FIXME not guaranteed to be aligned. +#endif +} + inline void ll_aligned_free_16(void *p) { #if defined(LL_WINDOWS) - _mm_free(p); + _aligned_free(p); #elif defined(LL_DARWIN) return free(p); #else free(p); // posix_memalign() is compatible with heap deallocator #endif } +#else // USE_TCMALLOC +// ll_aligned_foo_16 are not needed with tcmalloc +#define ll_aligned_malloc_16 malloc +#define ll_aligned_realloc_16 realloc +#define ll_aligned_free_16 free +#endif // USE_TCMALLOC inline void* ll_aligned_malloc_32(size_t size) // returned hunk MUST be freed with ll_aligned_free_32(). { #if defined(LL_WINDOWS) - return _mm_malloc(size, 32); + return _aligned_malloc(size, 32); #elif defined(LL_DARWIN) return ll_aligned_malloc( size, 32 ); #else @@ -87,22 +104,13 @@ inline void* ll_aligned_malloc_32(size_t size) // returned hunk MUST be freed wi inline void ll_aligned_free_32(void *p) { #if defined(LL_WINDOWS) - _mm_free(p); + _aligned_free(p); #elif defined(LL_DARWIN) ll_aligned_free( p ); #else free(p); // posix_memalign() is compatible with heap deallocator #endif } -#else // LL_DEBUG -// ll_aligned_foo are noops now that we use tcmalloc everywhere (tcmalloc aligns automatically at appropriate intervals) -#define ll_aligned_malloc( size, align ) malloc(size) -#define ll_aligned_free( ptr ) free(ptr) -#define ll_aligned_malloc_16 malloc -#define ll_aligned_free_16 free -#define ll_aligned_malloc_32 malloc -#define ll_aligned_free_32 free -#endif // LL_DEBUG #ifndef __DEBUG_PRIVATE_MEM__ #define __DEBUG_PRIVATE_MEM__ 0 @@ -512,4 +520,13 @@ void LLPrivateMemoryPoolTester::operator delete[](void* addr) // LLSingleton moved to llsingleton.h +LL_COMMON_API void ll_assert_aligned_func(uintptr_t ptr,U32 alignment); + +#ifdef SHOW_ASSERT +#define ll_assert_aligned(ptr,alignment) ll_assert_aligned_func(reinterpret_cast<uintptr_t>(ptr),((U32)alignment)) +#else +#define ll_assert_aligned(ptr,alignment) +#endif + + #endif diff --git a/indra/llcommon/llsd.cpp b/indra/llcommon/llsd.cpp index e295e3c621..8276ec836a 100644 --- a/indra/llcommon/llsd.cpp +++ b/indra/llcommon/llsd.cpp @@ -269,6 +269,7 @@ namespace virtual LLSD::UUID asUUID() const { return LLUUID(mValue); } virtual LLSD::Date asDate() const { return LLDate(mValue); } virtual LLSD::URI asURI() const { return LLURI(mValue); } + virtual int size() const { return mValue.size(); } }; LLSD::Integer ImplString::asInteger() const diff --git a/indra/llcommon/llstrider.h b/indra/llcommon/llstrider.h index f4c43bac61..ed9284d2c5 100644 --- a/indra/llcommon/llstrider.h +++ b/indra/llcommon/llstrider.h @@ -44,6 +44,15 @@ public: const LLStrider<Object>& operator = (Object *first) { mObjectp = first; return *this;} void setStride (S32 skipBytes) { mSkip = (skipBytes ? skipBytes : sizeof(Object));} + LLStrider<Object> operator+(const S32& index) + { + LLStrider<Object> ret; + ret.mBytep = mBytep + mSkip*index; + ret.mSkip = mSkip; + + return ret; + } + void skip(const U32 index) { mBytep += mSkip*index;} U32 getSkip() const { return mSkip; } Object* get() { return mObjectp; } @@ -51,6 +60,7 @@ public: Object& operator *() { return *mObjectp; } Object* operator ++(int) { Object* old = mObjectp; mBytep += mSkip; return old; } Object* operator +=(int i) { mBytep += mSkip*i; return mObjectp; } + Object& operator[](U32 index) { return *(Object*)(mBytep + (mSkip * index)); } }; diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h index 09733e8e2a..119efc7957 100644 --- a/indra/llcommon/llstring.h +++ b/indra/llcommon/llstring.h @@ -183,6 +183,9 @@ public: static bool isPunct(char a) { return ispunct((unsigned char)a) != 0; } static bool isPunct(llwchar a) { return iswpunct(a) != 0; } + static bool isAlpha(char a) { return isalpha((unsigned char)a) != 0; } + static bool isAlpha(llwchar a) { return iswalpha(a) != 0; } + static bool isAlnum(char a) { return isalnum((unsigned char)a) != 0; } static bool isAlnum(llwchar a) { return iswalnum(a) != 0; } diff --git a/indra/llcommon/llversionviewer.h b/indra/llcommon/llversionviewer.h index bfb30f900f..9af16a0ed8 100644 --- a/indra/llcommon/llversionviewer.h +++ b/indra/llcommon/llversionviewer.h @@ -29,7 +29,7 @@ const S32 LL_VERSION_MAJOR = 3; const S32 LL_VERSION_MINOR = 3; -const S32 LL_VERSION_PATCH = 3; +const S32 LL_VERSION_PATCH = 5; const S32 LL_VERSION_BUILD = 0; const char * const LL_CHANNEL = "Second Life Developer"; diff --git a/indra/llinventory/llparcel.h b/indra/llinventory/llparcel.h index e36d0b20d2..f0b2caca3d 100644 --- a/indra/llinventory/llparcel.h +++ b/indra/llinventory/llparcel.h @@ -45,7 +45,7 @@ const S32 PARCEL_UNIT_AREA = 16; const F32 PARCEL_HEIGHT = 50.f; //Height above ground which parcel boundries exist for explicitly banned avatars -const F32 BAN_HEIGHT = 768.f; +const F32 BAN_HEIGHT = 5000.f; // Maximum number of entries in an access list const S32 PARCEL_MAX_ACCESS_LIST = 300; diff --git a/indra/llmath/CMakeLists.txt b/indra/llmath/CMakeLists.txt index b5e59c1ca3..5865ae030c 100644 --- a/indra/llmath/CMakeLists.txt +++ b/indra/llmath/CMakeLists.txt @@ -117,6 +117,7 @@ if (LL_TESTS) # INTEGRATION TESTS set(test_libs llmath llcommon ${LLCOMMON_LIBRARIES} ${WINDOWS_LIBRARIES}) # TODO: Some of these need refactoring to be proper Unit tests rather than Integration tests. + LL_ADD_INTEGRATION_TEST(alignment "" "${test_libs}") LL_ADD_INTEGRATION_TEST(llbbox llbbox.cpp "${test_libs}") LL_ADD_INTEGRATION_TEST(llquaternion llquaternion.cpp "${test_libs}") LL_ADD_INTEGRATION_TEST(mathmisc "" "${test_libs}") diff --git a/indra/llmath/llcamera.h b/indra/llmath/llcamera.h index ec67b91d05..0b591be622 100644 --- a/indra/llmath/llcamera.h +++ b/indra/llmath/llcamera.h @@ -60,7 +60,7 @@ static const F32 MAX_FIELD_OF_VIEW = 175.f * DEG_TO_RAD; // roll(), pitch(), yaw() // etc... - +LL_ALIGN_PREFIX(16) class LLCamera : public LLCoordFrame { @@ -108,7 +108,7 @@ public: }; private: - LLPlane mAgentPlanes[7]; //frustum planes in agent space a la gluUnproject (I'm a bastard, I know) - DaveP + LL_ALIGN_16(LLPlane mAgentPlanes[7]); //frustum planes in agent space a la gluUnproject (I'm a bastard, I know) - DaveP U8 mPlaneMask[8]; // 8 for alignment F32 mView; // angle between top and bottom frustum planes in radians. @@ -116,13 +116,13 @@ private: S32 mViewHeightInPixels; // for ViewHeightInPixels() only F32 mNearPlane; F32 mFarPlane; - LLPlane mLocalPlanes[4]; + LL_ALIGN_16(LLPlane mLocalPlanes[4]); F32 mFixedDistance; // Always return this distance, unless < 0 LLVector3 mFrustCenter; // center of frustum and radius squared for ultra-quick exclusion test F32 mFrustRadiusSquared; - LLPlane mWorldPlanes[PLANE_NUM]; - LLPlane mHorizPlanes[HORIZ_PLANE_NUM]; + LL_ALIGN_16(LLPlane mWorldPlanes[PLANE_NUM]); + LL_ALIGN_16(LLPlane mHorizPlanes[HORIZ_PLANE_NUM]); U32 mPlaneCount; //defaults to 6, if setUserClipPlane is called, uses user supplied clip plane in @@ -208,7 +208,7 @@ protected: void calculateFrustumPlanes(F32 left, F32 right, F32 top, F32 bottom); void calculateFrustumPlanesFromWindow(F32 x1, F32 y1, F32 x2, F32 y2); void calculateWorldFrustumPlanes(); -}; +} LL_ALIGN_POSTFIX(16); #endif diff --git a/indra/llmath/llmath.h b/indra/llmath/llmath.h index 9297bcbac2..b93f89d674 100644 --- a/indra/llmath/llmath.h +++ b/indra/llmath/llmath.h @@ -85,7 +85,7 @@ const F32 F_ALMOST_ONE = 1.0f - F_ALMOST_ZERO; const F32 FP_MAG_THRESHOLD = 0.0000001f; // TODO: Replace with logic like is_approx_equal -inline BOOL is_approx_zero( F32 f ) { return (-F_APPROXIMATELY_ZERO < f) && (f < F_APPROXIMATELY_ZERO); } +inline bool is_approx_zero( F32 f ) { return (-F_APPROXIMATELY_ZERO < f) && (f < F_APPROXIMATELY_ZERO); } // These functions work by interpreting sign+exp+mantissa as an unsigned // integer. @@ -111,13 +111,13 @@ inline BOOL is_approx_zero( F32 f ) { return (-F_APPROXIMATELY_ZERO < f) && (f < // WARNING: Infinity is comparable with F32_MAX and negative // infinity is comparable with F32_MIN -inline BOOL is_approx_equal(F32 x, F32 y) +inline bool is_approx_equal(F32 x, F32 y) { const S32 COMPARE_MANTISSA_UP_TO_BIT = 0x02; return (std::abs((S32) ((U32&)x - (U32&)y) ) < COMPARE_MANTISSA_UP_TO_BIT); } -inline BOOL is_approx_equal(F64 x, F64 y) +inline bool is_approx_equal(F64 x, F64 y) { const S64 COMPARE_MANTISSA_UP_TO_BIT = 0x02; return (std::abs((S32) ((U64&)x - (U64&)y) ) < COMPARE_MANTISSA_UP_TO_BIT); diff --git a/indra/llmath/llmatrix3a.h b/indra/llmath/llmatrix3a.h index adb7e3389d..9916cfd2da 100644 --- a/indra/llmath/llmatrix3a.h +++ b/indra/llmath/llmatrix3a.h @@ -111,7 +111,7 @@ public: protected: - LLVector4a mColumns[3]; + LL_ALIGN_16(LLVector4a mColumns[3]); }; diff --git a/indra/llmath/llmatrix4a.h b/indra/llmath/llmatrix4a.h index 27cf5b79f6..c4cefdb4fa 100644 --- a/indra/llmath/llmatrix4a.h +++ b/indra/llmath/llmatrix4a.h @@ -34,7 +34,7 @@ class LLMatrix4a { public: - LLVector4a mMatrix[4]; + LL_ALIGN_16(LLVector4a mMatrix[4]); inline void clear() { diff --git a/indra/llmath/lloctree.h b/indra/llmath/lloctree.h index 1b11e83b4a..c3f6f7de2a 100644 --- a/indra/llmath/lloctree.h +++ b/indra/llmath/lloctree.h @@ -31,7 +31,6 @@ #include "v3math.h" #include "llvector4a.h" #include <vector> -#include <set> #define OCT_ERRS LL_WARNS("OctreeErrors") @@ -79,16 +78,18 @@ public: typedef LLOctreeTraveler<T> oct_traveler; typedef LLTreeTraveler<T> tree_traveler; - typedef typename std::set<LLPointer<T> > element_list; - typedef typename element_list::iterator element_iter; - typedef typename element_list::const_iterator const_element_iter; + typedef LLPointer<T>* element_list; + typedef LLPointer<T>* element_iter; + typedef const LLPointer<T>* const_element_iter; typedef typename std::vector<LLTreeListener<T>*>::iterator tree_listener_iter; - typedef typename std::vector<LLOctreeNode<T>* > child_list; + typedef LLOctreeNode<T>** child_list; + typedef LLOctreeNode<T>** child_iter; + typedef LLTreeNode<T> BaseType; typedef LLOctreeNode<T> oct_node; typedef LLOctreeListener<T> oct_listener; - /*void* operator new(size_t size) + void* operator new(size_t size) { return ll_aligned_malloc_16(size); } @@ -96,7 +97,7 @@ public: void operator delete(void* ptr) { ll_aligned_free_16(ptr); - }*/ + } LLOctreeNode( const LLVector4a& center, const LLVector4a& size, @@ -105,6 +106,9 @@ public: : mParent((oct_node*)parent), mOctant(octant) { + mData = NULL; + mDataEnd = NULL; + mCenter = center; mSize = size; @@ -123,6 +127,16 @@ public: { BaseType::destroyListeners(); + for (U32 i = 0; i < mElementCount; ++i) + { + mData[i]->setBinIndex(-1); + mData[i] = NULL; + } + + free(mData); + mData = NULL; + mDataEnd = NULL; + for (U32 i = 0; i < getChildCount(); i++) { delete getChild(i); @@ -219,12 +233,17 @@ public: } void accept(oct_traveler* visitor) { visitor->visit(this); } - virtual bool isLeaf() const { return mChild.empty(); } + virtual bool isLeaf() const { return mChildCount == 0; } U32 getElementCount() const { return mElementCount; } + bool isEmpty() const { return mElementCount == 0; } element_list& getData() { return mData; } const element_list& getData() const { return mData; } - + element_iter getDataBegin() { return mData; } + element_iter getDataEnd() { return mDataEnd; } + const_element_iter getDataBegin() const { return mData; } + const_element_iter getDataEnd() const { return mDataEnd; } + U32 getChildCount() const { return mChildCount; } oct_node* getChild(U32 index) { return mChild[index]; } const oct_node* getChild(U32 index) const { return mChild[index]; } @@ -289,7 +308,7 @@ public: virtual bool insert(T* data) { - if (data == NULL) + if (data == NULL || data->getBinIndex() != -1) { OCT_ERRS << "!!! INVALID ELEMENT ADDED TO OCTREE BRANCH !!!" << llendl; return false; @@ -302,13 +321,16 @@ public: if ((getElementCount() < gOctreeMaxCapacity && contains(data->getBinRadius()) || (data->getBinRadius() > getSize()[0] && parent && parent->getElementCount() >= gOctreeMaxCapacity))) { //it belongs here - //if this is a redundant insertion, error out (should never happen) - llassert(mData.find(data) == mData.end()); + mElementCount++; + mData = (element_list) realloc(mData, sizeof(LLPointer<T>)*mElementCount); - mData.insert(data); - BaseType::insert(data); + //avoid unref on uninitialized memory + memset(mData+mElementCount-1, 0, sizeof(LLPointer<T>)); - mElementCount = mData.size(); + mData[mElementCount-1] = data; + mDataEnd = mData + mElementCount; + data->setBinIndex(mElementCount-1); + BaseType::insert(data); return true; } else @@ -342,10 +364,16 @@ public: if( lt == 0x7 ) { - mData.insert(data); - BaseType::insert(data); + mElementCount++; + mData = (element_list) realloc(mData, sizeof(LLPointer<T>)*mElementCount); + + //avoid unref on uninitialized memory + memset(mData+mElementCount-1, 0, sizeof(LLPointer<T>)); - mElementCount = mData.size(); + mData[mElementCount-1] = data; + mDataEnd = mData + mElementCount; + data->setBinIndex(mElementCount-1); + BaseType::insert(data); return true; } @@ -394,23 +422,59 @@ public: return false; } + void _remove(T* data, S32 i) + { //precondition -- mElementCount > 0, idx is in range [0, mElementCount) + + mElementCount--; + data->setBinIndex(-1); + + if (mElementCount > 0) + { + if (mElementCount != i) + { + mData[i] = mData[mElementCount]; //might unref data, do not access data after this point + mData[i]->setBinIndex(i); + } + + mData[mElementCount] = NULL; //needed for unref + mData = (element_list) realloc(mData, sizeof(LLPointer<T>)*mElementCount); + mDataEnd = mData+mElementCount; + } + else + { + mData[0] = NULL; //needed for unref + free(mData); + mData = NULL; + mDataEnd = NULL; + } + + notifyRemoval(data); + checkAlive(); + } + bool remove(T* data) { - if (mData.find(data) != mData.end()) - { //we have data - mData.erase(data); - mElementCount = mData.size(); - notifyRemoval(data); - checkAlive(); - return true; - } - else if (isInside(data)) + S32 i = data->getBinIndex(); + + if (i >= 0 && i < mElementCount) + { + if (mData[i] == data) + { //found it + _remove(data, i); + llassert(data->getBinIndex() == -1); + return true; + } + } + + if (isInside(data)) { oct_node* dest = getNodeAt(data); if (dest != this) { - return dest->remove(data); + bool ret = dest->remove(data); + llassert(data->getBinIndex() == -1); + return ret; } } @@ -429,19 +493,20 @@ public: //node is now root llwarns << "!!! OCTREE REMOVING FACE BY ADDRESS, SEVERE PERFORMANCE PENALTY |||" << llendl; node->removeByAddress(data); + llassert(data->getBinIndex() == -1); return true; } void removeByAddress(T* data) { - if (mData.find(data) != mData.end()) + for (U32 i = 0; i < mElementCount; ++i) { - mData.erase(data); - mElementCount = mData.size(); - notifyRemoval(data); - llwarns << "FOUND!" << llendl; - checkAlive(); - return; + if (mData[i] == data) + { //we have data + _remove(data, i); + llwarns << "FOUND!" << llendl; + return; + } } for (U32 i = 0; i < getChildCount(); i++) @@ -453,8 +518,8 @@ public: void clearChildren() { - mChild.clear(); mChildCount = 0; + U32* foo = (U32*) mChildMap; foo[0] = foo[1] = 0xFFFFFFFF; } @@ -516,7 +581,7 @@ public: mChildMap[child->getOctant()] = mChildCount; - mChild.push_back(child); + mChild[mChildCount] = child; ++mChildCount; child->setParent(this); @@ -543,9 +608,12 @@ public: mChild[index]->destroy(); delete mChild[index]; } - mChild.erase(mChild.begin() + index); + --mChildCount; + mChild[index] = mChild[mChildCount]; + + //rebuild child map U32* foo = (U32*) mChildMap; foo[0] = foo[1] = 0xFFFFFFFF; @@ -601,11 +669,12 @@ protected: oct_node* mParent; U8 mOctant; - child_list mChild; + LLOctreeNode<T>* mChild[8]; U8 mChildMap[8]; U32 mChildCount; element_list mData; + element_iter mDataEnd; U32 mElementCount; }; diff --git a/indra/llmath/llplane.h b/indra/llmath/llplane.h index a611894721..3c32441b11 100644 --- a/indra/llmath/llplane.h +++ b/indra/llmath/llplane.h @@ -36,6 +36,8 @@ // The plane normal = [A, B, C] // The closest approach = D / sqrt(A*A + B*B + C*C) + +LL_ALIGN_PREFIX(16) class LLPlane { public: @@ -94,7 +96,7 @@ public: private: LLVector4a mV; -}; +} LL_ALIGN_POSTFIX(16); diff --git a/indra/llmath/llsimdmath.h b/indra/llmath/llsimdmath.h index c7cdf7b32c..01458521ec 100644 --- a/indra/llmath/llsimdmath.h +++ b/indra/llmath/llsimdmath.h @@ -67,11 +67,10 @@ template <typename T> T* LL_NEXT_ALIGNED_ADDRESS_64(T* address) #define LL_ALIGN_16(var) LL_ALIGN_PREFIX(16) var LL_ALIGN_POSTFIX(16) - - #include <xmmintrin.h> #include <emmintrin.h> +#include "llmemory.h" #include "llsimdtypes.h" #include "llsimdtypes.inl" diff --git a/indra/llmath/llsimdtypes.inl b/indra/llmath/llsimdtypes.inl index 712239e425..e905c84954 100644 --- a/indra/llmath/llsimdtypes.inl +++ b/indra/llmath/llsimdtypes.inl @@ -62,6 +62,7 @@ inline LLSimdScalar operator/(const LLSimdScalar& a, const LLSimdScalar& b) inline LLSimdScalar operator-(const LLSimdScalar& a) { static LL_ALIGN_16(const U32 signMask[4]) = {0x80000000, 0x80000000, 0x80000000, 0x80000000 }; + ll_assert_aligned(signMask,16); return _mm_xor_ps(*reinterpret_cast<const LLQuad*>(signMask), a); } @@ -146,6 +147,7 @@ inline LLSimdScalar& LLSimdScalar::operator/=(const LLSimdScalar& rhs) inline LLSimdScalar LLSimdScalar::getAbs() const { static const LL_ALIGN_16(U32 F_ABS_MASK_4A[4]) = { 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF }; + ll_assert_aligned(F_ABS_MASK_4A,16); return _mm_and_ps( mQ, *reinterpret_cast<const LLQuad*>(F_ABS_MASK_4A)); } diff --git a/indra/llmath/llvector4a.cpp b/indra/llmath/llvector4a.cpp index b66b7a7076..6edeb0fefe 100644 --- a/indra/llmath/llvector4a.cpp +++ b/indra/llmath/llvector4a.cpp @@ -24,6 +24,7 @@ * $/LicenseInfo$ */ +#include "llmemory.h" #include "llmath.h" #include "llquantize.h" @@ -44,7 +45,10 @@ extern const LLVector4a LL_V4A_EPSILON = reinterpret_cast<const LLVector4a&> ( F assert(dst != NULL); assert(bytes > 0); assert((bytes % sizeof(F32))== 0); - + ll_assert_aligned(src,16); + ll_assert_aligned(dst,16); + assert(bytes%16==0); + F32* end = dst + (bytes / sizeof(F32) ); if (bytes > 64) @@ -189,6 +193,8 @@ void LLVector4a::quantize16( const LLVector4a& low, const LLVector4a& high ) LLVector4a oneOverDelta; { static LL_ALIGN_16( const F32 F_TWO_4A[4] ) = { 2.f, 2.f, 2.f, 2.f }; + ll_assert_aligned(F_TWO_4A,16); + LLVector4a two; two.load4a( F_TWO_4A ); // Here we use _mm_rcp_ps plus one round of newton-raphson diff --git a/indra/llmath/llvector4a.h b/indra/llmath/llvector4a.h index 596082509d..0526793d3a 100644 --- a/indra/llmath/llvector4a.h +++ b/indra/llmath/llvector4a.h @@ -32,6 +32,7 @@ class LLRotation; #include <assert.h> #include "llpreprocessor.h" +#include "llmemory.h" /////////////////////////////////// // FIRST TIME USERS PLEASE READ @@ -46,6 +47,7 @@ class LLRotation; // LLVector3/LLVector4. ///////////////////////////////// +LL_ALIGN_PREFIX(16) class LLVector4a { public: @@ -82,6 +84,7 @@ public: } // Copy words 16-byte blocks from src to dst. Source and destination must not overlap. + // Source and dest must be 16-byte aligned and size must be multiple of 16. static void memcpyNonAliased16(F32* __restrict dst, const F32* __restrict src, size_t bytes); //////////////////////////////////// @@ -90,6 +93,7 @@ public: LLVector4a() { //DO NOT INITIALIZE -- The overhead is completely unnecessary + ll_assert_aligned(this,16); } LLVector4a(F32 x, F32 y, F32 z, F32 w = 0.f) @@ -313,7 +317,7 @@ public: private: LLQuad mQ; -}; +} LL_ALIGN_POSTFIX(16); inline void update_min_max(LLVector4a& min, LLVector4a& max, const LLVector4a& p) { diff --git a/indra/llmath/llvector4a.inl b/indra/llmath/llvector4a.inl index 7ad22a5631..7c52ffef21 100644 --- a/indra/llmath/llvector4a.inl +++ b/indra/llmath/llvector4a.inl @@ -475,6 +475,7 @@ inline void LLVector4a::setLerp(const LLVector4a& lhs, const LLVector4a& rhs, F3 inline LLBool32 LLVector4a::isFinite3() const { static LL_ALIGN_16(const U32 nanOrInfMask[4]) = { 0x7f800000, 0x7f800000, 0x7f800000, 0x7f800000 }; + ll_assert_aligned(nanOrInfMask,16); const __m128i nanOrInfMaskV = *reinterpret_cast<const __m128i*> (nanOrInfMask); const __m128i maskResult = _mm_and_si128( _mm_castps_si128(mQ), nanOrInfMaskV ); const LLVector4Logical equalityCheck = _mm_castsi128_ps(_mm_cmpeq_epi32( maskResult, nanOrInfMaskV )); diff --git a/indra/llmath/llvector4logical.h b/indra/llmath/llvector4logical.h index dd66b09d43..c5698f7cea 100644 --- a/indra/llmath/llvector4logical.h +++ b/indra/llmath/llvector4logical.h @@ -27,6 +27,7 @@ #ifndef LL_VECTOR4LOGICAL_H #define LL_VECTOR4LOGICAL_H +#include "llmemory.h" //////////////////////////// // LLVector4Logical @@ -77,6 +78,7 @@ public: inline LLVector4Logical& invert() { static const LL_ALIGN_16(U32 allOnes[4]) = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }; + ll_assert_aligned(allOnes,16); mQ = _mm_andnot_ps( mQ, *(LLQuad*)(allOnes) ); return *this; } diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index cc9744756f..53d56e96da 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -95,17 +95,6 @@ const S32 SCULPT_MIN_AREA_DETAIL = 1; extern BOOL gDebugGL; -void assert_aligned(void* ptr, uintptr_t alignment) -{ -#if 0 - uintptr_t t = (uintptr_t) ptr; - if (t%alignment != 0) - { - llerrs << "Alignment check failed." << llendl; - } -#endif -} - BOOL check_same_clock_dir( const LLVector3& pt1, const LLVector3& pt2, const LLVector3& pt3, const LLVector3& norm) { LLVector3 test = (pt2-pt1)%(pt3-pt2); @@ -328,16 +317,16 @@ public: LLVector4a& min = node->mExtents[0]; LLVector4a& max = node->mExtents[1]; - if (!branch->getData().empty()) + if (!branch->isEmpty()) { //node has data, find AABB that binds data set - const LLVolumeTriangle* tri = *(branch->getData().begin()); + const LLVolumeTriangle* tri = *(branch->getDataBegin()); //initialize min/max to first available vertex min = *(tri->mV[0]); max = *(tri->mV[0]); for (LLOctreeNode<LLVolumeTriangle>::const_element_iter iter = - branch->getData().begin(); iter != branch->getData().end(); ++iter) + branch->getDataBegin(); iter != branch->getDataEnd(); ++iter) { //for each triangle in node //stretch by triangles in node @@ -352,7 +341,7 @@ public: max.setMax(max, *tri->mV[2]); } } - else if (!branch->getChildren().empty()) + else if (!branch->isLeaf()) { //no data, but child nodes exist LLVolumeOctreeListener* child = (LLVolumeOctreeListener*) branch->getChild(0)->getListener(0); @@ -6962,14 +6951,14 @@ void LLVolumeFace::resizeVertices(S32 num_verts) if (num_verts) { mPositions = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts); - assert_aligned(mPositions, 16); + ll_assert_aligned(mPositions, 16); mNormals = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts); - assert_aligned(mNormals, 16); + ll_assert_aligned(mNormals, 16); //pad texture coordinate block end to allow for QWORD reads S32 size = ((num_verts*sizeof(LLVector2)) + 0xF) & ~0xF; mTexCoords = (LLVector2*) ll_aligned_malloc_16(size); - assert_aligned(mTexCoords, 16); + ll_assert_aligned(mTexCoords, 16); } else { @@ -6993,14 +6982,17 @@ void LLVolumeFace::pushVertex(const LLVector4a& pos, const LLVector4a& norm, con // S32 old_size = mNumVertices*16; //positions - mPositions = (LLVector4a*) realloc(mPositions, new_size); + mPositions = (LLVector4a*) ll_aligned_realloc_16(mPositions, new_size); + ll_assert_aligned(mPositions,16); //normals - mNormals = (LLVector4a*) realloc(mNormals, new_size); - + mNormals = (LLVector4a*) ll_aligned_realloc_16(mNormals, new_size); + ll_assert_aligned(mNormals,16); + //tex coords new_size = ((new_verts*8)+0xF) & ~0xF; - mTexCoords = (LLVector2*) realloc(mTexCoords, new_size); + mTexCoords = (LLVector2*) ll_aligned_realloc_16(mTexCoords, new_size); + ll_assert_aligned(mTexCoords,16); //just clear binormals @@ -7053,7 +7045,8 @@ void LLVolumeFace::pushIndex(const U16& idx) S32 old_size = ((mNumIndices*2)+0xF) & ~0xF; if (new_size != old_size) { - mIndices = (U16*) realloc(mIndices, new_size); + mIndices = (U16*) ll_aligned_realloc_16(mIndices, new_size); + ll_assert_aligned(mIndices,16); } mIndices[mNumIndices++] = idx; @@ -7094,12 +7087,12 @@ void LLVolumeFace::appendFace(const LLVolumeFace& face, LLMatrix4& mat_in, LLMat } //allocate new buffer space - mPositions = (LLVector4a*) realloc(mPositions, new_count*sizeof(LLVector4a)); - assert_aligned(mPositions, 16); - mNormals = (LLVector4a*) realloc(mNormals, new_count*sizeof(LLVector4a)); - assert_aligned(mNormals, 16); - mTexCoords = (LLVector2*) realloc(mTexCoords, (new_count*sizeof(LLVector2)+0xF) & ~0xF); - assert_aligned(mTexCoords, 16); + mPositions = (LLVector4a*) ll_aligned_realloc_16(mPositions, new_count*sizeof(LLVector4a)); + ll_assert_aligned(mPositions, 16); + mNormals = (LLVector4a*) ll_aligned_realloc_16(mNormals, new_count*sizeof(LLVector4a)); + ll_assert_aligned(mNormals, 16); + mTexCoords = (LLVector2*) ll_aligned_realloc_16(mTexCoords, (new_count*sizeof(LLVector2)+0xF) & ~0xF); + ll_assert_aligned(mTexCoords, 16); mNumVertices = new_count; @@ -7145,7 +7138,7 @@ void LLVolumeFace::appendFace(const LLVolumeFace& face, LLMatrix4& mat_in, LLMat new_count = mNumIndices + face.mNumIndices; //allocate new index buffer - mIndices = (U16*) realloc(mIndices, (new_count*sizeof(U16)+0xF) & ~0xF); + mIndices = (U16*) ll_aligned_realloc_16(mIndices, (new_count*sizeof(U16)+0xF) & ~0xF); //get destination address into new index buffer U16* dst_idx = mIndices+mNumIndices; diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h index 76cf9de613..2e6f9e2f71 100644 --- a/indra/llmath/llvolume.h +++ b/indra/llmath/llvolume.h @@ -54,6 +54,7 @@ class LLVolumeTriangle; #include "llstrider.h" #include "v4coloru.h" #include "llrefcount.h" +#include "llpointer.h" #include "llfile.h" //============================================================================ @@ -919,6 +920,10 @@ public: LLVector2* mTexCoords; U16* mIndices; + //vertex buffer filled in by LLFace to cache this volume face geometry in vram + // (declared as a LLPointer to LLRefCount to avoid dependency on LLVertexBuffer) + mutable LLPointer<LLRefCount> mVertexBuffer; + std::vector<S32> mEdge; //list of skin weights for rigged volumes diff --git a/indra/llmath/llvolumeoctree.cpp b/indra/llmath/llvolumeoctree.cpp index b5a935c2b5..cc83cb7235 100644 --- a/indra/llmath/llvolumeoctree.cpp +++ b/indra/llmath/llvolumeoctree.cpp @@ -131,7 +131,7 @@ void LLOctreeTriangleRayIntersect::traverse(const LLOctreeNode<LLVolumeTriangle> void LLOctreeTriangleRayIntersect::visit(const LLOctreeNode<LLVolumeTriangle>* node) { for (LLOctreeNode<LLVolumeTriangle>::const_element_iter iter = - node->getData().begin(); iter != node->getData().end(); ++iter) + node->getDataBegin(); iter != node->getDataEnd(); ++iter) { const LLVolumeTriangle* tri = *iter; @@ -236,8 +236,8 @@ void LLVolumeOctreeValidate::visit(const LLOctreeNode<LLVolumeTriangle>* branch) } //children fit, check data - for (LLOctreeNode<LLVolumeTriangle>::const_element_iter iter = branch->getData().begin(); - iter != branch->getData().end(); ++iter) + for (LLOctreeNode<LLVolumeTriangle>::const_element_iter iter = branch->getDataBegin(); + iter != branch->getDataEnd(); ++iter) { const LLVolumeTriangle* tri = *iter; diff --git a/indra/llmath/llvolumeoctree.h b/indra/llmath/llvolumeoctree.h index 688d91dc40..9ae34a0c4e 100644 --- a/indra/llmath/llvolumeoctree.h +++ b/indra/llmath/llvolumeoctree.h @@ -37,9 +37,19 @@ class LLVolumeTriangle : public LLRefCount { public: + void* operator new(size_t size) + { + return ll_aligned_malloc_16(size); + } + + void operator delete(void* ptr) + { + ll_aligned_free_16(ptr); + } + LLVolumeTriangle() { - + mBinIndex = -1; } LLVolumeTriangle(const LLVolumeTriangle& rhs) @@ -58,21 +68,38 @@ public: } - LLVector4a mPositionGroup; + LL_ALIGN_16(LLVector4a mPositionGroup); const LLVector4a* mV[3]; U16 mIndex[3]; F32 mRadius; + mutable S32 mBinIndex; + virtual const LLVector4a& getPositionGroup() const; virtual const F32& getBinRadius() const; + + S32 getBinIndex() const { return mBinIndex; } + void setBinIndex(S32 idx) const { mBinIndex = idx; } + + }; class LLVolumeOctreeListener : public LLOctreeListener<LLVolumeTriangle> { public: + void* operator new(size_t size) + { + return ll_aligned_malloc_16(size); + } + + void operator delete(void* ptr) + { + ll_aligned_free_16(ptr); + } + LLVolumeOctreeListener(LLOctreeNode<LLVolumeTriangle>* node); ~LLVolumeOctreeListener(); @@ -99,8 +126,8 @@ public: public: - LLVector4a mBounds[2]; // bounding box (center, size) of this node and all its children (tight fit to objects) - LLVector4a mExtents[2]; // extents (min, max) of this node and all its children + LL_ALIGN_16(LLVector4a mBounds[2]); // bounding box (center, size) of this node and all its children (tight fit to objects) + LL_ALIGN_16(LLVector4a mExtents[2]); // extents (min, max) of this node and all its children }; class LLOctreeTriangleRayIntersect : public LLOctreeTraveler<LLVolumeTriangle> diff --git a/indra/llmath/tests/alignment_test.cpp b/indra/llmath/tests/alignment_test.cpp new file mode 100644 index 0000000000..ac0c45ae6f --- /dev/null +++ b/indra/llmath/tests/alignment_test.cpp @@ -0,0 +1,128 @@ +/** + * @file v3dmath_test.cpp + * @author Vir + * @date 2011-12 + * @brief v3dmath test cases. + * + * $LicenseInfo:firstyear=2011&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$ + */ + +// Tests related to allocating objects with alignment constraints, particularly for SSE support. + +#include "linden_common.h" +#include "../test/lltut.h" +#include "../llmath.h" +#include "../llsimdmath.h" +#include "../llvector4a.h" + +void* operator new(size_t size) +{ + return ll_aligned_malloc_16(size); +} + +void operator delete(void *p) +{ + ll_aligned_free_16(p); +} + +namespace tut +{ + +#define is_aligned(ptr,alignment) ((reinterpret_cast<uintptr_t>(ptr))%(alignment)==0) +#define is_aligned_relative(ptr,base_ptr,alignment) ((reinterpret_cast<uintptr_t>(ptr)-reinterpret_cast<uintptr_t>(base_ptr))%(alignment)==0) + +struct alignment_test {}; + +typedef test_group<alignment_test> alignment_test_t; +typedef alignment_test_t::object alignment_test_object_t; +tut::alignment_test_t tut_alignment_test("LLAlignment"); + +LL_ALIGN_PREFIX(16) +class MyVector4a +{ + LLQuad mQ; +} LL_ALIGN_POSTFIX(16); + + +// Verify that aligned allocators perform as advertised. +template<> template<> +void alignment_test_object_t::test<1>() +{ +# ifdef LL_DEBUG + skip("This test fails on Windows when compiled in debug mode."); +# endif + + const int num_tests = 7; + void *align_ptr; + for (int i=0; i<num_tests; i++) + { + align_ptr = ll_aligned_malloc_16(sizeof(MyVector4a)); + ensure("ll_aligned_malloc_16 failed", is_aligned(align_ptr,16)); + + align_ptr = ll_aligned_realloc_16(align_ptr,2*sizeof(MyVector4a)); + ensure("ll_aligned_realloc_16 failed", is_aligned(align_ptr,16)); + + ll_aligned_free_16(align_ptr); + + align_ptr = ll_aligned_malloc_32(sizeof(MyVector4a)); + ensure("ll_aligned_malloc_32 failed", is_aligned(align_ptr,32)); + ll_aligned_free_32(align_ptr); + } +} + +// In-place allocation of objects and arrays. +template<> template<> +void alignment_test_object_t::test<2>() +{ + MyVector4a vec1; + ensure("LLAlignment vec1 unaligned", is_aligned(&vec1,16)); + + MyVector4a veca[12]; + ensure("LLAlignment veca unaligned", is_aligned(veca,16)); +} + +// Heap allocation of objects and arrays. +template<> template<> +void alignment_test_object_t::test<3>() +{ +# ifdef LL_DEBUG + skip("This test fails on Windows when compiled in debug mode."); +# endif + + const int ARR_SIZE = 7; + for(int i=0; i<ARR_SIZE; i++) + { + MyVector4a *vecp = new MyVector4a; + ensure("LLAlignment vecp unaligned", is_aligned(vecp,16)); + delete vecp; + } + + MyVector4a *veca = new MyVector4a[ARR_SIZE]; + ensure("LLAligment veca base", is_aligned(veca,16)); + for(int i=0; i<ARR_SIZE; i++) + { + std::cout << "veca[" << i << "]" << std::endl; + ensure("LLAlignment veca member unaligned", is_aligned(&veca[i],16)); + } +} + +} diff --git a/indra/llmessage/llsdmessagereader.cpp b/indra/llmessage/llsdmessagereader.cpp index 3d8ca2ad9f..a6fccd2a56 100644 --- a/indra/llmessage/llsdmessagereader.cpp +++ b/indra/llmessage/llsdmessagereader.cpp @@ -276,7 +276,7 @@ S32 getElementSize(const LLSD& llsd) case LLSD::TypeReal: return sizeof(F64); case LLSD::TypeString: - return llsd.asString().size(); + return llsd.size(); case LLSD::TypeUUID: return sizeof(LLUUID); case LLSD::TypeDate: diff --git a/indra/llmessage/llurlrequest.cpp b/indra/llmessage/llurlrequest.cpp index a16f5c7bf0..f3f0007205 100644 --- a/indra/llmessage/llurlrequest.cpp +++ b/indra/llmessage/llurlrequest.cpp @@ -289,6 +289,8 @@ LLIOPipe::EStatus LLURLRequest::handleError( } static LLFastTimer::DeclareTimer FTM_PROCESS_URL_REQUEST("URL Request"); +static LLFastTimer::DeclareTimer FTM_PROCESS_URL_REQUEST_GET_RESULT("Get Result"); +static LLFastTimer::DeclareTimer FTM_URL_PERFORM("Perform"); // virtual LLIOPipe::EStatus LLURLRequest::process_impl( @@ -358,7 +360,6 @@ LLIOPipe::EStatus LLURLRequest::process_impl( { PUMP_DEBUG; LLIOPipe::EStatus status = STATUS_BREAK; - static LLFastTimer::DeclareTimer FTM_URL_PERFORM("Perform"); { LLFastTimer t(FTM_URL_PERFORM); if(!mDetail->mCurlRequest->wait()) @@ -371,8 +372,6 @@ LLIOPipe::EStatus LLURLRequest::process_impl( { CURLcode result; - static LLFastTimer::DeclareTimer FTM_PROCESS_URL_REQUEST_GET_RESULT("Get Result"); - bool newmsg = false; { LLFastTimer t(FTM_PROCESS_URL_REQUEST_GET_RESULT); diff --git a/indra/llmessage/tests/llhttpclient_test.cpp b/indra/llmessage/tests/llhttpclient_test.cpp index 843c3bcc4b..e338d4ec71 100644 --- a/indra/llmessage/tests/llhttpclient_test.cpp +++ b/indra/llmessage/tests/llhttpclient_test.cpp @@ -258,6 +258,7 @@ namespace tut void HTTPClientTestObject::test<1>() { LLHTTPClient::get(local_server, newResult()); + runThePump(); ensureStatusOK(); ensure("result object wasn't destroyed", mResultDeleted); diff --git a/indra/llprimitive/llmodel.cpp b/indra/llprimitive/llmodel.cpp index cb32a510b8..28ed051c55 100644 --- a/indra/llprimitive/llmodel.cpp +++ b/indra/llprimitive/llmodel.cpp @@ -1026,7 +1026,8 @@ void LLModel::setVolumeFaceData( if (tc.get()) { - LLVector4a::memcpyNonAliased16((F32*) face.mTexCoords, (F32*) tc.get(), num_verts*2*sizeof(F32)); + U32 tex_size = (num_verts*2*sizeof(F32)+0xF)&~0xF; + LLVector4a::memcpyNonAliased16((F32*) face.mTexCoords, (F32*) tc.get(), tex_size); } else { diff --git a/indra/llprimitive/object_flags.h b/indra/llprimitive/object_flags.h index b06a5ad4e3..31dbd15ae0 100644 --- a/indra/llprimitive/object_flags.h +++ b/indra/llprimitive/object_flags.h @@ -40,26 +40,34 @@ const U32 FLAGS_OBJECT_MOVE = (1U << 8); const U32 FLAGS_TAKES_MONEY = (1U << 9); const U32 FLAGS_PHANTOM = (1U << 10); const U32 FLAGS_INVENTORY_EMPTY = (1U << 11); -const U32 FLAGS_OBJECT_PERMANENT = (1U << 12); + +const U32 FLAGS_AFFECTS_NAVMESH = (1U << 12); const U32 FLAGS_CHARACTER = (1U << 13); -//const U32 FLAGS_UNUSED_000 = (1U << 14); // was FLAGS_JOINT_LP2P +const U32 FLAGS_VOLUME_DETECT = (1U << 14); const U32 FLAGS_INCLUDE_IN_SEARCH = (1U << 15); + const U32 FLAGS_ALLOW_INVENTORY_DROP = (1U << 16); const U32 FLAGS_OBJECT_TRANSFER = (1U << 17); const U32 FLAGS_OBJECT_GROUP_OWNED = (1U << 18); -//const U32 FLAGS_UNUSED_001 = (1U << 19); // was FLAGS_OBJECT_YOU_OFFICER +//const U32 FLAGS_UNUSED_000 = (1U << 19); // was FLAGS_OBJECT_YOU_OFFICER + const U32 FLAGS_CAMERA_DECOUPLED = (1U << 20); const U32 FLAGS_ANIM_SOURCE = (1U << 21); const U32 FLAGS_CAMERA_SOURCE = (1U << 22); -//const U32 FLAGS_UNUSED_002 = (1U << 23); // was FLAGS_CAST_SHADOWS -//const U32 FLAGS_UNUSED_003 = (1U << 24); -//const U32 FLAGS_UNUSED_004 = (1U << 25); -//const U32 FLAGS_UNUSED_005 = (1U << 26); -//const U32 FLAGS_UNUSED_006 = (1U << 27); + +//const U32 FLAGS_UNUSED_001 = (1U << 23); // was FLAGS_CAST_SHADOWS + +//const U32 FLAGS_UNUSED_002 = (1U << 24); +//const U32 FLAGS_UNUSED_003 = (1U << 25); +//const U32 FLAGS_UNUSED_004 = (1U << 26); +//const U32 FLAGS_UNUSED_005 = (1U << 27); + const U32 FLAGS_OBJECT_OWNER_MODIFY = (1U << 28); + const U32 FLAGS_TEMPORARY_ON_REZ = (1U << 29); -//const U32 FLAGS_UNUSED_007 = (1U << 30); // was FLAGS_TEMPORARY -//const U32 FLAGS_UNUSED_008 = (1U << 31); // was FLAGS_ZLIB_COMPRESSED +//const U32 FLAGS_UNUSED_006 = (1U << 30); // was FLAGS_TEMPORARY +//const U32 FLAGS_UNUSED_007 = (1U << 31); // was FLAGS_ZLIB_COMPRESSED + const U32 FLAGS_LOCAL = FLAGS_ANIM_SOURCE | FLAGS_CAMERA_SOURCE; typedef enum e_havok_joint_type diff --git a/indra/llrender/llcubemap.cpp b/indra/llrender/llcubemap.cpp index 45a3b18179..362452d837 100644 --- a/indra/llrender/llcubemap.cpp +++ b/indra/llrender/llcubemap.cpp @@ -81,7 +81,7 @@ void LLCubeMap::initGL() { U32 texname = 0; - LLImageGL::generateTextures(1, &texname); + LLImageGL::generateTextures(LLTexUnit::TT_CUBE_MAP, GL_RGB8, 1, &texname); for (int i = 0; i < 6; i++) { diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp index fccbf37a8d..4dc2fcd714 100644 --- a/indra/llrender/llfontgl.cpp +++ b/indra/llrender/llfontgl.cpp @@ -422,6 +422,16 @@ S32 LLFontGL::renderUTF8(const std::string &text, S32 begin_offset, S32 x, S32 y } // font metrics - override for LLFontFreetype that returns units of virtual pixels +F32 LLFontGL::getAscenderHeight() const +{ + return mFontFreetype->getAscenderHeight() / sScaleY; +} + +F32 LLFontGL::getDescenderHeight() const +{ + return mFontFreetype->getDescenderHeight() / sScaleY; +} + S32 LLFontGL::getLineHeight() const { return llceil(mFontFreetype->getAscenderHeight() / sScaleY) + llceil(mFontFreetype->getDescenderHeight() / sScaleY); diff --git a/indra/llrender/llfontgl.h b/indra/llrender/llfontgl.h index 74bdbb43e7..5ed5d2c4eb 100644 --- a/indra/llrender/llfontgl.h +++ b/indra/llrender/llfontgl.h @@ -115,6 +115,8 @@ public: S32 renderUTF8(const std::string &text, S32 begin_offset, S32 x, S32 y, const LLColor4 &color, HAlign halign, VAlign valign, U8 style = NORMAL, ShadowType shadow = NO_SHADOW) const; // font metrics - override for LLFontFreetype that returns units of virtual pixels + F32 getAscenderHeight() const; + F32 getDescenderHeight() const; S32 getLineHeight() const; S32 getWidth(const std::string& utf8text) const; diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp index 628a8d6131..0b56b3889c 100644 --- a/indra/llrender/llgl.cpp +++ b/indra/llrender/llgl.cpp @@ -249,6 +249,12 @@ PFNGLTEXIMAGE3DMULTISAMPLEPROC glTexImage3DMultisample = NULL; PFNGLGETMULTISAMPLEFVPROC glGetMultisamplefv = NULL; PFNGLSAMPLEMASKIPROC glSampleMaski = NULL; +//transform feedback (4.0 core) +PFNGLBEGINTRANSFORMFEEDBACKPROC glBeginTransformFeedback = NULL; +PFNGLENDTRANSFORMFEEDBACKPROC glEndTransformFeedback = NULL; +PFNGLTRANSFORMFEEDBACKVARYINGSPROC glTransformFeedbackVaryings = NULL; +PFNGLBINDBUFFERRANGEPROC glBindBufferRange = NULL; + //GL_ARB_debug_output PFNGLDEBUGMESSAGECONTROLARBPROC glDebugMessageControlARB = NULL; PFNGLDEBUGMESSAGEINSERTARBPROC glDebugMessageInsertARB = NULL; @@ -421,6 +427,7 @@ LLGLManager::LLGLManager() : mHasDrawBuffers(FALSE), mHasTextureRectangle(FALSE), mHasTextureMultisample(FALSE), + mHasTransformFeedback(FALSE), mMaxSampleMaskWords(0), mMaxColorTextureSamples(0), mMaxDepthTextureSamples(0), @@ -558,7 +565,8 @@ bool LLGLManager::initGL() parse_gl_version( &mDriverVersionMajor, &mDriverVersionMinor, &mDriverVersionRelease, - &mDriverVersionVendorString ); + &mDriverVersionVendorString, + &mGLVersionString); mGLVersion = mDriverVersionMajor + mDriverVersionMinor * .1f; @@ -938,7 +946,6 @@ void LLGLManager::initExtensions() mHasMultitexture = glh_init_extensions("GL_ARB_multitexture"); mHasATIMemInfo = ExtensionExists("GL_ATI_meminfo", gGLHExts.mSysExts); mHasNVXMemInfo = ExtensionExists("GL_NVX_gpu_memory_info", gGLHExts.mSysExts); - mHasMipMapGeneration = glh_init_extensions("GL_SGIS_generate_mipmap"); mHasSeparateSpecularColor = glh_init_extensions("GL_EXT_separate_specular_color"); mHasAnisotropic = glh_init_extensions("GL_EXT_texture_filter_anisotropic"); glh_init_extensions("GL_ARB_texture_cube_map"); @@ -963,11 +970,14 @@ void LLGLManager::initExtensions() ExtensionExists("GL_EXT_packed_depth_stencil", gGLHExts.mSysExts); #endif + mHasMipMapGeneration = mHasFramebufferObject || mGLVersion >= 1.4f; + mHasDrawBuffers = ExtensionExists("GL_ARB_draw_buffers", gGLHExts.mSysExts); mHasBlendFuncSeparate = ExtensionExists("GL_EXT_blend_func_separate", gGLHExts.mSysExts); mHasTextureRectangle = ExtensionExists("GL_ARB_texture_rectangle", gGLHExts.mSysExts); mHasTextureMultisample = ExtensionExists("GL_ARB_texture_multisample", gGLHExts.mSysExts); mHasDebugOutput = ExtensionExists("GL_ARB_debug_output", gGLHExts.mSysExts); + mHasTransformFeedback = mGLVersion >= 4.f ? TRUE : FALSE; #if !LL_DARWIN mHasPointParameters = !mIsATI && ExtensionExists("GL_ARB_point_parameters", gGLHExts.mSysExts); #endif @@ -1207,7 +1217,14 @@ void LLGLManager::initExtensions() glTexImage3DMultisample = (PFNGLTEXIMAGE3DMULTISAMPLEPROC) GLH_EXT_GET_PROC_ADDRESS("glTexImage3DMultisample"); glGetMultisamplefv = (PFNGLGETMULTISAMPLEFVPROC) GLH_EXT_GET_PROC_ADDRESS("glGetMultisamplefv"); glSampleMaski = (PFNGLSAMPLEMASKIPROC) GLH_EXT_GET_PROC_ADDRESS("glSampleMaski"); - } + } + if (mHasTransformFeedback) + { + glBeginTransformFeedback = (PFNGLBEGINTRANSFORMFEEDBACKPROC) GLH_EXT_GET_PROC_ADDRESS("glBeginTransformFeedback"); + glEndTransformFeedback = (PFNGLENDTRANSFORMFEEDBACKPROC) GLH_EXT_GET_PROC_ADDRESS("glEndTransformFeedback"); + glTransformFeedbackVaryings = (PFNGLTRANSFORMFEEDBACKVARYINGSPROC) GLH_EXT_GET_PROC_ADDRESS("glTransformFeedbackVaryings"); + glBindBufferRange = (PFNGLBINDBUFFERRANGEPROC) GLH_EXT_GET_PROC_ADDRESS("glBindBufferRange"); + } if (mHasDebugOutput) { glDebugMessageControlARB = (PFNGLDEBUGMESSAGECONTROLARBPROC) GLH_EXT_GET_PROC_ADDRESS("glDebugMessageControlARB"); @@ -1964,6 +1981,7 @@ LLGLState::LLGLState(LLGLenum state, S32 enabled) : case GL_COLOR_MATERIAL: case GL_FOG: case GL_LINE_STIPPLE: + case GL_POLYGON_STIPPLE: mState = 0; break; } @@ -2052,7 +2070,7 @@ void LLGLManager::initGLStates() //////////////////////////////////////////////////////////////////////////////// -void parse_gl_version( S32* major, S32* minor, S32* release, std::string* vendor_specific ) +void parse_gl_version( S32* major, S32* minor, S32* release, std::string* vendor_specific, std::string* version_string ) { // GL_VERSION returns a null-terminated string with the format: // <major>.<minor>[.<release>] [<vendor specific>] @@ -2068,6 +2086,8 @@ void parse_gl_version( S32* major, S32* minor, S32* release, std::string* vendor return; } + version_string->assign(version); + std::string ver_copy( version ); S32 len = (S32)strlen( version ); /* Flawfinder: ignore */ S32 i = 0; @@ -2429,3 +2449,65 @@ LLGLSquashToFarClip::~LLGLSquashToFarClip() gGL.matrixMode(LLRender::MM_MODELVIEW); } + + +LLGLSyncFence::LLGLSyncFence() +{ +#ifdef GL_ARB_sync + mSync = 0; +#endif +} + +LLGLSyncFence::~LLGLSyncFence() +{ +#ifdef GL_ARB_sync + if (mSync) + { + glDeleteSync(mSync); + } +#endif +} + +void LLGLSyncFence::placeFence() +{ +#ifdef GL_ARB_sync + if (mSync) + { + glDeleteSync(mSync); + } + mSync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); +#endif +} + +bool LLGLSyncFence::isCompleted() +{ + bool ret = true; +#ifdef GL_ARB_sync + if (mSync) + { + GLenum status = glClientWaitSync(mSync, 0, 1); + if (status == GL_TIMEOUT_EXPIRED) + { + ret = false; + } + } +#endif + return ret; +} + +void LLGLSyncFence::wait() +{ +#ifdef GL_ARB_sync + if (mSync) + { + while (glClientWaitSync(mSync, 0, FENCE_WAIT_TIME_NANOSECONDS) == GL_TIMEOUT_EXPIRED) + { //track the number of times we've waited here + static S32 waits = 0; + waits++; + } + } +#endif +} + + + diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h index 5a33c98708..964495a3ab 100644 --- a/indra/llrender/llgl.h +++ b/indra/llrender/llgl.h @@ -104,6 +104,7 @@ public: BOOL mHasDepthClamp; BOOL mHasTextureRectangle; BOOL mHasTextureMultisample; + BOOL mHasTransformFeedback; S32 mMaxSampleMaskWords; S32 mMaxColorTextureSamples; S32 mMaxDepthTextureSamples; @@ -141,6 +142,7 @@ public: S32 mGLSLVersionMajor; S32 mGLSLVersionMinor; std::string mDriverVersionVendorString; + std::string mGLVersionString; S32 mVRAM; // VRAM in MB S32 mGLMaxVertexRange; @@ -417,13 +419,38 @@ public: virtual void updateGL() = 0; }; +const U32 FENCE_WAIT_TIME_NANOSECONDS = 1000; //1 ms + +class LLGLFence +{ +public: + virtual void placeFence() = 0; + virtual bool isCompleted() = 0; + virtual void wait() = 0; +}; + +class LLGLSyncFence : public LLGLFence +{ +public: +#ifdef GL_ARB_sync + GLsync mSync; +#endif + + LLGLSyncFence(); + virtual ~LLGLSyncFence(); + + void placeFence(); + bool isCompleted(); + void wait(); +}; + extern LLMatrix4 gGLObliqueProjectionInverse; #include "llglstates.h" void init_glstates(); -void parse_gl_version( S32* major, S32* minor, S32* release, std::string* vendor_specific ); +void parse_gl_version( S32* major, S32* minor, S32* release, std::string* vendor_specific, std::string* version_string ); extern BOOL gClothRipple; extern BOOL gHeadlessClient; diff --git a/indra/llrender/llglheaders.h b/indra/llrender/llglheaders.h index d61ec707f0..a0727b8686 100644 --- a/indra/llrender/llglheaders.h +++ b/indra/llrender/llglheaders.h @@ -528,6 +528,13 @@ extern PFNGLTEXIMAGE3DMULTISAMPLEPROC glTexImage3DMultisample; extern PFNGLGETMULTISAMPLEFVPROC glGetMultisamplefv; extern PFNGLSAMPLEMASKIPROC glSampleMaski; +//transform feedback (4.0 core) +extern PFNGLBEGINTRANSFORMFEEDBACKPROC glBeginTransformFeedback; +extern PFNGLENDTRANSFORMFEEDBACKPROC glEndTransformFeedback; +extern PFNGLTRANSFORMFEEDBACKVARYINGSPROC glTransformFeedbackVaryings; +extern PFNGLBINDBUFFERRANGEPROC glBindBufferRange; + + #elif LL_WINDOWS //---------------------------------------------------------------------------- // LL_WINDOWS @@ -759,6 +766,12 @@ extern PFNGLTEXIMAGE3DMULTISAMPLEPROC glTexImage3DMultisample; extern PFNGLGETMULTISAMPLEFVPROC glGetMultisamplefv; extern PFNGLSAMPLEMASKIPROC glSampleMaski; +//transform feedback (4.0 core) +extern PFNGLBEGINTRANSFORMFEEDBACKPROC glBeginTransformFeedback; +extern PFNGLENDTRANSFORMFEEDBACKPROC glEndTransformFeedback; +extern PFNGLTRANSFORMFEEDBACKVARYINGSPROC glTransformFeedbackVaryings; +extern PFNGLBINDBUFFERRANGEPROC glBindBufferRange; + //GL_ARB_debug_output extern PFNGLDEBUGMESSAGECONTROLARBPROC glDebugMessageControlARB; extern PFNGLDEBUGMESSAGEINSERTARBPROC glDebugMessageInsertARB; diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index 4b7e639aed..7cbf39096e 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -129,7 +129,9 @@ void LLGLSLShader::unload() } BOOL LLGLSLShader::createShader(vector<string> * attributes, - vector<string> * uniforms) + vector<string> * uniforms, + U32 varying_count, + const char** varyings) { //reloading, reset matrix hash values for (U32 i = 0; i < LLRender::NUM_MATRIX_MODES; ++i) @@ -172,6 +174,13 @@ BOOL LLGLSLShader::createShader(vector<string> * attributes, mFeatures.mIndexedTextureChannels = llmin(mFeatures.mIndexedTextureChannels, 1); } +#ifdef GL_INTERLEAVED_ATTRIBS + if (varying_count > 0 && varyings) + { + glTransformFeedbackVaryings(mProgramObject, varying_count, varyings, GL_INTERLEAVED_ATTRIBS); + } +#endif + // Map attributes and uniforms if (success) { diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h index 7873fe3c4e..5c68cb46eb 100644 --- a/indra/llrender/llglslshader.h +++ b/indra/llrender/llglslshader.h @@ -76,7 +76,9 @@ public: void unload(); BOOL createShader(std::vector<std::string> * attributes, - std::vector<std::string> * uniforms); + std::vector<std::string> * uniforms, + U32 varying_count = 0, + const char** varyings = NULL); BOOL attachObject(std::string object); void attachObject(GLhandleARB object); void attachObjects(GLhandleARB* objects = NULL, S32 count = 0); diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index c04a3f6b41..a842211764 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -42,6 +42,10 @@ //---------------------------------------------------------------------------- const F32 MIN_TEXTURE_LIFETIME = 10.f; +//which power of 2 is i? +//assumes i is a power of 2 > 0 +U32 wpo2(U32 i); + //statics U32 LLImageGL::sUniqueCount = 0; @@ -50,7 +54,8 @@ S32 LLImageGL::sGlobalTextureMemoryInBytes = 0; S32 LLImageGL::sBoundTextureMemoryInBytes = 0; S32 LLImageGL::sCurBoundTextureMemory = 0; S32 LLImageGL::sCount = 0; -std::list<U32> LLImageGL::sDeadTextureList; +LLImageGL::dead_texturelist_t LLImageGL::sDeadTextureList[LLTexUnit::TT_NONE]; +U32 LLImageGL::sCurTexName = 1; BOOL LLImageGL::sGlobalUseAnisotropic = FALSE; F32 LLImageGL::sLastFrameTime = 0.f; @@ -232,9 +237,11 @@ S32 LLImageGL::dataFormatComponents(S32 dataformat) //---------------------------------------------------------------------------- +static LLFastTimer::DeclareTimer FTM_IMAGE_UPDATE_STATS("Image Stats"); // static void LLImageGL::updateStats(F32 current_time) { + LLFastTimer t(FTM_IMAGE_UPDATE_STATS); sLastFrameTime = current_time; sBoundTextureMemoryInBytes = sCurBoundTextureMemory; sCurBoundTextureMemory = 0; @@ -416,6 +423,7 @@ void LLImageGL::init(BOOL usemipmaps) mTarget = GL_TEXTURE_2D; mBindTarget = LLTexUnit::TT_TEXTURE; mHasMipMaps = false; + mMipLevels = -1; mIsResident = 0; @@ -606,8 +614,24 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) is_compressed = true; } + + + if (mUseMipMaps) + { + //set has mip maps to true before binding image so tex parameters get set properly + gGL.getTexUnit(0)->unbind(mBindTarget); + mHasMipMaps = true; + mTexOptionsDirty = true; + setFilteringOption(LLTexUnit::TFO_ANISOTROPIC); + } + else + { + mHasMipMaps = false; + } + llverify(gGL.getTexUnit(0)->bind(this)); + if (mUseMipMaps) { if (data_hasmips) @@ -620,6 +644,9 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) S32 w = getWidth(d); S32 h = getHeight(d); S32 gl_level = d-mCurrentDiscardLevel; + + mMipLevels = llmax(mMipLevels, gl_level); + if (d > mCurrentDiscardLevel) { data_in -= dataFormatBytes(mFormatPrimary, w, h); // see above comment @@ -662,10 +689,6 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) { if (mAutoGenMips) { - if (!gGLManager.mHasFramebufferObject) - { - glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_GENERATE_MIPMAP_SGIS, TRUE); - } stop_glerror(); { // LLFastTimer t2(FTM_TEMP4); @@ -679,6 +702,11 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) S32 w = getWidth(mCurrentDiscardLevel); S32 h = getHeight(mCurrentDiscardLevel); + mMipLevels = wpo2(llmax(w, h)); + + //use legacy mipmap generation mode + glTexParameteri(mTarget, GL_GENERATE_MIPMAP, GL_TRUE); + LLImageGL::setManualImage(mTarget, 0, mFormatInternal, w, h, mFormatPrimary, mFormatType, @@ -694,16 +722,10 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) stop_glerror(); } } - - if (gGLManager.mHasFramebufferObject) - { - glGenerateMipmap(LLTexUnit::getInternalType(mBindTarget)); - } } else { // Create mips by hand - // about 30% faster than autogen on ATI 9800, 50% slower on nVidia 4800 // ~4x faster than gluBuild2DMipmaps S32 width = getWidth(mCurrentDiscardLevel); S32 height = getHeight(mCurrentDiscardLevel); @@ -713,6 +735,9 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) const U8* cur_mip_data = 0; S32 prev_mip_size = 0; S32 cur_mip_size = 0; + + mMipLevels = nummips; + for (int m=0; m<nummips; m++) { if (m==0) @@ -777,10 +802,10 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) { llerrs << "Compressed Image has mipmaps but data does not (can not auto generate compressed mips)" << llendl; } - mHasMipMaps = true; } else { + mMipLevels = 0; S32 w = getWidth(); S32 h = getHeight(); if (is_compressed) @@ -812,7 +837,6 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) } } - mHasMipMaps = false; } stop_glerror(); mGLTextureCreated = true; @@ -1025,23 +1049,65 @@ BOOL LLImageGL::setSubImageFromFrameBuffer(S32 fb_x, S32 fb_y, S32 x_pos, S32 y_ } // static -void LLImageGL::generateTextures(S32 numTextures, U32 *textures) +void LLImageGL::generateTextures(LLTexUnit::eTextureType type, U32 format, S32 numTextures, U32 *textures) { - glGenTextures(numTextures, (GLuint*)textures); + bool empty = true; + + dead_texturelist_t::iterator iter = sDeadTextureList[type].find(format); + + if (iter != sDeadTextureList[type].end()) + { + empty = iter->second.empty(); + } + + for (S32 i = 0; i < numTextures; ++i) + { + if (!empty) + { + textures[i] = iter->second.front(); + iter->second.pop_front(); + empty = iter->second.empty(); + } + else + { + textures[i] = sCurTexName++; + } + } } // static -void LLImageGL::deleteTextures(S32 numTextures, U32 *textures, bool immediate) +void LLImageGL::deleteTextures(LLTexUnit::eTextureType type, U32 format, S32 mip_levels, S32 numTextures, U32 *textures, bool immediate) { - for (S32 i = 0; i < numTextures; i++) + if (gGLManager.mInited) { - sDeadTextureList.push_back(textures[i]); - } + if (format == 0 || type == LLTexUnit::TT_CUBE_MAP || mip_levels == -1) + { //unknown internal format or unknown number of mip levels, not safe to reuse + glDeleteTextures(numTextures, textures); + } + else + { + for (S32 i = 0; i < numTextures; ++i) + { //remove texture from VRAM by setting its size to zero + for (S32 j = 0; j <= mip_levels; j++) + { + gGL.getTexUnit(0)->bindManual(type, textures[i]); + + glTexImage2D(LLTexUnit::getInternalType(type), j, format, 0, 0, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + } + + llassert(std::find(sDeadTextureList[type][format].begin(), + sDeadTextureList[type][format].end(), textures[i]) == + sDeadTextureList[type][format].end()); - if (immediate) + sDeadTextureList[type][format].push_back(textures[i]); + } + } + } + + /*if (immediate) { LLImageGL::deleteDeadTextures(); - } + }*/ } // static @@ -1166,10 +1232,11 @@ BOOL LLImageGL::createGLTexture() if(mTexName) { - glDeleteTextures(1, (reinterpret_cast<GLuint*>(&mTexName))) ; + LLImageGL::deleteTextures(mBindTarget, mFormatInternal, mMipLevels, 1, (reinterpret_cast<GLuint*>(&mTexName))) ; } - glGenTextures(1, (GLuint*)&mTexName); + + LLImageGL::generateTextures(mBindTarget, mFormatInternal, 1, &mTexName); stop_glerror(); if (!mTexName) { @@ -1282,7 +1349,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_ } else { - LLImageGL::generateTextures(1, &mTexName); + LLImageGL::generateTextures(mBindTarget, mFormatInternal, 1, &mTexName); stop_glerror(); { llverify(gGL.getTexUnit(0)->bind(this)); @@ -1327,7 +1394,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_ { sGlobalTextureMemoryInBytes -= mTextureMemory; - LLImageGL::deleteTextures(1, &old_name); + LLImageGL::deleteTextures(mBindTarget, mFormatInternal, mMipLevels, 1, &old_name); stop_glerror(); } @@ -1456,7 +1523,7 @@ void LLImageGL::deleteDeadTextures() { bool reset = false; - while (!sDeadTextureList.empty()) + /*while (!sDeadTextureList.empty()) { GLuint tex = sDeadTextureList.front(); sDeadTextureList.pop_front(); @@ -1478,7 +1545,7 @@ void LLImageGL::deleteDeadTextures() glDeleteTextures(1, &tex); stop_glerror(); - } + }*/ if (reset) { @@ -1496,7 +1563,7 @@ void LLImageGL::destroyGLTexture() mTextureMemory = 0; } - LLImageGL::deleteTextures(1, &mTexName); + LLImageGL::deleteTextures(mBindTarget, mFormatInternal, mMipLevels, 1, &mTexName); mCurrentDiscardLevel = -1 ; //invalidate mCurrentDiscardLevel. mTexName = 0; mGLTextureCreated = FALSE ; diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h index f34b9fa91a..e118c28c1b 100644 --- a/indra/llrender/llimagegl.h +++ b/indra/llrender/llimagegl.h @@ -45,8 +45,16 @@ class LLImageGL : public LLRefCount { friend class LLTexUnit; public: - static std::list<U32> sDeadTextureList; + static U32 sCurTexName; + //previously used but now available texture names + // sDeadTextureList[<usage>][<internal format>] + typedef std::map<U32, std::list<U32> > dead_texturelist_t; + static dead_texturelist_t sDeadTextureList[LLTexUnit::TT_NONE]; + + // These 2 functions replace glGenTextures() and glDeleteTextures() + static void generateTextures(LLTexUnit::eTextureType type, U32 format, S32 numTextures, U32 *textures); + static void deleteTextures(LLTexUnit::eTextureType type, U32 format, S32 mip_levels, S32 numTextures, U32 *textures, bool immediate = false); static void deleteDeadTextures(); // Size calculation @@ -96,10 +104,6 @@ public: void setComponents(S32 ncomponents) { mComponents = (S8)ncomponents ;} void setAllowCompression(bool allow) { mAllowCompression = allow; } - // These 3 functions currently wrap glGenTextures(), glDeleteTextures(), and glTexImage2D() - // for tracking purposes and will be deprecated in the future - static void generateTextures(S32 numTextures, U32 *textures); - static void deleteTextures(S32 numTextures, U32 *textures, bool immediate = false); static void setManualImage(U32 target, S32 miplevel, S32 intformat, S32 width, S32 height, U32 pixformat, U32 pixtype, const void *pixels, bool allow_compression = true); BOOL createGLTexture() ; @@ -217,7 +221,8 @@ protected: LLGLenum mTarget; // Normally GL_TEXTURE2D, sometimes something else (ex. cube maps) LLTexUnit::eTextureType mBindTarget; // Normally TT_TEXTURE, sometimes something else (ex. cube maps) bool mHasMipMaps; - + S32 mMipLevels; + LLGLboolean mIsResident; S8 mComponents; diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index 93bac4c779..348c1eb1b7 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -408,12 +408,14 @@ void LLTexUnit::unbind(eTextureType type) if (mIndex < 0) return; + //always flush and activate for consistency + // some code paths assume unbind always flushes and sets the active texture + gGL.flush(); + activate(); + // Disabled caching of binding state. if (mCurrTexType == type) { - gGL.flush(); - - activate(); mCurrTexture = 0; if (LLGLSLShader::sNoFixedFunction && type == LLTexUnit::TT_TEXTURE) { @@ -464,11 +466,25 @@ void LLTexUnit::setTextureFilteringOption(LLTexUnit::eTextureFilterOptions optio } else if (option >= TFO_BILINEAR) { - glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_LINEAR); + if (mHasMipMaps) + { + glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); + } + else + { + glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_LINEAR); + } } else { - glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_NEAREST); + if (mHasMipMaps) + { + glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); + } + else + { + glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_NEAREST); + } } if (gGLManager.mHasAnisotropic) diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp index 780f1dc484..cc5c232380 100644 --- a/indra/llrender/llrendertarget.cpp +++ b/indra/llrender/llrendertarget.cpp @@ -55,7 +55,6 @@ bool LLRenderTarget::sUseFBO = false; LLRenderTarget::LLRenderTarget() : mResX(0), mResY(0), - mTex(0), mFBO(0), mDepth(0), mStencil(0), @@ -70,6 +69,42 @@ LLRenderTarget::~LLRenderTarget() release(); } +void LLRenderTarget::resize(U32 resx, U32 resy, U32 color_fmt) +{ + //for accounting, get the number of pixels added/subtracted + S32 pix_diff = (resx*resy)-(mResX*mResY); + + mResX = resx; + mResY = resy; + + for (U32 i = 0; i < mTex.size(); ++i) + { //resize color attachments + gGL.getTexUnit(0)->bindManual(mUsage, mTex[i]); + LLImageGL::setManualImage(LLTexUnit::getInternalType(mUsage), 0, color_fmt, mResX, mResY, GL_RGBA, GL_UNSIGNED_BYTE, NULL, false); + sBytesAllocated += pix_diff*4; + } + + if (mDepth) + { //resize depth attachment + if (mStencil) + { + //use render buffers where stencil buffers are in play + glBindRenderbuffer(GL_RENDERBUFFER, mDepth); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, mResX, mResY); + glBindRenderbuffer(GL_RENDERBUFFER, 0); + } + else + { + gGL.getTexUnit(0)->bindManual(mUsage, mDepth); + U32 internal_type = LLTexUnit::getInternalType(mUsage); + LLImageGL::setManualImage(internal_type, 0, GL_DEPTH_COMPONENT24, mResX, mResY, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL, false); + } + + sBytesAllocated += pix_diff*4; + } +} + + bool LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo, S32 samples) { stop_glerror(); @@ -135,7 +170,7 @@ bool LLRenderTarget::addColorAttachment(U32 color_fmt) } U32 tex; - LLImageGL::generateTextures(1, &tex); + LLImageGL::generateTextures(mUsage, color_fmt, 1, &tex); gGL.getTexUnit(0)->bindManual(mUsage, tex); stop_glerror(); @@ -193,6 +228,7 @@ bool LLRenderTarget::addColorAttachment(U32 color_fmt) } mTex.push_back(tex); + mInternalFormat.push_back(color_fmt); if (gDebugGL) { //bind and unbind to validate target @@ -217,7 +253,7 @@ bool LLRenderTarget::allocateDepth() } else { - LLImageGL::generateTextures(1, &mDepth); + LLImageGL::generateTextures(mUsage, GL_DEPTH_COMPONENT24, 1, &mDepth); gGL.getTexUnit(0)->bindManual(mUsage, mDepth); U32 internal_type = LLTexUnit::getInternalType(mUsage); @@ -294,7 +330,7 @@ void LLRenderTarget::release() } else { - LLImageGL::deleteTextures(1, &mDepth, true); + LLImageGL::deleteTextures(mUsage, 0, 0, 1, &mDepth, true); stop_glerror(); } mDepth = 0; @@ -326,8 +362,9 @@ void LLRenderTarget::release() if (mTex.size() > 0) { sBytesAllocated -= mResX*mResY*4*mTex.size(); - LLImageGL::deleteTextures(mTex.size(), &mTex[0], true); + LLImageGL::deleteTextures(mUsage, mInternalFormat[0], 0, mTex.size(), &mTex[0], true); mTex.clear(); + mInternalFormat.clear(); } mResX = mResY = 0; diff --git a/indra/llrender/llrendertarget.h b/indra/llrender/llrendertarget.h index 2735ab21c5..e1a51304f1 100644 --- a/indra/llrender/llrendertarget.h +++ b/indra/llrender/llrendertarget.h @@ -57,8 +57,6 @@ */ -class LLMultisampleBuffer; - class LLRenderTarget { public: @@ -74,6 +72,12 @@ public: //multiple calls will release previously allocated resources bool allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage = LLTexUnit::TT_TEXTURE, bool use_fbo = false, S32 samples = 0); + //resize existing attachments to use new resolution and color format + // CAUTION: if the GL runs out of memory attempting to resize, this render target will be undefined + // DO NOT use for screen space buffers or for scratch space for an image that might be uploaded + // DO use for render targets that resize often and aren't likely to ruin someone's day if they break + void resize(U32 resx, U32 resy, U32 color_fmt); + //add color buffer attachment //limit of 4 color attachments per render target bool addColorAttachment(U32 color_fmt); @@ -142,6 +146,7 @@ protected: U32 mResX; U32 mResY; std::vector<U32> mTex; + std::vector<U32> mInternalFormat; U32 mFBO; U32 mDepth; bool mStencil; diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index 5a6e6cab3e..a9248d4d73 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -702,7 +702,7 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade if (texture_index_channels > 1) { - text[count++] = strdup("VARYING_FLAT ivec4 vary_texture_index;\n"); + text[count++] = strdup("VARYING_FLAT int vary_texture_index;\n"); } text[count++] = strdup("vec4 diffuseLookup(vec2 texcoord)\n"); @@ -716,20 +716,33 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade } else if (major_version > 1 || minor_version >= 30) { //switches are supported in GLSL 1.30 and later - text[count++] = strdup("\tvec4 ret = vec4(1,0,1,1);\n"); - text[count++] = strdup("\tswitch (vary_texture_index.r)\n"); - text[count++] = strdup("\t{\n"); - - //switch body - for (S32 i = 0; i < texture_index_channels; ++i) - { - std::string case_str = llformat("\t\tcase %d: ret = texture2D(tex%d, texcoord); break;\n", i, i); - text[count++] = strdup(case_str.c_str()); + if (gGLManager.mIsNVIDIA) + { //switches are unreliable on some NVIDIA drivers + for (U32 i = 0; i < texture_index_channels; ++i) + { + std::string if_string = llformat("\t%sif (vary_texture_index == %d) { return texture2D(tex%d, texcoord); }\n", i > 0 ? "else " : "", i, i); + text[count++] = strdup(if_string.c_str()); + } + text[count++] = strdup("\treturn vec4(1,0,1,1);\n"); + text[count++] = strdup("}\n"); } + else + { + text[count++] = strdup("\tvec4 ret = vec4(1,0,1,1);\n"); + text[count++] = strdup("\tswitch (vary_texture_index)\n"); + text[count++] = strdup("\t{\n"); + + //switch body + for (S32 i = 0; i < texture_index_channels; ++i) + { + std::string case_str = llformat("\t\tcase %d: return texture2D(tex%d, texcoord);\n", i, i); + text[count++] = strdup(case_str.c_str()); + } - text[count++] = strdup("\t}\n"); - text[count++] = strdup("\treturn ret;\n"); - text[count++] = strdup("}\n"); + text[count++] = strdup("\t}\n"); + text[count++] = strdup("\treturn ret;\n"); + text[count++] = strdup("}\n"); + } } else { //should never get here. Indexed texture rendering requires GLSL 1.30 or later @@ -1026,6 +1039,9 @@ void LLShaderMgr::initAttribsAndUniforms() mReservedUniforms.push_back("size"); mReservedUniforms.push_back("falloff"); + mReservedUniforms.push_back("box_center"); + mReservedUniforms.push_back("box_size"); + mReservedUniforms.push_back("minLuminance"); mReservedUniforms.push_back("maxExtractAlpha"); diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h index f792faa8f0..7a16b7c20f 100644 --- a/indra/llrender/llshadermgr.h +++ b/indra/llrender/llshadermgr.h @@ -97,6 +97,8 @@ public: LIGHT_CENTER, LIGHT_SIZE, LIGHT_FALLOFF, + BOX_CENTER, + BOX_SIZE, GLOW_MIN_LUMINANCE, GLOW_MAX_EXTRACT_ALPHA, diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 823c6b9dc5..eadef93c89 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -38,12 +38,6 @@ #include "llglslshader.h" #include "llmemory.h" -#if LL_DARWIN -#define LL_VBO_POOLING 1 -#else -#define LL_VBO_POOLING 0 -#endif - //Next Highest Power Of Two //helper function, returns first number > v that is a power of 2, or v if v is already a power of 2 U32 nhpo2(U32 v) @@ -71,6 +65,7 @@ U32 wpo2(U32 i) const U32 LL_VBO_BLOCK_SIZE = 2048; +const U32 LL_VBO_POOL_MAX_SEED_SIZE = 256*1024; U32 vbo_block_size(U32 size) { //what block size will fit size? @@ -83,6 +78,7 @@ U32 vbo_block_index(U32 size) return vbo_block_size(size)/LL_VBO_BLOCK_SIZE; } +const U32 LL_VBO_POOL_SEED_COUNT = vbo_block_index(LL_VBO_POOL_MAX_SEED_SIZE); //============================================================================ @@ -95,6 +91,11 @@ LLVBOPool LLVertexBuffer::sDynamicIBOPool(GL_DYNAMIC_DRAW_ARB, GL_ELEMENT_ARRAY_ U32 LLVBOPool::sBytesPooled = 0; U32 LLVBOPool::sIndexBytesPooled = 0; +U32 LLVBOPool::sCurGLName = 1; + +std::list<U32> LLVertexBuffer::sAvailableVAOName; +U32 LLVertexBuffer::sCurVAOName = 1; + U32 LLVertexBuffer::sAllocatedIndexBytes = 0; U32 LLVertexBuffer::sIndexCount = 0; @@ -119,69 +120,55 @@ bool LLVertexBuffer::sUseStreamDraw = true; bool LLVertexBuffer::sUseVAO = false; bool LLVertexBuffer::sPreferStreamDraw = false; -const U32 FENCE_WAIT_TIME_NANOSECONDS = 10000; //1 ms -class LLGLSyncFence : public LLGLFence +U32 LLVBOPool::genBuffer() { -public: -#ifdef GL_ARB_sync - GLsync mSync; -#endif - - LLGLSyncFence() - { -#ifdef GL_ARB_sync - mSync = 0; -#endif - } + U32 ret = 0; - virtual ~LLGLSyncFence() + if (mGLNamePool.empty()) { -#ifdef GL_ARB_sync - if (mSync) - { - glDeleteSync(mSync); - } -#endif + ret = sCurGLName++; } - - void placeFence() + else { -#ifdef GL_ARB_sync - if (mSync) - { - glDeleteSync(mSync); - } - mSync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); -#endif + ret = mGLNamePool.front(); + mGLNamePool.pop_front(); } - void wait() + return ret; +} + +void LLVBOPool::deleteBuffer(U32 name) +{ + if (gGLManager.mInited) { -#ifdef GL_ARB_sync - if (mSync) - { - while (glClientWaitSync(mSync, 0, FENCE_WAIT_TIME_NANOSECONDS) == GL_TIMEOUT_EXPIRED) - { //track the number of times we've waited here - static S32 waits = 0; - waits++; - } - } -#endif - } + LLVertexBuffer::unbind(); + glBindBufferARB(mType, name); + glBufferDataARB(mType, 0, NULL, mUsage); -}; + llassert(std::find(mGLNamePool.begin(), mGLNamePool.end(), name) == mGLNamePool.end()); + mGLNamePool.push_back(name); + + glBindBufferARB(mType, 0); + } +} -volatile U8* LLVBOPool::allocate(U32& name, U32 size) + +LLVBOPool::LLVBOPool(U32 vboUsage, U32 vboType) +: mUsage(vboUsage), mType(vboType) +{ + mMissCount.resize(LL_VBO_POOL_SEED_COUNT); + std::fill(mMissCount.begin(), mMissCount.end(), 0); +} + +volatile U8* LLVBOPool::allocate(U32& name, U32 size, bool for_seed) { llassert(vbo_block_size(size) == size); volatile U8* ret = NULL; -#if LL_VBO_POOLING - U32 i = vbo_block_index(size); if (mFreeList.size() <= i) @@ -189,12 +176,18 @@ volatile U8* LLVBOPool::allocate(U32& name, U32 size) mFreeList.resize(i+1); } - if (mFreeList[i].empty()) + if (mFreeList[i].empty() || for_seed) { //make a new buffer - glGenBuffersARB(1, &name); + name = genBuffer(); + glBindBufferARB(mType, name); + if (!for_seed && i < LL_VBO_POOL_SEED_COUNT) + { //record this miss + mMissCount[i]++; + } + if (mType == GL_ARRAY_BUFFER_ARB) { LLVertexBuffer::sAllocatedBytes += size; @@ -215,6 +208,25 @@ volatile U8* LLVBOPool::allocate(U32& name, U32 size) } glBindBufferARB(mType, 0); + + if (for_seed) + { //put into pool for future use + llassert(mFreeList.size() > i); + + Record rec; + rec.mGLName = name; + rec.mClientData = ret; + + if (mType == GL_ARRAY_BUFFER_ARB) + { + sBytesPooled += size; + } + else + { + sIndexBytesPooled += size; + } + mFreeList[i].push_back(rec); + } } else { @@ -232,33 +244,6 @@ volatile U8* LLVBOPool::allocate(U32& name, U32 size) mFreeList[i].pop_front(); } -#else //no pooling - - glGenBuffersARB(1, &name); - glBindBufferARB(mType, name); - - if (mType == GL_ARRAY_BUFFER_ARB) - { - LLVertexBuffer::sAllocatedBytes += size; - } - else - { - LLVertexBuffer::sAllocatedIndexBytes += size; - } - - if (LLVertexBuffer::sDisableVBOMapping || mUsage != GL_DYNAMIC_DRAW_ARB) - { - glBufferDataARB(mType, size, 0, mUsage); - ret = (U8*) ll_aligned_malloc_16(size); - } - else - { //always use a true hint of static draw when allocating non-client-backed buffers - glBufferDataARB(mType, size, 0, GL_STATIC_DRAW_ARB); - } - - glBindBufferARB(mType, 0); - -#endif return ret; } @@ -267,50 +252,48 @@ void LLVBOPool::release(U32 name, volatile U8* buffer, U32 size) { llassert(vbo_block_size(size) == size); -#if LL_VBO_POOLING - - U32 i = vbo_block_index(size); - - llassert(mFreeList.size() > i); + deleteBuffer(name); + ll_aligned_free_16((U8*) buffer); - Record rec; - rec.mGLName = name; - rec.mClientData = buffer; - - if (buffer == NULL) + if (mType == GL_ARRAY_BUFFER_ARB) { - glDeleteBuffersARB(1, &rec.mGLName); + LLVertexBuffer::sAllocatedBytes -= size; } else { - if (mType == GL_ARRAY_BUFFER_ARB) - { - sBytesPooled += size; - } - else - { - sIndexBytesPooled += size; - } - mFreeList[i].push_back(rec); + LLVertexBuffer::sAllocatedIndexBytes -= size; } -#else //no pooling - glDeleteBuffersARB(1, &name); - ll_aligned_free_16((U8*) buffer); +} - if (mType == GL_ARRAY_BUFFER_ARB) +void LLVBOPool::seedPool() +{ + U32 dummy_name = 0; + + if (mFreeList.size() < LL_VBO_POOL_SEED_COUNT) { - LLVertexBuffer::sAllocatedBytes -= size; + mFreeList.resize(LL_VBO_POOL_SEED_COUNT); } - else + + for (U32 i = 0; i < LL_VBO_POOL_SEED_COUNT; i++) { - LLVertexBuffer::sAllocatedIndexBytes -= size; + if (mMissCount[i] > mFreeList[i].size()) + { + U32 size = i*LL_VBO_BLOCK_SIZE; + + S32 count = mMissCount[i] - mFreeList[i].size(); + for (U32 j = 0; j < count; ++j) + { + allocate(dummy_name, size, true); + } + } } -#endif } + + void LLVBOPool::cleanup() { - U32 size = 1; + U32 size = LL_VBO_BLOCK_SIZE; for (U32 i = 0; i < mFreeList.size(); ++i) { @@ -320,8 +303,8 @@ void LLVBOPool::cleanup() { Record& r = l.front(); - glDeleteBuffersARB(1, &r.mGLName); - + deleteBuffer(r.mGLName); + if (r.mClientData) { ll_aligned_free_16((void*) r.mClientData); @@ -341,8 +324,11 @@ void LLVBOPool::cleanup() } } - size *= 2; + size += LL_VBO_BLOCK_SIZE; } + + //reset miss counts + std::fill(mMissCount.begin(), mMissCount.end(), 0); } @@ -376,6 +362,41 @@ U32 LLVertexBuffer::sGLMode[LLRender::NUM_MODES] = GL_LINE_LOOP, }; +//static +U32 LLVertexBuffer::getVAOName() +{ + U32 ret = 0; + + if (!sAvailableVAOName.empty()) + { + ret = sAvailableVAOName.front(); + sAvailableVAOName.pop_front(); + } + else + { +#ifdef GL_ARB_vertex_array_object + glGenVertexArrays(1, &ret); +#endif + } + + return ret; +} + +//static +void LLVertexBuffer::releaseVAOName(U32 name) +{ + sAvailableVAOName.push_back(name); +} + + +//static +void LLVertexBuffer::seedPools() +{ + sStreamVBOPool.seedPool(); + sDynamicVBOPool.seedPool(); + sStreamIBOPool.seedPool(); + sDynamicIBOPool.seedPool(); +} //static void LLVertexBuffer::setupClientArrays(U32 data_mask) @@ -985,7 +1006,7 @@ LLVertexBuffer::~LLVertexBuffer() if (mGLArray) { #if GL_ARB_vertex_array_object - glDeleteVertexArrays(1, &mGLArray); + releaseVAOName(mGLArray); #endif } @@ -1211,10 +1232,10 @@ void LLVertexBuffer::updateNumVerts(S32 nverts) llassert(nverts >= 0); - if (nverts >= 65535) + if (nverts > 65536) { llwarns << "Vertex buffer overflow!" << llendl; - nverts = 65535; + nverts = 65536; } U32 needed_size = calcOffsets(mTypeMask, mOffsets, nverts); @@ -1270,7 +1291,7 @@ void LLVertexBuffer::allocateBuffer(S32 nverts, S32 nindices, bool create) if (gGLManager.mHasVertexArrayObject && useVBOs() && (LLRender::sGLCoreProfile || sUseVAO)) { #if GL_ARB_vertex_array_object - glGenVertexArrays(1, &mGLArray); + mGLArray = getVAOName(); #endif setupVertexArray(); } @@ -1306,7 +1327,7 @@ void LLVertexBuffer::setupVertexArray() 1, //TYPE_WEIGHT, 4, //TYPE_WEIGHT4, 4, //TYPE_CLOTHWEIGHT, - 4, //TYPE_TEXTURE_INDEX + 1, //TYPE_TEXTURE_INDEX }; U32 attrib_type[] = @@ -1323,7 +1344,7 @@ void LLVertexBuffer::setupVertexArray() GL_FLOAT, //TYPE_WEIGHT, GL_FLOAT, //TYPE_WEIGHT4, GL_FLOAT, //TYPE_CLOTHWEIGHT, - GL_UNSIGNED_BYTE, //TYPE_TEXTURE_INDEX + GL_UNSIGNED_INT, //TYPE_TEXTURE_INDEX }; bool attrib_integer[] = @@ -2140,6 +2161,16 @@ void LLVertexBuffer::flush() } } +// bind for transform feedback (quick 'n dirty) +void LLVertexBuffer::bindForFeedback(U32 channel, U32 type, U32 index, U32 count) +{ +#ifdef GL_TRANSFORM_FEEDBACK_BUFFER + U32 offset = mOffsets[type] + sTypeSize[type]*index; + U32 size= (sTypeSize[type]*count); + glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, channel, mGLBuffer, offset, size); +#endif +} + // Set for rendering void LLVertexBuffer::setBuffer(U32 data_mask) { @@ -2291,10 +2322,10 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask) stop_glerror(); volatile U8* base = useVBOs() ? (U8*) mAlignedOffset : mMappedData; - /*if ((data_mask & mTypeMask) != data_mask) + if (gDebugGL && ((data_mask & mTypeMask) != data_mask)) { llerrs << "LLVertexBuffer::setupVertexBuffer missing required components for supplied data mask." << llendl; - }*/ + } if (LLGLSLShader::sNoFixedFunction) { @@ -2370,7 +2401,7 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask) #if !LL_DARWIN S32 loc = TYPE_TEXTURE_INDEX; void *ptr = (void*) (base + mOffsets[TYPE_VERTEX] + 12); - glVertexAttribIPointer(loc, 4, GL_UNSIGNED_BYTE, LLVertexBuffer::sTypeSize[TYPE_VERTEX], ptr); + glVertexAttribIPointer(loc, 1, GL_UNSIGNED_INT, LLVertexBuffer::sTypeSize[TYPE_VERTEX], ptr); #endif } if (data_mask & MAP_VERTEX) diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h index 7477dec3ad..11fa4ab6a0 100644 --- a/indra/llrender/llvertexbuffer.h +++ b/indra/llrender/llvertexbuffer.h @@ -57,23 +57,28 @@ public: static U32 sBytesPooled; static U32 sIndexBytesPooled; - LLVBOPool(U32 vboUsage, U32 vboType) - : mUsage(vboUsage) - , mType(vboType) - {} + static U32 sCurGLName; + LLVBOPool(U32 vboUsage, U32 vboType); + const U32 mUsage; const U32 mType; //size MUST be a power of 2 - volatile U8* allocate(U32& name, U32 size); + volatile U8* allocate(U32& name, U32 size, bool for_seed = false); //size MUST be the size provided to allocate that returned the given name void release(U32 name, volatile U8* buffer, U32 size); + //batch allocate buffers to be provided to the application on demand + void seedPool(); + //destroy all records in mFreeList void cleanup(); + U32 genBuffer(); + void deleteBuffer(U32 name); + class Record { public: @@ -81,17 +86,15 @@ public: volatile U8* mClientData; }; + std::list<U32> mGLNamePool; + typedef std::list<Record> record_list_t; std::vector<record_list_t> mFreeList; -}; + std::vector<U32> mMissCount; -class LLGLFence -{ -public: - virtual void placeFence() = 0; - virtual void wait() = 0; }; + //============================================================================ // base class class LLPrivateMemoryPool; @@ -125,13 +128,22 @@ public: static LLVBOPool sStreamIBOPool; static LLVBOPool sDynamicIBOPool; + static std::list<U32> sAvailableVAOName; + static U32 sCurVAOName; + static bool sUseStreamDraw; static bool sUseVAO; static bool sPreferStreamDraw; + static void seedPools(); + + static U32 getVAOName(); + static void releaseVAOName(U32 name); + static void initClass(bool use_vbo, bool no_vbo_mapping); static void cleanupClass(); static void setupClientArrays(U32 data_mask); + static void pushPositions(U32 mode, const LLVector4a* pos, U32 count); static void drawArrays(U32 mode, const std::vector<LLVector3>& pos, const std::vector<LLVector3>& norm); static void drawElements(U32 mode, const LLVector4a* pos, const LLVector2* tc, S32 num_indices, const U16* indicesp); @@ -208,7 +220,6 @@ protected: void destroyGLIndices(); void updateNumVerts(S32 nverts); void updateNumIndices(S32 nindices); - bool useVBOs() const; void unmapBuffer(); public: @@ -218,6 +229,8 @@ public: volatile U8* mapVertexBuffer(S32 type, S32 index, S32 count, bool map_range); volatile U8* mapIndexBuffer(S32 index, S32 count, bool map_range); + void bindForFeedback(U32 channel, U32 type, U32 index, U32 count); + // set for rendering virtual void setBuffer(U32 data_mask); // calls setupVertexBuffer() if data_mask is not 0 void flush(); //flush pending data to GL memory @@ -240,12 +253,14 @@ public: bool getNormalStrider(LLStrider<LLVector3>& strider, S32 index=0, S32 count = -1, bool map_range = false); bool getBinormalStrider(LLStrider<LLVector3>& strider, S32 index=0, S32 count = -1, bool map_range = false); bool getColorStrider(LLStrider<LLColor4U>& strider, S32 index=0, S32 count = -1, bool map_range = false); + bool getTextureIndexStrider(LLStrider<LLColor4U>& strider, S32 index=0, S32 count = -1, bool map_range = false); bool getEmissiveStrider(LLStrider<LLColor4U>& strider, S32 index=0, S32 count = -1, bool map_range = false); bool getWeightStrider(LLStrider<F32>& strider, S32 index=0, S32 count = -1, bool map_range = false); bool getWeight4Strider(LLStrider<LLVector4>& strider, S32 index=0, S32 count = -1, bool map_range = false); bool getClothWeightStrider(LLStrider<LLVector4>& strider, S32 index=0, S32 count = -1, bool map_range = false); + bool useVBOs() const; bool isEmpty() const { return mEmpty; } bool isLocked() const { return mVertexLocked || mIndexLocked; } S32 getNumVerts() const { return mNumVerts; } diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt index 20c3456a56..cca4ca3981 100644 --- a/indra/llui/CMakeLists.txt +++ b/indra/llui/CMakeLists.txt @@ -23,6 +23,7 @@ include_directories( ${LLWINDOW_INCLUDE_DIRS} ${LLVFS_INCLUDE_DIRS} ${LLXML_INCLUDE_DIRS} + ${LIBS_PREBUILD_DIR}/include/hunspell ) set(llui_SOURCE_FILES @@ -84,6 +85,7 @@ set(llui_SOURCE_FILES llsearcheditor.cpp llslider.cpp llsliderctrl.cpp + llspellcheck.cpp llspinctrl.cpp llstatbar.cpp llstatgraph.cpp @@ -191,6 +193,8 @@ set(llui_HEADER_FILES llscrolllistitem.h llsliderctrl.h llslider.h + llspellcheck.h + llspellcheckmenuhandler.h llspinctrl.h llstatbar.h llstatgraph.h @@ -260,6 +264,7 @@ target_link_libraries(llui ${LLXUIXML_LIBRARIES} ${LLXML_LIBRARIES} ${LLMATH_LIBRARIES} + ${HUNSPELL_LIBRARY} ${LLCOMMON_LIBRARIES} # must be after llimage, llwindow, llrender ) diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp index d0fbf4b913..48d49af588 100644 --- a/indra/llui/lllineeditor.cpp +++ b/indra/llui/lllineeditor.cpp @@ -45,6 +45,7 @@ #include "llkeyboard.h" #include "llrect.h" #include "llresmgr.h" +#include "llspellcheck.h" #include "llstring.h" #include "llwindow.h" #include "llui.h" @@ -65,6 +66,7 @@ const S32 SCROLL_INCREMENT_ADD = 0; // make space for typing const S32 SCROLL_INCREMENT_DEL = 4; // make space for baskspacing const F32 AUTO_SCROLL_TIME = 0.05f; const F32 TRIPLE_CLICK_INTERVAL = 0.3f; // delay between double and triple click. *TODO: make this equal to the double click interval? +const F32 SPELLCHECK_DELAY = 0.5f; // delay between the last keypress and spell checking the word the cursor is on const std::string PASSWORD_ASTERISK( "\xE2\x80\xA2" ); // U+2022 BULLET @@ -88,6 +90,7 @@ LLLineEditor::Params::Params() background_image_focused("background_image_focused"), select_on_focus("select_on_focus", false), revert_on_esc("revert_on_esc", true), + spellcheck("spellcheck", false), commit_on_focus_lost("commit_on_focus_lost", true), ignore_tab("ignore_tab", true), is_password("is_password", false), @@ -134,6 +137,9 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p) mIgnoreArrowKeys( FALSE ), mIgnoreTab( p.ignore_tab ), mDrawAsterixes( p.is_password ), + mSpellCheck( p.spellcheck ), + mSpellCheckStart(-1), + mSpellCheckEnd(-1), mSelectAllonFocusReceived( p.select_on_focus ), mSelectAllonCommit( TRUE ), mPassDelete(FALSE), @@ -151,7 +157,8 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p) mHighlightColor(p.highlight_color()), mPreeditBgColor(p.preedit_bg_color()), mGLFont(p.font), - mContextMenuHandle() + mContextMenuHandle(), + mAutoreplaceCallback() { llassert( mMaxLengthBytes > 0 ); @@ -177,6 +184,12 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p) updateTextPadding(); setCursor(mText.length()); + if (mSpellCheck) + { + LLSpellChecker::setSettingsChangeCallback(boost::bind(&LLLineEditor::onSpellCheckSettingsChange, this)); + } + mSpellCheckTimer.reset(); + setPrevalidateInput(p.prevalidate_input_callback()); setPrevalidate(p.prevalidate_callback()); @@ -195,7 +208,6 @@ LLLineEditor::~LLLineEditor() gFocusMgr.releaseFocusIfNeeded( this ); } - void LLLineEditor::onFocusReceived() { gEditMenuHandler = this; @@ -519,6 +531,99 @@ void LLLineEditor::selectAll() updatePrimary(); } +bool LLLineEditor::getSpellCheck() const +{ + return (LLSpellChecker::getUseSpellCheck()) && (!mReadOnly) && (mSpellCheck); +} + +const std::string& LLLineEditor::getSuggestion(U32 index) const +{ + return (index < mSuggestionList.size()) ? mSuggestionList[index] : LLStringUtil::null; +} + +U32 LLLineEditor::getSuggestionCount() const +{ + return mSuggestionList.size(); +} + +void LLLineEditor::replaceWithSuggestion(U32 index) +{ + for (std::list<std::pair<U32, U32> >::const_iterator it = mMisspellRanges.begin(); it != mMisspellRanges.end(); ++it) + { + if ( (it->first <= (U32)mCursorPos) && (it->second >= (U32)mCursorPos) ) + { + deselect(); + + // Delete the misspelled word + mText.erase(it->first, it->second - it->first); + + // Insert the suggestion in its place + LLWString suggestion = utf8str_to_wstring(mSuggestionList[index]); + mText.insert(it->first, suggestion); + setCursor(it->first + (S32)suggestion.length()); + + break; + } + } + mSpellCheckStart = mSpellCheckEnd = -1; +} + +void LLLineEditor::addToDictionary() +{ + if (canAddToDictionary()) + { + LLSpellChecker::instance().addToCustomDictionary(getMisspelledWord(mCursorPos)); + } +} + +bool LLLineEditor::canAddToDictionary() const +{ + return (getSpellCheck()) && (isMisspelledWord(mCursorPos)); +} + +void LLLineEditor::addToIgnore() +{ + if (canAddToIgnore()) + { + LLSpellChecker::instance().addToIgnoreList(getMisspelledWord(mCursorPos)); + } +} + +bool LLLineEditor::canAddToIgnore() const +{ + return (getSpellCheck()) && (isMisspelledWord(mCursorPos)); +} + +std::string LLLineEditor::getMisspelledWord(U32 pos) const +{ + for (std::list<std::pair<U32, U32> >::const_iterator it = mMisspellRanges.begin(); it != mMisspellRanges.end(); ++it) + { + if ( (it->first <= pos) && (it->second >= pos) ) + { + return wstring_to_utf8str(mText.getWString().substr(it->first, it->second - it->first)); + } + } + return LLStringUtil::null; +} + +bool LLLineEditor::isMisspelledWord(U32 pos) const +{ + for (std::list<std::pair<U32, U32> >::const_iterator it = mMisspellRanges.begin(); it != mMisspellRanges.end(); ++it) + { + if ( (it->first <= pos) && (it->second >= pos) ) + { + return true; + } + } + return false; +} + +void LLLineEditor::onSpellCheckSettingsChange() +{ + // Recheck the spelling on every change + mMisspellRanges.clear(); + mSpellCheckStart = mSpellCheckEnd = -1; +} BOOL LLLineEditor::handleDoubleClick(S32 x, S32 y, MASK mask) { @@ -866,6 +971,12 @@ void LLLineEditor::addChar(const llwchar uni_char) LLUI::reportBadKeystroke(); } + if (!mReadOnly && mAutoreplaceCallback != NULL) + { + // call callback + mAutoreplaceCallback(mText, mCursorPos); + } + getWindow()->hideCursorUntilMouseMove(); } @@ -1058,9 +1169,8 @@ void LLLineEditor::cut() LLUI::reportBadKeystroke(); } else - if( mKeystrokeCallback ) { - mKeystrokeCallback( this ); + onKeystroke(); } } } @@ -1187,9 +1297,8 @@ void LLLineEditor::pasteHelper(bool is_primary) LLUI::reportBadKeystroke(); } else - if( mKeystrokeCallback ) { - mKeystrokeCallback( this ); + onKeystroke(); } } } @@ -1442,9 +1551,10 @@ BOOL LLLineEditor::handleKeyHere(KEY key, MASK mask ) // Notify owner if requested if (!need_to_rollback && handled) { - if (mKeystrokeCallback) + onKeystroke(); + if ( (!selection_modified) && (KEY_BACKSPACE == key) ) { - mKeystrokeCallback(this); + mSpellCheckTimer.setTimerExpirySec(SPELLCHECK_DELAY); } } } @@ -1497,12 +1607,11 @@ BOOL LLLineEditor::handleUnicodeCharHere(llwchar uni_char) // Notify owner if requested if( !need_to_rollback && handled ) { - if( mKeystrokeCallback ) - { - // HACK! The only usage of this callback doesn't do anything with the character. - // We'll have to do something about this if something ever changes! - Doug - mKeystrokeCallback( this ); - } + // HACK! The only usage of this callback doesn't do anything with the character. + // We'll have to do something about this if something ever changes! - Doug + onKeystroke(); + + mSpellCheckTimer.setTimerExpirySec(SPELLCHECK_DELAY); } } return handled; @@ -1531,9 +1640,7 @@ void LLLineEditor::doDelete() if (!prevalidateInput(text_to_delete)) { - if( mKeystrokeCallback ) - mKeystrokeCallback( this ); - + onKeystroke(); return; } setCursor(getCursor() + 1); @@ -1549,10 +1656,9 @@ void LLLineEditor::doDelete() } else { - if( mKeystrokeCallback ) - { - mKeystrokeCallback( this ); - } + onKeystroke(); + + mSpellCheckTimer.setTimerExpirySec(SPELLCHECK_DELAY); } } } @@ -1624,6 +1730,10 @@ void LLLineEditor::draw() background.stretch( -mBorderThickness ); S32 lineeditor_v_pad = (background.getHeight() - mGLFont->getLineHeight()) / 2; + if (mSpellCheck) + { + lineeditor_v_pad += 1; + } drawBackground(); @@ -1698,14 +1808,14 @@ void LLLineEditor::draw() { S32 select_left; S32 select_right; - if( mSelectionStart < getCursor() ) + if (mSelectionStart < mSelectionEnd) { select_left = mSelectionStart; - select_right = getCursor(); + select_right = mSelectionEnd; } else { - select_left = getCursor(); + select_left = mSelectionEnd; select_right = mSelectionStart; } @@ -1749,7 +1859,7 @@ void LLLineEditor::draw() if( (rendered_pixels_right < (F32)mTextRightEdge) && (rendered_text < text_len) ) { // unselected, right side - mGLFont->render( + rendered_text += mGLFont->render( mText, mScrollHPos + rendered_text, rendered_pixels_right, text_bottom, text_color, @@ -1763,7 +1873,7 @@ void LLLineEditor::draw() } else { - mGLFont->render( + rendered_text = mGLFont->render( mText, mScrollHPos, rendered_pixels_right, text_bottom, text_color, @@ -1778,6 +1888,101 @@ void LLLineEditor::draw() mBorder->setVisible(FALSE); // no more programmatic art. #endif + if ( (getSpellCheck()) && (mText.length() > 2) ) + { + // Calculate start and end indices for the first and last visible word + U32 start = prevWordPos(mScrollHPos), end = nextWordPos(mScrollHPos + rendered_text); + + if ( (mSpellCheckStart != start) || (mSpellCheckEnd != end) ) + { + const LLWString& text = mText.getWString().substr(start, end); + + // Find the start of the first word + U32 word_start = 0, word_end = 0; + while ( (word_start < text.length()) && (!LLStringOps::isAlpha(text[word_start])) ) + { + word_start++; + } + + // Iterate over all words in the text block and check them one by one + mMisspellRanges.clear(); + while (word_start < text.length()) + { + // Find the end of the current word (special case handling for "'" when it's used as a contraction) + word_end = word_start + 1; + while ( (word_end < text.length()) && + ((LLWStringUtil::isPartOfWord(text[word_end])) || + ((L'\'' == text[word_end]) && (word_end + 1 < text.length()) && + (LLStringOps::isAlnum(text[word_end - 1])) && (LLStringOps::isAlnum(text[word_end + 1])))) ) + { + word_end++; + } + if (word_end > text.length()) + { + break; + } + + // Don't process words shorter than 3 characters + std::string word = wstring_to_utf8str(text.substr(word_start, word_end - word_start)); + if ( (word.length() >= 3) && (!LLSpellChecker::instance().checkSpelling(word)) ) + { + mMisspellRanges.push_back(std::pair<U32, U32>(start + word_start, start + word_end)); + } + + // Find the start of the next word + word_start = word_end + 1; + while ( (word_start < text.length()) && (!LLWStringUtil::isPartOfWord(text[word_start])) ) + { + word_start++; + } + } + + mSpellCheckStart = start; + mSpellCheckEnd = end; + } + + // Draw squiggly lines under any (visible) misspelled words + for (std::list<std::pair<U32, U32> >::const_iterator it = mMisspellRanges.begin(); it != mMisspellRanges.end(); ++it) + { + // Skip over words that aren't (partially) visible + if ( ((it->first < start) && (it->second < start)) || (it->first > end) ) + { + continue; + } + + // Skip the current word if the user is still busy editing it + if ( (!mSpellCheckTimer.hasExpired()) && (it->first <= (U32)mCursorPos) && (it->second >= (U32)mCursorPos) ) + { + continue; + } + + S32 pxWidth = getRect().getWidth(); + S32 pxStart = findPixelNearestPos(it->first - getCursor()); + if (pxStart > pxWidth) + { + continue; + } + S32 pxEnd = findPixelNearestPos(it->second - getCursor()); + if (pxEnd > pxWidth) + { + pxEnd = pxWidth; + } + + S32 pxBottom = (S32)(text_bottom + mGLFont->getDescenderHeight()); + + gGL.color4ub(255, 0, 0, 200); + while (pxStart + 1 < pxEnd) + { + gl_line_2d(pxStart, pxBottom, pxStart + 2, pxBottom - 2); + if (pxStart + 3 < pxEnd) + { + gl_line_2d(pxStart + 2, pxBottom - 3, pxStart + 4, pxBottom - 1); + } + pxStart += 4; + } + } + } + // If we're editing... if( hasFocus()) { @@ -2109,6 +2314,15 @@ void LLLineEditor::setSelectAllonFocusReceived(BOOL b) mSelectAllonFocusReceived = b; } +void LLLineEditor::onKeystroke() +{ + if (mKeystrokeCallback) + { + mKeystrokeCallback(this); + } + + mSpellCheckStart = mSpellCheckEnd = -1; +} void LLLineEditor::setKeystrokeCallback(callback_t callback, void* user_data) { @@ -2231,10 +2445,9 @@ void LLLineEditor::updatePreedit(const LLWString &preedit_string, // Update of the preedit should be caused by some key strokes. mKeystrokeTimer.reset(); - if( mKeystrokeCallback ) - { - mKeystrokeCallback( this ); - } + onKeystroke(); + + mSpellCheckTimer.setTimerExpirySec(SPELLCHECK_DELAY); } BOOL LLLineEditor::getPreeditLocation(S32 query_offset, LLCoordGL *coord, LLRect *bounds, LLRect *control) const @@ -2386,7 +2599,38 @@ void LLLineEditor::showContextMenu(S32 x, S32 y) S32 screen_x, screen_y; localPointToScreen(x, y, &screen_x, &screen_y); - menu->show(screen_x, screen_y); + + setCursorAtLocalPos(x); + if (hasSelection()) + { + if ( (mCursorPos < llmin(mSelectionStart, mSelectionEnd)) || (mCursorPos > llmax(mSelectionStart, mSelectionEnd)) ) + { + deselect(); + } + else + { + setCursor(llmax(mSelectionStart, mSelectionEnd)); + } + } + + bool use_spellcheck = getSpellCheck(), is_misspelled = false; + if (use_spellcheck) + { + mSuggestionList.clear(); + + // If the cursor is on a misspelled word, retrieve suggestions for it + std::string misspelled_word = getMisspelledWord(mCursorPos); + if ((is_misspelled = !misspelled_word.empty()) == true) + { + LLSpellChecker::instance().getSuggestions(misspelled_word, mSuggestionList); + } + } + + menu->setItemVisible("Suggestion Separator", (use_spellcheck) && (!mSuggestionList.empty())); + menu->setItemVisible("Add to Dictionary", (use_spellcheck) && (is_misspelled)); + menu->setItemVisible("Add to Ignore", (use_spellcheck) && (is_misspelled)); + menu->setItemVisible("Spellcheck Separator", (use_spellcheck) && (is_misspelled)); + menu->show(screen_x, screen_y, this); } } diff --git a/indra/llui/lllineeditor.h b/indra/llui/lllineeditor.h index 2518dbe3c7..71dd53f608 100644 --- a/indra/llui/lllineeditor.h +++ b/indra/llui/lllineeditor.h @@ -40,6 +40,7 @@ #include "llframetimer.h" #include "lleditmenuhandler.h" +#include "llspellcheckmenuhandler.h" #include "lluictrl.h" #include "lluiimage.h" #include "lluistring.h" @@ -54,7 +55,7 @@ class LLButton; class LLContextMenu; class LLLineEditor -: public LLUICtrl, public LLEditMenuHandler, protected LLPreeditor +: public LLUICtrl, public LLEditMenuHandler, protected LLPreeditor, public LLSpellCheckMenuHandler { public: @@ -86,6 +87,7 @@ public: Optional<bool> select_on_focus, revert_on_esc, + spellcheck, commit_on_focus_lost, ignore_tab, is_password; @@ -146,6 +148,24 @@ public: virtual void deselect(); virtual BOOL canDeselect() const; + // LLSpellCheckMenuHandler overrides + /*virtual*/ bool getSpellCheck() const; + + /*virtual*/ const std::string& getSuggestion(U32 index) const; + /*virtual*/ U32 getSuggestionCount() const; + /*virtual*/ void replaceWithSuggestion(U32 index); + + /*virtual*/ void addToDictionary(); + /*virtual*/ bool canAddToDictionary() const; + + /*virtual*/ void addToIgnore(); + /*virtual*/ bool canAddToIgnore() const; + + // Spell checking helper functions + std::string getMisspelledWord(U32 pos) const; + bool isMisspelledWord(U32 pos) const; + void onSpellCheckSettingsChange(); + // view overrides virtual void draw(); virtual void reshape(S32 width,S32 height,BOOL called_from_parent=TRUE); @@ -169,6 +189,9 @@ public: virtual BOOL setTextArg( const std::string& key, const LLStringExplicit& text ); virtual BOOL setLabelArg( const std::string& key, const LLStringExplicit& text ); + typedef boost::function<void(LLUIString&, S32&)> autoreplace_callback_t; + autoreplace_callback_t mAutoreplaceCallback; + void setAutoreplaceCallback(autoreplace_callback_t cb) { mAutoreplaceCallback = cb; } void setLabel(const LLStringExplicit &new_label) { mLabel = new_label; } const std::string& getLabel() { return mLabel.getString(); } @@ -223,6 +246,7 @@ public: void setSelectAllonFocusReceived(BOOL b); void setSelectAllonCommit(BOOL b) { mSelectAllonCommit = b; } + void onKeystroke(); typedef boost::function<void (LLLineEditor* caller, void* user_data)> callback_t; void setKeystrokeCallback(callback_t callback, void* user_data); @@ -322,6 +346,13 @@ protected: S32 mLastSelectionStart; S32 mLastSelectionEnd; + bool mSpellCheck; + S32 mSpellCheckStart; + S32 mSpellCheckEnd; + LLTimer mSpellCheckTimer; + std::list<std::pair<U32, U32> > mMisspellRanges; + std::vector<std::string> mSuggestionList; + LLTextValidate::validate_func_t mPrevalidateFunc; LLTextValidate::validate_func_t mPrevalidateInputFunc; diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index ff6928ffda..efb9848a90 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -3854,7 +3854,7 @@ void LLContextMenu::setVisible(BOOL visible) } // Takes cursor position in screen space? -void LLContextMenu::show(S32 x, S32 y) +void LLContextMenu::show(S32 x, S32 y, LLView* spawning_view) { if (getChildList()->empty()) { @@ -3908,6 +3908,14 @@ void LLContextMenu::show(S32 x, S32 y) setRect(rect); arrange(); + if (spawning_view) + { + mSpawningViewHandle = spawning_view->getHandle(); + } + else + { + mSpawningViewHandle.markDead(); + } LLView::setVisible(TRUE); } diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h index 36f3ba34b9..67b3e1fbe6 100644 --- a/indra/llui/llmenugl.h +++ b/indra/llui/llmenugl.h @@ -670,7 +670,7 @@ public: virtual void draw (); - virtual void show (S32 x, S32 y); + virtual void show (S32 x, S32 y, LLView* spawning_view = NULL); virtual void hide (); virtual BOOL handleHover ( S32 x, S32 y, MASK mask ); @@ -683,10 +683,14 @@ public: LLHandle<LLContextMenu> getHandle() { return getDerivedHandle<LLContextMenu>(); } + LLView* getSpawningView() const { return mSpawningViewHandle.get(); } + void setSpawningView(LLHandle<LLView> spawning_view) { mSpawningViewHandle = spawning_view; } + protected: BOOL mHoveredAnyItem; LLMenuItemGL* mHoverItem; LLRootHandle<LLContextMenu> mHandle; + LLHandle<LLView> mSpawningViewHandle; }; diff --git a/indra/llui/llscrollcontainer.cpp b/indra/llui/llscrollcontainer.cpp index 9b7e30bb04..2fd187a526 100644 --- a/indra/llui/llscrollcontainer.cpp +++ b/indra/llui/llscrollcontainer.cpp @@ -389,12 +389,11 @@ void LLScrollContainer::calcVisibleSize( S32 *visible_width, S32 *visible_height { *show_h_scrollbar = TRUE; *visible_height -= scrollbar_size; - + // Note: Do *not* recompute *show_v_scrollbar here because with // The view inside the scroll container should not be extended // to container's full height to ensure the correct computation // of *show_v_scrollbar after subtracting horizontal scrollbar_size. - // Must retest now that visible_height has changed if( !*show_v_scrollbar && ((doc_height - *visible_height) > 1) ) { *show_v_scrollbar = TRUE; diff --git a/indra/llui/llspellcheck.cpp b/indra/llui/llspellcheck.cpp new file mode 100644 index 0000000000..a189375fbe --- /dev/null +++ b/indra/llui/llspellcheck.cpp @@ -0,0 +1,505 @@ +/** + * @file llspellcheck.cpp + * @brief Spell checking functionality + * + * $LicenseInfo:firstyear=2001&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 "linden_common.h" + +#include "lldir.h" +#include "llsdserialize.h" + +#include "llspellcheck.h" +#if LL_WINDOWS + #include <hunspell/hunspelldll.h> + #pragma comment(lib, "libhunspell.lib") +#else + #include <hunspell/hunspell.hxx> +#endif + +static const std::string DICT_DIR = "dictionaries"; +static const std::string DICT_FILE_CUSTOM = "user_custom.dic"; +static const std::string DICT_FILE_IGNORE = "user_ignore.dic"; + +static const std::string DICT_FILE_MAIN = "dictionaries.xml"; +static const std::string DICT_FILE_USER = "user_dictionaries.xml"; + +LLSD LLSpellChecker::sDictMap; +LLSpellChecker::settings_change_signal_t LLSpellChecker::sSettingsChangeSignal; + +LLSpellChecker::LLSpellChecker() + : mHunspell(NULL) +{ + // Load initial dictionary information + refreshDictionaryMap(); +} + +LLSpellChecker::~LLSpellChecker() +{ + delete mHunspell; +} + +bool LLSpellChecker::checkSpelling(const std::string& word) const +{ + if ( (!mHunspell) || (word.length() < 3) || (0 != mHunspell->spell(word.c_str())) ) + { + return true; + } + if (mIgnoreList.size() > 0) + { + std::string word_lower(word); + LLStringUtil::toLower(word_lower); + return (mIgnoreList.end() != std::find(mIgnoreList.begin(), mIgnoreList.end(), word_lower)); + } + return false; +} + +S32 LLSpellChecker::getSuggestions(const std::string& word, std::vector<std::string>& suggestions) const +{ + suggestions.clear(); + if ( (!mHunspell) || (word.length() < 3) ) + { + return 0; + } + + char** suggestion_list; int suggestion_cnt = 0; + if ( (suggestion_cnt = mHunspell->suggest(&suggestion_list, word.c_str())) != 0 ) + { + for (int suggestion_index = 0; suggestion_index < suggestion_cnt; suggestion_index++) + { + suggestions.push_back(suggestion_list[suggestion_index]); + } + mHunspell->free_list(&suggestion_list, suggestion_cnt); + } + return suggestions.size(); +} + +// static +const LLSD LLSpellChecker::getDictionaryData(const std::string& dict_language) +{ + for (LLSD::array_const_iterator it = sDictMap.beginArray(); it != sDictMap.endArray(); ++it) + { + const LLSD& dict_entry = *it; + if (dict_language == dict_entry["language"].asString()) + { + return dict_entry; + } + } + return LLSD(); +} + +// static +bool LLSpellChecker::hasDictionary(const std::string& dict_language, bool check_installed) +{ + const LLSD dict_info = getDictionaryData(dict_language); + return dict_info.has("language") && ( (!check_installed) || (dict_info["installed"].asBoolean()) ); +} + +// static +void LLSpellChecker::setDictionaryData(const LLSD& dict_info) +{ + const std::string dict_language = dict_info["language"].asString(); + if (dict_language.empty()) + { + return; + } + + for (LLSD::array_iterator it = sDictMap.beginArray(); it != sDictMap.endArray(); ++it) + { + LLSD& dict_entry = *it; + if (dict_language == dict_entry["language"].asString()) + { + dict_entry = dict_info; + return; + } + } + sDictMap.append(dict_info); + return; +} + +// static +void LLSpellChecker::refreshDictionaryMap() +{ + const std::string app_path = getDictionaryAppPath(); + const std::string user_path = getDictionaryUserPath(); + + // Load dictionary information (file name, friendly name, ...) + llifstream user_file(user_path + DICT_FILE_MAIN, std::ios::binary); + if ( (!user_file.is_open()) || (0 == LLSDSerialize::fromXMLDocument(sDictMap, user_file)) || (0 == sDictMap.size()) ) + { + llifstream app_file(app_path + DICT_FILE_MAIN, std::ios::binary); + if ( (!app_file.is_open()) || (0 == LLSDSerialize::fromXMLDocument(sDictMap, app_file)) || (0 == sDictMap.size()) ) + { + return; + } + } + + // Load user installed dictionary information + llifstream custom_file(user_path + DICT_FILE_USER, std::ios::binary); + if (custom_file.is_open()) + { + LLSD custom_dict_map; + LLSDSerialize::fromXMLDocument(custom_dict_map, custom_file); + for (LLSD::array_iterator it = custom_dict_map.beginArray(); it != custom_dict_map.endArray(); ++it) + { + LLSD& dict_info = *it; + dict_info["user_installed"] = true; + setDictionaryData(dict_info); + } + custom_file.close(); + } + + // Look for installed dictionaries + std::string tmp_app_path, tmp_user_path; + for (LLSD::array_iterator it = sDictMap.beginArray(); it != sDictMap.endArray(); ++it) + { + LLSD& sdDict = *it; + tmp_app_path = (sdDict.has("name")) ? app_path + sdDict["name"].asString() : LLStringUtil::null; + tmp_user_path = (sdDict.has("name")) ? user_path + sdDict["name"].asString() : LLStringUtil::null; + sdDict["installed"] = + (!tmp_app_path.empty()) && ((gDirUtilp->fileExists(tmp_user_path + ".dic")) || (gDirUtilp->fileExists(tmp_app_path + ".dic"))); + } + + sSettingsChangeSignal(); +} + +void LLSpellChecker::addToCustomDictionary(const std::string& word) +{ + if (mHunspell) + { + mHunspell->add(word.c_str()); + } + addToDictFile(getDictionaryUserPath() + DICT_FILE_CUSTOM, word); + sSettingsChangeSignal(); +} + +void LLSpellChecker::addToIgnoreList(const std::string& word) +{ + std::string word_lower(word); + LLStringUtil::toLower(word_lower); + if (mIgnoreList.end() == std::find(mIgnoreList.begin(), mIgnoreList.end(), word_lower)) + { + mIgnoreList.push_back(word_lower); + addToDictFile(getDictionaryUserPath() + DICT_FILE_IGNORE, word_lower); + sSettingsChangeSignal(); + } +} + +void LLSpellChecker::addToDictFile(const std::string& dict_path, const std::string& word) +{ + std::vector<std::string> word_list; + + if (gDirUtilp->fileExists(dict_path)) + { + llifstream file_in(dict_path, std::ios::in); + if (file_in.is_open()) + { + std::string word; int line_num = 0; + while (getline(file_in, word)) + { + // Skip over the first line since that's just a line count + if (0 != line_num) + { + word_list.push_back(word); + } + line_num++; + } + } + else + { + // TODO: show error message? + return; + } + } + + word_list.push_back(word); + + llofstream file_out(dict_path, std::ios::out | std::ios::trunc); + if (file_out.is_open()) + { + file_out << word_list.size() << std::endl; + for (std::vector<std::string>::const_iterator itWord = word_list.begin(); itWord != word_list.end(); ++itWord) + { + file_out << *itWord << std::endl; + } + file_out.close(); + } +} + +bool LLSpellChecker::isActiveDictionary(const std::string& dict_language) const +{ + return + (mDictLanguage == dict_language) || + (mDictSecondary.end() != std::find(mDictSecondary.begin(), mDictSecondary.end(), dict_language)); +} + +void LLSpellChecker::setSecondaryDictionaries(dict_list_t dict_list) +{ + if (!getUseSpellCheck()) + { + return; + } + + // Check if we're only adding secondary dictionaries, or removing them + dict_list_t dict_add(llmax(dict_list.size(), mDictSecondary.size())), dict_rem(llmax(dict_list.size(), mDictSecondary.size())); + dict_list.sort(); + mDictSecondary.sort(); + dict_list_t::iterator end_added = std::set_difference(dict_list.begin(), dict_list.end(), mDictSecondary.begin(), mDictSecondary.end(), dict_add.begin()); + dict_list_t::iterator end_removed = std::set_difference(mDictSecondary.begin(), mDictSecondary.end(), dict_list.begin(), dict_list.end(), dict_rem.begin()); + + if (end_removed != dict_rem.begin()) // We can't remove secondary dictionaries so we need to recreate the Hunspell instance + { + mDictSecondary = dict_list; + + std::string dict_language = mDictLanguage; + initHunspell(dict_language); + } + else if (end_added != dict_add.begin()) // Add the new secondary dictionaries one by one + { + const std::string app_path = getDictionaryAppPath(); + const std::string user_path = getDictionaryUserPath(); + for (dict_list_t::const_iterator it_added = dict_add.begin(); it_added != end_added; ++it_added) + { + const LLSD dict_entry = getDictionaryData(*it_added); + if ( (!dict_entry.isDefined()) || (!dict_entry["installed"].asBoolean()) ) + { + continue; + } + + const std::string strFileDic = dict_entry["name"].asString() + ".dic"; + if (gDirUtilp->fileExists(user_path + strFileDic)) + { + mHunspell->add_dic((user_path + strFileDic).c_str()); + } + else if (gDirUtilp->fileExists(app_path + strFileDic)) + { + mHunspell->add_dic((app_path + strFileDic).c_str()); + } + } + mDictSecondary = dict_list; + sSettingsChangeSignal(); + } +} + +void LLSpellChecker::initHunspell(const std::string& dict_language) +{ + if (mHunspell) + { + delete mHunspell; + mHunspell = NULL; + mDictLanguage.clear(); + mDictFile.clear(); + mIgnoreList.clear(); + } + + const LLSD dict_entry = (!dict_language.empty()) ? getDictionaryData(dict_language) : LLSD(); + if ( (!dict_entry.isDefined()) || (!dict_entry["installed"].asBoolean()) || (!dict_entry["is_primary"].asBoolean())) + { + sSettingsChangeSignal(); + return; + } + + const std::string app_path = getDictionaryAppPath(); + const std::string user_path = getDictionaryUserPath(); + if (dict_entry.has("name")) + { + const std::string filename_aff = dict_entry["name"].asString() + ".aff"; + const std::string filename_dic = dict_entry["name"].asString() + ".dic"; + if ( (gDirUtilp->fileExists(user_path + filename_aff)) && (gDirUtilp->fileExists(user_path + filename_dic)) ) + { + mHunspell = new Hunspell((user_path + filename_aff).c_str(), (user_path + filename_dic).c_str()); + } + else if ( (gDirUtilp->fileExists(app_path + filename_aff)) && (gDirUtilp->fileExists(app_path + filename_dic)) ) + { + mHunspell = new Hunspell((app_path + filename_aff).c_str(), (app_path + filename_dic).c_str()); + } + if (!mHunspell) + { + return; + } + + mDictLanguage = dict_language; + mDictFile = dict_entry["name"].asString(); + + if (gDirUtilp->fileExists(user_path + DICT_FILE_CUSTOM)) + { + mHunspell->add_dic((user_path + DICT_FILE_CUSTOM).c_str()); + } + + if (gDirUtilp->fileExists(user_path + DICT_FILE_IGNORE)) + { + llifstream file_in(user_path + DICT_FILE_IGNORE, std::ios::in); + if (file_in.is_open()) + { + std::string word; int idxLine = 0; + while (getline(file_in, word)) + { + // Skip over the first line since that's just a line count + if (0 != idxLine) + { + LLStringUtil::toLower(word); + mIgnoreList.push_back(word); + } + idxLine++; + } + } + } + + for (dict_list_t::const_iterator it = mDictSecondary.begin(); it != mDictSecondary.end(); ++it) + { + const LLSD dict_entry = getDictionaryData(*it); + if ( (!dict_entry.isDefined()) || (!dict_entry["installed"].asBoolean()) ) + { + continue; + } + + const std::string filename_dic = dict_entry["name"].asString() + ".dic"; + if (gDirUtilp->fileExists(user_path + filename_dic)) + { + mHunspell->add_dic((user_path + filename_dic).c_str()); + } + else if (gDirUtilp->fileExists(app_path + filename_dic)) + { + mHunspell->add_dic((app_path + filename_dic).c_str()); + } + } + } + + sSettingsChangeSignal(); +} + +// static +const std::string LLSpellChecker::getDictionaryAppPath() +{ + std::string dict_path = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, DICT_DIR, ""); + return dict_path; +} + +// static +const std::string LLSpellChecker::getDictionaryUserPath() +{ + std::string dict_path = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, DICT_DIR, ""); + if (!gDirUtilp->fileExists(dict_path)) + { + LLFile::mkdir(dict_path); + } + return dict_path; +} + +// static +bool LLSpellChecker::getUseSpellCheck() +{ + return (LLSpellChecker::instanceExists()) && (LLSpellChecker::instance().mHunspell); +} + +// static +bool LLSpellChecker::canRemoveDictionary(const std::string& dict_language) +{ + // Only user-installed inactive dictionaries can be removed + const LLSD dict_info = getDictionaryData(dict_language); + return + (dict_info["user_installed"].asBoolean()) && + ( (!getUseSpellCheck()) || (!LLSpellChecker::instance().isActiveDictionary(dict_language)) ); +} + +// static +void LLSpellChecker::removeDictionary(const std::string& dict_language) +{ + if (!canRemoveDictionary(dict_language)) + { + return; + } + + LLSD dict_map = loadUserDictionaryMap(); + for (LLSD::array_const_iterator it = dict_map.beginArray(); it != dict_map.endArray(); ++it) + { + const LLSD& dict_info = *it; + if (dict_info["language"].asString() == dict_language) + { + const std::string dict_dic = getDictionaryUserPath() + dict_info["name"].asString() + ".dic"; + if (gDirUtilp->fileExists(dict_dic)) + { + LLFile::remove(dict_dic); + } + const std::string dict_aff = getDictionaryUserPath() + dict_info["name"].asString() + ".aff"; + if (gDirUtilp->fileExists(dict_aff)) + { + LLFile::remove(dict_aff); + } + dict_map.erase(it - dict_map.beginArray()); + break; + } + } + saveUserDictionaryMap(dict_map); + + refreshDictionaryMap(); +} + +// static +LLSD LLSpellChecker::loadUserDictionaryMap() +{ + LLSD dict_map; + llifstream dict_file(getDictionaryUserPath() + DICT_FILE_USER, std::ios::binary); + if (dict_file.is_open()) + { + LLSDSerialize::fromXMLDocument(dict_map, dict_file); + dict_file.close(); + } + return dict_map; +} + +// static +void LLSpellChecker::saveUserDictionaryMap(const LLSD& dict_map) +{ + llofstream dict_file(getDictionaryUserPath() + DICT_FILE_USER, std::ios::trunc); + if (dict_file.is_open()) + { + LLSDSerialize::toPrettyXML(dict_map, dict_file); + dict_file.close(); + } +} + +// static +boost::signals2::connection LLSpellChecker::setSettingsChangeCallback(const settings_change_signal_t::slot_type& cb) +{ + return sSettingsChangeSignal.connect(cb); +} + +// static +void LLSpellChecker::setUseSpellCheck(const std::string& dict_language) +{ + if ( (((dict_language.empty()) && (getUseSpellCheck())) || (!dict_language.empty())) && + (LLSpellChecker::instance().mDictLanguage != dict_language) ) + { + LLSpellChecker::instance().initHunspell(dict_language); + } +} + +// static +void LLSpellChecker::initClass() +{ + if (sDictMap.isUndefined()) + { + refreshDictionaryMap(); + } +} diff --git a/indra/llui/llspellcheck.h b/indra/llui/llspellcheck.h new file mode 100644 index 0000000000..4ab80195ea --- /dev/null +++ b/indra/llui/llspellcheck.h @@ -0,0 +1,93 @@ +/** + * @file llspellcheck.h + * @brief Spell checking functionality + * + * $LicenseInfo:firstyear=2001&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 LLSPELLCHECK_H +#define LLSPELLCHECK_H + +#include "llsingleton.h" +#include "llui.h" +#include <boost/signals2.hpp> + +class Hunspell; + +class LLSpellChecker : public LLSingleton<LLSpellChecker>, public LLInitClass<LLSpellChecker> +{ + friend class LLSingleton<LLSpellChecker>; + friend class LLInitClass<LLSpellChecker>; +protected: + LLSpellChecker(); + ~LLSpellChecker(); + +public: + void addToCustomDictionary(const std::string& word); + void addToIgnoreList(const std::string& word); + bool checkSpelling(const std::string& word) const; + S32 getSuggestions(const std::string& word, std::vector<std::string>& suggestions) const; +protected: + void addToDictFile(const std::string& dict_path, const std::string& word); + void initHunspell(const std::string& dict_language); + +public: + typedef std::list<std::string> dict_list_t; + + const std::string& getPrimaryDictionary() const { return mDictLanguage; } + const dict_list_t& getSecondaryDictionaries() const { return mDictSecondary; } + bool isActiveDictionary(const std::string& dict_language) const; + void setSecondaryDictionaries(dict_list_t dict_list); + + static bool canRemoveDictionary(const std::string& dict_language); + static const std::string getDictionaryAppPath(); + static const std::string getDictionaryUserPath(); + static const LLSD getDictionaryData(const std::string& dict_language); + static const LLSD& getDictionaryMap() { return sDictMap; } + static bool getUseSpellCheck(); + static bool hasDictionary(const std::string& dict_language, bool check_installed = false); + static void refreshDictionaryMap(); + static void removeDictionary(const std::string& dict_language); + static void setUseSpellCheck(const std::string& dict_language); +protected: + static LLSD loadUserDictionaryMap(); + static void setDictionaryData(const LLSD& dict_info); + static void saveUserDictionaryMap(const LLSD& dict_map); + +public: + typedef boost::signals2::signal<void()> settings_change_signal_t; + static boost::signals2::connection setSettingsChangeCallback(const settings_change_signal_t::slot_type& cb); +protected: + static void initClass(); + +protected: + Hunspell* mHunspell; + std::string mDictLanguage; + std::string mDictFile; + dict_list_t mDictSecondary; + std::vector<std::string> mIgnoreList; + + static LLSD sDictMap; + static settings_change_signal_t sSettingsChangeSignal; +}; + +#endif // LLSPELLCHECK_H diff --git a/indra/llui/llspellcheckmenuhandler.h b/indra/llui/llspellcheckmenuhandler.h new file mode 100644 index 0000000000..d5c95bad39 --- /dev/null +++ b/indra/llui/llspellcheckmenuhandler.h @@ -0,0 +1,46 @@ +/** + * @file llspellcheckmenuhandler.h + * @brief Interface used by spell check menu handling + * + * $LicenseInfo:firstyear=2001&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 LLSPELLCHECKMENUHANDLER_H +#define LLSPELLCHECKMENUHANDLER_H + +class LLSpellCheckMenuHandler +{ +public: + virtual bool getSpellCheck() const { return false; } + + virtual const std::string& getSuggestion(U32 index) const { return LLStringUtil::null; } + virtual U32 getSuggestionCount() const { return 0; } + virtual void replaceWithSuggestion(U32 index){} + + virtual void addToDictionary() {} + virtual bool canAddToDictionary() const { return false; } + + virtual void addToIgnore() {} + virtual bool canAddToIgnore() const { return false; } +}; + +#endif // LLSPELLCHECKMENUHANDLER_H diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 7aeeae298f..3815eec447 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -32,6 +32,7 @@ #include "lllocalcliprect.h" #include "llmenugl.h" #include "llscrollcontainer.h" +#include "llspellcheck.h" #include "llstl.h" #include "lltextparser.h" #include "lltextutil.h" @@ -155,6 +156,7 @@ LLTextBase::Params::Params() plain_text("plain_text",false), track_end("track_end", false), read_only("read_only", false), + spellcheck("spellcheck", false), v_pad("v_pad", 0), h_pad("h_pad", 0), clip("clip", true), @@ -181,6 +183,9 @@ LLTextBase::LLTextBase(const LLTextBase::Params &p) mFontShadow(p.font_shadow), mPopupMenu(NULL), mReadOnly(p.read_only), + mSpellCheck(p.spellcheck), + mSpellCheckStart(-1), + mSpellCheckEnd(-1), mCursorColor(p.cursor_color), mFgColor(p.text_color), mBorderVisible( p.border_visible ), @@ -246,6 +251,12 @@ LLTextBase::LLTextBase(const LLTextBase::Params &p) addChild(mDocumentView); } + if (mSpellCheck) + { + LLSpellChecker::setSettingsChangeCallback(boost::bind(&LLTextBase::onSpellCheckSettingsChange, this)); + } + mSpellCheckTimer.reset(); + createDefaultSegment(); updateRects(); @@ -280,12 +291,23 @@ bool LLTextBase::truncate() if (getLength() >= S32(mMaxTextByteLength / 4)) { // Have to check actual byte size - LLWString text(getWText()); - S32 utf8_byte_size = wstring_utf8_length(text); + S32 utf8_byte_size = 0; + LLSD value = getViewModel()->getValue(); + if (value.type() == LLSD::TypeString) + { + // save a copy for strings. + utf8_byte_size = value.size(); + } + else + { + // non string LLSDs need explicit conversion to string + utf8_byte_size = value.asString().size(); + } + if ( utf8_byte_size > mMaxTextByteLength ) { // Truncate safely in UTF-8 - std::string temp_utf8_text = wstring_to_utf8str(text); + std::string temp_utf8_text = value.asString(); temp_utf8_text = utf8str_truncate( temp_utf8_text, mMaxTextByteLength ); LLWString text = utf8str_to_wstring( temp_utf8_text ); // remove extra bit of current string, to preserve formatting, etc. @@ -530,8 +552,92 @@ void LLTextBase::drawText() return; } + // Perform spell check if needed + if ( (getSpellCheck()) && (getWText().length() > 2) ) + { + // Calculate start and end indices for the spell checking range + S32 start = line_start, end = getLineEnd(last_line); + + if ( (mSpellCheckStart != start) || (mSpellCheckEnd != end) ) + { + const LLWString& wstrText = getWText(); + mMisspellRanges.clear(); + + segment_set_t::const_iterator seg_it = getSegIterContaining(start); + while (mSegments.end() != seg_it) + { + LLTextSegmentPtr text_segment = *seg_it; + if ( (text_segment.isNull()) || (text_segment->getStart() >= end) ) + { + break; + } + + if (!text_segment->canEdit()) + { + ++seg_it; + continue; + } + + // Combine adjoining text segments into one + U32 seg_start = text_segment->getStart(), seg_end = llmin(text_segment->getEnd(), end); + while (mSegments.end() != ++seg_it) + { + text_segment = *seg_it; + if ( (text_segment.isNull()) || (!text_segment->canEdit()) || (text_segment->getStart() >= end) ) + { + break; + } + seg_end = llmin(text_segment->getEnd(), end); + } + + // Find the start of the first word + U32 word_start = seg_start, word_end = -1; + while ( (word_start < wstrText.length()) && (!LLStringOps::isAlpha(wstrText[word_start])) ) + { + word_start++; + } + + // Iterate over all words in the text block and check them one by one + while (word_start < seg_end) + { + // Find the end of the current word (special case handling for "'" when it's used as a contraction) + word_end = word_start + 1; + while ( (word_end < seg_end) && + ((LLWStringUtil::isPartOfWord(wstrText[word_end])) || + ((L'\'' == wstrText[word_end]) && + (LLStringOps::isAlnum(wstrText[word_end - 1])) && (LLStringOps::isAlnum(wstrText[word_end + 1])))) ) + { + word_end++; + } + if (word_end > seg_end) + { + break; + } + + // Don't process words shorter than 3 characters + std::string word = wstring_to_utf8str(wstrText.substr(word_start, word_end - word_start)); + if ( (word.length() >= 3) && (!LLSpellChecker::instance().checkSpelling(word)) ) + { + mMisspellRanges.push_back(std::pair<U32, U32>(word_start, word_end)); + } + + // Find the start of the next word + word_start = word_end + 1; + while ( (word_start < seg_end) && (!LLWStringUtil::isPartOfWord(wstrText[word_start])) ) + { + word_start++; + } + } + } + + mSpellCheckStart = start; + mSpellCheckEnd = end; + } + } + LLTextSegmentPtr cur_segment = *seg_iter; + std::list<std::pair<U32, U32> >::const_iterator misspell_it = std::lower_bound(mMisspellRanges.begin(), mMisspellRanges.end(), std::pair<U32, U32>(line_start, 0)); for (S32 cur_line = first_line; cur_line < last_line; cur_line++) { S32 next_line = cur_line + 1; @@ -566,7 +672,8 @@ void LLTextBase::drawText() cur_segment = *seg_iter; } - S32 clipped_end = llmin( line_end, cur_segment->getEnd() ) - cur_segment->getStart(); + S32 seg_end = llmin(line_end, cur_segment->getEnd()); + S32 clipped_end = seg_end - cur_segment->getStart(); if (mUseEllipses // using ellipses && clipped_end == line_end // last segment on line @@ -578,6 +685,46 @@ void LLTextBase::drawText() text_rect.mRight -= 2; } + // Draw squiggly lines under any visible misspelled words + while ( (mMisspellRanges.end() != misspell_it) && (misspell_it->first < seg_end) && (misspell_it->second > seg_start) ) + { + // Skip the current word if the user is still busy editing it + if ( (!mSpellCheckTimer.hasExpired()) && (misspell_it->first <= (U32)mCursorPos) && (misspell_it->second >= (U32)mCursorPos) ) + { + ++misspell_it; + continue; + } + + U32 misspell_start = llmax<U32>(misspell_it->first, seg_start), misspell_end = llmin<U32>(misspell_it->second, seg_end); + S32 squiggle_start = 0, squiggle_end = 0, pony = 0; + cur_segment->getDimensions(seg_start - cur_segment->getStart(), misspell_start - seg_start, squiggle_start, pony); + cur_segment->getDimensions(misspell_start - cur_segment->getStart(), misspell_end - misspell_start, squiggle_end, pony); + squiggle_start += text_rect.mLeft; + + pony = (squiggle_end + 3) / 6; + squiggle_start += squiggle_end / 2 - pony * 3; + squiggle_end = squiggle_start + pony * 6; + + S32 squiggle_bottom = text_rect.mBottom + (S32)cur_segment->getStyle()->getFont()->getDescenderHeight(); + + gGL.color4ub(255, 0, 0, 200); + while (squiggle_start + 1 < squiggle_end) + { + gl_line_2d(squiggle_start, squiggle_bottom, squiggle_start + 2, squiggle_bottom - 2); + if (squiggle_start + 3 < squiggle_end) + { + gl_line_2d(squiggle_start + 2, squiggle_bottom - 3, squiggle_start + 4, squiggle_bottom - 1); + } + squiggle_start += 4; + } + + if (misspell_it->second > seg_end) + { + break; + } + ++misspell_it; + } + text_rect.mLeft = (S32)(cur_segment->draw(seg_start - cur_segment->getStart(), clipped_end, selection_left, selection_right, text_rect)); seg_start = clipped_end + cur_segment->getStart(); @@ -592,8 +739,7 @@ void LLTextBase::drawText() S32 LLTextBase::insertStringNoUndo(S32 pos, const LLWString &wstr, LLTextBase::segment_vec_t* segments ) { - LLWString text(getWText()); - S32 old_len = text.length(); // length() returns character length + S32 old_len = getLength(); // length() returns character length S32 insert_len = wstr.length(); pos = getEditableIndex(pos, true); @@ -653,8 +799,7 @@ S32 LLTextBase::insertStringNoUndo(S32 pos, const LLWString &wstr, LLTextBase::s } } - text.insert(pos, wstr); - getViewModel()->setDisplay(text); + getViewModel()->getEditableDisplay().insert(pos, wstr); if ( truncate() ) { @@ -669,7 +814,6 @@ S32 LLTextBase::insertStringNoUndo(S32 pos, const LLWString &wstr, LLTextBase::s S32 LLTextBase::removeStringNoUndo(S32 pos, S32 length) { - LLWString text(getWText()); segment_set_t::iterator seg_iter = getSegIterContaining(pos); while(seg_iter != mSegments.end()) { @@ -715,8 +859,7 @@ S32 LLTextBase::removeStringNoUndo(S32 pos, S32 length) ++seg_iter; } - text.erase(pos, length); - getViewModel()->setDisplay(text); + getViewModel()->getEditableDisplay().erase(pos, length); // recreate default segment in case we erased everything createDefaultSegment(); @@ -733,9 +876,7 @@ S32 LLTextBase::overwriteCharNoUndo(S32 pos, llwchar wc) { return 0; } - LLWString text(getWText()); - text[pos] = wc; - getViewModel()->setDisplay(text); + getViewModel()->getEditableDisplay()[pos] = wc; onValueChange(pos, pos + 1); needsReflow(pos); @@ -1103,6 +1244,99 @@ void LLTextBase::deselect() mIsSelecting = FALSE; } +bool LLTextBase::getSpellCheck() const +{ + return (LLSpellChecker::getUseSpellCheck()) && (!mReadOnly) && (mSpellCheck); +} + +const std::string& LLTextBase::getSuggestion(U32 index) const +{ + return (index < mSuggestionList.size()) ? mSuggestionList[index] : LLStringUtil::null; +} + +U32 LLTextBase::getSuggestionCount() const +{ + return mSuggestionList.size(); +} + +void LLTextBase::replaceWithSuggestion(U32 index) +{ + for (std::list<std::pair<U32, U32> >::const_iterator it = mMisspellRanges.begin(); it != mMisspellRanges.end(); ++it) + { + if ( (it->first <= (U32)mCursorPos) && (it->second >= (U32)mCursorPos) ) + { + deselect(); + + // Delete the misspelled word + removeStringNoUndo(it->first, it->second - it->first); + + // Insert the suggestion in its place + LLWString suggestion = utf8str_to_wstring(mSuggestionList[index]); + insertStringNoUndo(it->first, utf8str_to_wstring(mSuggestionList[index])); + setCursorPos(it->first + (S32)suggestion.length()); + + break; + } + } + mSpellCheckStart = mSpellCheckEnd = -1; +} + +void LLTextBase::addToDictionary() +{ + if (canAddToDictionary()) + { + LLSpellChecker::instance().addToCustomDictionary(getMisspelledWord(mCursorPos)); + } +} + +bool LLTextBase::canAddToDictionary() const +{ + return (getSpellCheck()) && (isMisspelledWord(mCursorPos)); +} + +void LLTextBase::addToIgnore() +{ + if (canAddToIgnore()) + { + LLSpellChecker::instance().addToIgnoreList(getMisspelledWord(mCursorPos)); + } +} + +bool LLTextBase::canAddToIgnore() const +{ + return (getSpellCheck()) && (isMisspelledWord(mCursorPos)); +} + +std::string LLTextBase::getMisspelledWord(U32 pos) const +{ + for (std::list<std::pair<U32, U32> >::const_iterator it = mMisspellRanges.begin(); it != mMisspellRanges.end(); ++it) + { + if ( (it->first <= pos) && (it->second >= pos) ) + { + return wstring_to_utf8str(getWText().substr(it->first, it->second - it->first)); + } + } + return LLStringUtil::null; +} + +bool LLTextBase::isMisspelledWord(U32 pos) const +{ + for (std::list<std::pair<U32, U32> >::const_iterator it = mMisspellRanges.begin(); it != mMisspellRanges.end(); ++it) + { + if ( (it->first <= pos) && (it->second >= pos) ) + { + return true; + } + } + return false; +} + +void LLTextBase::onSpellCheckSettingsChange() +{ + // Recheck the spelling on every change + mMisspellRanges.clear(); + mSpellCheckStart = mSpellCheckEnd = -1; +} // Sets the scrollbar from the cursor position void LLTextBase::updateScrollFromCursor() @@ -1685,6 +1919,8 @@ static LLUIImagePtr image_from_icon_name(const std::string& icon_name) } } +static LLFastTimer::DeclareTimer FTM_PARSE_HTML("Parse HTML"); + void LLTextBase::appendTextImpl(const std::string &new_text, const LLStyle::Params& input_params) { LLStyle::Params style_params(input_params); @@ -1693,15 +1929,13 @@ void LLTextBase::appendTextImpl(const std::string &new_text, const LLStyle::Para S32 part = (S32)LLTextParser::WHOLE; if (mParseHTML && !style_params.is_link) // Don't search for URLs inside a link segment (STORM-358). { + LLFastTimer _(FTM_PARSE_HTML); S32 start=0,end=0; LLUrlMatch match; std::string text = new_text; while ( LLUrlRegistry::instance().findUrl(text, match, boost::bind(&LLTextBase::replaceUrl, this, _1, _2, _3)) ) { - - LLTextUtil::processUrlMatch(&match,this); - start = match.getStart(); end = match.getEnd()+1; @@ -1737,6 +1971,8 @@ void LLTextBase::appendTextImpl(const std::string &new_text, const LLStyle::Para } } + LLTextUtil::processUrlMatch(&match,this); + // move on to the rest of the text after the Url if (end < (S32)text.length()) { @@ -1760,8 +1996,11 @@ void LLTextBase::appendTextImpl(const std::string &new_text, const LLStyle::Para } } +static LLFastTimer::DeclareTimer FTM_APPEND_TEXT("Append Text"); + void LLTextBase::appendText(const std::string &new_text, bool prepend_newline, const LLStyle::Params& input_params) { + LLFastTimer _(FTM_APPEND_TEXT); if (new_text.empty()) return; diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index 0549141b72..90b147cee1 100644 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -30,6 +30,7 @@ #include "v4color.h" #include "lleditmenuhandler.h" +#include "llspellcheckmenuhandler.h" #include "llstyle.h" #include "llkeywords.h" #include "llpanel.h" @@ -230,7 +231,8 @@ typedef LLPointer<LLTextSegment> LLTextSegmentPtr; /// class LLTextBase : public LLUICtrl, - protected LLEditMenuHandler + protected LLEditMenuHandler, + public LLSpellCheckMenuHandler { public: friend class LLTextSegment; @@ -259,6 +261,7 @@ public: border_visible, track_end, read_only, + spellcheck, allow_scroll, plain_text, wrap, @@ -311,6 +314,24 @@ public: /*virtual*/ BOOL canDeselect() const; /*virtual*/ void deselect(); + // LLSpellCheckMenuHandler overrides + /*virtual*/ bool getSpellCheck() const; + + /*virtual*/ const std::string& getSuggestion(U32 index) const; + /*virtual*/ U32 getSuggestionCount() const; + /*virtual*/ void replaceWithSuggestion(U32 index); + + /*virtual*/ void addToDictionary(); + /*virtual*/ bool canAddToDictionary() const; + + /*virtual*/ void addToIgnore(); + /*virtual*/ bool canAddToIgnore() const; + + // Spell checking helper functions + std::string getMisspelledWord(U32 pos) const; + bool isMisspelledWord(U32 pos) const; + void onSpellCheckSettingsChange(); + // used by LLTextSegment layout code bool getWordWrap() { return mWordWrap; } bool getUseEllipses() { return mUseEllipses; } @@ -540,6 +561,14 @@ protected: BOOL mIsSelecting; // Are we in the middle of a drag-select? + // spell checking + bool mSpellCheck; + S32 mSpellCheckStart; + S32 mSpellCheckEnd; + LLTimer mSpellCheckTimer; + std::list<std::pair<U32, U32> > mMisspellRanges; + std::vector<std::string> mSuggestionList; + // configuration S32 mHPad; // padding on left of text S32 mVPad; // padding above text diff --git a/indra/llui/lltextbox.cpp b/indra/llui/lltextbox.cpp index 6a905b7ec0..11cfa1d263 100644 --- a/indra/llui/lltextbox.cpp +++ b/indra/llui/lltextbox.cpp @@ -150,7 +150,7 @@ S32 LLTextBox::getTextPixelHeight() LLSD LLTextBox::getValue() const { - return LLSD(getText()); + return getViewModel()->getValue(); } BOOL LLTextBox::setTextArg( const std::string& key, const LLStringExplicit& text ) diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index 9720dded6c..144b6960a1 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -54,6 +54,7 @@ #include "llwindow.h" #include "lltextparser.h" #include "llscrollcontainer.h" +#include "llspellcheck.h" #include "llpanel.h" #include "llurlregistry.h" #include "lltooltip.h" @@ -77,6 +78,7 @@ template class LLTextEditor* LLView::getChild<class LLTextEditor>( const S32 UI_TEXTEDITOR_LINE_NUMBER_MARGIN = 32; const S32 UI_TEXTEDITOR_LINE_NUMBER_DIGITS = 4; const S32 SPACES_PER_TAB = 4; +const F32 SPELLCHECK_DELAY = 0.5f; // delay between the last keypress and spell checking the word the cursor is on /////////////////////////////////////////////////////////////////// @@ -1953,7 +1955,38 @@ void LLTextEditor::showContextMenu(S32 x, S32 y) S32 screen_x, screen_y; localPointToScreen(x, y, &screen_x, &screen_y); - mContextMenu->show(screen_x, screen_y); + + setCursorAtLocalPos(x, y, false); + if (hasSelection()) + { + if ( (mCursorPos < llmin(mSelectionStart, mSelectionEnd)) || (mCursorPos > llmax(mSelectionStart, mSelectionEnd)) ) + { + deselect(); + } + else + { + setCursorPos(llmax(mSelectionStart, mSelectionEnd)); + } + } + + bool use_spellcheck = getSpellCheck(), is_misspelled = false; + if (use_spellcheck) + { + mSuggestionList.clear(); + + // If the cursor is on a misspelled word, retrieve suggestions for it + std::string misspelled_word = getMisspelledWord(mCursorPos); + if ((is_misspelled = !misspelled_word.empty()) == true) + { + LLSpellChecker::instance().getSuggestions(misspelled_word, mSuggestionList); + } + } + + mContextMenu->setItemVisible("Suggestion Separator", (use_spellcheck) && (!mSuggestionList.empty())); + mContextMenu->setItemVisible("Add to Dictionary", (use_spellcheck) && (is_misspelled)); + mContextMenu->setItemVisible("Add to Ignore", (use_spellcheck) && (is_misspelled)); + mContextMenu->setItemVisible("Spellcheck Separator", (use_spellcheck) && (is_misspelled)); + mContextMenu->show(screen_x, screen_y, this); } @@ -2838,6 +2871,9 @@ void LLTextEditor::setKeystrokeCallback(const keystroke_signal_t::slot_type& cal void LLTextEditor::onKeyStroke() { mKeystrokeSignal(this); + + mSpellCheckStart = mSpellCheckEnd = -1; + mSpellCheckTimer.setTimerExpirySec(SPELLCHECK_DELAY); } //virtual diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp index b5e27616b7..87bf518aa1 100644 --- a/indra/llui/llui.cpp +++ b/indra/llui/llui.cpp @@ -831,7 +831,11 @@ void gl_stippled_line_3d( const LLVector3& start, const LLVector3& end, const LL gGL.flush(); glLineWidth(2.5f); - glLineStipple(2, 0x3333 << shift); + + if (!LLGLSLShader::sNoFixedFunction) + { + glLineStipple(2, 0x3333 << shift); + } gGL.begin(LLRender::LINES); { diff --git a/indra/llui/llviewmodel.h b/indra/llui/llviewmodel.h index 763af5d8a2..ef2e314799 100644 --- a/indra/llui/llviewmodel.h +++ b/indra/llui/llviewmodel.h @@ -102,6 +102,7 @@ public: // New functions /// Get the stored value in string form const LLWString& getDisplay() const { return mDisplay; } + LLWString& getEditableDisplay() { mDirty = true; mUpdateFromDisplay = true; return mDisplay; } /** * Set the display string directly (see LLTextEditor). What the user is diff --git a/indra/llwindow/llkeyboard.cpp b/indra/llwindow/llkeyboard.cpp index 53cecf9d4a..8b356ba138 100644 --- a/indra/llwindow/llkeyboard.cpp +++ b/indra/llwindow/llkeyboard.cpp @@ -46,7 +46,7 @@ LLKeyStringTranslatorFunc* LLKeyboard::mStringTranslator = NULL; // Used for l10 // Class Implementation // -LLKeyboard::LLKeyboard() : mCallbacks(NULL), mNumpadDistinct(ND_NUMLOCK_OFF) +LLKeyboard::LLKeyboard() : mCallbacks(NULL) { S32 i; diff --git a/indra/llwindow/llkeyboard.h b/indra/llwindow/llkeyboard.h index ba472cfde5..c155c1b362 100644 --- a/indra/llwindow/llkeyboard.h +++ b/indra/llwindow/llkeyboard.h @@ -63,14 +63,6 @@ class LLWindowCallbacks; class LLKeyboard { public: - typedef enum e_numpad_distinct - { - ND_NEVER, - ND_NUMLOCK_OFF, - ND_NUMLOCK_ON - } ENumpadDistinct; - -public: LLKeyboard(); virtual ~LLKeyboard(); @@ -107,8 +99,6 @@ public: static BOOL keyFromString(const std::string& str, KEY *key); // False on failure static std::string stringFromKey(KEY key); static std::string stringFromAccelerator( MASK accel_mask, KEY key ); - e_numpad_distinct getNumpadDistinct() { return mNumpadDistinct; } - void setNumpadDistinct(e_numpad_distinct val) { mNumpadDistinct = val; } void setCallbacks(LLWindowCallbacks *cbs) { mCallbacks = cbs; } F32 getKeyElapsedTime( KEY key ); // Returns time in seconds since key was pressed. @@ -135,8 +125,6 @@ protected: static LLKeyStringTranslatorFunc* mStringTranslator; // Used for l10n + PC/Mac/Linux accelerator labeling - e_numpad_distinct mNumpadDistinct; - EKeyboardInsertMode mInsertMode; static std::map<KEY,std::string> sKeysToNames; diff --git a/indra/llwindow/llkeyboardmacosx.cpp b/indra/llwindow/llkeyboardmacosx.cpp index ecc2631669..7f8f303517 100644 --- a/indra/llwindow/llkeyboardmacosx.cpp +++ b/indra/llwindow/llkeyboardmacosx.cpp @@ -299,28 +299,11 @@ void LLKeyboardMacOSX::scanKeyboard() BOOL LLKeyboardMacOSX::translateNumpadKey( const U16 os_key, KEY *translated_key ) { - if(mNumpadDistinct == ND_NUMLOCK_ON) - { - std::map<U16, KEY>::iterator iter= mTranslateNumpadMap.find(os_key); - if(iter != mTranslateNumpadMap.end()) - { - *translated_key = iter->second; - return TRUE; - } - } return translateKey(os_key, translated_key); } U16 LLKeyboardMacOSX::inverseTranslateNumpadKey(const KEY translated_key) { - if(mNumpadDistinct == ND_NUMLOCK_ON) - { - std::map<KEY, U16>::iterator iter= mInvTranslateNumpadMap.find(translated_key); - if(iter != mInvTranslateNumpadMap.end()) - { - return iter->second; - } - } return inverseTranslateKey(translated_key); } diff --git a/indra/llwindow/llkeyboardsdl.cpp b/indra/llwindow/llkeyboardsdl.cpp index 4bb9603368..7c9aa1d340 100644 --- a/indra/llwindow/llkeyboardsdl.cpp +++ b/indra/llwindow/llkeyboardsdl.cpp @@ -312,29 +312,11 @@ void LLKeyboardSDL::scanKeyboard() BOOL LLKeyboardSDL::translateNumpadKey( const U16 os_key, KEY *translated_key) { - if(mNumpadDistinct == ND_NUMLOCK_ON) - { - std::map<U16, KEY>::iterator iter= mTranslateNumpadMap.find(os_key); - if(iter != mTranslateNumpadMap.end()) - { - *translated_key = iter->second; - return TRUE; - } - } - BOOL success = translateKey(os_key, translated_key); - return success; + return translateKey(os_key, translated_key); } U16 LLKeyboardSDL::inverseTranslateNumpadKey(const KEY translated_key) { - if(mNumpadDistinct == ND_NUMLOCK_ON) - { - std::map<KEY, U16>::iterator iter= mInvTranslateNumpadMap.find(translated_key); - if(iter != mInvTranslateNumpadMap.end()) - { - return iter->second; - } - } return inverseTranslateKey(translated_key); } diff --git a/indra/llwindow/llkeyboardwin32.cpp b/indra/llwindow/llkeyboardwin32.cpp index df78816bd6..be3fe5deb0 100644 --- a/indra/llwindow/llkeyboardwin32.cpp +++ b/indra/llwindow/llkeyboardwin32.cpp @@ -299,69 +299,13 @@ void LLKeyboardWin32::scanKeyboard() BOOL LLKeyboardWin32::translateExtendedKey(const U16 os_key, const MASK mask, KEY *translated_key) { - if(mNumpadDistinct == ND_NUMLOCK_ON) - { - std::map<U16, KEY>::iterator iter = mTranslateNumpadMap.find(os_key); - if (iter != mTranslateNumpadMap.end()) - { - *translated_key = iter->second; - return TRUE; - } - } - - BOOL success = translateKey(os_key, translated_key); - if(mNumpadDistinct != ND_NEVER) { - if(!success) return success; - if(mask & MASK_EXTENDED) - { - // this is where we'd create new keycodes for extended keys - // the set of extended keys includes the 'normal' arrow keys and - // the pgup/dn/insert/home/end/delete cluster above the arrow keys - // see http://windowssdk.msdn.microsoft.com/en-us/library/ms646280.aspx - - // only process the return key if numlock is off - if(((mNumpadDistinct == ND_NUMLOCK_OFF && - !(GetKeyState(VK_NUMLOCK) & 1)) - || mNumpadDistinct == ND_NUMLOCK_ON) && - *translated_key == KEY_RETURN) { - *translated_key = KEY_PAD_RETURN; - } - } - else - { - // the non-extended keys, those are in the numpad - switch (*translated_key) - { - case KEY_LEFT: - *translated_key = KEY_PAD_LEFT; break; - case KEY_RIGHT: - *translated_key = KEY_PAD_RIGHT; break; - case KEY_UP: - *translated_key = KEY_PAD_UP; break; - case KEY_DOWN: - *translated_key = KEY_PAD_DOWN; break; - case KEY_HOME: - *translated_key = KEY_PAD_HOME; break; - case KEY_END: - *translated_key = KEY_PAD_END; break; - case KEY_PAGE_UP: - *translated_key = KEY_PAD_PGUP; break; - case KEY_PAGE_DOWN: - *translated_key = KEY_PAD_PGDN; break; - case KEY_INSERT: - *translated_key = KEY_PAD_INS; break; - case KEY_DELETE: - *translated_key = KEY_PAD_DEL; break; - } - } - } - return success; + return translateKey(os_key, translated_key); } U16 LLKeyboardWin32::inverseTranslateExtendedKey(const KEY translated_key) { // if numlock is on, then we need to translate KEY_PAD_FOO to the corresponding number pad number - if((mNumpadDistinct == ND_NUMLOCK_ON) && (GetKeyState(VK_NUMLOCK) & 1)) + if(GetKeyState(VK_NUMLOCK) & 1) { std::map<KEY, U16>::iterator iter = mInvTranslateNumpadMap.find(translated_key); if (iter != mInvTranslateNumpadMap.end()) diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index be0f8bc7af..9a4dd41c4e 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -367,6 +367,10 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks, U32 fsaa_samples) : LLWindow(callbacks, fullscreen, flags) { + + //MAINT-516 -- force a load of opengl32.dll just in case windows went sideways + LoadLibrary(L"opengl32.dll"); + mFSAASamples = fsaa_samples; mIconResource = gIconResource; mOverrideAspectRatio = 0.f; diff --git a/indra/llxml/llcontrol.cpp b/indra/llxml/llcontrol.cpp index 0809d95628..53d9380f4f 100644 --- a/indra/llxml/llcontrol.cpp +++ b/indra/llxml/llcontrol.cpp @@ -201,7 +201,8 @@ void LLControlVariable::setValue(const LLSD& new_value, bool saved_value) } LLSD storable_value = getComparableValue(new_value); - bool value_changed = llsd_compare(getValue(), storable_value) == FALSE; + LLSD original_value = getValue(); + bool value_changed = llsd_compare(original_value, storable_value) == FALSE; if(saved_value) { // If we're going to save this value, return to default but don't fire @@ -237,7 +238,7 @@ void LLControlVariable::setValue(const LLSD& new_value, bool saved_value) if(value_changed) { - mCommitSignal(this, storable_value); + firePropertyChanged(original_value); } } @@ -249,12 +250,13 @@ void LLControlVariable::setDefaultValue(const LLSD& value) // *NOTE: Default values are not saved, only read. LLSD comparable_value = getComparableValue(value); - bool value_changed = (llsd_compare(getValue(), comparable_value) == FALSE); + LLSD original_value = getValue(); + bool value_changed = (llsd_compare(original_value, comparable_value) == FALSE); resetToDefault(false); mValues[0] = comparable_value; if(value_changed) { - firePropertyChanged(); + firePropertyChanged(original_value); } } @@ -277,6 +279,8 @@ void LLControlVariable::resetToDefault(bool fire_signal) { //The first setting is always the default //Pop to it and fire off the listener + LLSD originalValue = mValues.back(); + while(mValues.size() > 1) { mValues.pop_back(); @@ -284,7 +288,7 @@ void LLControlVariable::resetToDefault(bool fire_signal) if(fire_signal) { - firePropertyChanged(); + firePropertyChanged(originalValue); } } diff --git a/indra/llxml/llcontrol.h b/indra/llxml/llcontrol.h index 597031ec70..9a3a40e476 100644 --- a/indra/llxml/llcontrol.h +++ b/indra/llxml/llcontrol.h @@ -98,7 +98,7 @@ class LLControlVariable : public LLRefCount public: typedef boost::signals2::signal<bool(LLControlVariable* control, const LLSD&), boost_boolean_combiner> validate_signal_t; - typedef boost::signals2::signal<void(LLControlVariable* control, const LLSD&)> commit_signal_t; + typedef boost::signals2::signal<void(LLControlVariable* control, const LLSD&, const LLSD&)> commit_signal_t; private: std::string mName; @@ -146,11 +146,11 @@ public: void setHiddenFromSettingsEditor(bool hide); void setComment(const std::string& comment); - void firePropertyChanged() +private: + void firePropertyChanged(const LLSD &pPreviousValue) { - mCommitSignal(this, mValues.back()); + mCommitSignal(this, mValues.back(), pPreviousValue); } -private: LLSD getComparableValue(const LLSD& value); bool llsd_compare(const LLSD& a, const LLSD & b); }; diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index b5c64925c6..753dbd7438 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) @@ -73,6 +74,7 @@ include_directories( ${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 ) @@ -99,6 +101,7 @@ set(viewer_SOURCE_FILES llassetuploadresponders.cpp llattachmentsmgr.cpp llaudiosourcevo.cpp + llautoreplace.cpp llavataractions.cpp llavatariconctrl.cpp llavatarlist.cpp @@ -170,6 +173,7 @@ set(viewer_SOURCE_FILES llfloaterabout.cpp llfloaterbvhpreview.cpp llfloaterauction.cpp + llfloaterautoreplacesettings.cpp llfloateravatar.cpp llfloateravatarpicker.cpp llfloateravatartextures.cpp @@ -213,7 +217,6 @@ set(viewer_SOURCE_FILES llfloatermemleak.cpp llfloatermodelpreview.cpp llfloatermodeluploadbase.cpp - llfloatermodelwizard.cpp llfloaternamedesc.cpp llfloaternotificationsconsole.cpp llfloaterobjectweights.cpp @@ -239,6 +242,7 @@ set(viewer_SOURCE_FILES llfloatersidepanelcontainer.cpp llfloatersnapshot.cpp llfloatersounddevices.cpp + llfloaterspellchecksettings.cpp llfloatertelehub.cpp llfloatertestinspectors.cpp llfloatertestlistview.cpp @@ -673,6 +677,7 @@ set(viewer_HEADER_FILES llassetuploadresponders.h llattachmentsmgr.h llaudiosourcevo.h + llautoreplace.h llavataractions.h llavatariconctrl.h llavatarlist.h @@ -744,6 +749,7 @@ set(viewer_HEADER_FILES llfloaterabout.h llfloaterbvhpreview.h llfloaterauction.h + llfloaterautoreplacesettings.h llfloateravatar.h llfloateravatarpicker.h llfloateravatartextures.h @@ -787,7 +793,6 @@ set(viewer_HEADER_FILES llfloatermemleak.h llfloatermodelpreview.h llfloatermodeluploadbase.h - llfloatermodelwizard.h llfloaternamedesc.h llfloaternotificationsconsole.h llfloaterobjectweights.h @@ -813,6 +818,7 @@ set(viewer_HEADER_FILES llfloatersidepanelcontainer.h llfloatersnapshot.h llfloatersounddevices.h + llfloaterspellchecksettings.h llfloatertelehub.h llfloatertestinspectors.h llfloatertestlistview.h @@ -1555,9 +1561,7 @@ set(PACKAGE ON CACHE BOOL if (WINDOWS) set_target_properties(${VIEWER_BINARY_NAME} PROPERTIES - # *TODO -reenable this once we get server usage sorted out - #LINK_FLAGS "/debug /NODEFAULTLIB:LIBCMT /SUBSYSTEM:WINDOWS /INCLUDE:\"__tcmalloc\"" - LINK_FLAGS "/debug /NODEFAULTLIB:LIBCMT /SUBSYSTEM:WINDOWS /INCLUDE:__tcmalloc " + LINK_FLAGS "/debug /NODEFAULTLIB:LIBCMT /SUBSYSTEM:WINDOWS ${TCMALLOC_LINK_FLAGS}" LINK_FLAGS_DEBUG "/NODEFAULTLIB:\"LIBCMT;LIBCMTD;MSVCRT\" /INCREMENTAL:NO" LINK_FLAGS_RELEASE "/FORCE:MULTIPLE /MAP\"secondlife-bin.MAP\" /OPT:REF" ) @@ -1576,7 +1580,7 @@ if (WINDOWS) # In the meantime, if you have any ideas on how to easily maintain one list, either here or in viewer_manifest.py # and have the build deps get tracked *please* tell me about it. - if(USE_GOOGLE_PERFTOOLS) + if(USE_TCMALLOC) # Configure a var for tcmalloc location, if used. # Note the need to specify multiple names explicitly. set(GOOGLE_PERF_TOOLS_SOURCE @@ -1584,7 +1588,7 @@ if (WINDOWS) ${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/libtcmalloc_minimal.dll ${SHARED_LIB_STAGING_DIR}/Debug/libtcmalloc_minimal-debug.dll ) - endif(USE_GOOGLE_PERFTOOLS) + endif(USE_TCMALLOC) set(COPY_INPUT_DEPENDENCIES @@ -1614,6 +1618,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 @@ -1803,6 +1810,7 @@ target_link_libraries(${VIEWER_BINARY_NAME} ${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/settings.xml b/indra/newview/app_settings/settings.xml index 0f3ae89fa8..2af71d98b8 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -148,7 +148,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> @@ -335,6 +335,17 @@ <key>Value</key> <integer>1</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> @@ -4293,6 +4304,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> @@ -6356,17 +6378,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> @@ -7274,7 +7285,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> @@ -8093,6 +8104,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> @@ -9172,7 +9195,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> @@ -9180,7 +9203,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> @@ -10863,7 +10898,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> @@ -12227,6 +12263,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> @@ -12260,6 +12307,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> @@ -13886,39 +13955,6 @@ <real>2.3</real> </map> - <key>PathfindingDisablePermanentObjects</key> - <map> - <key>Comment</key> - <string>Disables the viewer from seeing the permanent object flag. Useful for testing server-side enforcement of permanent object rules.</string> - <key>Persist</key> - <integer>0</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>0</integer> - </map> - <key>PathfindingDisableCharacterObjects</key> - <map> - <key>Comment</key> - <string>Disables the viewer from seeing the character object flag. Useful for testing server-side enforcement of character object rules.</string> - <key>Persist</key> - <integer>0</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>0</integer> - </map> - <key>PathfindingEnableAlwaysAllowRebakeNavMesh</key> - <map> - <key>Comment</key> - <string>Always allows the rebake navmesh button to appear on dirty regions, regardless of whether the user has permissions.</string> - <key>Persist</key> - <integer>0</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>0</integer> - </map> <key>PathfindingWaterColor</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/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/interface/pathfindingF.glsl b/indra/newview/app_settings/shaders/class1/interface/pathfindingF.glsl index 40605bee78..7379360e17 100644 --- a/indra/newview/app_settings/shaders/class1/interface/pathfindingF.glsl +++ b/indra/newview/app_settings/shaders/class1/interface/pathfindingF.glsl @@ -24,12 +24,14 @@ */ #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif VARYING vec4 vertex_color; void main() { - gl_FragColor = vertex_color; + frag_color = vertex_color; } 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/alphaNonIndexedNoColorF.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaNonIndexedNoColorF.glsl index ba6f3ace53..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; @@ -97,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) @@ -164,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/featuretable.txt b/indra/newview/featuretable.txt index e8a109e661..eeb632acaf 100644 --- a/indra/newview/featuretable.txt +++ b/indra/newview/featuretable.txt @@ -520,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_xp.txt b/indra/newview/featuretable_xp.txt index 398a64378e..a945f7a693 100644 --- a/indra/newview/featuretable_xp.txt +++ b/indra/newview/featuretable_xp.txt @@ -517,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/llagent.cpp b/indra/newview/llagent.cpp index cf6b0e1562..447836910d 100755 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -82,6 +82,7 @@ #include "llviewermenu.h" #include "llviewerobjectlist.h" #include "llviewerparcelmgr.h" +#include "llviewerregion.h" #include "llviewerstats.h" #include "llviewerwindow.h" #include "llvoavatarself.h" @@ -113,6 +114,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 // @@ -247,6 +347,17 @@ LLAgent::LLAgent() : mGodLevelChangeSignal(), 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), @@ -332,9 +443,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; } @@ -344,6 +467,14 @@ void LLAgent::init() void LLAgent::cleanup() { mRegionp = NULL; + if (mTeleportFinishedSlot.connected()) + { + mTeleportFinishedSlot.disconnect(); + } + if (mTeleportFailedSlot.connected()) + { + mTeleportFailedSlot.disconnect(); + } } //----------------------------------------------------------------------------- @@ -2375,49 +2506,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 @@ -2446,11 +2806,6 @@ LLAgent::god_level_change_slot_t LLAgent::registerGodLevelChanageListener(god_le return mGodLevelChangeSignal.connect(pGodLevelChangeCallback); } -void LLAgent::setAOTransition() -{ - mAgentAccess->setTransition(); -} - const LLAgentAccess& LLAgent::getAgentAccess() { return *mAgentAccess; @@ -2461,9 +2816,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())); } //---------------------------------------------------------------------------- @@ -3398,7 +3753,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; @@ -3476,6 +3831,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, @@ -3508,6 +3959,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()) { @@ -3523,6 +3980,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()) { @@ -3554,24 +4017,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); @@ -3614,6 +4086,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); @@ -4055,5 +4533,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 72f695d917..99904e118c 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; @@ -660,13 +699,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/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index faadfb4b87..6d67e098a6 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -229,12 +229,13 @@ LLUpdateAppearanceOnDestroy::LLUpdateAppearanceOnDestroy(bool update_base_outfit LLUpdateAppearanceOnDestroy::~LLUpdateAppearanceOnDestroy() { - LL_INFOS("Avatar") << self_av_string() << "done update appearance on destroy" << LL_ENDL; - - selfStopPhase("update_appearance_on_destroy"); - 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); } } diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 95f030b0cf..63737c78d0 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -89,11 +89,13 @@ #include "lllogininstance.h" #include "llprogressview.h" #include "llvocache.h" +#include "llvopartgroup.h" #include "llweb.h" #include "llsecondlifeurls.h" #include "llupdaterservice.h" #include "llcallfloater.h" #include "llfloatertexturefetchdebugger.h" +#include "llspellcheck.h" // Linden library includes #include "llavatarnamecache.h" @@ -118,6 +120,7 @@ // Third party library includes #include <boost/bind.hpp> #include <boost/foreach.hpp> +#include <boost/algorithm/string.hpp> @@ -626,6 +629,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), @@ -676,6 +680,9 @@ bool LLAppViewer::init() // initialize SSE options LLVector4a::initClass(); + //initialize particle index pool + LLVOPartGroup::initClass(); + // Need to do this initialization before we do anything else, since anything // that touches files should really go through the lldir API gDirUtilp->initAppDirs("SecondLife"); @@ -1163,6 +1170,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"); @@ -1348,6 +1357,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); } @@ -1800,6 +1810,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); @@ -2554,6 +2571,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. @@ -5013,6 +5043,10 @@ void LLAppViewer::handleLoginComplete() mOnLoginCompleted(); writeDebugInfo(); + + // 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 f7d019ccba..ae3c795d1e 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -247,6 +247,7 @@ private: bool mPurgeOnExit; bool mSavedFinalSnapshot; + bool mSavePerAccountSettings; // only save per account settings if login succeeded bool mForceGraphicsDetail; diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index bad60a9757..53c77fa22e 100644 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -130,6 +130,8 @@ int APIENTRY WINMAIN(HINSTANCE hInstance, // This results in a 2-3x improvement in opening a new Inventory window (which uses a large numebr of allocations) // Note: This won't work when running from the debugger unless the _NO_DEBUG_HEAP environment variable is set to 1 + // Enable to get mem debugging within visual studio. + //_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); _CrtSetDbgFlag(0); // default, just making explicit ULONG ulEnableLFH = 2; 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/llchathistory.cpp b/indra/newview/llchathistory.cpp index f530d10ddc..84e73e96fa 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -495,7 +495,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) { @@ -689,8 +689,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(); llassert(mEditor); @@ -783,7 +786,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL timestamp_style.color(timestamp_color); timestamp_style.readonly_color(timestamp_color); } - mEditor->appendText("[" + chat.mTimeStr + "] ", mEditor->getText().size() != 0, timestamp_style); + mEditor->appendText("[" + chat.mTimeStr + "] ", mEditor->getLength() != 0, timestamp_style); if (utf8str_trim(chat.mFromName).size() != 0) { @@ -842,7 +845,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL else { view = getHeader(chat, style_params, args); - if (mEditor->getText().size() == 0) + if (mEditor->getLength() == 0) p.top_pad = 0; else p.top_pad = mTopHeaderPad; diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp index 21b21c152a..89a2e9f407 100644 --- a/indra/newview/lldrawable.cpp +++ b/indra/newview/lldrawable.cpp @@ -57,6 +57,8 @@ const F32 MIN_SHADOW_CASTER_RADIUS = 2.0f; static LLFastTimer::DeclareTimer FTM_CULL_REBOUND("Cull Rebound"); +extern bool gShiftFrame; + //////////////////////// // @@ -108,6 +110,8 @@ void LLDrawable::init() mGeneration = -1; mBinRadius = 1.f; + mBinIndex = -1; + mSpatialBridge = NULL; } @@ -450,7 +454,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 +542,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 +553,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 +582,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 +608,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 +667,6 @@ BOOL LLDrawable::updateMoveUndamped() } mVObjp->clearChanged(LLXform::MOVED); - return TRUE; } @@ -703,6 +718,11 @@ void LLDrawable::updateDistance(LLCamera& camera, bool force_update) return; } + if (gShiftFrame) + { + return; + } + //switch LOD with the spatial group to avoid artifacts //LLSpatialGroup* sg = getSpatialGroup(); @@ -727,7 +747,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 +792,6 @@ void LLDrawable::updateTexture() if (getVOVolume()) { - /*if (isActive()) - { - if (isRoot()) - { - mQuietCount = 0; - } - else - { - getParent()->mQuietCount = 0; - } - }*/ - gPipeline.markRebuild(this, LLDrawable::REBUILD_MATERIAL, TRUE); } } @@ -811,14 +820,19 @@ void LLDrawable::shiftPos(const LLVector4a &shift_vector) mXform.setPosition(mVObjp->getPositionAgent()); } - mXform.setRotation(mVObjp->getRotation()); - mXform.setScale(1,1,1); mXform.updateMatrix(); if (isStatic()) { LLVOVolume* volume = getVOVolume(); - if (!volume) + + bool rebuild = (!volume && + getRenderType() != LLPipeline::RENDER_TYPE_TREE && + getRenderType() != LLPipeline::RENDER_TYPE_TERRAIN && + getRenderType() != LLPipeline::RENDER_TYPE_SKY && + getRenderType() != LLPipeline::RENDER_TYPE_GROUND); + + if (rebuild) { gPipeline.markRebuild(this, LLDrawable::REBUILD_ALL, TRUE); } @@ -826,13 +840,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 (rebuild && facep->hasGeometry()) + { + facep->clearVertexBuffer(); + } } } @@ -940,6 +957,12 @@ void LLDrawable::updateUVMinMax() { } +LLSpatialGroup* LLDrawable::getSpatialGroup() const +{ + llassert((mSpatialGroupp == NULL) ? getBinIndex() == -1 : getBinIndex() != -1); + return mSpatialGroupp; +} + void LLDrawable::setSpatialGroup(LLSpatialGroup *groupp) { /*if (mSpatialGroupp && (groupp != mSpatialGroupp)) @@ -954,11 +977,16 @@ void LLDrawable::setSpatialGroup(LLSpatialGroup *groupp) for (S32 i = 0; i < getNumFaces(); ++i) { LLFace* facep = getFace(i); - facep->clearVertexBuffer(); + if (facep) + { + facep->clearVertexBuffer(); + } } } mSpatialGroupp = groupp; + + llassert((mSpatialGroupp == NULL) ? getBinIndex() == -1 : getBinIndex() != -1); } LLSpatialPartition* LLDrawable::getSpatialPartition() @@ -1081,6 +1109,8 @@ LLSpatialBridge::LLSpatialBridge(LLDrawable* root, BOOL render_by_group, U32 dat mDrawable = root; root->setSpatialBridge(this); + mBinIndex = -1; + mRenderType = mDrawable->mRenderType; mDrawableType = mDrawable->mRenderType; @@ -1384,6 +1414,11 @@ void LLSpatialBridge::updateDistance(LLCamera& camera_in, bool force_update) markDead(); return; } + + if (gShiftFrame) + { + return; + } if (mDrawable->getVObj()) { @@ -1462,7 +1497,13 @@ void LLSpatialBridge::cleanupReferences() LLDrawable::cleanupReferences(); if (mDrawable) { - mDrawable->setSpatialGroup(NULL); + LLSpatialGroup* group = mDrawable->getSpatialGroup(); + if (group) + { + group->mOctreeNode->remove(mDrawable); + mDrawable->setSpatialGroup(NULL); + } + if (mDrawable->getVObj()) { LLViewerObject::const_child_list_t& child_list = mDrawable->getVObj()->getChildren(); @@ -1473,7 +1514,12 @@ void LLSpatialBridge::cleanupReferences() LLDrawable* drawable = child->mDrawable; if (drawable) { - drawable->setSpatialGroup(NULL); + LLSpatialGroup* group = drawable->getSpatialGroup(); + if (group) + { + group->mOctreeNode->remove(drawable); + drawable->setSpatialGroup(NULL); + } } } } @@ -1529,10 +1575,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..960c64fa9e 100644 --- a/indra/newview/lldrawable.h +++ b/indra/newview/lldrawable.h @@ -59,6 +59,7 @@ class LLViewerTexture; const U32 SILHOUETTE_HIGHLIGHT = 0; // All data for new renderer goes into this class. +LL_ALIGN_PREFIX(16) class LLDrawable : public LLRefCount { public: @@ -75,6 +76,16 @@ public: static void initClass(); + void* operator new(size_t size) + { + return ll_aligned_malloc_16(size); + } + + void operator delete(void* ptr) + { + ll_aligned_free_16(ptr); + } + LLDrawable() { init(); } MEM_TYPE_NEW(LLMemType::MTYPE_DRAWABLE); @@ -109,6 +120,9 @@ public: F32 getIntensity() const { return llmin(mXform.getScale().mV[0], 4.f); } S32 getLOD() const { return mVObjp ? mVObjp->getLOD() : 1; } F32 getBinRadius() const { return mBinRadius; } + S32 getBinIndex() const { return mBinIndex; } + void setBinIndex(S32 index) const { mBinIndex = index; } + void getMinMax(LLVector3& min,LLVector3& max) const { mXform.getMinMax(min,max); } LLXformMatrix* getXform() { return &mXform; } @@ -194,7 +208,7 @@ public: S32 findReferences(LLDrawable *drawablep); // Not const because of @#$! iterators... void setSpatialGroup(LLSpatialGroup *groupp); - LLSpatialGroup *getSpatialGroup() const { return mSpatialGroupp; } + LLSpatialGroup *getSpatialGroup() const; LLSpatialPartition* getSpatialPartition(); // Statics @@ -277,11 +291,12 @@ public: HAS_ALPHA = 0x04000000, RIGGED = 0x08000000, PARTITION_MOVE = 0x10000000, + ANIMATED_CHILD = 0x20000000, } EDrawableFlags; private: //aligned members - LLVector4a mExtents[2]; - LLVector4a mPositionGroup; + LL_ALIGN_16(LLVector4a mExtents[2]); + LL_ALIGN_16(LLVector4a mPositionGroup); public: LLXformMatrix mXform; @@ -314,6 +329,7 @@ private: mutable U32 mVisible; F32 mRadius; F32 mBinRadius; + mutable S32 mBinIndex; S32 mGeneration; LLVector3 mCurrentScale; @@ -322,7 +338,7 @@ private: static U32 sNumZombieDrawables; static LLDynamicArrayPtr<LLPointer<LLDrawable> > sDeadList; -}; +} LL_ALIGN_POSTFIX(16); inline LLFace* LLDrawable::getFace(const S32 i) const @@ -333,12 +349,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/lldrawpool.cpp b/indra/newview/lldrawpool.cpp index 81f4e3d48f..013c698445 100644 --- a/indra/newview/lldrawpool.cpp +++ b/indra/newview/lldrawpool.cpp @@ -254,48 +254,6 @@ void LLFacePool::dirtyTextures(const std::set<LLViewerFetchedTexture*>& textures { } -// static -S32 LLFacePool::drawLoop(face_array_t& face_list) -{ - S32 res = 0; - if (!face_list.empty()) - { - for (std::vector<LLFace*>::iterator iter = face_list.begin(); - iter != face_list.end(); iter++) - { - LLFace *facep = *iter; - res += facep->renderIndexed(); - } - } - return res; -} - -// static -S32 LLFacePool::drawLoopSetTex(face_array_t& face_list, S32 stage) -{ - S32 res = 0; - if (!face_list.empty()) - { - for (std::vector<LLFace*>::iterator iter = face_list.begin(); - iter != face_list.end(); iter++) - { - LLFace *facep = *iter; - gGL.getTexUnit(stage)->bind(facep->getTexture(), TRUE) ; - gGL.getTexUnit(0)->activate(); - res += facep->renderIndexed(); - } - } - return res; -} - -void LLFacePool::drawLoop() -{ - if (!mDrawFace.empty()) - { - drawLoop(mDrawFace); - } -} - void LLFacePool::enqueue(LLFace* facep) { mDrawFace.push_back(facep); @@ -443,7 +401,7 @@ void LLRenderPass::renderTexture(U32 type, U32 mask) void LLRenderPass::pushBatches(U32 type, U32 mask, BOOL texture, BOOL batch_textures) { - for (LLCullResult::drawinfo_list_t::iterator i = gPipeline.beginRenderMap(type); i != gPipeline.endRenderMap(type); ++i) + for (LLCullResult::drawinfo_iterator i = gPipeline.beginRenderMap(type); i != gPipeline.endRenderMap(type); ++i) { LLDrawInfo* pparams = *i; if (pparams) diff --git a/indra/newview/lldrawpool.h b/indra/newview/lldrawpool.h index 977acf7aec..ab9bb9e611 100644 --- a/indra/newview/lldrawpool.h +++ b/indra/newview/lldrawpool.h @@ -190,10 +190,6 @@ public: void buildEdges(); - static S32 drawLoop(face_array_t& face_list); - static S32 drawLoopSetTex(face_array_t& face_list, S32 stage); - void drawLoop(); - void addFaceReference(LLFace *facep); void removeFaceReference(LLFace *facep); diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp index 5b62dbc560..b4f6bf9383 100644 --- a/indra/newview/lldrawpoolalpha.cpp +++ b/indra/newview/lldrawpoolalpha.cpp @@ -348,7 +348,7 @@ void LLDrawPoolAlpha::render(S32 pass) void LLDrawPoolAlpha::renderAlphaHighlight(U32 mask) { - for (LLCullResult::sg_list_t::iterator i = gPipeline.beginAlphaGroups(); i != gPipeline.endAlphaGroups(); ++i) + for (LLCullResult::sg_iterator i = gPipeline.beginAlphaGroups(); i != gPipeline.endAlphaGroups(); ++i) { LLSpatialGroup* group = *i; if (group->mSpatialPartition->mRenderByGroup && @@ -385,7 +385,7 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask) BOOL use_shaders = gPipeline.canUseVertexShaders(); - for (LLCullResult::sg_list_t::iterator i = gPipeline.beginAlphaGroups(); i != gPipeline.endAlphaGroups(); ++i) + for (LLCullResult::sg_iterator i = gPipeline.beginAlphaGroups(); i != gPipeline.endAlphaGroups(); ++i) { LLSpatialGroup* group = *i; llassert(group); @@ -405,6 +405,18 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask) { LLDrawInfo& params = **k; + if ((params.mVertexBuffer->getTypeMask() & mask) != mask) + { //FIXME! + llwarns << "Missing required components, skipping render batch." << llendl; + continue; + } + + 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..730ad1a364 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); } @@ -1034,9 +1036,13 @@ void LLDrawPoolAvatar::endDeferredSkinned() gGL.getTexUnit(0)->activate(); } +static LLFastTimer::DeclareTimer FTM_RENDER_AVATARS("renderAvatars"); + void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass) { + LLFastTimer t(FTM_RENDER_AVATARS); + if (pass == -1) { for (S32 i = 1; i < getNumPasses(); i++) @@ -1193,15 +1199,6 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass) if (pass >= 7 && pass < 9) { - LLGLEnable blend(GL_BLEND); - - gGL.setColorMask(true, true); - gGL.blendFunc(LLRender::BF_SOURCE_ALPHA, - LLRender::BF_ONE_MINUS_SOURCE_ALPHA, - LLRender::BF_ZERO, - LLRender::BF_ONE_MINUS_SOURCE_ALPHA); - - if (pass == 7) { renderRiggedAlpha(avatarp); @@ -1217,20 +1214,8 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass) if (pass == 9) { - LLGLEnable blend(GL_BLEND); - LLGLDisable test(GL_ALPHA_TEST); - gGL.flush(); - - LLGLEnable polyOffset(GL_POLYGON_OFFSET_FILL); - glPolygonOffset(-1.0f, -1.0f); - gGL.setSceneBlendType(LLRender::BT_ADD); - - LLGLDepthTest depth(GL_TRUE, GL_FALSE); - gGL.setColorMask(false, true); - renderRiggedGlow(avatarp); - gGL.setColorMask(true, false); - gGL.setSceneBlendType(LLRender::BT_ALPHA); + return; } @@ -1428,7 +1413,7 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace* void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow) { - if (avatar->isSelf() && !gAgent.needsRenderAvatar() || !gMeshRepo.meshRezEnabled()) + if (avatar->isSelf() && !gAgent.needsRenderAvatar()) { return; } @@ -1557,8 +1542,12 @@ void LLDrawPoolAvatar::renderDeferredRiggedBump(LLVOAvatar* avatar) renderRigged(avatar, RIGGED_DEFERRED_BUMP); } +static LLFastTimer::DeclareTimer FTM_RIGGED_VBO("Rigged VBO"); + void LLDrawPoolAvatar::updateRiggedVertexBuffers(LLVOAvatar* avatar) { + LLFastTimer t(FTM_RIGGED_VBO); + //update rigged vertex buffers for (U32 type = 0; type < NUM_RIGGED_PASSES; ++type) { @@ -1630,17 +1619,56 @@ void LLDrawPoolAvatar::renderRiggedFullbrightShiny(LLVOAvatar* avatar) void LLDrawPoolAvatar::renderRiggedAlpha(LLVOAvatar* avatar) { - renderRigged(avatar, RIGGED_ALPHA); + if (!mRiggedFace[RIGGED_ALPHA].empty()) + { + LLGLEnable blend(GL_BLEND); + + gGL.setColorMask(true, true); + gGL.blendFunc(LLRender::BF_SOURCE_ALPHA, + LLRender::BF_ONE_MINUS_SOURCE_ALPHA, + LLRender::BF_ZERO, + LLRender::BF_ONE_MINUS_SOURCE_ALPHA); + + renderRigged(avatar, RIGGED_ALPHA); + } } void LLDrawPoolAvatar::renderRiggedFullbrightAlpha(LLVOAvatar* avatar) { - renderRigged(avatar, RIGGED_FULLBRIGHT_ALPHA); + if (!mRiggedFace[RIGGED_FULLBRIGHT_ALPHA].empty()) + { + LLGLEnable blend(GL_BLEND); + + gGL.setColorMask(true, true); + gGL.blendFunc(LLRender::BF_SOURCE_ALPHA, + LLRender::BF_ONE_MINUS_SOURCE_ALPHA, + LLRender::BF_ZERO, + LLRender::BF_ONE_MINUS_SOURCE_ALPHA); + + renderRigged(avatar, RIGGED_FULLBRIGHT_ALPHA); + } } void LLDrawPoolAvatar::renderRiggedGlow(LLVOAvatar* avatar) { - renderRigged(avatar, RIGGED_GLOW, true); + if (!mRiggedFace[RIGGED_GLOW].empty()) + { + LLGLEnable blend(GL_BLEND); + LLGLDisable test(GL_ALPHA_TEST); + gGL.flush(); + + LLGLEnable polyOffset(GL_POLYGON_OFFSET_FILL); + glPolygonOffset(-1.0f, -1.0f); + gGL.setSceneBlendType(LLRender::BT_ADD); + + LLGLDepthTest depth(GL_TRUE, GL_FALSE); + gGL.setColorMask(false, true); + + renderRigged(avatar, RIGGED_GLOW, true); + + gGL.setColorMask(true, false); + gGL.setSceneBlendType(LLRender::BT_ALPHA); + } } diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp index 6f71e6ebc8..a264eae302 100644 --- a/indra/newview/lldrawpoolbump.cpp +++ b/indra/newview/lldrawpoolbump.cpp @@ -847,12 +847,12 @@ void LLDrawPoolBump::renderDeferred(S32 pass) LLFastTimer ftm(FTM_RENDER_BUMP); U32 type = LLRenderPass::PASS_BUMP; - LLCullResult::drawinfo_list_t::iterator begin = gPipeline.beginRenderMap(type); - LLCullResult::drawinfo_list_t::iterator end = gPipeline.endRenderMap(type); + LLCullResult::drawinfo_iterator begin = gPipeline.beginRenderMap(type); + LLCullResult::drawinfo_iterator end = gPipeline.endRenderMap(type); U32 mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_BINORMAL | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_COLOR; - for (LLCullResult::drawinfo_list_t::iterator i = begin; i != end; ++i) + for (LLCullResult::drawinfo_iterator i = begin; i != end; ++i) { LLDrawInfo& params = **i; @@ -1448,10 +1448,10 @@ void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerTexture *src_vi, LLI void LLDrawPoolBump::renderBump(U32 type, U32 mask) { - LLCullResult::drawinfo_list_t::iterator begin = gPipeline.beginRenderMap(type); - LLCullResult::drawinfo_list_t::iterator end = gPipeline.endRenderMap(type); + LLCullResult::drawinfo_iterator begin = gPipeline.beginRenderMap(type); + LLCullResult::drawinfo_iterator end = gPipeline.endRenderMap(type); - for (LLCullResult::drawinfo_list_t::iterator i = begin; i != end; ++i) + for (LLCullResult::drawinfo_iterator i = begin; i != end; ++i) { LLDrawInfo& params = **i; diff --git a/indra/newview/lldrawpoolterrain.cpp b/indra/newview/lldrawpoolterrain.cpp index b95d8296fa..7fc78fb382 100644 --- a/indra/newview/lldrawpoolterrain.cpp +++ b/indra/newview/lldrawpoolterrain.cpp @@ -294,6 +294,34 @@ void LLDrawPoolTerrain::renderShadow(S32 pass) //glCullFace(GL_BACK); } + +void LLDrawPoolTerrain::drawLoop() +{ + if (!mDrawFace.empty()) + { + for (std::vector<LLFace*>::iterator iter = mDrawFace.begin(); + iter != mDrawFace.end(); iter++) + { + LLFace *facep = *iter; + + LLMatrix4* model_matrix = &(facep->getDrawable()->getRegion()->mRenderMatrix); + + if (model_matrix != gGLLastMatrix) + { + gGLLastMatrix = model_matrix; + gGL.loadMatrix(gGLModelView); + if (model_matrix) + { + gGL.multMatrix((GLfloat*) model_matrix->mMatrix); + } + gPipeline.mMatrixOpCount++; + } + + facep->renderIndexed(); + } + } +} + void LLDrawPoolTerrain::renderFullShader() { // Hack! Get the region that this draw pool is rendering from! diff --git a/indra/newview/lldrawpoolterrain.h b/indra/newview/lldrawpoolterrain.h index 283ed87f1a..2163d087e1 100644 --- a/indra/newview/lldrawpoolterrain.h +++ b/indra/newview/lldrawpoolterrain.h @@ -83,6 +83,7 @@ protected: void renderFull2TU(); void renderFull4TU(); void renderFullShader(); + void drawLoop(); }; #endif // LL_LLDRAWPOOLSIMPLE_H diff --git a/indra/newview/lldrawpooltree.cpp b/indra/newview/lldrawpooltree.cpp index 3165a3516c..83f04e45a8 100644 --- a/indra/newview/lldrawpooltree.cpp +++ b/indra/newview/lldrawpooltree.cpp @@ -37,6 +37,7 @@ #include "llviewershadermgr.h" #include "llrender.h" #include "llviewercontrol.h" +#include "llviewerregion.h" S32 LLDrawPoolTree::sDiffTex = 0; static LLGLSLShader* shader = NULL; @@ -104,8 +105,22 @@ void LLDrawPoolTree::render(S32 pass) { LLFace *face = *iter; LLVertexBuffer* buff = face->getVertexBuffer(); + if(buff) { + LLMatrix4* model_matrix = &(face->getDrawable()->getRegion()->mRenderMatrix); + + if (model_matrix != gGLLastMatrix) + { + gGLLastMatrix = model_matrix; + gGL.loadMatrix(gGLModelView); + if (model_matrix) + { + gGL.multMatrix((GLfloat*) model_matrix->mMatrix); + } + gPipeline.mMatrixOpCount++; + } + buff->setBuffer(LLDrawPoolTree::VERTEX_DATA_MASK); buff->drawRange(LLRender::TRIANGLES, 0, buff->getNumVerts()-1, buff->getNumIndices(), 0); gPipeline.addTrianglesDrawn(buff->getNumIndices()); diff --git a/indra/newview/lldriverparam.cpp b/indra/newview/lldriverparam.cpp index 64eb11fc9b..885cae1737 100644 --- a/indra/newview/lldriverparam.cpp +++ b/indra/newview/lldriverparam.cpp @@ -155,6 +155,7 @@ LLDriverParam::LLDriverParam(LLVOAvatar *avatarp) : mAvatarp(avatarp), mWearablep(NULL) { + mDefaultVec.clear(); } LLDriverParam::LLDriverParam(LLWearable *wearablep) : @@ -162,6 +163,7 @@ LLDriverParam::LLDriverParam(LLWearable *wearablep) : mAvatarp(NULL), mWearablep(wearablep) { + mDefaultVec.clear(); } LLDriverParam::~LLDriverParam() @@ -341,18 +343,19 @@ F32 LLDriverParam::getTotalDistortion() return sum; } -const LLVector3 &LLDriverParam::getAvgDistortion() +const LLVector4a &LLDriverParam::getAvgDistortion() { // It's not actually correct to take the average of averages, but it good enough here. - LLVector3 sum; + LLVector4a sum; + sum.clear(); S32 count = 0; for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); iter++ ) { LLDrivenEntry* driven = &(*iter); - sum += driven->mParam->getAvgDistortion(); + sum.add(driven->mParam->getAvgDistortion()); count++; } - sum /= (F32)count; + sum.mul( 1.f/(F32)count); mDefaultVec = sum; return mDefaultVec; @@ -375,21 +378,22 @@ F32 LLDriverParam::getMaxDistortion() } -LLVector3 LLDriverParam::getVertexDistortion(S32 index, LLPolyMesh *poly_mesh) +LLVector4a LLDriverParam::getVertexDistortion(S32 index, LLPolyMesh *poly_mesh) { - LLVector3 sum; + LLVector4a sum; + sum.clear(); for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); iter++ ) { LLDrivenEntry* driven = &(*iter); - sum += driven->mParam->getVertexDistortion( index, poly_mesh ); + sum.add(driven->mParam->getVertexDistortion( index, poly_mesh )); } return sum; } -const LLVector3* LLDriverParam::getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh) +const LLVector4a* LLDriverParam::getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh) { mCurrentDistortionParam = NULL; - const LLVector3* v = NULL; + const LLVector4a* v = NULL; for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); iter++ ) { LLDrivenEntry* driven = &(*iter); @@ -404,7 +408,7 @@ const LLVector3* LLDriverParam::getFirstDistortion(U32 *index, LLPolyMesh **poly return v; }; -const LLVector3* LLDriverParam::getNextDistortion(U32 *index, LLPolyMesh **poly_mesh) +const LLVector4a* LLDriverParam::getNextDistortion(U32 *index, LLPolyMesh **poly_mesh) { llassert( mCurrentDistortionParam ); if( !mCurrentDistortionParam ) @@ -432,7 +436,7 @@ const LLVector3* LLDriverParam::getNextDistortion(U32 *index, LLPolyMesh **poly_ } // We're already in the middle of a param's distortions, so get the next one. - const LLVector3* v = driven->mParam->getNextDistortion( index, poly_mesh ); + const LLVector4a* v = driven->mParam->getNextDistortion( index, poly_mesh ); if( (!v) && (iter != mDriven.end()) ) { // This param is finished, so start the next param. It might not have any diff --git a/indra/newview/lldriverparam.h b/indra/newview/lldriverparam.h index fb1b44458c..7a4d711d4e 100644 --- a/indra/newview/lldriverparam.h +++ b/indra/newview/lldriverparam.h @@ -105,18 +105,18 @@ public: // LLViewerVisualParam Virtual functions /*virtual*/ F32 getTotalDistortion(); - /*virtual*/ const LLVector3& getAvgDistortion(); + /*virtual*/ const LLVector4a& getAvgDistortion(); /*virtual*/ F32 getMaxDistortion(); - /*virtual*/ LLVector3 getVertexDistortion(S32 index, LLPolyMesh *poly_mesh); - /*virtual*/ const LLVector3* getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh); - /*virtual*/ const LLVector3* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh); + /*virtual*/ LLVector4a getVertexDistortion(S32 index, LLPolyMesh *poly_mesh); + /*virtual*/ const LLVector4a* getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh); + /*virtual*/ const LLVector4a* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh); protected: F32 getDrivenWeight(const LLDrivenEntry* driven, F32 input_weight); void setDrivenWeight(LLDrivenEntry *driven, F32 driven_weight, bool upload_bake); - LLVector3 mDefaultVec; // temp holder + LLVector4a mDefaultVec; // temp holder typedef std::vector<LLDrivenEntry> entry_list_t; entry_list_t mDriven; LLViewerVisualParam* mCurrentDistortionParam; diff --git a/indra/newview/lldynamictexture.h b/indra/newview/lldynamictexture.h index e18090545d..c51e7d1e1a 100644 --- a/indra/newview/lldynamictexture.h +++ b/indra/newview/lldynamictexture.h @@ -36,6 +36,16 @@ class LLViewerDynamicTexture : public LLViewerTexture { public: + void* operator new(size_t size) + { + return ll_aligned_malloc_16(size); + } + + void operator delete(void* ptr) + { + ll_aligned_free_16(ptr); + } + enum { LL_VIEWER_DYNAMIC_TEXTURE = LLViewerTexture::DYNAMIC_TEXTURE, @@ -85,7 +95,7 @@ protected: protected: BOOL mClamp; LLCoordGL mOrigin; - LLCamera mCamera; + LL_ALIGN_16(LLCamera mCamera); typedef std::set<LLViewerDynamicTexture*> instance_list_t; static instance_list_t sInstances[ LLViewerDynamicTexture::ORDER_COUNT ]; diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index 4108d69e82..8d0664770b 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,8 +163,10 @@ void LLFace::init(LLDrawable* drawablep, LLViewerObject* objp) mGeomCount = 0; mGeomIndex = 0; mIndicesCount = 0; - mIndicesIndex = 0; - mIndexInTex = 0; + + //special value to indicate uninitialized position + mIndicesIndex = 0xFFFFFFFF; + mTexture = NULL; mTEOffset = -1; mTextureIndex = 255; @@ -177,12 +181,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 +201,12 @@ void LLFace::destroy() mTexture->removeFace(this) ; } + if (isState(LLFace::PARTICLE)) + { + LLVOPartGroup::freeVBSlot(getGeomIndex()/4); + clearState(LLFace::PARTICLE); + } + if (mDrawPoolp) { if (this->isState(LLFace::RIGGED) && mDrawPoolp->getType() == LLDrawPool::POOL_AVATAR) @@ -313,7 +317,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 +389,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 +781,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 +1042,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 +1087,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 +1171,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, @@ -1139,21 +1198,25 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, { if (num_indices + (S32) mIndicesIndex > mVertexBuffer->getNumIndices()) { - llwarns << "Index buffer overflow!" << llendl; - llwarns << "Indices Count: " << mIndicesCount - << " 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 - << " Pool Type: " << mPoolType << llendl; + if (gDebugGL) + { + llwarns << "Index buffer overflow!" << llendl; + llwarns << "Indices Count: " << mIndicesCount + << " VF Num Indices: " << num_indices + << " Indices Index: " << mIndicesIndex + << " VB Num Indices: " << mVertexBuffer->getNumIndices() << llendl; + llwarns << " Face Index: " << f + << " Pool Type: " << mPoolType << llendl; + } return FALSE; } if (num_vertices + mGeomIndex > mVertexBuffer->getNumVerts()) { - llwarns << "Vertex buffer overflow!" << llendl; + if (gDebugGL) + { + llwarns << "Vertex buffer overflow!" << llendl; + } return FALSE; } } @@ -1284,17 +1347,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 +1379,757 @@ 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; - bool do_bump = bump_code && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD1); - bool do_tex_mat = tex_mode && mTextureMatrix; + 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; - 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); + do_xform = false; + } - if (texgen != LLTextureEntry::TEX_GEN_PLANAR) - { - LLFastTimer t(FTM_FACE_TEX_QUICK); - if (!do_tex_mat) + if (getVirtualSize() >= MIN_TEX_ANIM_SIZE) + { //don't override texture transform during tc bake + tex_mode = 0; + } + } + + 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_NO_XFORM); - LLVector4a::memcpyNonAliased16((F32*) tex_coords.get(), (F32*) vf.mTexCoords, num_vertices*2*sizeof(F32)); - } - else + LLFastTimer t(FTM_FACE_TEX_QUICK); + if (!do_tex_mat) { - 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); + S32 tc_size = (num_vertices*2*sizeof(F32)+0xF) & ~0xF; + LLVector4a::memcpyNonAliased16((F32*) tex_coords.get(), (F32*) vf.mTexCoords, tc_size); + } + 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); - - LLVector4a* src = vf.mPositions; - volatile F32* dst = (volatile F32*) vert.get(); + LLMatrix4a mat_vert; + mat_vert.loadu(mat_vert_in); - volatile F32* end = dst+num_vertices*4; - LLVector4a res; + LLVector4a* src = vf.mPositions; + volatile F32* dst = (volatile F32*) vert.get(); - LLVector4a texIdx; + volatile F32* end = dst+num_vertices*4; + LLVector4a res; - U8 index = mTextureIndex < 255 ? mTextureIndex : 0; + LLVector4a texIdx; - F32 val = 0.f; - U8* vp = (U8*) &val; - vp[0] = index; - vp[1] = 0; - vp[2] = 0; - vp[3] = 0; + S32 index = mTextureIndex < 255 ? mTextureIndex : 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); - - { - LLFastTimer t(FTM_FACE_POSITION_STORE); - LLVector4a tmp; + texIdx.set(0,0,0,val); - 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) + { + --aligned_pad_vertices; + res.store4a((F32*) dst); + dst += 4; + } + } - while (aligned_pad_vertices > 0) + 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 +2146,6 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, } - mLastVertexBuffer = mVertexBuffer; - mLastGeomCount = mGeomCount; - mLastGeomIndex = mGeomIndex; - mLastIndicesCount = mIndicesCount; - mLastIndicesIndex = mIndicesIndex; - return TRUE; } @@ -2516,7 +2724,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..efc3424858 100644 --- a/indra/newview/llface.h +++ b/indra/newview/llface.h @@ -59,6 +59,17 @@ class LLFace { public: + void* operator new(size_t size) + { + return ll_aligned_malloc_16(size); + } + + void operator delete(void* ptr) + { + ll_aligned_free_16(ptr); + } + + LLFace(const LLFace& rhs) { *this = rhs; @@ -79,10 +90,13 @@ public: USE_FACE_COLOR = 0x0010, TEXTURE_ANIM = 0x0020, RIGGED = 0x0040, + PARTICLE = 0x0080, }; static void initClass(); + static void cacheFaceInVRAM(const LLVolumeFace& vf); + public: LLFace(LLDrawable* drawablep, LLViewerObject* objp) { init(drawablep, objp); } ~LLFace() { destroy(); } @@ -222,7 +236,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 +269,7 @@ public: private: LLPointer<LLVertexBuffer> mVertexBuffer; - LLPointer<LLVertexBuffer> mLastVertexBuffer; - + U32 mState; LLFacePool* mDrawPoolp; U32 mPoolType; @@ -269,12 +282,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 575b613ccf..4cbc9cab4a 100644 --- a/indra/newview/llfavoritesbar.cpp +++ b/indra/newview/llfavoritesbar.cpp @@ -1191,7 +1191,7 @@ void LLFavoritesBarCtrl::doToSelected(const LLSD& userdata) } else if (action == "paste") { - pastFromClipboard(); + pasteFromClipboard(); } else if (action == "delete") { @@ -1239,7 +1239,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 2f75b3bb0e..447d30f1f4 100644 --- a/indra/newview/llfavoritesbar.h +++ b/indra/newview/llfavoritesbar.h @@ -90,7 +90,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 ec2493dd2e..393f8b9d46 100644 --- a/indra/newview/llfeaturemanager.cpp +++ b/indra/newview/llfeaturemanager.cpp @@ -697,6 +697,7 @@ void LLFeatureManager::setGraphicsLevel(S32 level, bool skipFeatures) LLViewerShaderMgr::sSkipReload = false; LLViewerShaderMgr::instance()->setShaders(); + gPipeline.refreshCachedSettings(); } void LLFeatureManager::applyBaseMasks() 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..c4dca4cb79 100644 --- a/indra/newview/llflexibleobject.cpp +++ b/indra/newview/llflexibleobject.cpp @@ -65,7 +65,7 @@ LLVolumeImplFlexible::LLVolumeImplFlexible(LLViewerObject* vo, LLFlexibleObjectD mFrameNum = 0; mCollisionSphereRadius = 0.f; mRenderRes = 1; - + if(mVO->mDrawable.notNull()) { mVO->mDrawable->makeActive() ; @@ -255,50 +255,28 @@ void LLVolumeImplFlexible::onSetVolume(const LLVolumeParams &volume_params, cons { } -//--------------------------------------------------------------------------------- -// This calculates the physics of the flexible object. Note that it has to be 0 -// updated every time step. In the future, perhaps there could be an -// optimization similar to what Havok does for objects that are stationary. -//--------------------------------------------------------------------------------- -static LLFastTimer::DeclareTimer FTM_FLEXIBLE_UPDATE("Update Flexies"); -BOOL LLVolumeImplFlexible::doIdleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) -{ - if (mVO->mDrawable.isNull()) - { - // Don't do anything until we have a drawable - return FALSE; // (we are not initialized or updated) - } - - BOOL force_update = mSimulateRes == 0 ? TRUE : FALSE; - //flexible objects never go static - mVO->mDrawable->mQuietCount = 0; - if (!mVO->mDrawable->isRoot()) - { - LLViewerObject* parent = (LLViewerObject*) mVO->getParent(); - parent->mDrawable->mQuietCount = 0; - } +void LLVolumeImplFlexible::updateRenderRes() +{ + LLDrawable* drawablep = mVO->mDrawable; - LLFastTimer ftm(FTM_FLEXIBLE_UPDATE); - S32 new_res = mAttributes->getSimulateLOD(); - //number of segments only cares about z axis - F32 app_angle = llround((F32) atan2( mVO->getScale().mV[2]*2.f, mVO->mDrawable->mDistanceWRTCamera) * RAD_TO_DEG, 0.01f); +#if 1 //optimal approximation of previous behavior that doesn't rely on atan2 + F32 app_angle = mVO->getScale().mV[2]/drawablep->mDistanceWRTCamera; // Rendering sections increases with visible angle on the screen - mRenderRes = (S32)(FLEXIBLE_OBJECT_MAX_SECTIONS*4*app_angle*DEG_TO_RAD/LLViewerCamera::getInstance()->getView()); - if (mRenderRes > FLEXIBLE_OBJECT_MAX_SECTIONS) - { - mRenderRes = FLEXIBLE_OBJECT_MAX_SECTIONS; - } - + mRenderRes = (S32) (12.f*app_angle); +#else //legacy behavior + //number of segments only cares about z axis + F32 app_angle = llround((F32) atan2( mVO->getScale().mV[2]*2.f, drawablep->mDistanceWRTCamera) * RAD_TO_DEG, 0.01f); - // Bottom cap at 1/4 the original number of sections - if (mRenderRes < mAttributes->getSimulateLOD()-1) - { - mRenderRes = mAttributes->getSimulateLOD()-1; - } + // Rendering sections increases with visible angle on the screen + mRenderRes = (S32)(FLEXIBLE_OBJECT_MAX_SECTIONS*4*app_angle*DEG_TO_RAD/LLViewerCamera::getInstance()->getView()); +#endif + + mRenderRes = llclamp(mRenderRes, new_res-1, (S32) FLEXIBLE_OBJECT_MAX_SECTIONS); + // Throttle back simulation of segments we're not rendering if (mRenderRes < new_res) { @@ -311,43 +289,65 @@ BOOL LLVolumeImplFlexible::doIdleUpdate(LLAgent &agent, LLWorld &world, const F6 setAttributesOfAllSections(); mInitialized = TRUE; } - if (!gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_FLEXIBLE)) - { - return FALSE; // (we are not initialized or updated) - } - - bool visible = mVO->mDrawable->isVisible(); +} +//--------------------------------------------------------------------------------- +// This calculates the physics of the flexible object. Note that it has to be 0 +// updated every time step. In the future, perhaps there could be an +// optimization similar to what Havok does for objects that are stationary. +//--------------------------------------------------------------------------------- +static LLFastTimer::DeclareTimer FTM_FLEXIBLE_UPDATE("Update Flexies"); +void LLVolumeImplFlexible::doIdleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) +{ + LLDrawable* drawablep = mVO->mDrawable; - if (force_update && visible) + if (drawablep) { - gPipeline.markRebuild(mVO->mDrawable, LLDrawable::REBUILD_POSITION, FALSE); - } - else if (visible && - !mVO->mDrawable->isState(LLDrawable::IN_REBUILD_Q1) && - mVO->getPixelArea() > 256.f) - { - U32 id; - F32 pixel_area = mVO->getPixelArea(); + //LLFastTimer ftm(FTM_FLEXIBLE_UPDATE); - if (mVO->isRootEdit()) + //flexible objects never go static + drawablep->mQuietCount = 0; + if (!drawablep->isRoot()) { - id = mID; + LLViewerObject* parent = (LLViewerObject*) mVO->getParent(); + parent->mDrawable->mQuietCount = 0; } - else + + if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_FLEXIBLE)) { - LLVOVolume* parent = (LLVOVolume*) mVO->getParent(); - id = parent->getVolumeInterfaceID(); - } + bool visible = drawablep->isVisible(); - U32 update_period = (U32) (LLViewerCamera::getInstance()->getScreenPixelArea()*0.01f/(pixel_area*(sUpdateFactor+1.f)))+1; + if ((mSimulateRes == 0) && visible) + { + updateRenderRes(); + gPipeline.markRebuild(drawablep, LLDrawable::REBUILD_POSITION, FALSE); + } + else if (visible && + !drawablep->isState(LLDrawable::IN_REBUILD_Q1) && + mVO->getPixelArea() > 256.f) + { + U32 id; + F32 pixel_area = mVO->getPixelArea(); - if ((LLDrawable::getCurrentFrame()+id)%update_period == 0) - { - gPipeline.markRebuild(mVO->mDrawable, LLDrawable::REBUILD_POSITION, FALSE); + if (mVO->isRootEdit()) + { + id = mID; + } + else + { + LLVOVolume* parent = (LLVOVolume*) mVO->getParent(); + id = parent->getVolumeInterfaceID(); + } + + U32 update_period = (U32) (LLViewerCamera::getInstance()->getScreenPixelArea()*0.01f/(pixel_area*(sUpdateFactor+1.f)))+1; + + if ((LLDrawable::getCurrentFrame()+id)%update_period == 0) + { + updateRenderRes(); + gPipeline.markRebuild(drawablep, LLDrawable::REBUILD_POSITION, FALSE); + } + } } } - - return force_update; } inline S32 log2(S32 x) @@ -368,8 +368,10 @@ void LLVolumeImplFlexible::doFlexibleUpdate() LLPath *path = &volume->getPath(); if ((mSimulateRes == 0 || !mInitialized) && mVO->mDrawable->isVisible()) { - mVO->markForUpdate(TRUE); - if (!doIdleUpdate(gAgent, *LLWorld::getInstance(), 0.0)) + //mVO->markForUpdate(TRUE); + doIdleUpdate(gAgent, *LLWorld::getInstance(), 0.0); + + if (mSimulateRes == 0) { return; // we did not get updated or initialized, proceeding without can be dangerous } @@ -729,7 +731,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 +820,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..56d579d86f 100644 --- a/indra/newview/llflexibleobject.h +++ b/indra/newview/llflexibleobject.h @@ -78,7 +78,8 @@ class LLVolumeImplFlexible : public LLVolumeInterface LLVector3 getFramePosition() const; LLQuaternion getFrameRotation() const; LLVolumeInterfaceType getInterfaceType() const { return INTERFACE_FLEXIBLE; } - BOOL doIdleUpdate(LLAgent &agent, LLWorld &world, const F64 &time); + void updateRenderRes(); + void doIdleUpdate(LLAgent &agent, LLWorld &world, const F64 &time); BOOL doUpdateGeometry(LLDrawable *drawable); LLVector3 getPivotPosition() const; void onSetVolume(const LLVolumeParams &volume_params, const S32 detail); @@ -89,7 +90,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(); @@ -128,7 +129,7 @@ class LLVolumeImplFlexible : public LLVolumeInterface LLVector3 mCollisionSpherePosition; F32 mCollisionSphereRadius; U32 mID; - + //-------------------------------------- // private methods //-------------------------------------- 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/llfloaterbuycontents.cpp b/indra/newview/llfloaterbuycontents.cpp index bca4b5e447..809d344d01 100644 --- a/indra/newview/llfloaterbuycontents.cpp +++ b/indra/newview/llfloaterbuycontents.cpp @@ -211,8 +211,8 @@ void LLFloaterBuyContents::inventoryChanged(LLViewerObject* obj, BOOL item_is_multi = FALSE; if ((inv_item->getFlags() & LLInventoryItemFlags::II_FLAGS_LANDMARK_VISITED - || inv_item->getFlags() & LLInventoryItemFlags::II_FLAGS_OBJECT_HAS_MULTIPLE_ITEMS) - && !(inv_item->getFlags() & LLInventoryItemFlags::II_FLAGS_WEARABLES_MASK)) + || inv_item->getFlags() & LLInventoryItemFlags::II_FLAGS_OBJECT_HAS_MULTIPLE_ITEMS) + && !(inv_item->getFlags() & LLInventoryItemFlags::II_FLAGS_WEARABLES_MASK)) { item_is_multi = TRUE; } diff --git a/indra/newview/llfloaterbvhpreview.cpp b/indra/newview/llfloaterbvhpreview.cpp index ac33a05f42..fa0ad20fdb 100644 --- a/indra/newview/llfloaterbvhpreview.cpp +++ b/indra/newview/llfloaterbvhpreview.cpp @@ -1124,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/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..df8ecb6fd9 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 @@ -2226,8 +2212,8 @@ void LLPanelLandOptions::onCommitAny(LLUICtrl *ctrl, void *userdata) BOOL allow_damage = !self->mCheckSafe->get(); BOOL allow_fly = self->mCheckFly->get(); BOOL allow_landmark = TRUE; // cannot restrict landmark creation - BOOL allow_group_scripts = self->mCheckGroupScripts->get() || self->mCheckOtherScripts->get(); BOOL allow_other_scripts = self->mCheckOtherScripts->get(); + BOOL allow_group_scripts = self->mCheckGroupScripts->get() || allow_other_scripts; BOOL allow_publish = FALSE; BOOL mature_publish = self->mMatureCtrl->get(); BOOL push_restriction = self->mPushRestrictionCtrl->get(); @@ -2240,11 +2226,16 @@ void LLPanelLandOptions::onCommitAny(LLUICtrl *ctrl, void *userdata) LLViewerRegion* region; region = LLViewerParcelMgr::getInstance()->getSelectionRegion(); - if (!allow_other_scripts && region && region->getAllowDamage()) - { - - LLNotificationsUtil::add("UnableToDisableOutsideScripts"); - return; + if (region && region->getAllowDamage()) + { // Damage is allowed on the region - server will always allow scripts + if ( (!allow_other_scripts && parcel->getParcelFlag(PF_ALLOW_OTHER_SCRIPTS)) || + (!allow_group_scripts && parcel->getParcelFlag(PF_ALLOW_GROUP_SCRIPTS)) ) + { // Don't allow turning off "Run Scripts" if damage is allowed in the region + self->mCheckOtherScripts->set(parcel->getParcelFlag(PF_ALLOW_OTHER_SCRIPTS)); // Restore UI to actual settings + self->mCheckGroupScripts->set(parcel->getParcelFlag(PF_ALLOW_GROUP_SCRIPTS)); + LLNotificationsUtil::add("UnableToDisableOutsideScripts"); + return; + } } // Push data into current parcel diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp index 489f0eca9b..a071f338ba 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; } @@ -4780,7 +4774,8 @@ void LLModelPreview::genBuffers(S32 lod, bool include_skin_weights) if (vf.mTexCoords) { vb->getTexCoord0Strider(tc_strider); - LLVector4a::memcpyNonAliased16((F32*) tc_strider.get(), (F32*) vf.mTexCoords, num_vertices*2*sizeof(F32)); + S32 tex_size = (num_vertices*2*sizeof(F32)+0xF) & ~0xF; + LLVector4a::memcpyNonAliased16((F32*) tc_strider.get(), (F32*) vf.mTexCoords, tex_size); } if (vf.mNormals) @@ -5053,15 +5048,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(); @@ -5614,7 +5601,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/llfloaterpathfindingconsole.cpp b/indra/newview/llfloaterpathfindingconsole.cpp index 2fe60a8d8f..298454724b 100644 --- a/indra/newview/llfloaterpathfindingconsole.cpp +++ b/indra/newview/llfloaterpathfindingconsole.cpp @@ -53,6 +53,7 @@ #include "lltextbase.h" #include "lltoolmgr.h" #include "lltoolfocus.h" +#include "llviewercontrol.h" #include "llviewerparcelmgr.h" #include "pipeline.h" diff --git a/indra/newview/llfloaterpathfindinglinksets.cpp b/indra/newview/llfloaterpathfindinglinksets.cpp index bb0ac8f4b9..ecb68a786a 100644 --- a/indra/newview/llfloaterpathfindinglinksets.cpp +++ b/indra/newview/llfloaterpathfindinglinksets.cpp @@ -459,7 +459,6 @@ LLSD LLFloaterPathfindingLinksets::buildLinksetUseScrollListData(const std::stri LLSD columns; columns[0]["column"] = "name"; - columns[0]["relwidth"] = static_cast<LLSD::Real>(100.0f); columns[0]["value"] = pLabel; columns[0]["font"] = "SANSSERIF"; diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 4e962e085e..60556147a9 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 ); } @@ -435,6 +437,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(); @@ -604,6 +608,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) @@ -931,7 +938,6 @@ void LLFloaterPreference::refreshSkin(void* data) self->getChild<LLRadioGroup>("skin_selection", true)->setValue(sSkin); } - void LLFloaterPreference::buildPopupLists() { LLScrollListCtrl& disabled_popups = @@ -1515,6 +1521,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/llfolderview.cpp b/indra/newview/llfolderview.cpp index 1fa194ab19..7d047ec67e 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/newview/llfolderview.cpp @@ -562,7 +562,6 @@ void LLFolderView::reshape(S32 width, S32 height, BOOL called_from_parent) { width = scroll_rect.getWidth(); } - LLView::reshape(width, height, called_from_parent); mReshapeSignal(mSelectedItems, FALSE); } @@ -2236,12 +2235,16 @@ void LLFolderView::doIdle() arrangeAll(); } + mNeedsAutoSelect = mFilter->hasFilterString() && + !(gFocusMgr.childHasKeyboardFocus(this) || gFocusMgr.getMouseCapture()); + + if (mFilter->isModified() && mFilter->isNotDefault()) { mNeedsAutoSelect = TRUE; } mFilter->clearModified(); - + // filter to determine visibility before arranging filterFromRoot(); diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index f67464078b..63eedcdfea 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -56,7 +56,7 @@ #include "llrootview.h" #include "llspeakers.h" #include "llviewerchat.h" - +#include "llautoreplace.h" LLIMFloater::LLIMFloater(const LLUUID& session_id) : LLTransientDockableFloater(NULL, true, session_id), @@ -255,6 +255,8 @@ BOOL LLIMFloater::postBuild() mInputEditor->setMaxTextLength(1023); // enable line history support for instant message bar mInputEditor->setEnableLineHistory(TRUE); + // *TODO Establish LineEditor with autoreplace callback + mInputEditor->setAutoreplaceCallback(boost::bind(&LLAutoReplace::autoreplaceCallback, LLAutoReplace::getInstance(), _1, _2)); LLFontGL* font = LLViewerChat::getChatFont(); mInputEditor->setFont(font); diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 8092f3bf36..6e23d7c701 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) diff --git a/indra/newview/llmaniptranslate.cpp b/indra/newview/llmaniptranslate.cpp index 7a35562f86..10608463b4 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 @@ -1582,7 +1583,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) { @@ -1647,17 +1652,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); @@ -1668,6 +1684,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 @@ -1677,10 +1694,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); @@ -1731,6 +1750,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 1e1243c78a..0b009b68f7 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 c899e8991e..bc7f522848 100755 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -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/llnearbychatbar.cpp b/indra/newview/llnearbychatbar.cpp index 00ff81724c..f8f0f7d243 100644 --- a/indra/newview/llnearbychatbar.cpp +++ b/indra/newview/llnearbychatbar.cpp @@ -52,6 +52,7 @@ #include "lltranslate.h" #include "llresizehandle.h" +#include "llautoreplace.h" S32 LLNearbyChatBar::sLastSpecialChatChannel = 0; @@ -89,6 +90,7 @@ BOOL LLNearbyChatBar::postBuild() { mChatBox = getChild<LLLineEditor>("chat_box"); + mChatBox->setAutoreplaceCallback(boost::bind(&LLAutoReplace::autoreplaceCallback, LLAutoReplace::getInstance(), _1, _2)); mChatBox->setCommitCallback(boost::bind(&LLNearbyChatBar::onChatBoxCommit, this)); mChatBox->setKeystrokeCallback(&onChatBoxKeystroke, this); mChatBox->setFocusLostCallback(boost::bind(&onChatBoxFocusLost, _1, this)); diff --git a/indra/newview/llnotificationhandlerutil.cpp b/indra/newview/llnotificationhandlerutil.cpp index 7c6287967a..16c51138a9 100644 --- a/indra/newview/llnotificationhandlerutil.cpp +++ b/indra/newview/llnotificationhandlerutil.cpp @@ -128,6 +128,8 @@ const static std::string GRANTED_MODIFY_RIGHTS("GrantedModifyRights"), FRIEND_ONLINE("FriendOnline"), FRIEND_OFFLINE("FriendOffline"), SERVER_OBJECT_MESSAGE("ServerObjectMessage"), TELEPORT_OFFERED("TeleportOffered"), + TELEPORT_OFFERED_MATURITY_EXCEEDED("TeleportOffered_MaturityExceeded"), + TELEPORT_OFFERED_MATURITY_BLOCKED("TeleportOffered_MaturityBlocked"), TELEPORT_OFFER_SENT("TeleportOfferSent"), IM_SYSTEM_MESSAGE_TIP("IMSystemMessageTip"); @@ -149,6 +151,8 @@ bool LLHandlerUtil::canLogToIM(const LLNotificationPtr& notification) || INVENTORY_DECLINED == notification->getName() || USER_GIVE_ITEM == notification->getName() || TELEPORT_OFFERED == notification->getName() + || TELEPORT_OFFERED_MATURITY_EXCEEDED == notification->getName() + || TELEPORT_OFFERED_MATURITY_BLOCKED == notification->getName() || TELEPORT_OFFER_SENT == notification->getName() || IM_SYSTEM_MESSAGE_TIP == notification->getName(); } @@ -169,7 +173,9 @@ bool LLHandlerUtil::canSpawnIMSession(const LLNotificationPtr& notification) { return OFFER_FRIENDSHIP == notification->getName() || USER_GIVE_ITEM == notification->getName() - || TELEPORT_OFFERED == notification->getName(); + || TELEPORT_OFFERED == notification->getName() + || TELEPORT_OFFERED_MATURITY_EXCEEDED == notification->getName() + || TELEPORT_OFFERED_MATURITY_BLOCKED == notification->getName(); } // static @@ -177,7 +183,9 @@ bool LLHandlerUtil::canAddNotifPanelToIM(const LLNotificationPtr& notification) { return OFFER_FRIENDSHIP == notification->getName() || USER_GIVE_ITEM == notification->getName() - || TELEPORT_OFFERED == notification->getName(); + || TELEPORT_OFFERED == notification->getName() + || TELEPORT_OFFERED_MATURITY_EXCEEDED == notification->getName() + || TELEPORT_OFFERED_MATURITY_BLOCKED == notification->getName(); } // static @@ -185,7 +193,9 @@ bool LLHandlerUtil::isNotificationReusable(const LLNotificationPtr& notification { return OFFER_FRIENDSHIP == notification->getName() || USER_GIVE_ITEM == notification->getName() - || TELEPORT_OFFERED == notification->getName(); + || TELEPORT_OFFERED == notification->getName() + || TELEPORT_OFFERED_MATURITY_EXCEEDED == notification->getName() + || TELEPORT_OFFERED_MATURITY_BLOCKED == notification->getName(); } // static @@ -212,7 +222,9 @@ bool LLHandlerUtil::canSpawnToast(const LLNotificationPtr& notification) if(OFFER_FRIENDSHIP == notification->getName() || USER_GIVE_ITEM == notification->getName() - || TELEPORT_OFFERED == notification->getName()) + || TELEPORT_OFFERED == notification->getName() + || TELEPORT_OFFERED_MATURITY_EXCEEDED == notification->getName() + || TELEPORT_OFFERED_MATURITY_BLOCKED == notification->getName()) { // When ANY offer arrives, show toast, unless IM window is already open - EXT-5904 return ! isIMFloaterOpened(notification); 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 05d9a32108..202be9671b 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 068ccf23b5..d87b565b32 100644 --- a/indra/newview/llpanelobject.cpp +++ b/indra/newview/llpanelobject.cpp @@ -244,6 +244,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; @@ -515,9 +516,10 @@ void LLPanelObject::getState( ) mCheckTemporary->setEnabled( roots_selected>0 && editable && !is_permanent); mIsPhantom = root_objectp->flagPhantom(); + BOOL is_volume_detect = root_objectp->flagVolumeDetect(); llassert(!is_character || !mIsPhantom); // should never have a character that is also a phantom mCheckPhantom->set( mIsPhantom ); - mCheckPhantom->setEnabled( roots_selected>0 && editable && !is_flexible && !is_permanent_enforced && !is_character); + mCheckPhantom->setEnabled( roots_selected>0 && editable && !is_flexible && !is_permanent_enforced && !is_character && !is_volume_detect); //---------------------------------------------------------------------------- diff --git a/indra/newview/llpanelpathfindingrebakenavmesh.cpp b/indra/newview/llpanelpathfindingrebakenavmesh.cpp index 8df041f578..7efb1a9227 100644 --- a/indra/newview/llpanelpathfindingrebakenavmesh.cpp +++ b/indra/newview/llpanelpathfindingrebakenavmesh.cpp @@ -45,7 +45,6 @@ #include "lltoolbar.h" #include "lltoolbarview.h" #include "lltooltip.h" -#include "llviewercontrol.h" #include "llviewerregion.h" LLPanelPathfindingRebakeNavmesh* LLPanelPathfindingRebakeNavmesh::getInstance() @@ -239,7 +238,7 @@ void LLPanelPathfindingRebakeNavmesh::createNavMeshStatusListenerForCurrentRegio bool LLPanelPathfindingRebakeNavmesh::doDraw() const { - return ((mCanRebakeRegion || gSavedSettings.getBOOL("PathfindingEnableAlwaysAllowRebakeNavMesh")) && (mRebakeNavMeshMode != kRebakeNavMesh_NotAvailable)); + return (mCanRebakeRegion && (mRebakeNavMeshMode != kRebakeNavMesh_NotAvailable)); } void LLPanelPathfindingRebakeNavmesh::updatePosition() diff --git a/indra/newview/llpathfindingobject.cpp b/indra/newview/llpathfindingobject.cpp index c2f509c951..916eceb4c8 100644 --- a/indra/newview/llpathfindingobject.cpp +++ b/indra/newview/llpathfindingobject.cpp @@ -38,10 +38,11 @@ #include "lluuid.h" #include "v3math.h" -#define PATHFINDING_OBJECT_NAME_FIELD "name" -#define PATHFINDING_OBJECT_DESCRIPTION_FIELD "description" -#define PATHFINDING_OBJECT_OWNER_FIELD "owner" -#define PATHFINDING_OBJECT_POSITION_FIELD "position" +#define PATHFINDING_OBJECT_NAME_FIELD "name" +#define PATHFINDING_OBJECT_DESCRIPTION_FIELD "description" +#define PATHFINDING_OBJECT_OWNER_FIELD "owner" +#define PATHFINDING_OBJECT_POSITION_FIELD "position" +#define PATHFINDING_OBJECT_IS_GROUP_OWNED_FIELD "owner_is_group" //--------------------------------------------------------------------------- // LLPathfindingObject @@ -54,6 +55,7 @@ LLPathfindingObject::LLPathfindingObject() mOwnerUUID(), mHasOwnerName(false), mOwnerName(), + mIsGroupOwned(false), mLocation() { } @@ -65,6 +67,7 @@ LLPathfindingObject::LLPathfindingObject(const std::string &pUUID, const LLSD &p mOwnerUUID(), mHasOwnerName(false), mOwnerName(), + mIsGroupOwned(false), mLocation() { parseObjectData(pObjectData); @@ -77,6 +80,7 @@ LLPathfindingObject::LLPathfindingObject(const LLPathfindingObject& pOther) mOwnerUUID(pOther.mOwnerUUID), mHasOwnerName(false), mOwnerName(), + mIsGroupOwned(pOther.mIsGroupOwned), mLocation(pOther.mLocation) { fetchOwnerName(); @@ -93,6 +97,7 @@ LLPathfindingObject &LLPathfindingObject::operator =(const LLPathfindingObject& mDescription = pOther.mDescription; mOwnerUUID = pOther.mOwnerUUID; fetchOwnerName(); + mIsGroupOwned = pOther.mIsGroupOwned; mLocation = pOther.mLocation; return *this; @@ -125,6 +130,12 @@ void LLPathfindingObject::parseObjectData(const LLSD &pObjectData) mOwnerUUID = pObjectData.get(PATHFINDING_OBJECT_OWNER_FIELD).asUUID(); fetchOwnerName(); + if (pObjectData.has(PATHFINDING_OBJECT_IS_GROUP_OWNED_FIELD)) + { + llassert(pObjectData.get(PATHFINDING_OBJECT_IS_GROUP_OWNED_FIELD).isBoolean()); + mIsGroupOwned = pObjectData.get(PATHFINDING_OBJECT_IS_GROUP_OWNED_FIELD).asBoolean(); + } + llassert(pObjectData.has(PATHFINDING_OBJECT_POSITION_FIELD)); llassert(pObjectData.get(PATHFINDING_OBJECT_POSITION_FIELD).isArray()); mLocation.setValue(pObjectData.get(PATHFINDING_OBJECT_POSITION_FIELD)); @@ -135,7 +146,11 @@ void LLPathfindingObject::fetchOwnerName() mHasOwnerName = false; if (hasOwner()) { - LLAvatarNameCache::get(mOwnerUUID, boost::bind(&LLPathfindingObject::handleAvatarNameFetch, this, _1, _2)); + mHasOwnerName = LLAvatarNameCache::get(mOwnerUUID, &mOwnerName); + if (!mHasOwnerName) + { + LLAvatarNameCache::get(mOwnerUUID, boost::bind(&LLPathfindingObject::handleAvatarNameFetch, this, _1, _2)); + } } } diff --git a/indra/newview/llpathfindingobject.h b/indra/newview/llpathfindingobject.h index 4b2d546bb1..d45cc554fd 100644 --- a/indra/newview/llpathfindingobject.h +++ b/indra/newview/llpathfindingobject.h @@ -56,6 +56,7 @@ public: inline BOOL hasOwner() const {return mOwnerUUID.notNull();}; inline bool hasOwnerName() const {return mHasOwnerName;}; std::string getOwnerName() const; + inline BOOL isGroupOwned() const {return mIsGroupOwned;}; inline const LLVector3& getLocation() const {return mLocation;}; protected: @@ -72,6 +73,7 @@ private: LLUUID mOwnerUUID; bool mHasOwnerName; LLAvatarName mOwnerName; + BOOL mIsGroupOwned; LLVector3 mLocation; }; diff --git a/indra/newview/llphysicsmotion.cpp b/indra/newview/llphysicsmotion.cpp index e124916c48..cb6989c9dd 100644 --- a/indra/newview/llphysicsmotion.cpp +++ b/indra/newview/llphysicsmotion.cpp @@ -67,6 +67,19 @@ inline F64 llsgn(const F64 a) class LLPhysicsMotion { public: + typedef enum + { + SMOOTHING = 0, + MASS, + GRAVITY, + SPRING, + GAIN, + DAMPING, + DRAG, + MAX_EFFECT, + NUM_PARAMS + } eParamName; + /* param_driver_name: The param that controls the params that are being affected by the physics. joint_name: The joint that the body part is attached to. The joint is @@ -98,6 +111,11 @@ public: mPositionLastUpdate_local(0) { mJointState = new LLJointState; + + for (U32 i = 0; i < NUM_PARAMS; ++i) + { + mParamCache[i] = NULL; + } } BOOL initialize(); @@ -111,16 +129,43 @@ public: return mJointState; } protected: - F32 getParamValue(const std::string& controller_key) - { - const controller_map_t::const_iterator& entry = mParamControllers.find(controller_key); + + F32 getParamValue(eParamName param) + { + static std::string controller_key[] = + { + "Smoothing", + "Mass", + "Gravity", + "Spring", + "Gain", + "Damping", + "Drag", + "MaxEffect" + }; + + if (!mParamCache[param]) + { + const controller_map_t::const_iterator& entry = mParamControllers.find(controller_key[param]); if (entry == mParamControllers.end()) { - return sDefaultController[controller_key]; + return sDefaultController[controller_key[param]]; } const std::string& param_name = (*entry).second.c_str(); - return mCharacter->getVisualParamWeight(param_name.c_str()); - } + mParamCache[param] = mCharacter->getVisualParam(param_name.c_str()); + } + + if (mParamCache[param]) + { + return mParamCache[param]->getWeight(); + } + else + { + return sDefaultController[controller_key[param]]; + } + } + + void setParamValue(LLViewerVisualParam *param, const F32 new_value_local, F32 behavior_maxeffect); @@ -150,6 +195,8 @@ private: F32 mLastTime; + LLVisualParam* mParamCache[NUM_PARAMS]; + static default_controller_map_t sDefaultController; }; @@ -427,7 +474,6 @@ BOOL LLPhysicsMotionController::onUpdate(F32 time, U8* joint_mask) return TRUE; } - // Return TRUE if character has to update visual params. BOOL LLPhysicsMotion::onUpdate(F32 time) { @@ -471,15 +517,16 @@ BOOL LLPhysicsMotion::onUpdate(F32 time) LLJoint *joint = mJointState->getJoint(); - const F32 behavior_mass = getParamValue("Mass"); - const F32 behavior_gravity = getParamValue("Gravity"); - const F32 behavior_spring = getParamValue("Spring"); - const F32 behavior_gain = getParamValue("Gain"); - const F32 behavior_damping = getParamValue("Damping"); - const F32 behavior_drag = getParamValue("Drag"); - const BOOL physics_test = FALSE; // Enable this to simulate bouncing on all parts. + const F32 behavior_mass = getParamValue(MASS); + const F32 behavior_gravity = getParamValue(GRAVITY); + const F32 behavior_spring = getParamValue(SPRING); + const F32 behavior_gain = getParamValue(GAIN); + const F32 behavior_damping = getParamValue(DAMPING); + const F32 behavior_drag = getParamValue(DRAG); + F32 behavior_maxeffect = getParamValue(MAX_EFFECT); + + const BOOL physics_test = FALSE; // Enable this to simulate bouncing on all parts. - F32 behavior_maxeffect = getParamValue("MaxEffect"); if (physics_test) behavior_maxeffect = 1.0f; diff --git a/indra/newview/llpolymesh.cpp b/indra/newview/llpolymesh.cpp index 450f9b2be7..70f3b5335e 100644 --- a/indra/newview/llpolymesh.cpp +++ b/indra/newview/llpolymesh.cpp @@ -129,22 +129,22 @@ void LLPolyMeshSharedData::freeMeshData() { mNumVertices = 0; - delete [] mBaseCoords; + ll_aligned_free_16(mBaseCoords); mBaseCoords = NULL; - delete [] mBaseNormals; + ll_aligned_free_16(mBaseNormals); mBaseNormals = NULL; - delete [] mBaseBinormals; + ll_aligned_free_16(mBaseBinormals); mBaseBinormals = NULL; - delete [] mTexCoords; + ll_aligned_free_16(mTexCoords); mTexCoords = NULL; - delete [] mDetailTexCoords; + ll_aligned_free_16(mDetailTexCoords); mDetailTexCoords = NULL; - delete [] mWeights; + ll_aligned_free_16(mWeights); mWeights = NULL; } @@ -229,15 +229,19 @@ U32 LLPolyMeshSharedData::getNumKB() BOOL LLPolyMeshSharedData::allocateVertexData( U32 numVertices ) { U32 i; - mBaseCoords = new LLVector3[ numVertices ]; - mBaseNormals = new LLVector3[ numVertices ]; - mBaseBinormals = new LLVector3[ numVertices ]; - mTexCoords = new LLVector2[ numVertices ]; - mDetailTexCoords = new LLVector2[ numVertices ]; - mWeights = new F32[ numVertices ]; + mBaseCoords = (LLVector4a*) ll_aligned_malloc_16(numVertices*sizeof(LLVector4a)); + mBaseNormals = (LLVector4a*) ll_aligned_malloc_16(numVertices*sizeof(LLVector4a)); + mBaseBinormals = (LLVector4a*) ll_aligned_malloc_16(numVertices*sizeof(LLVector4a)); + mTexCoords = (LLVector2*) ll_aligned_malloc_16(numVertices*sizeof(LLVector2)); + mDetailTexCoords = (LLVector2*) ll_aligned_malloc_16(numVertices*sizeof(LLVector2)); + mWeights = (F32*) ll_aligned_malloc_16(numVertices*sizeof(F32)); for (i = 0; i < numVertices; i++) { - mWeights[i] = 0.f; + mBaseCoords[i].clear(); + mBaseNormals[i].clear(); + mBaseBinormals[i].clear(); + mTexCoords[i].clear(); + mWeights[i] = 0.f; } mNumVertices = numVertices; return TRUE; @@ -408,39 +412,47 @@ BOOL LLPolyMeshSharedData::loadMesh( const std::string& fileName ) allocateVertexData( numVertices ); - //---------------------------------------------------------------- - // Coords - //---------------------------------------------------------------- - numRead = fread(mBaseCoords, 3*sizeof(float), numVertices, fp); - llendianswizzle(mBaseCoords, sizeof(float), 3*numVertices); - if (numRead != numVertices) - { - llerrs << "can't read Coordinates from " << fileName << llendl; - return FALSE; - } - - //---------------------------------------------------------------- - // Normals - //---------------------------------------------------------------- - numRead = fread(mBaseNormals, 3*sizeof(float), numVertices, fp); - llendianswizzle(mBaseNormals, sizeof(float), 3*numVertices); - if (numRead != numVertices) - { - llerrs << " can't read Normals from " << fileName << llendl; - return FALSE; - } - - //---------------------------------------------------------------- - // Binormals - //---------------------------------------------------------------- - numRead = fread(mBaseBinormals, 3*sizeof(float), numVertices, fp); - llendianswizzle(mBaseBinormals, sizeof(float), 3*numVertices); - if (numRead != numVertices) - { - llerrs << " can't read Binormals from " << fileName << llendl; - return FALSE; - } - + for (U16 i = 0; i < numVertices; ++i) + { + //---------------------------------------------------------------- + // Coords + //---------------------------------------------------------------- + numRead = fread(&mBaseCoords[i], sizeof(float), 3, fp); + llendianswizzle(&mBaseCoords[i], sizeof(float), 3); + if (numRead != 3) + { + llerrs << "can't read Coordinates from " << fileName << llendl; + return FALSE; + } + } + + for (U16 i = 0; i < numVertices; ++i) + { + //---------------------------------------------------------------- + // Normals + //---------------------------------------------------------------- + numRead = fread(&mBaseNormals[i], sizeof(float), 3, fp); + llendianswizzle(&mBaseNormals[i], sizeof(float), 3); + if (numRead != 3) + { + llerrs << " can't read Normals from " << fileName << llendl; + return FALSE; + } + } + + for (U16 i = 0; i < numVertices; ++i) + { + //---------------------------------------------------------------- + // Binormals + //---------------------------------------------------------------- + numRead = fread(&mBaseBinormals[i], sizeof(float), 3, fp); + llendianswizzle(&mBaseBinormals[i], sizeof(float), 3); + if (numRead != 3) + { + llerrs << " can't read Binormals from " << fileName << llendl; + return FALSE; + } + } //---------------------------------------------------------------- // TexCoords @@ -767,21 +779,28 @@ LLPolyMesh::LLPolyMesh(LLPolyMeshSharedData *shared_data, LLPolyMesh *reference_ { // Allocate memory without initializing every vector // NOTE: This makes asusmptions about the size of LLVector[234] - int nverts = mSharedData->mNumVertices; - int nfloats = nverts * (2*4 + 3*3 + 2 + 4); + S32 nverts = mSharedData->mNumVertices; + //make sure it's an even number of verts for alignment + nverts += nverts%2; + S32 nfloats = nverts * ( + 4 + //coords + 4 + //normals + 4 + //weights + 2 + //coords + 4 + //scaled normals + 4 + //binormals + 4); //scaled binormals + //use 16 byte aligned vertex data to make LLPolyMesh SSE friendly mVertexData = (F32*) ll_aligned_malloc_16(nfloats*4); - int offset = 0; - mCoords = (LLVector4*)(mVertexData + offset); offset += 4*nverts; - mNormals = (LLVector4*)(mVertexData + offset); offset += 4*nverts; - mClothingWeights = (LLVector4*)(mVertexData + offset); offset += 4*nverts; - mTexCoords = (LLVector2*)(mVertexData + offset); offset += 2*nverts; - - // these members don't need to be 16-byte aligned, but the first one might be - // read during an aligned memcpy of mTexCoords - mScaledNormals = (LLVector3*)(mVertexData + offset); offset += 3*nverts; - mBinormals = (LLVector3*)(mVertexData + offset); offset += 3*nverts; - mScaledBinormals = (LLVector3*)(mVertexData + offset); offset += 3*nverts; + S32 offset = 0; + mCoords = (LLVector4a*)(mVertexData + offset); offset += 4*nverts; + mNormals = (LLVector4a*)(mVertexData + offset); offset += 4*nverts; + mClothingWeights = (LLVector4a*)(mVertexData + offset); offset += 4*nverts; + mTexCoords = (LLVector2*)(mVertexData + offset); offset += 2*nverts; + mScaledNormals = (LLVector4a*)(mVertexData + offset); offset += 4*nverts; + mBinormals = (LLVector4a*)(mVertexData + offset); offset += 4*nverts; + mScaledBinormals = (LLVector4a*)(mVertexData + offset); offset += 4*nverts; initializeForMorph(); } } @@ -906,7 +925,7 @@ void LLPolyMesh::dumpDiagInfo() //----------------------------------------------------------------------------- // getWritableCoords() //----------------------------------------------------------------------------- -LLVector4 *LLPolyMesh::getWritableCoords() +LLVector4a *LLPolyMesh::getWritableCoords() { return mCoords; } @@ -914,7 +933,7 @@ LLVector4 *LLPolyMesh::getWritableCoords() //----------------------------------------------------------------------------- // getWritableNormals() //----------------------------------------------------------------------------- -LLVector4 *LLPolyMesh::getWritableNormals() +LLVector4a *LLPolyMesh::getWritableNormals() { return mNormals; } @@ -922,7 +941,7 @@ LLVector4 *LLPolyMesh::getWritableNormals() //----------------------------------------------------------------------------- // getWritableBinormals() //----------------------------------------------------------------------------- -LLVector3 *LLPolyMesh::getWritableBinormals() +LLVector4a *LLPolyMesh::getWritableBinormals() { return mBinormals; } @@ -931,7 +950,7 @@ LLVector3 *LLPolyMesh::getWritableBinormals() //----------------------------------------------------------------------------- // getWritableClothingWeights() //----------------------------------------------------------------------------- -LLVector4 *LLPolyMesh::getWritableClothingWeights() +LLVector4a *LLPolyMesh::getWritableClothingWeights() { return mClothingWeights; } @@ -947,7 +966,7 @@ LLVector2 *LLPolyMesh::getWritableTexCoords() //----------------------------------------------------------------------------- // getScaledNormals() //----------------------------------------------------------------------------- -LLVector3 *LLPolyMesh::getScaledNormals() +LLVector4a *LLPolyMesh::getScaledNormals() { return mScaledNormals; } @@ -955,7 +974,7 @@ LLVector3 *LLPolyMesh::getScaledNormals() //----------------------------------------------------------------------------- // getScaledBinormals() //----------------------------------------------------------------------------- -LLVector3 *LLPolyMesh::getScaledBinormals() +LLVector4a *LLPolyMesh::getScaledBinormals() { return mScaledBinormals; } @@ -966,17 +985,17 @@ LLVector3 *LLPolyMesh::getScaledBinormals() //----------------------------------------------------------------------------- void LLPolyMesh::initializeForMorph() { - for (U32 i = 0; i < mSharedData->mNumVertices; ++i) + LLVector4a::memcpyNonAliased16((F32*) mCoords, (F32*) mSharedData->mBaseCoords, sizeof(LLVector4a) * mSharedData->mNumVertices); + LLVector4a::memcpyNonAliased16((F32*) mNormals, (F32*) mSharedData->mBaseNormals, sizeof(LLVector4a) * mSharedData->mNumVertices); + LLVector4a::memcpyNonAliased16((F32*) mScaledNormals, (F32*) mSharedData->mBaseNormals, sizeof(LLVector4a) * mSharedData->mNumVertices); + LLVector4a::memcpyNonAliased16((F32*) mBinormals, (F32*) mSharedData->mBaseNormals, sizeof(LLVector4a) * mSharedData->mNumVertices); + LLVector4a::memcpyNonAliased16((F32*) mScaledBinormals, (F32*) mSharedData->mBaseNormals, sizeof(LLVector4a) * mSharedData->mNumVertices); + LLVector4a::memcpyNonAliased16((F32*) mTexCoords, (F32*) mSharedData->mTexCoords, sizeof(LLVector2) * (mSharedData->mNumVertices + mSharedData->mNumVertices%2)); + + for (U32 i = 0; i < mSharedData->mNumVertices; ++i) { - mCoords[i] = LLVector4(mSharedData->mBaseCoords[i]); - mNormals[i] = LLVector4(mSharedData->mBaseNormals[i]); + mClothingWeights[i].clear(); } - - memcpy(mScaledNormals, mSharedData->mBaseNormals, sizeof(LLVector3) * mSharedData->mNumVertices); /*Flawfinder: ignore*/ - memcpy(mBinormals, mSharedData->mBaseBinormals, sizeof(LLVector3) * mSharedData->mNumVertices); /*Flawfinder: ignore*/ - memcpy(mScaledBinormals, mSharedData->mBaseBinormals, sizeof(LLVector3) * mSharedData->mNumVertices); /*Flawfinder: ignore*/ - memcpy(mTexCoords, mSharedData->mTexCoords, sizeof(LLVector2) * mSharedData->mNumVertices); /*Flawfinder: ignore*/ - memset(mClothingWeights, 0, sizeof(LLVector4) * mSharedData->mNumVertices); } //----------------------------------------------------------------------------- @@ -1098,7 +1117,7 @@ BOOL LLPolySkeletalDistortionInfo::parseXml(LLXmlTreeNode* node) LLPolySkeletalDistortion::LLPolySkeletalDistortion(LLVOAvatar *avatarp) { mAvatar = avatarp; - mDefaultVec.setVec(0.001f, 0.001f, 0.001f); + mDefaultVec.splat(0.001f); } //----------------------------------------------------------------------------- @@ -1171,8 +1190,12 @@ BOOL LLPolySkeletalDistortion::setInfo(LLPolySkeletalDistortionInfo *info) //----------------------------------------------------------------------------- // apply() //----------------------------------------------------------------------------- +static LLFastTimer::DeclareTimer FTM_POLYSKELETAL_DISTORTION_APPLY("Skeletal Distortion"); + void LLPolySkeletalDistortion::apply( ESex avatar_sex ) { + LLFastTimer t(FTM_POLYSKELETAL_DISTORTION_APPLY); + F32 effective_weight = ( getSex() & avatar_sex ) ? mCurWeight : getDefaultWeight(); LLJoint* joint; @@ -1228,11 +1251,14 @@ LLPolyMorphData *clone_morph_param_direction(const LLPolyMorphData *src_data, { LLPolyMorphData* cloned_morph_data = new LLPolyMorphData(*src_data); cloned_morph_data->mName = name; + LLVector4a dir; + dir.load3(direction.mV); + for (U32 v=0; v < cloned_morph_data->mNumIndices; v++) { - cloned_morph_data->mCoords[v] = direction; - cloned_morph_data->mNormals[v] = LLVector3(0,0,0); - cloned_morph_data->mBinormals[v] = LLVector3(0,0,0); + cloned_morph_data->mCoords[v] = dir; + cloned_morph_data->mNormals[v].clear(); + cloned_morph_data->mBinormals[v].clear(); } return cloned_morph_data; } @@ -1243,17 +1269,27 @@ LLPolyMorphData *clone_morph_param_cleavage(const LLPolyMorphData *src_data, { LLPolyMorphData* cloned_morph_data = new LLPolyMorphData(*src_data); cloned_morph_data->mName = name; + + LLVector4a sc; + sc.splat(scale); + + LLVector4a nsc; + nsc.set(scale, -scale, scale, scale); + for (U32 v=0; v < cloned_morph_data->mNumIndices; v++) { - cloned_morph_data->mCoords[v] = src_data->mCoords[v]*scale; - cloned_morph_data->mNormals[v] = src_data->mNormals[v]*scale; - cloned_morph_data->mBinormals[v] = src_data->mBinormals[v]*scale; - if (cloned_morph_data->mCoords[v][1] < 0) - { - cloned_morph_data->mCoords[v][1] *= -1; - cloned_morph_data->mNormals[v][1] *= -1; - cloned_morph_data->mBinormals[v][1] *= -1; - } + if (cloned_morph_data->mCoords[v][1] < 0) + { + cloned_morph_data->mCoords[v].setMul(src_data->mCoords[v],nsc); + cloned_morph_data->mNormals[v].setMul(src_data->mNormals[v],nsc); + cloned_morph_data->mBinormals[v].setMul(src_data->mBinormals[v],nsc); + } + else + { + cloned_morph_data->mCoords[v].setMul(src_data->mCoords[v],sc); + cloned_morph_data->mNormals[v].setMul(src_data->mNormals[v], sc); + cloned_morph_data->mBinormals[v].setMul(src_data->mBinormals[v],sc); + } } return cloned_morph_data; } diff --git a/indra/newview/llpolymesh.h b/indra/newview/llpolymesh.h index ba2bf85570..ffb11a3f7e 100644 --- a/indra/newview/llpolymesh.h +++ b/indra/newview/llpolymesh.h @@ -73,9 +73,9 @@ private: // vertex data S32 mNumVertices; - LLVector3 *mBaseCoords; - LLVector3 *mBaseNormals; - LLVector3 *mBaseBinormals; + LLVector4a *mBaseCoords; + LLVector4a *mBaseNormals; + LLVector4a *mBaseBinormals; LLVector2 *mTexCoords; LLVector2 *mDetailTexCoords; F32 *mWeights; @@ -217,41 +217,41 @@ public: } // Get coords - const LLVector4 *getCoords() const{ + const LLVector4a *getCoords() const{ return mCoords; } // non const version - LLVector4 *getWritableCoords(); + LLVector4a *getWritableCoords(); // Get normals - const LLVector4 *getNormals() const{ + const LLVector4a *getNormals() const{ return mNormals; } // Get normals - const LLVector3 *getBinormals() const{ + const LLVector4a *getBinormals() const{ return mBinormals; } // Get base mesh normals - const LLVector3 *getBaseNormals() const{ + const LLVector4a *getBaseNormals() const{ llassert(mSharedData); return mSharedData->mBaseNormals; } // Get base mesh normals - const LLVector3 *getBaseBinormals() const{ + const LLVector4a *getBaseBinormals() const{ llassert(mSharedData); return mSharedData->mBaseBinormals; } // intermediate morphed normals and output normals - LLVector4 *getWritableNormals(); - LLVector3 *getScaledNormals(); + LLVector4a *getWritableNormals(); + LLVector4a *getScaledNormals(); - LLVector3 *getWritableBinormals(); - LLVector3 *getScaledBinormals(); + LLVector4a *getWritableBinormals(); + LLVector4a *getScaledBinormals(); // Get texCoords const LLVector2 *getTexCoords() const { @@ -275,9 +275,9 @@ public: F32 *getWritableWeights() const; - LLVector4 *getWritableClothingWeights(); + LLVector4a *getWritableClothingWeights(); - const LLVector4 *getClothingWeights() + const LLVector4a *getClothingWeights() { return mClothingWeights; } @@ -341,17 +341,17 @@ protected: // Single array of floats for allocation / deletion F32 *mVertexData; // deformed vertices (resulting from application of morph targets) - LLVector4 *mCoords; + LLVector4a *mCoords; // deformed normals (resulting from application of morph targets) - LLVector3 *mScaledNormals; + LLVector4a *mScaledNormals; // output normals (after normalization) - LLVector4 *mNormals; + LLVector4a *mNormals; // deformed binormals (resulting from application of morph targets) - LLVector3 *mScaledBinormals; + LLVector4a *mScaledBinormals; // output binormals (after normalization) - LLVector3 *mBinormals; + LLVector4a *mBinormals; // weight values that mark verts as clothing/skin - LLVector4 *mClothingWeights; + LLVector4a *mClothingWeights; // output texture coordinates LLVector2 *mTexCoords; @@ -419,17 +419,17 @@ public: // LLViewerVisualParam Virtual functions /*virtual*/ F32 getTotalDistortion() { return 0.1f; } - /*virtual*/ const LLVector3& getAvgDistortion() { return mDefaultVec; } + /*virtual*/ const LLVector4a& getAvgDistortion() { return mDefaultVec; } /*virtual*/ F32 getMaxDistortion() { return 0.1f; } - /*virtual*/ LLVector3 getVertexDistortion(S32 index, LLPolyMesh *poly_mesh){return LLVector3(0.001f, 0.001f, 0.001f);} - /*virtual*/ const LLVector3* getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh){index = 0; poly_mesh = NULL; return &mDefaultVec;}; - /*virtual*/ const LLVector3* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh){index = 0; poly_mesh = NULL; return NULL;}; + /*virtual*/ LLVector4a getVertexDistortion(S32 index, LLPolyMesh *poly_mesh){return LLVector4a(0.001f, 0.001f, 0.001f);} + /*virtual*/ const LLVector4a* getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh){index = 0; poly_mesh = NULL; return &mDefaultVec;}; + /*virtual*/ const LLVector4a* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh){index = 0; poly_mesh = NULL; return NULL;}; protected: typedef std::map<LLJoint*, LLVector3> joint_vec_map_t; joint_vec_map_t mJointScales; joint_vec_map_t mJointOffsets; - LLVector3 mDefaultVec; + LLVector4a mDefaultVec; // Backlink only; don't make this an LLPointer. LLVOAvatar *mAvatar; }; diff --git a/indra/newview/llpolymorph.cpp b/indra/newview/llpolymorph.cpp index cefd7df3fe..d25d1420ee 100644 --- a/indra/newview/llpolymorph.cpp +++ b/indra/newview/llpolymorph.cpp @@ -48,7 +48,7 @@ LLPolyMorphData::LLPolyMorphData(const std::string& morph_name) mNumIndices = 0; mCurrentIndex = 0; mTotalDistortion = 0.f; - mAvgDistortion.zeroVec(); + mAvgDistortion.clear(); mMaxDistortion = 0.f; mVertexIndices = NULL; mCoords = NULL; @@ -73,9 +73,9 @@ LLPolyMorphData::LLPolyMorphData(const LLPolyMorphData &rhs) : { const S32 numVertices = mNumIndices; - mCoords = new LLVector3[numVertices]; - mNormals = new LLVector3[numVertices]; - mBinormals = new LLVector3[numVertices]; + mCoords = new LLVector4a[numVertices]; + mNormals = new LLVector4a[numVertices]; + mBinormals = new LLVector4a[numVertices]; mTexCoords = new LLVector2[numVertices]; mVertexIndices = new U32[numVertices]; @@ -121,16 +121,16 @@ BOOL LLPolyMorphData::loadBinary(LLFILE *fp, LLPolyMeshSharedData *mesh) //------------------------------------------------------------------------- // allocate vertices //------------------------------------------------------------------------- - mCoords = new LLVector3[numVertices]; - mNormals = new LLVector3[numVertices]; - mBinormals = new LLVector3[numVertices]; + mCoords = new LLVector4a[numVertices]; + mNormals = new LLVector4a[numVertices]; + mBinormals = new LLVector4a[numVertices]; mTexCoords = new LLVector2[numVertices]; // Actually, we are allocating more space than we need for the skiplist mVertexIndices = new U32[numVertices]; mNumIndices = 0; mTotalDistortion = 0.f; mMaxDistortion = 0.f; - mAvgDistortion.zeroVec(); + mAvgDistortion.clear(); mMesh = mesh; //------------------------------------------------------------------------- @@ -152,36 +152,36 @@ BOOL LLPolyMorphData::loadBinary(LLFILE *fp, LLPolyMeshSharedData *mesh) } - numRead = fread(&mCoords[v].mV, sizeof(F32), 3, fp); - llendianswizzle(&mCoords[v].mV, sizeof(F32), 3); + numRead = fread(&mCoords[v], sizeof(F32), 3, fp); + llendianswizzle(&mCoords[v], sizeof(F32), 3); if (numRead != 3) { llwarns << "Can't read morph target vertex coordinates" << llendl; return FALSE; } - F32 magnitude = mCoords[v].magVec(); + F32 magnitude = mCoords[v].getLength3().getF32(); mTotalDistortion += magnitude; - mAvgDistortion.mV[VX] += fabs(mCoords[v].mV[VX]); - mAvgDistortion.mV[VY] += fabs(mCoords[v].mV[VY]); - mAvgDistortion.mV[VZ] += fabs(mCoords[v].mV[VZ]); + LLVector4a t; + t.setAbs(mCoords[v]); + mAvgDistortion.add(t); if (magnitude > mMaxDistortion) { mMaxDistortion = magnitude; } - numRead = fread(&mNormals[v].mV, sizeof(F32), 3, fp); - llendianswizzle(&mNormals[v].mV, sizeof(F32), 3); + numRead = fread(&mNormals[v], sizeof(F32), 3, fp); + llendianswizzle(&mNormals[v], sizeof(F32), 3); if (numRead != 3) { llwarns << "Can't read morph target normal" << llendl; return FALSE; } - numRead = fread(&mBinormals[v].mV, sizeof(F32), 3, fp); - llendianswizzle(&mBinormals[v].mV, sizeof(F32), 3); + numRead = fread(&mBinormals[v], sizeof(F32), 3, fp); + llendianswizzle(&mBinormals[v], sizeof(F32), 3); if (numRead != 3) { llwarns << "Can't read morph target binormal" << llendl; @@ -200,8 +200,8 @@ BOOL LLPolyMorphData::loadBinary(LLFILE *fp, LLPolyMeshSharedData *mesh) mNumIndices++; } - mAvgDistortion = mAvgDistortion * (1.f/(F32)mNumIndices); - mAvgDistortion.normVec(); + mAvgDistortion.mul(1.f/(F32)mNumIndices); + mAvgDistortion.normalize3fast(); return TRUE; } @@ -367,9 +367,9 @@ BOOL LLPolyMorphTarget::parseData(LLXmlTreeNode* node) //----------------------------------------------------------------------------- // getVertexDistortion() //----------------------------------------------------------------------------- -LLVector3 LLPolyMorphTarget::getVertexDistortion(S32 requested_index, LLPolyMesh *mesh) +LLVector4a LLPolyMorphTarget::getVertexDistortion(S32 requested_index, LLPolyMesh *mesh) { - if (!mMorphData || mMesh != mesh) return LLVector3::zero; + if (!mMorphData || mMesh != mesh) return LLVector4a::getZero(); for(U32 index = 0; index < mMorphData->mNumIndices; index++) { @@ -379,17 +379,17 @@ LLVector3 LLPolyMorphTarget::getVertexDistortion(S32 requested_index, LLPolyMesh } } - return LLVector3::zero; + return LLVector4a::getZero(); } //----------------------------------------------------------------------------- // getFirstDistortion() //----------------------------------------------------------------------------- -const LLVector3 *LLPolyMorphTarget::getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh) +const LLVector4a *LLPolyMorphTarget::getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh) { - if (!mMorphData) return &LLVector3::zero; + if (!mMorphData) return &LLVector4a::getZero(); - LLVector3* resultVec; + LLVector4a* resultVec; mMorphData->mCurrentIndex = 0; if (mMorphData->mNumIndices) { @@ -411,11 +411,11 @@ const LLVector3 *LLPolyMorphTarget::getFirstDistortion(U32 *index, LLPolyMesh ** //----------------------------------------------------------------------------- // getNextDistortion() //----------------------------------------------------------------------------- -const LLVector3 *LLPolyMorphTarget::getNextDistortion(U32 *index, LLPolyMesh **poly_mesh) +const LLVector4a *LLPolyMorphTarget::getNextDistortion(U32 *index, LLPolyMesh **poly_mesh) { - if (!mMorphData) return &LLVector3::zero; + if (!mMorphData) return &LLVector4a::getZero(); - LLVector3* resultVec; + LLVector4a* resultVec; mMorphData->mCurrentIndex++; if (mMorphData->mCurrentIndex < mMorphData->mNumIndices) { @@ -451,7 +451,7 @@ F32 LLPolyMorphTarget::getTotalDistortion() //----------------------------------------------------------------------------- // getAvgDistortion() //----------------------------------------------------------------------------- -const LLVector3& LLPolyMorphTarget::getAvgDistortion() +const LLVector4a& LLPolyMorphTarget::getAvgDistortion() { if (mMorphData) { @@ -459,7 +459,7 @@ const LLVector3& LLPolyMorphTarget::getAvgDistortion() } else { - return LLVector3::zero; + return LLVector4a::getZero(); } } @@ -481,6 +481,8 @@ F32 LLPolyMorphTarget::getMaxDistortion() //----------------------------------------------------------------------------- // apply() //----------------------------------------------------------------------------- +static LLFastTimer::DeclareTimer FTM_APPLY_MORPH_TARGET("Apply Morph"); + void LLPolyMorphTarget::apply( ESex avatar_sex ) { if (!mMorphData || mNumMorphMasksPending > 0) @@ -488,6 +490,8 @@ void LLPolyMorphTarget::apply( ESex avatar_sex ) return; } + LLFastTimer t(FTM_APPLY_MORPH_TARGET); + mLastSex = avatar_sex; // Check for NaN condition (NaN is detected if a variable doesn't equal itself. @@ -508,15 +512,15 @@ void LLPolyMorphTarget::apply( ESex avatar_sex ) if (delta_weight != 0.f) { llassert(!mMesh->isLOD()); - LLVector4 *coords = mMesh->getWritableCoords(); + LLVector4a *coords = mMesh->getWritableCoords(); - LLVector3 *scaled_normals = mMesh->getScaledNormals(); - LLVector4 *normals = mMesh->getWritableNormals(); + LLVector4a *scaled_normals = mMesh->getScaledNormals(); + LLVector4a *normals = mMesh->getWritableNormals(); - LLVector3 *scaled_binormals = mMesh->getScaledBinormals(); - LLVector3 *binormals = mMesh->getWritableBinormals(); + LLVector4a *scaled_binormals = mMesh->getScaledBinormals(); + LLVector4a *binormals = mMesh->getWritableBinormals(); - LLVector4 *clothing_weights = mMesh->getWritableClothingWeights(); + LLVector4a *clothing_weights = mMesh->getWritableClothingWeights(); LLVector2 *tex_coords = mMesh->getWritableTexCoords(); F32 *maskWeightArray = (mVertMask) ? mVertMask->getMorphMaskWeights() : NULL; @@ -531,31 +535,38 @@ void LLPolyMorphTarget::apply( ESex avatar_sex ) maskWeight = maskWeightArray[vert_index_morph]; } - coords[vert_index_mesh] += LLVector4(mMorphData->mCoords[vert_index_morph] * delta_weight * maskWeight); + + LLVector4a pos = mMorphData->mCoords[vert_index_morph]; + pos.mul(delta_weight*maskWeight); + coords[vert_index_mesh].add(pos); if (getInfo()->mIsClothingMorph && clothing_weights) { - LLVector3 clothing_offset = mMorphData->mCoords[vert_index_morph] * delta_weight * maskWeight; - LLVector4* clothing_weight = &clothing_weights[vert_index_mesh]; - clothing_weight->mV[VX] += clothing_offset.mV[VX]; - clothing_weight->mV[VY] += clothing_offset.mV[VY]; - clothing_weight->mV[VZ] += clothing_offset.mV[VZ]; - clothing_weight->mV[VW] = maskWeight; + LLVector4a clothing_offset = mMorphData->mCoords[vert_index_morph]; + clothing_offset.mul(delta_weight * maskWeight); + LLVector4a* clothing_weight = &clothing_weights[vert_index_mesh]; + clothing_weight->add(clothing_offset); + clothing_weight->getF32ptr()[VW] = maskWeight; } // calculate new normals based on half angles - scaled_normals[vert_index_mesh] += mMorphData->mNormals[vert_index_morph] * delta_weight * maskWeight * NORMAL_SOFTEN_FACTOR; - LLVector3 normalized_normal = scaled_normals[vert_index_mesh]; - normalized_normal.normVec(); - normals[vert_index_mesh] = LLVector4(normalized_normal); + LLVector4a norm = mMorphData->mNormals[vert_index_morph]; + norm.mul(delta_weight*maskWeight*NORMAL_SOFTEN_FACTOR); + scaled_normals[vert_index_mesh].add(norm); + norm = scaled_normals[vert_index_mesh]; + norm.normalize3fast(); + normals[vert_index_mesh] = norm; // calculate new binormals - scaled_binormals[vert_index_mesh] += mMorphData->mBinormals[vert_index_morph] * delta_weight * maskWeight * NORMAL_SOFTEN_FACTOR; - LLVector3 tangent = scaled_binormals[vert_index_mesh] % normalized_normal; - LLVector3 normalized_binormal = normalized_normal % tangent; - normalized_binormal.normVec(); - binormals[vert_index_mesh] = normalized_binormal; - + LLVector4a binorm = mMorphData->mBinormals[vert_index_morph]; + binorm.mul(delta_weight*maskWeight*NORMAL_SOFTEN_FACTOR); + scaled_binormals[vert_index_mesh].add(binorm); + LLVector4a tangent; + tangent.setCross3(scaled_binormals[vert_index_mesh], norm); + LLVector4a& normalized_binormal = binormals[vert_index_mesh]; + normalized_binormal.setCross3(norm, tangent); + normalized_binormal.normalize3fast(); + tex_coords[vert_index_mesh] += mMorphData->mTexCoords[vert_index_morph] * delta_weight * maskWeight; } @@ -582,7 +593,7 @@ void LLPolyMorphTarget::apply( ESex avatar_sex ) //----------------------------------------------------------------------------- void LLPolyMorphTarget::applyMask(U8 *maskTextureData, S32 width, S32 height, S32 num_components, BOOL invert) { - LLVector4 *clothing_weights = getInfo()->mIsClothingMorph ? mMesh->getWritableClothingWeights() : NULL; + LLVector4a *clothing_weights = getInfo()->mIsClothingMorph ? mMesh->getWritableClothingWeights() : NULL; if (!mVertMask) { @@ -596,29 +607,47 @@ void LLPolyMorphTarget::applyMask(U8 *maskTextureData, S32 width, S32 height, S3 if (maskWeights) { - LLVector4 *coords = mMesh->getWritableCoords(); - LLVector3 *scaled_normals = mMesh->getScaledNormals(); - LLVector3 *scaled_binormals = mMesh->getScaledBinormals(); + LLVector4a *coords = mMesh->getWritableCoords(); + LLVector4a *scaled_normals = mMesh->getScaledNormals(); + LLVector4a *scaled_binormals = mMesh->getScaledBinormals(); LLVector2 *tex_coords = mMesh->getWritableTexCoords(); + LLVector4Logical clothing_mask; + clothing_mask.clear(); + clothing_mask.setElement<0>(); + clothing_mask.setElement<1>(); + clothing_mask.setElement<2>(); + + for(U32 vert = 0; vert < mMorphData->mNumIndices; vert++) { F32 lastMaskWeight = mLastWeight * maskWeights[vert]; S32 out_vert = mMorphData->mVertexIndices[vert]; // remove effect of existing masked morph - coords[out_vert] -= LLVector4(mMorphData->mCoords[vert]) * lastMaskWeight; - scaled_normals[out_vert] -= mMorphData->mNormals[vert] * lastMaskWeight * NORMAL_SOFTEN_FACTOR; - scaled_binormals[out_vert] -= mMorphData->mBinormals[vert] * lastMaskWeight * NORMAL_SOFTEN_FACTOR; + LLVector4a t; + t = mMorphData->mCoords[vert]; + t.mul(lastMaskWeight); + coords[out_vert].sub(t); + + t = mMorphData->mNormals[vert]; + t.mul(lastMaskWeight*NORMAL_SOFTEN_FACTOR); + scaled_normals[out_vert].sub(t); + + t = mMorphData->mBinormals[vert]; + t.mul(lastMaskWeight*NORMAL_SOFTEN_FACTOR); + scaled_binormals[out_vert].sub(t); + tex_coords[out_vert] -= mMorphData->mTexCoords[vert] * lastMaskWeight; if (clothing_weights) { - LLVector3 clothing_offset = mMorphData->mCoords[vert] * lastMaskWeight; - LLVector4* clothing_weight = &clothing_weights[out_vert]; - clothing_weight->mV[VX] -= clothing_offset.mV[VX]; - clothing_weight->mV[VY] -= clothing_offset.mV[VY]; - clothing_weight->mV[VZ] -= clothing_offset.mV[VZ]; + LLVector4a clothing_offset = mMorphData->mCoords[vert]; + clothing_offset.mul(lastMaskWeight); + LLVector4a* clothing_weight = &clothing_weights[out_vert]; + LLVector4a t; + t.setSub(*clothing_weight, clothing_offset); + clothing_weight->setSelectWithMask(clothing_mask, t, *clothing_weight); } } } @@ -654,7 +683,7 @@ LLPolyVertexMask::~LLPolyVertexMask() //----------------------------------------------------------------------------- // generateMask() //----------------------------------------------------------------------------- -void LLPolyVertexMask::generateMask(U8 *maskTextureData, S32 width, S32 height, S32 num_components, BOOL invert, LLVector4 *clothing_weights) +void LLPolyVertexMask::generateMask(U8 *maskTextureData, S32 width, S32 height, S32 num_components, BOOL invert, LLVector4a *clothing_weights) { // RN debug output that uses Image Debugger (http://www.cs.unc.edu/~baxter/projects/imdebug/) // BOOL debugImg = FALSE; @@ -698,7 +727,7 @@ void LLPolyVertexMask::generateMask(U8 *maskTextureData, S32 width, S32 height, if (clothing_weights) { - clothing_weights[vertIndex].mV[VW] = mWeights[index]; + clothing_weights[vertIndex].getF32ptr()[VW] = mWeights[index]; } } mWeightsGenerated = TRUE; diff --git a/indra/newview/llpolymorph.h b/indra/newview/llpolymorph.h index 8a024f2e9e..46e23b7792 100644 --- a/indra/newview/llpolymorph.h +++ b/indra/newview/llpolymorph.h @@ -58,14 +58,14 @@ public: U32 mNumIndices; U32* mVertexIndices; U32 mCurrentIndex; - LLVector3* mCoords; - LLVector3* mNormals; - LLVector3* mBinormals; + LLVector4a* mCoords; + LLVector4a* mNormals; + LLVector4a* mBinormals; LLVector2* mTexCoords; F32 mTotalDistortion; // vertex distortion summed over entire morph F32 mMaxDistortion; // maximum single vertex distortion in a given morph - LLVector3 mAvgDistortion; // average vertex distortion, to infer directionality of the morph + LLVector4a mAvgDistortion; // average vertex distortion, to infer directionality of the morph LLPolyMeshSharedData* mMesh; }; @@ -78,7 +78,7 @@ public: LLPolyVertexMask(LLPolyMorphData* morph_data); ~LLPolyVertexMask(); - void generateMask(U8 *maskData, S32 width, S32 height, S32 num_components, BOOL invert, LLVector4 *clothing_weights); + void generateMask(U8 *maskData, S32 width, S32 height, S32 num_components, BOOL invert, LLVector4a *clothing_weights); F32* getMorphMaskWeights(); @@ -157,11 +157,11 @@ public: // LLViewerVisualParam Virtual functions /*virtual*/ F32 getTotalDistortion(); - /*virtual*/ const LLVector3& getAvgDistortion(); + /*virtual*/ const LLVector4a& getAvgDistortion(); /*virtual*/ F32 getMaxDistortion(); - /*virtual*/ LLVector3 getVertexDistortion(S32 index, LLPolyMesh *poly_mesh); - /*virtual*/ const LLVector3* getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh); - /*virtual*/ const LLVector3* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh); + /*virtual*/ LLVector4a getVertexDistortion(S32 index, LLPolyMesh *poly_mesh); + /*virtual*/ const LLVector4a* getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh); + /*virtual*/ const LLVector4a* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh); void applyMask(U8 *maskData, S32 width, S32 height, S32 num_components, BOOL invert); void addPendingMorphMask() { mNumMorphMasksPending++; } diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index b9449e806f..3b52dd552f 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -1518,6 +1518,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() //----------------------------------------------------------------------------- @@ -1569,8 +1612,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 { @@ -2804,7 +2857,9 @@ BOOL LLSelectMgr::selectGetEditableLinksets() if (object->flagUsePhysics() || object->flagTemporaryOnRez() || object->flagCharacter() || + object->flagVolumeDetect() || object->flagAnimSource() || + (object->getRegion() != gAgent.getRegion()) || (!gAgent.isGodlike() && !gAgent.canManageEstate() && !object->permYouOwner() && @@ -2817,6 +2872,30 @@ BOOL LLSelectMgr::selectGetEditableLinksets() } //----------------------------------------------------------------------------- +// selectGetViewableCharacters() - return TRUE if all objects are characters +// viewable within the pathfinding characters floater +//----------------------------------------------------------------------------- +BOOL LLSelectMgr::selectGetViewableCharacters() +{ + for (LLObjectSelection::iterator iter = getSelection()->begin(); + iter != getSelection()->end(); iter++ ) + { + LLSelectNode* node = *iter; + LLViewerObject* object = node->getObject(); + if( !object || !node->mValid ) + { + return FALSE; + } + if( !object->flagCharacter() || + (object->getRegion() != gAgent.getRegion())) + { + return FALSE; + } + } + return TRUE; +} + +//----------------------------------------------------------------------------- // selectGetRootsTransfer() - return TRUE if current agent can transfer all // selected root objects. //----------------------------------------------------------------------------- @@ -5851,7 +5930,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); } } @@ -5878,7 +5957,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 feab6ebdf8..ecbb20df1b 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: @@ -585,6 +594,7 @@ public: BOOL selectGetNonCharacter(); BOOL selectGetEditableLinksets(); + BOOL selectGetViewableCharacters(); // returns TRUE if selected objects can be transferred. BOOL selectGetRootsTransfer(); diff --git a/indra/newview/llsidepaneliteminfo.cpp b/indra/newview/llsidepaneliteminfo.cpp index 1ce05da849..92c2863ffd 100644 --- a/indra/newview/llsidepaneliteminfo.cpp +++ b/indra/newview/llsidepaneliteminfo.cpp @@ -352,7 +352,7 @@ void LLSidepanelItemInfo::refreshFromItem(LLViewerInventoryItem* item) getChildView("BtnCreator")->setEnabled(FALSE); getChildView("LabelCreatorTitle")->setEnabled(FALSE); getChildView("LabelCreatorName")->setEnabled(FALSE); - getChild<LLUICtrl>("LabelCreatorName")->setValue(getString("unknown")); + getChild<LLUICtrl>("LabelCreatorName")->setValue(getString("unknown_multiple")); } //////////////// diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index 8e62b79d7f..78c905f6ff 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -68,6 +68,7 @@ const F32 SG_OCCLUSION_FUDGE = 0.25f; #define assert_states_valid(x) #endif +extern bool gShiftFrame; static U32 sZombieGroups = 0; U32 LLSpatialGroup::sNodeCount = 0; @@ -85,12 +86,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 +119,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 +281,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 +376,6 @@ LLSpatialGroup::~LLSpatialGroup() } } - mOcclusionVerts = NULL; - LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); clearDrawMap(); clearAtlasList() ; @@ -550,6 +530,7 @@ void LLSpatialGroup::setVisible() void LLSpatialGroup::validate() { + ll_assert_aligned(this,64); #if LL_OCTREE_PARANOIA_CHECK sg_assert(!isState(DIRTY)); @@ -562,7 +543,7 @@ void LLSpatialGroup::validate() validateDrawMap(); - for (element_iter i = getData().begin(); i != getData().end(); ++i) + for (element_iter i = getDataBegin(); i != getDataEnd(); ++i) { LLDrawable* drawable = *i; sg_assert(drawable->getSpatialGroup() == this); @@ -687,6 +668,11 @@ void LLSpatialGroup::rebuildGeom() if (!isDead()) { mSpatialPartition->rebuildGeom(this); + + if (isState(LLSpatialGroup::MESH_DIRTY)) + { + gPipeline.markMeshDirty(this); + } } } @@ -699,6 +685,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 +709,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 { @@ -762,7 +760,7 @@ BOOL LLSpatialGroup::boundObjects(BOOL empty, LLVector4a& minOut, LLVector4a& ma { const OctreeNode* node = mOctreeNode; - if (node->getData().empty()) + if (node->isEmpty()) { //don't do anything if there are no objects if (empty && mOctreeNode->getParent()) { //only root is allowed to be empty @@ -779,14 +777,14 @@ BOOL LLSpatialGroup::boundObjects(BOOL empty, LLVector4a& minOut, LLVector4a& ma clearState(OBJECT_DIRTY); //initialize bounding box to first element - OctreeNode::const_element_iter i = node->getData().begin(); + OctreeNode::const_element_iter i = node->getDataBegin(); LLDrawable* drawablep = *i; const LLVector4a* minMax = drawablep->getSpatialExtents(); newMin = minMax[0]; newMax = minMax[1]; - for (++i; i != node->getData().end(); ++i) + for (++i; i != node->getDataEnd(); ++i) { drawablep = *i; minMax = drawablep->getSpatialExtents(); @@ -927,16 +925,14 @@ void LLSpatialGroup::shift(const LLVector4a &offset) mObjectExtents[0].add(offset); mObjectExtents[1].add(offset); - //if (!mSpatialPartition->mRenderByGroup) + if (!mSpatialPartition->mRenderByGroup && + mSpatialPartition->mPartitionType != LLViewerRegion::PARTITION_TREE && + mSpatialPartition->mPartitionType != LLViewerRegion::PARTITION_TERRAIN && + mSpatialPartition->mPartitionType != LLViewerRegion::PARTITION_BRIDGE) { setState(GEOM_DIRTY); gPipeline.markRebuild(this, TRUE); } - - if (mOcclusionVerts.notNull()) - { - setState(OCCLUSION_DIRTY); - } } class LLSpatialSetState : public LLSpatialGroup::OctreeTraveler @@ -1204,6 +1200,8 @@ LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) : mCurUpdatingSlotp(NULL), mCurUpdatingTexture (NULL) { + ll_assert_aligned(this,16); + sNodeCount++; LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); @@ -1235,8 +1233,6 @@ LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) : mVisible[i] = 0; } - mOcclusionVerts = NULL; - mRadius = 1; mPixelArea = 1024.f; } @@ -1249,13 +1245,18 @@ void LLSpatialGroup::updateDistance(LLCamera &camera) return; } + if (gShiftFrame) + { + return; + } + #if !LL_RELEASE_FOR_DOWNLOAD if (isState(LLSpatialGroup::OBJECT_DIRTY)) { llerrs << "Spatial group dirty on distance update." << llendl; } #endif - if (!getData().empty()) + if (!isEmpty()) { mRadius = mSpatialPartition->mRenderByGroup ? mObjectBounds[1].getLength3().getF32() : (F32) mOctreeNode->getSize().getLength3().getF32(); @@ -1406,7 +1407,7 @@ void LLSpatialGroup::handleDestruction(const TreeNode* node) LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); setState(DEAD); - for (element_iter i = getData().begin(); i != getData().end(); ++i) + for (element_iter i = getDataBegin(); i != getDataEnd(); ++i) { LLDrawable* drawable = *i; if (drawable->getSpatialGroup() == this) @@ -1465,10 +1466,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; @@ -1476,24 +1481,29 @@ 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) + for (LLSpatialGroup::element_iter i = getDataBegin(); i != getDataEnd(); ++i) { LLDrawable* drawable = *i; for (S32 j = 0; j < drawable->getNumFaces(); j++) { LLFace* facep = drawable->getFace(j); - facep->clearVertexBuffer(); + if (facep) + { + facep->clearVertexBuffer(); + } } } } @@ -1556,15 +1566,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() { @@ -1584,7 +1592,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); @@ -1635,7 +1645,9 @@ void LLSpatialGroup::checkOcclusion() else { assert_states_valid(this); + setOcclusionState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF); + assert_states_valid(this); } @@ -1690,12 +1702,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. @@ -1726,10 +1732,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) { @@ -1738,12 +1747,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 @@ -1751,12 +1760,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])); } } @@ -1841,12 +1850,14 @@ BOOL LLSpatialPartition::remove(LLDrawable *drawablep, LLSpatialGroup *curp) { LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); - drawablep->setSpatialGroup(NULL); - if (!curp->removeObject(drawablep)) { OCT_ERRS << "Failed to remove drawable from octree!" << llendl; } + else + { + drawablep->setSpatialGroup(NULL); + } assert_octree_valid(mOctree); @@ -2117,7 +2128,7 @@ public: virtual void processGroup(LLSpatialGroup* group) { - llassert(!group->isState(LLSpatialGroup::DIRTY) && !group->getData().empty()) + llassert(!group->isState(LLSpatialGroup::DIRTY) && !group->isEmpty()) if (mRes < 2) { @@ -2184,7 +2195,7 @@ public: { LLSpatialGroup::OctreeNode* branch = group->mOctreeNode; - for (LLSpatialGroup::OctreeNode::const_element_iter i = branch->getData().begin(); i != branch->getData().end(); ++i) + for (LLSpatialGroup::OctreeNode::const_element_iter i = branch->getDataBegin(); i != branch->getDataEnd(); ++i) { LLDrawable* drawable = *i; @@ -2308,7 +2319,7 @@ public: LLSpatialGroup* group = (LLSpatialGroup*) state->getListener(0); group->destroyGL(); - for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i) + for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) { LLDrawable* drawable = *i; if (drawable->getVObj().notNull() && !group->mSpatialPartition->mRenderByGroup) @@ -2480,18 +2491,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); + } } } @@ -2615,7 +2629,7 @@ void renderOctree(LLSpatialGroup* group) gGL.flush(); glLineWidth(1.f); gGL.flush(); - for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i) + for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) { LLDrawable* drawable = *i; if (!group->mSpatialPartition->isBridge()) @@ -2628,7 +2642,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) { @@ -2661,7 +2675,7 @@ void renderOctree(LLSpatialGroup* group) } else { - if (group->mBufferUsage == GL_STATIC_DRAW_ARB && !group->getData().empty() + if (group->mBufferUsage == GL_STATIC_DRAW_ARB && !group->isEmpty() && group->mSpatialPartition->mRenderByGroup) { col.setVec(0.8f, 0.4f, 0.1f, 0.1f); @@ -2729,7 +2743,7 @@ void renderVisibility(LLSpatialGroup* group, LLCamera* camera) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); BOOL render_objects = (!LLPipeline::sUseOcclusion || !group->isOcclusionState(LLSpatialGroup::OCCLUDED)) && group->isVisible() && - !group->getData().empty(); + !group->isEmpty(); if (render_objects) { @@ -2757,19 +2771,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); - }*/ } } @@ -2999,15 +3000,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 @@ -3471,7 +3474,7 @@ void renderPhysicsShape(LLDrawable* drawable, LLVOVolume* volume) void renderPhysicsShapes(LLSpatialGroup* group) { - for (LLSpatialGroup::OctreeNode::const_element_iter i = group->getData().begin(); i != group->getData().end(); ++i) + for (LLSpatialGroup::OctreeNode::const_element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) { LLDrawable* drawable = *i; LLVOVolume* volume = drawable->getVOVolume(); @@ -3499,18 +3502,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); + } } } } @@ -3534,6 +3540,7 @@ void renderTexturePriority(LLDrawable* drawable) //LLViewerTexture* imagep = facep->getTexture(); //if (imagep) + if (facep) { //F32 vsize = imagep->mMaxVirtualSize; @@ -3586,7 +3593,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(); } @@ -3767,7 +3778,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(); @@ -3808,7 +3823,7 @@ public: LLVector3 center, size; - if (branch->getData().empty()) + if (branch->isEmpty()) { gGL.diffuseColor3f(1.f,0.2f,0.f); center.set(branch->getCenter().getF32ptr()); @@ -3844,8 +3859,8 @@ public: } gGL.begin(LLRender::TRIANGLES); - for (LLOctreeNode<LLVolumeTriangle>::const_element_iter iter = branch->getData().begin(); - iter != branch->getData().end(); + for (LLOctreeNode<LLVolumeTriangle>::const_element_iter iter = branch->getDataBegin(); + iter != branch->getDataEnd(); ++iter) { const LLVolumeTriangle* tri = *iter; @@ -4082,7 +4097,7 @@ public: if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_BBOXES)) { - if (!group->getData().empty()) + if (!group->isEmpty()) { gGL.diffuseColor3f(0,0,1); drawBoxOutline(group->mObjectBounds[0], @@ -4090,7 +4105,7 @@ public: } } - for (LLSpatialGroup::OctreeNode::const_element_iter i = branch->getData().begin(); i != branch->getData().end(); ++i) + for (LLSpatialGroup::OctreeNode::const_element_iter i = branch->getDataBegin(); i != branch->getDataEnd(); ++i) { LLDrawable* drawable = *i; @@ -4169,18 +4184,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; + } } } } @@ -4276,7 +4294,7 @@ public: return; } - for (LLSpatialGroup::OctreeNode::const_element_iter i = branch->getData().begin(); i != branch->getData().end(); ++i) + for (LLSpatialGroup::OctreeNode::const_element_iter i = branch->getDataBegin(); i != branch->getDataEnd(); ++i) { LLDrawable* drawable = *i; @@ -4500,7 +4518,7 @@ public: virtual void visit(const LLSpatialGroup::OctreeNode* branch) { - for (LLSpatialGroup::OctreeNode::const_element_iter i = branch->getData().begin(); i != branch->getData().end(); ++i) + for (LLSpatialGroup::OctreeNode::const_element_iter i = branch->getDataBegin(); i != branch->getDataEnd(); ++i) { check(*i); } @@ -4686,28 +4704,62 @@ LLVertexBuffer* LLGeometryManager::createVertexBuffer(U32 type_mask, U32 usage) LLCullResult::LLCullResult() { + mVisibleGroupsAllocated = 0; + mAlphaGroupsAllocated = 0; + mOcclusionGroupsAllocated = 0; + mDrawableGroupsAllocated = 0; + mVisibleListAllocated = 0; + mVisibleBridgeAllocated = 0; + + mVisibleGroups = NULL; + mVisibleGroupsEnd = NULL; + mAlphaGroups = NULL; + mAlphaGroupsEnd = NULL; + mOcclusionGroups = NULL; + mOcclusionGroupsEnd = NULL; + mDrawableGroups = NULL; + mDrawableGroupsEnd = NULL; + mVisibleList = NULL; + mVisibleListEnd = NULL; + mVisibleBridge = NULL; + mVisibleBridgeEnd = NULL; + + for (U32 i = 0; i < LLRenderPass::NUM_RENDER_TYPES; i++) + { + mRenderMap[i] = NULL; + mRenderMapEnd[i] = NULL; + mRenderMapAllocated[i] = 0; + } + clear(); } +void LLCullResult::pushBack(void**& head, U32& count, void* val) +{ + count++; + head = (void**) realloc((void*) head, sizeof(void*) * count); + head[count-1] = val; +} + void LLCullResult::clear() { mVisibleGroupsSize = 0; - mVisibleGroupsEnd = mVisibleGroups.begin(); + mVisibleGroupsEnd = mVisibleGroups; mAlphaGroupsSize = 0; - mAlphaGroupsEnd = mAlphaGroups.begin(); + mAlphaGroupsEnd = mAlphaGroups; mOcclusionGroupsSize = 0; - mOcclusionGroupsEnd = mOcclusionGroups.begin(); + mOcclusionGroupsEnd = mOcclusionGroups; mDrawableGroupsSize = 0; - mDrawableGroupsEnd = mDrawableGroups.begin(); + mDrawableGroupsEnd = mDrawableGroups; mVisibleListSize = 0; - mVisibleListEnd = mVisibleList.begin(); + mVisibleListEnd = mVisibleList; mVisibleBridgeSize = 0; - mVisibleBridgeEnd = mVisibleBridge.begin(); + mVisibleBridgeEnd = mVisibleBridge; for (U32 i = 0; i < LLRenderPass::NUM_RENDER_TYPES; i++) @@ -4717,176 +4769,176 @@ void LLCullResult::clear() mRenderMap[i][j] = 0; } mRenderMapSize[i] = 0; - mRenderMapEnd[i] = mRenderMap[i].begin(); + mRenderMapEnd[i] = mRenderMap[i]; } } -LLCullResult::sg_list_t::iterator LLCullResult::beginVisibleGroups() +LLCullResult::sg_iterator LLCullResult::beginVisibleGroups() { - return mVisibleGroups.begin(); + return mVisibleGroups; } -LLCullResult::sg_list_t::iterator LLCullResult::endVisibleGroups() +LLCullResult::sg_iterator LLCullResult::endVisibleGroups() { return mVisibleGroupsEnd; } -LLCullResult::sg_list_t::iterator LLCullResult::beginAlphaGroups() +LLCullResult::sg_iterator LLCullResult::beginAlphaGroups() { - return mAlphaGroups.begin(); + return mAlphaGroups; } -LLCullResult::sg_list_t::iterator LLCullResult::endAlphaGroups() +LLCullResult::sg_iterator LLCullResult::endAlphaGroups() { return mAlphaGroupsEnd; } -LLCullResult::sg_list_t::iterator LLCullResult::beginOcclusionGroups() +LLCullResult::sg_iterator LLCullResult::beginOcclusionGroups() { - return mOcclusionGroups.begin(); + return mOcclusionGroups; } -LLCullResult::sg_list_t::iterator LLCullResult::endOcclusionGroups() +LLCullResult::sg_iterator LLCullResult::endOcclusionGroups() { return mOcclusionGroupsEnd; } -LLCullResult::sg_list_t::iterator LLCullResult::beginDrawableGroups() +LLCullResult::sg_iterator LLCullResult::beginDrawableGroups() { - return mDrawableGroups.begin(); + return mDrawableGroups; } -LLCullResult::sg_list_t::iterator LLCullResult::endDrawableGroups() +LLCullResult::sg_iterator LLCullResult::endDrawableGroups() { return mDrawableGroupsEnd; } -LLCullResult::drawable_list_t::iterator LLCullResult::beginVisibleList() +LLCullResult::drawable_iterator LLCullResult::beginVisibleList() { - return mVisibleList.begin(); + return mVisibleList; } -LLCullResult::drawable_list_t::iterator LLCullResult::endVisibleList() +LLCullResult::drawable_iterator LLCullResult::endVisibleList() { return mVisibleListEnd; } -LLCullResult::bridge_list_t::iterator LLCullResult::beginVisibleBridge() +LLCullResult::bridge_iterator LLCullResult::beginVisibleBridge() { - return mVisibleBridge.begin(); + return mVisibleBridge; } -LLCullResult::bridge_list_t::iterator LLCullResult::endVisibleBridge() +LLCullResult::bridge_iterator LLCullResult::endVisibleBridge() { return mVisibleBridgeEnd; } -LLCullResult::drawinfo_list_t::iterator LLCullResult::beginRenderMap(U32 type) +LLCullResult::drawinfo_iterator LLCullResult::beginRenderMap(U32 type) { - return mRenderMap[type].begin(); + return mRenderMap[type]; } -LLCullResult::drawinfo_list_t::iterator LLCullResult::endRenderMap(U32 type) +LLCullResult::drawinfo_iterator LLCullResult::endRenderMap(U32 type) { return mRenderMapEnd[type]; } void LLCullResult::pushVisibleGroup(LLSpatialGroup* group) { - if (mVisibleGroupsSize < mVisibleGroups.size()) + if (mVisibleGroupsSize < mVisibleGroupsAllocated) { mVisibleGroups[mVisibleGroupsSize] = group; } else { - mVisibleGroups.push_back(group); + pushBack((void**&) mVisibleGroups, mVisibleGroupsAllocated, (void*) group); } ++mVisibleGroupsSize; - mVisibleGroupsEnd = mVisibleGroups.begin()+mVisibleGroupsSize; + mVisibleGroupsEnd = mVisibleGroups+mVisibleGroupsSize; } void LLCullResult::pushAlphaGroup(LLSpatialGroup* group) { - if (mAlphaGroupsSize < mAlphaGroups.size()) + if (mAlphaGroupsSize < mAlphaGroupsAllocated) { mAlphaGroups[mAlphaGroupsSize] = group; } else { - mAlphaGroups.push_back(group); + pushBack((void**&) mAlphaGroups, mAlphaGroupsAllocated, (void*) group); } ++mAlphaGroupsSize; - mAlphaGroupsEnd = mAlphaGroups.begin()+mAlphaGroupsSize; + mAlphaGroupsEnd = mAlphaGroups+mAlphaGroupsSize; } void LLCullResult::pushOcclusionGroup(LLSpatialGroup* group) { - if (mOcclusionGroupsSize < mOcclusionGroups.size()) + if (mOcclusionGroupsSize < mOcclusionGroupsAllocated) { mOcclusionGroups[mOcclusionGroupsSize] = group; } else { - mOcclusionGroups.push_back(group); + pushBack((void**&) mOcclusionGroups, mOcclusionGroupsAllocated, (void*) group); } ++mOcclusionGroupsSize; - mOcclusionGroupsEnd = mOcclusionGroups.begin()+mOcclusionGroupsSize; + mOcclusionGroupsEnd = mOcclusionGroups+mOcclusionGroupsSize; } void LLCullResult::pushDrawableGroup(LLSpatialGroup* group) { - if (mDrawableGroupsSize < mDrawableGroups.size()) + if (mDrawableGroupsSize < mDrawableGroupsAllocated) { mDrawableGroups[mDrawableGroupsSize] = group; } else { - mDrawableGroups.push_back(group); + pushBack((void**&) mDrawableGroups, mDrawableGroupsAllocated, (void*) group); } ++mDrawableGroupsSize; - mDrawableGroupsEnd = mDrawableGroups.begin()+mDrawableGroupsSize; + mDrawableGroupsEnd = mDrawableGroups+mDrawableGroupsSize; } void LLCullResult::pushDrawable(LLDrawable* drawable) { - if (mVisibleListSize < mVisibleList.size()) + if (mVisibleListSize < mVisibleListAllocated) { mVisibleList[mVisibleListSize] = drawable; } else { - mVisibleList.push_back(drawable); + pushBack((void**&) mVisibleList, mVisibleListAllocated, (void*) drawable); } ++mVisibleListSize; - mVisibleListEnd = mVisibleList.begin()+mVisibleListSize; + mVisibleListEnd = mVisibleList+mVisibleListSize; } void LLCullResult::pushBridge(LLSpatialBridge* bridge) { - if (mVisibleBridgeSize < mVisibleBridge.size()) + if (mVisibleBridgeSize < mVisibleBridgeAllocated) { mVisibleBridge[mVisibleBridgeSize] = bridge; } else { - mVisibleBridge.push_back(bridge); + pushBack((void**&) mVisibleBridge, mVisibleBridgeAllocated, (void*) bridge); } ++mVisibleBridgeSize; - mVisibleBridgeEnd = mVisibleBridge.begin()+mVisibleBridgeSize; + mVisibleBridgeEnd = mVisibleBridge+mVisibleBridgeSize; } void LLCullResult::pushDrawInfo(U32 type, LLDrawInfo* draw_info) { - if (mRenderMapSize[type] < mRenderMap[type].size()) + if (mRenderMapSize[type] < mRenderMapAllocated[type]) { mRenderMap[type][mRenderMapSize[type]] = draw_info; } else { - mRenderMap[type].push_back(draw_info); + pushBack((void**&) mRenderMap[type], mRenderMapAllocated[type], (void*) draw_info); } ++mRenderMapSize[type]; - mRenderMapEnd[type] = mRenderMap[type].begin() + mRenderMapSize[type]; + mRenderMapEnd[type] = mRenderMap[type] + mRenderMapSize[type]; } diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h index 1a93145cc5..f050df2b39 100644 --- a/indra/newview/llspatialpartition.h +++ b/indra/newview/llspatialpartition.h @@ -68,6 +68,16 @@ protected: ~LLDrawInfo(); public: + void* operator new(size_t size) + { + return ll_aligned_malloc_16(size); + } + + void operator delete(void* ptr) + { + ll_aligned_free_16(ptr); + } + LLDrawInfo(const LLDrawInfo& rhs) { @@ -106,7 +116,7 @@ public: F32 mPartSize; F32 mVSize; LLSpatialGroup* mGroup; - LLFace* mFace; //associated face + LL_ALIGN_16(LLFace* mFace); //associated face F32 mDistance; U32 mDrawMode; @@ -181,7 +191,7 @@ public: }; }; -LL_ALIGN_PREFIX(64) +LL_ALIGN_PREFIX(16) class LLSpatialGroup : public LLOctreeListener<LLDrawable> { friend class LLSpatialPartition; @@ -193,6 +203,16 @@ public: *this = rhs; } + void* operator new(size_t size) + { + return ll_aligned_malloc_16(size); + } + + void operator delete(void* ptr) + { + ll_aligned_free_16(ptr); + } + const LLSpatialGroup& operator=(const LLSpatialGroup& rhs) { llerrs << "Illegal operation!" << llendl; @@ -263,11 +283,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 +332,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(); @@ -327,8 +345,13 @@ public: void dirtyGeom() { setState(GEOM_DIRTY); } void dirtyMesh() { setState(MESH_DIRTY); } + + //octree wrappers to make code more readable element_list& getData() { return mOctreeNode->getData(); } + element_iter getDataBegin() { return mOctreeNode->getDataBegin(); } + element_iter getDataEnd() { return mOctreeNode->getDataEnd(); } U32 getElementCount() const { return mOctreeNode->getElementCount(); } + bool isEmpty() const { return mOctreeNode->isEmpty(); } void drawObjectBox(LLColor4 col); @@ -372,12 +395,12 @@ public: V4_COUNT = 10 } eV4Index; - LLVector4a mBounds[2]; // bounding box (center, size) of this node and all its children (tight fit to objects) - LLVector4a mExtents[2]; // extents (min, max) of this node and all its children - LLVector4a mObjectExtents[2]; // extents (min, max) of objects in this node - LLVector4a mObjectBounds[2]; // bounding box (center, size) of objects in this node - LLVector4a mViewAngle; - LLVector4a mLastUpdateViewAngle; + LL_ALIGN_16(LLVector4a mBounds[2]); // bounding box (center, size) of this node and all its children (tight fit to objects) + LL_ALIGN_16(LLVector4a mExtents[2]); // extents (min, max) of this node and all its children + LL_ALIGN_16(LLVector4a mObjectExtents[2]); // extents (min, max) of objects in this node + LL_ALIGN_16(LLVector4a mObjectBounds[2]); // bounding box (center, size) of objects in this node + LL_ALIGN_16(LLVector4a mViewAngle); + LL_ALIGN_16(LLVector4a mLastUpdateViewAngle); F32 mObjectBoxSize; //cached mObjectBounds[1].getLength3() @@ -415,7 +438,6 @@ public: LLSpatialPartition* mSpatialPartition; LLPointer<LLVertexBuffer> mVertexBuffer; - LLPointer<LLVertexBuffer> mOcclusionVerts; GLuint mOcclusionQuery[LLViewerCamera::NUM_CAMERAS]; U32 mBufferUsage; @@ -545,34 +567,39 @@ class LLCullResult public: LLCullResult(); - typedef std::vector<LLSpatialGroup*> sg_list_t; - typedef std::vector<LLDrawable*> drawable_list_t; - typedef std::vector<LLSpatialBridge*> bridge_list_t; - typedef std::vector<LLDrawInfo*> drawinfo_list_t; + typedef LLSpatialGroup** sg_list_t; + typedef LLDrawable** drawable_list_t; + typedef LLSpatialBridge** bridge_list_t; + typedef LLDrawInfo** drawinfo_list_t; + + typedef LLSpatialGroup** sg_iterator; + typedef LLSpatialBridge** bridge_iterator; + typedef LLDrawInfo** drawinfo_iterator; + typedef LLDrawable** drawable_iterator; void clear(); - sg_list_t::iterator beginVisibleGroups(); - sg_list_t::iterator endVisibleGroups(); + sg_iterator beginVisibleGroups(); + sg_iterator endVisibleGroups(); - sg_list_t::iterator beginAlphaGroups(); - sg_list_t::iterator endAlphaGroups(); + sg_iterator beginAlphaGroups(); + sg_iterator endAlphaGroups(); bool hasOcclusionGroups() { return mOcclusionGroupsSize > 0; } - sg_list_t::iterator beginOcclusionGroups(); - sg_list_t::iterator endOcclusionGroups(); + sg_iterator beginOcclusionGroups(); + sg_iterator endOcclusionGroups(); - sg_list_t::iterator beginDrawableGroups(); - sg_list_t::iterator endDrawableGroups(); + sg_iterator beginDrawableGroups(); + sg_iterator endDrawableGroups(); - drawable_list_t::iterator beginVisibleList(); - drawable_list_t::iterator endVisibleList(); + drawable_iterator beginVisibleList(); + drawable_iterator endVisibleList(); - bridge_list_t::iterator beginVisibleBridge(); - bridge_list_t::iterator endVisibleBridge(); + bridge_iterator beginVisibleBridge(); + bridge_iterator endVisibleBridge(); - drawinfo_list_t::iterator beginRenderMap(U32 type); - drawinfo_list_t::iterator endRenderMap(U32 type); + drawinfo_iterator beginRenderMap(U32 type); + drawinfo_iterator endRenderMap(U32 type); void pushVisibleGroup(LLSpatialGroup* group); void pushAlphaGroup(LLSpatialGroup* group); @@ -592,28 +619,41 @@ public: void assertDrawMapsEmpty(); private: + + void pushBack(void** &head, U32& count, void* val); + U32 mVisibleGroupsSize; U32 mAlphaGroupsSize; U32 mOcclusionGroupsSize; U32 mDrawableGroupsSize; U32 mVisibleListSize; U32 mVisibleBridgeSize; + + U32 mVisibleGroupsAllocated; + U32 mAlphaGroupsAllocated; + U32 mOcclusionGroupsAllocated; + U32 mDrawableGroupsAllocated; + U32 mVisibleListAllocated; + U32 mVisibleBridgeAllocated; + U32 mRenderMapSize[LLRenderPass::NUM_RENDER_TYPES]; sg_list_t mVisibleGroups; - sg_list_t::iterator mVisibleGroupsEnd; + sg_iterator mVisibleGroupsEnd; sg_list_t mAlphaGroups; - sg_list_t::iterator mAlphaGroupsEnd; + sg_iterator mAlphaGroupsEnd; sg_list_t mOcclusionGroups; - sg_list_t::iterator mOcclusionGroupsEnd; + sg_iterator mOcclusionGroupsEnd; sg_list_t mDrawableGroups; - sg_list_t::iterator mDrawableGroupsEnd; + sg_iterator mDrawableGroupsEnd; drawable_list_t mVisibleList; - drawable_list_t::iterator mVisibleListEnd; + drawable_iterator mVisibleListEnd; bridge_list_t mVisibleBridge; - bridge_list_t::iterator mVisibleBridgeEnd; + bridge_iterator mVisibleBridgeEnd; drawinfo_list_t mRenderMap[LLRenderPass::NUM_RENDER_TYPES]; - drawinfo_list_t::iterator mRenderMapEnd[LLRenderPass::NUM_RENDER_TYPES]; + U32 mRenderMapAllocated[LLRenderPass::NUM_RENDER_TYPES]; + drawinfo_iterator mRenderMapEnd[LLRenderPass::NUM_RENDER_TYPES]; + }; @@ -657,6 +697,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); @@ -671,10 +712,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 417419d13c..a28d8d3546 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -741,6 +741,7 @@ bool idle_startup() { display_startup(); initialize_edit_menu(); + initialize_spellcheck_menu(); display_startup(); init_menus(); display_startup(); @@ -3208,17 +3209,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/llsurface.cpp b/indra/newview/llsurface.cpp index 65393cc168..f64a72a616 100644 --- a/indra/newview/llsurface.cpp +++ b/indra/newview/llsurface.cpp @@ -56,6 +56,7 @@ #include "lldrawable.h" extern LLPipeline gPipeline; +extern bool gShiftFrame; LLColor4U MAX_WATER_COLOR(0, 48, 96, 240); @@ -294,7 +295,7 @@ void LLSurface::initTextures() mWaterObjp = (LLVOWater *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_WATER, mRegionp); gPipeline.createObject(mWaterObjp); LLVector3d water_pos_global = from_region_handle(mRegionp->getHandle()); - water_pos_global += LLVector3d(128.0, 128.0, DEFAULT_WATER_HEIGHT); + water_pos_global += LLVector3d(128.0, 128.0, DEFAULT_WATER_HEIGHT); // region doesn't have a valid water height yet mWaterObjp->setPositionGlobal(water_pos_global); } } @@ -621,6 +622,11 @@ void LLSurface::moveZ(const S32 x, const S32 y, const F32 delta) void LLSurface::updatePatchVisibilities(LLAgent &agent) { + if (gShiftFrame) + { + return; + } + LLVector3 pos_region = mRegionp->getPosRegionFromGlobal(gAgentCamera.getCameraPositionGlobal()); LLSurfacePatch *patchp; diff --git a/indra/newview/llsurfacepatch.cpp b/indra/newview/llsurfacepatch.cpp index 5077c2c7e1..a9ba2bce9c 100644 --- a/indra/newview/llsurfacepatch.cpp +++ b/indra/newview/llsurfacepatch.cpp @@ -43,6 +43,7 @@ #include "lldrawpool.h" #include "noise.h" +extern bool gShiftFrame; extern U64 gFrameTime; extern LLPipeline gPipeline; @@ -218,7 +219,7 @@ void LLSurfacePatch::eval(const U32 x, const U32 y, const U32 stride, LLVector3 pos_agent.mV[VX] += x * mSurfacep->getMetersPerGrid(); pos_agent.mV[VY] += y * mSurfacep->getMetersPerGrid(); pos_agent.mV[VZ] = *(mDataZ + point_offset); - *vertex = pos_agent; + *vertex = pos_agent-mVObjp->getRegion()->getOriginAgent(); LLVector3 rel_pos = pos_agent - mSurfacep->getOriginAgent(); LLVector3 tex_pos = rel_pos * (1.f/surface_stride); @@ -366,10 +367,13 @@ void LLSurfacePatch::updateCameraDistanceRegion(const LLVector3 &pos_region) { if (LLPipeline::sDynamicLOD) { - LLVector3 dv = pos_region; - dv -= mCenterRegion; - mVisInfo.mDistance = llmax(0.f, (F32)(dv.magVec() - mRadius))/ - llmax(LLVOSurfacePatch::sLODFactor, 0.1f); + if (!gShiftFrame) + { + LLVector3 dv = pos_region; + dv -= mCenterRegion; + mVisInfo.mDistance = llmax(0.f, (F32)(dv.magVec() - mRadius))/ + llmax(LLVOSurfacePatch::sLODFactor, 0.1f); + } } else { diff --git a/indra/newview/lltexlayerparams.h b/indra/newview/lltexlayerparams.h index 74c22b0cdf..2c0da60b48 100644 --- a/indra/newview/lltexlayerparams.h +++ b/indra/newview/lltexlayerparams.h @@ -76,11 +76,11 @@ public: // LLViewerVisualParam Virtual functions /*virtual*/ F32 getTotalDistortion() { return 1.f; } - /*virtual*/ const LLVector3& getAvgDistortion() { return mAvgDistortionVec; } + /*virtual*/ const LLVector4a& getAvgDistortion() { return mAvgDistortionVec; } /*virtual*/ F32 getMaxDistortion() { return 3.f; } - /*virtual*/ LLVector3 getVertexDistortion(S32 index, LLPolyMesh *poly_mesh) { return LLVector3(1.f, 1.f, 1.f);} - /*virtual*/ const LLVector3* getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh) { index = 0; poly_mesh = NULL; return &mAvgDistortionVec;}; - /*virtual*/ const LLVector3* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh) { index = 0; poly_mesh = NULL; return NULL;}; + /*virtual*/ LLVector4a getVertexDistortion(S32 index, LLPolyMesh *poly_mesh) { return LLVector4a(1.f, 1.f, 1.f);} + /*virtual*/ const LLVector4a* getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh) { index = 0; poly_mesh = NULL; return &mAvgDistortionVec;}; + /*virtual*/ const LLVector4a* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh) { index = 0; poly_mesh = NULL; return NULL;}; // New functions BOOL render( S32 x, S32 y, S32 width, S32 height ); @@ -94,7 +94,7 @@ private: LLPointer<LLImageRaw> mStaticImageRaw; BOOL mNeedsCreateTexture; BOOL mStaticImageInvalid; - LLVector3 mAvgDistortionVec; + LLVector4a mAvgDistortionVec; F32 mCachedEffectiveWeight; public: @@ -155,18 +155,18 @@ public: // LLViewerVisualParam Virtual functions /*virtual*/ F32 getTotalDistortion() { return 1.f; } - /*virtual*/ const LLVector3& getAvgDistortion() { return mAvgDistortionVec; } + /*virtual*/ const LLVector4a& getAvgDistortion() { return mAvgDistortionVec; } /*virtual*/ F32 getMaxDistortion() { return 3.f; } - /*virtual*/ LLVector3 getVertexDistortion(S32 index, LLPolyMesh *poly_mesh) { return LLVector3(1.f, 1.f, 1.f); } - /*virtual*/ const LLVector3* getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh) { index = 0; poly_mesh = NULL; return &mAvgDistortionVec;}; - /*virtual*/ const LLVector3* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh) { index = 0; poly_mesh = NULL; return NULL;}; + /*virtual*/ LLVector4a getVertexDistortion(S32 index, LLPolyMesh *poly_mesh) { return LLVector4a(1.f, 1.f, 1.f); } + /*virtual*/ const LLVector4a* getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh) { index = 0; poly_mesh = NULL; return &mAvgDistortionVec;}; + /*virtual*/ const LLVector4a* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh) { index = 0; poly_mesh = NULL; return NULL;}; // New functions LLColor4 getNetColor() const; protected: virtual void onGlobalColorChanged(bool upload_bake) {} private: - LLVector3 mAvgDistortionVec; + LLVector4a mAvgDistortionVec; }; class LLTexLayerParamColorInfo : public LLViewerVisualParamInfo 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 ed9faa0706..ec36cf48c2 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -97,6 +97,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); @@ -134,6 +135,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 ); @@ -175,6 +179,7 @@ protected: LLFilterEditor* mFilterEdit; LLInventoryPanel* mInventoryPanel; PermissionMask mImmediateFilterPermMask; + PermissionMask mDnDFilterPermMask; PermissionMask mNonImmediateFilterPermMask; BOOL mCanApplyImmediately; BOOL mNoCopyTextureSelected; @@ -184,12 +189,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) @@ -205,9 +216,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; @@ -319,7 +333,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) @@ -464,7 +478,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) @@ -546,7 +560,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()); @@ -702,8 +716,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); } @@ -713,6 +726,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() ); @@ -724,6 +738,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(); } @@ -804,13 +819,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(); @@ -947,7 +966,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(); @@ -958,6 +977,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; @@ -1108,6 +1137,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 ) @@ -1188,12 +1226,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); @@ -1318,6 +1363,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 7e6dfbc9d9..7e6dfbc9d9 100755..100644 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp diff --git a/indra/newview/lltextureview.cpp b/indra/newview/lltextureview.cpp index 425bf7ee87..52d085dd2c 100644 --- a/indra/newview/lltextureview.cpp +++ b/indra/newview/lltextureview.cpp @@ -510,7 +510,7 @@ void LLGLTexMemBar::draw() F32 discard_bias = LLViewerTexture::sDesiredDiscardBias; 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 = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f); + S32 line_height = LLFontGL::getFontMonospace()->getLineHeight(); 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); diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp index a473ee7ce0..d629f3abac 100644 --- a/indra/newview/lltoastnotifypanel.cpp +++ b/indra/newview/lltoastnotifypanel.cpp @@ -457,7 +457,7 @@ button_name_set_t getButtonDisableList(const std::string& notification_name, con { search_map = user_give_item_disable_map; } - else if("TeleportOffered" == notification_name) + else if(("TeleportOffered" == notification_name) || ("TeleportOffered_MaturityExceeded" == notification_name)) { search_map = teleport_offered_disable_map; } diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index 4f4eef0f3d..c69999981c 100644 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -1007,7 +1007,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. } @@ -1022,7 +1029,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 245c2a23e6..41aee484db 100644 --- a/indra/newview/lltooldraganddrop.h +++ b/indra/newview/lltooldraganddrop.h @@ -93,6 +93,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 { @@ -219,13 +226,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/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/llviewercamera.h b/indra/newview/llviewercamera.h index 184033de42..b857c7fe89 100644 --- a/indra/newview/llviewercamera.h +++ b/indra/newview/llviewercamera.h @@ -51,9 +51,19 @@ const BOOL NOT_FOR_SELECTION = FALSE; extern template class LLViewerCamera* LLSingleton<class LLViewerCamera>::getInstance(); #endif +LL_ALIGN_PREFIX(16) class LLViewerCamera : public LLCamera, public LLSingleton<LLViewerCamera> { public: + void* operator new(size_t size) + { + return ll_aligned_malloc_16(size); + } + + void operator delete(void* ptr) + { + ll_aligned_free_16(ptr); + } typedef enum { @@ -137,6 +147,7 @@ protected: S16 mZoomSubregion; public: -}; +} LL_ALIGN_POSTFIX(16); + #endif // LL_LLVIEWERCAMERA_H diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index f2712e7590..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 @@ -325,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; } @@ -337,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()) @@ -501,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() ) @@ -637,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)); @@ -706,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 9a45d40b65..d58ee05fb6 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -79,6 +79,7 @@ #include "llpostprocess.h" extern LLPointer<LLViewerTexture> gStartTexture; +extern bool gShiftFrame; LLPointer<LLViewerTexture> gDisconnectedImagep = NULL; @@ -162,8 +163,11 @@ void display_startup() glClear(GL_DEPTH_BUFFER_BIT); } +static LLFastTimer::DeclareTimer FTM_UPDATE_CAMERA("Update Camera"); + void display_update_camera() { + LLFastTimer t(FTM_UPDATE_CAMERA); LLMemType mt_uc(LLMemType::MTYPE_DISPLAY_UPDATE_CAMERA); // TODO: cut draw distance down if customizing avatar? // TODO: cut draw distance on per-parcel basis? @@ -217,6 +221,11 @@ static LLFastTimer::DeclareTimer FTM_IMAGE_UPDATE_CLASS("Class"); static LLFastTimer::DeclareTimer FTM_IMAGE_UPDATE_BUMP("Bump"); static LLFastTimer::DeclareTimer FTM_IMAGE_UPDATE_LIST("List"); static LLFastTimer::DeclareTimer FTM_IMAGE_UPDATE_DELETE("Delete"); +static LLFastTimer::DeclareTimer FTM_RESIZE_WINDOW("Resize Window"); +static LLFastTimer::DeclareTimer FTM_HUD_UPDATE("HUD Update"); +static LLFastTimer::DeclareTimer FTM_DISPLAY_UPDATE_GEOM("Update Geom"); +static LLFastTimer::DeclareTimer FTM_TEXTURE_UNBIND("Texture Unbind"); +static LLFastTimer::DeclareTimer FTM_TELEPORT_DISPLAY("Teleport Display"); // Paint the display! void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) @@ -226,6 +235,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) if (gWindowResized) { //skip render on frames where window has been resized + LLFastTimer t(FTM_RESIZE_WINDOW); gGL.flush(); glClear(GL_COLOR_BUFFER_BIT); gViewerWindow->getWindow()->swapBuffers(); @@ -362,6 +372,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) if (gTeleportDisplay) { + LLFastTimer t(FTM_TELEPORT_DISPLAY); LLAppViewer::instance()->pingMainloopTimeout("Display:Teleport"); const F32 TELEPORT_ARRIVAL_DELAY = 2.f; // Time to preload the world before raising the curtain after we've actually already arrived. @@ -383,21 +394,30 @@ 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"]); + LLAgent::sTeleportProgressMessages["requesting"]); + gViewerWindow->setProgressString(LLAgent::sTeleportProgressMessages["requesting"]); break; case LLAgent::TELEPORT_REQUESTED: // Waiting for source simulator to respond gViewerWindow->setProgressPercent( llmin(teleport_percent, 37.5f) ); - gViewerWindow->setProgressString(message); + gViewerWindow->setProgressString(message); break; case LLAgent::TELEPORT_MOVING: @@ -415,7 +435,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) gAgent.setTeleportMessage( LLAgent::sTeleportProgressMessages["arriving"]); gTextureList.mForceResetTextureStats = TRUE; - gAgentCamera.resetView(TRUE, TRUE); + gAgentCamera.resetView(TRUE, TRUE); break; @@ -450,7 +470,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) case LLAgent::TELEPORT_NONE: // No teleport in progress gViewerWindow->setShowProgress(FALSE); - gTeleportDisplay = FALSE; + gTeleportDisplay = FALSE; break; } } @@ -582,6 +602,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) // *TODO: merge these two methods { + LLFastTimer t(FTM_HUD_UPDATE); LLMemType mt_uh(LLMemType::MTYPE_DISPLAY_UPDATE_HUD); LLHUDManager::getInstance()->updateEffects(); LLHUDObject::updateAll(); @@ -589,6 +610,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) } { + LLFastTimer t(FTM_DISPLAY_UPDATE_GEOM); LLMemType mt_ug(LLMemType::MTYPE_DISPLAY_UPDATE_GEOM); const F32 max_geom_update_time = 0.005f*10.f*gFrameIntervalSeconds; // 50 ms/second update time gPipeline.createObjects(max_geom_update_time); @@ -598,6 +620,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) } gPipeline.updateGL(); + stop_glerror(); S32 water_clip = 0; @@ -623,11 +646,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 @@ -756,13 +774,13 @@ 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(); LLGLState::checkClientArrays(); @@ -890,6 +908,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) { @@ -912,14 +952,18 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) stop_glerror(); } - for (U32 i = 0; i < gGLManager.mNumTextureImageUnits; i++) - { //dummy cleanup of any currently bound textures - if (gGL.getTexUnit(i)->getCurrType() != LLTexUnit::TT_NONE) - { - gGL.getTexUnit(i)->unbind(gGL.getTexUnit(i)->getCurrType()); - gGL.getTexUnit(i)->disable(); + { + LLFastTimer t(FTM_TEXTURE_UNBIND); + for (U32 i = 0; i < gGLManager.mNumTextureImageUnits; i++) + { //dummy cleanup of any currently bound textures + if (gGL.getTexUnit(i)->getCurrType() != LLTexUnit::TT_NONE) + { + gGL.getTexUnit(i)->unbind(gGL.getTexUnit(i)->getCurrType()); + gGL.getTexUnit(i)->disable(); + } } } + LLAppViewer::instance()->pingMainloopTimeout("Display:RenderFlush"); if (to_texture) @@ -985,6 +1029,8 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) display_stats(); LLAppViewer::instance()->pingMainloopTimeout("Display:Done"); + + gShiftFrame = false; } void render_hud_attachments() diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index 225afa5e03..1f7cf0cdd4 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" @@ -103,6 +102,7 @@ #include "llfloatersidepanelcontainer.h" #include "llfloatersnapshot.h" #include "llfloatersounddevices.h" +#include "llfloaterspellchecksettings.h" #include "llfloatertelehub.h" #include "llfloatertestinspectors.h" #include "llfloatertestlistview.h" @@ -260,7 +260,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>); @@ -310,7 +313,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/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 f029ae5302..5d1aa870a3 100644 --- a/indra/newview/llviewerjointmesh.cpp +++ b/indra/newview/llviewerjointmesh.cpp @@ -729,8 +729,10 @@ void LLViewerJointMesh::updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_w F32* vw = (F32*) vertex_weightsp.get(); F32* cw = (F32*) clothing_weightsp.get(); - LLVector4a::memcpyNonAliased16(tc, (F32*) mMesh->getTexCoords(), num_verts*2*sizeof(F32)); - LLVector4a::memcpyNonAliased16(vw, (F32*) mMesh->getWeights(), num_verts*sizeof(F32)); + S32 tc_size = (num_verts*2*sizeof(F32)+0xF) & ~0xF; + LLVector4a::memcpyNonAliased16(tc, (F32*) mMesh->getTexCoords(), tc_size); + S32 vw_size = (num_verts*sizeof(F32)+0xF) & ~0xF; + LLVector4a::memcpyNonAliased16(vw, (F32*) mMesh->getWeights(), vw_size); LLVector4a::memcpyNonAliased16(cw, (F32*) mMesh->getClothingWeights(), num_verts*4*sizeof(F32)); } diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 3eb0538328..01a54509ef 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -88,6 +88,7 @@ #include "llrootview.h" #include "llsceneview.h" #include "llselectmgr.h" +#include "llspellcheckmenuhandler.h" #include "llstatusbar.h" #include "lltextureview.h" #include "lltoolcomp.h" @@ -302,7 +303,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*); @@ -1645,23 +1645,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) @@ -2041,7 +2024,6 @@ class LLAdvancedCompressImage : public view_listener_t }; - ///////////////////////// // SHOW DEBUG SETTINGS // ///////////////////////// @@ -2809,7 +2791,7 @@ bool enable_object_select_in_pathfinding_linksets() bool enable_object_select_in_pathfinding_characters() { - return LLPathfindingManager::getInstance()->isPathfindingEnabledForCurrentRegion() && LLSelectMgr::getInstance()->selectGetCharacter(); + return LLPathfindingManager::getInstance()->isPathfindingEnabledForCurrentRegion() && LLSelectMgr::getInstance()->selectGetViewableCharacters(); } class LLSelfRemoveAllAttachments : public view_listener_t @@ -5158,6 +5140,78 @@ bool enable_object_return() (gAgent.isGodlike() || can_derez(DRD_RETURN_TO_OWNER))); } +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 = @@ -5446,6 +5500,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 { @@ -6818,15 +6880,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; @@ -8152,6 +8205,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. @@ -8233,6 +8299,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"); view_listener_t::addMenu(new LLWorldCreateLandmark(), "World.CreateLandmark"); @@ -8394,7 +8463,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"); diff --git a/indra/newview/llviewermenu.h b/indra/newview/llviewermenu.h index f10891737f..3515aa4302 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 475d9fc5b9..903f4437a7 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> @@ -132,6 +134,7 @@ static const U32 LLREQUEST_PERMISSION_THROTTLE_LIMIT = 5; // requests static const F32 LLREQUEST_PERMISSION_THROTTLE_INTERVAL = 10.0f; // seconds extern BOOL gDebugClicks; +extern bool gShiftFrame; // function prototypes bool check_offer_throttle(const std::string& from_name, bool check_only); @@ -1992,6 +1995,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(); @@ -2770,7 +2813,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; @@ -2795,7 +2842,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; @@ -2814,7 +2861,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; @@ -2879,15 +2926,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; @@ -2896,28 +2982,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; @@ -3441,6 +3629,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); @@ -3460,11 +3651,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; @@ -3734,6 +3931,7 @@ void process_avatar_init_complete(LLMessageSystem* msg, void**) void process_agent_movement_complete(LLMessageSystem* msg, void**) { + gShiftFrame = true; gAgentMovementCompleted = true; LLUUID agent_id; @@ -4064,6 +4262,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) || @@ -4072,19 +4272,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) // { @@ -4092,9 +4293,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; } @@ -4129,6 +4330,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); @@ -4297,8 +4518,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)) { @@ -4321,6 +4540,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); + } } @@ -5401,23 +5626,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; @@ -5426,39 +5663,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) @@ -5502,16 +5848,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)) @@ -5563,6 +5913,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 @@ -5586,7 +5960,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) { @@ -6172,6 +6549,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) { @@ -6201,7 +6581,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 ) { @@ -6230,9 +6610,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 8d658adc8f..31e4fd1ed5 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -199,6 +199,7 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe mID(id), mLocalID(0), mTotalCRC(0), + mListIndex(-1), mTEImages(NULL), mGLName(0), mbCanSelect(TRUE), @@ -432,7 +433,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) @@ -2168,8 +2171,8 @@ BOOL LLViewerObject::isActive() const BOOL LLViewerObject::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) { - static LLFastTimer::DeclareTimer ftm("Viewer Object"); - LLFastTimer t(ftm); + //static LLFastTimer::DeclareTimer ftm("Viewer Object"); + //LLFastTimer t(ftm); if (mDead) { @@ -2388,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); @@ -2797,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 { @@ -2903,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. @@ -4444,7 +4492,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; @@ -4459,7 +4511,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; @@ -4736,9 +4792,11 @@ void LLViewerObject::deleteParticleSource() // virtual void LLViewerObject::updateDrawable(BOOL force_damped) { - if (mDrawable.notNull() && - !mDrawable->isState(LLDrawable::ON_MOVE_LIST) && - isChanged(MOVED)) + if (!isChanged(MOVED)) + { //most common case, having an empty if case here makes for better branch prediction + } + else if (mDrawable.notNull() && + !mDrawable->isState(LLDrawable::ON_MOVE_LIST)) { BOOL damped_motion = !isChanged(SHIFTED) && // not shifted between regions this frame and... diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index 4a33c3a674..f8f6327750 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -45,7 +45,6 @@ #include "llvertexbuffer.h" #include "llbbox.h" #include "llbbox.h" -#include "llviewercontrol.h" class LLAgent; // TODO: Get rid of this. class LLAudioSource; @@ -230,6 +229,8 @@ public: const LLUUID &getID() const { return mID; } U32 getLocalID() const { return mLocalID; } U32 getCRC() const { return mTotalCRC; } + S32 getListIndex() const { return mListIndex; } + void setListIndex(S32 idx) { mListIndex = idx; } virtual BOOL isFlexible() const { return FALSE; } virtual BOOL isSculpted() const { return FALSE; } @@ -432,12 +433,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, @@ -477,8 +481,9 @@ public: inline BOOL flagObjectCopy() const { return ((mFlags & FLAGS_OBJECT_COPY) != 0); } inline BOOL flagObjectMove() const { return ((mFlags & FLAGS_OBJECT_MOVE) != 0); } inline BOOL flagObjectTransfer() const { return ((mFlags & FLAGS_OBJECT_TRANSFER) != 0); } - inline BOOL flagObjectPermanent() const { return gSavedSettings.getBOOL("PathfindingDisablePermanentObjects") ? FALSE : ((mFlags & FLAGS_OBJECT_PERMANENT) != 0); } - inline BOOL flagCharacter() const { return gSavedSettings.getBOOL("PathfindingDisableCharacterObjects") ? FALSE : ((mFlags & FLAGS_CHARACTER) != 0); } + inline BOOL flagObjectPermanent() const { return ((mFlags & FLAGS_AFFECTS_NAVMESH) != 0); } + inline BOOL flagCharacter() const { return ((mFlags & FLAGS_CHARACTER) != 0); } + inline BOOL flagVolumeDetect() const { return ((mFlags & FLAGS_VOLUME_DETECT) != 0); } inline BOOL flagIncludeInSearch() const { return ((mFlags & FLAGS_INCLUDE_IN_SEARCH) != 0); } inline BOOL flagScripted() const { return ((mFlags & FLAGS_SCRIPTED) != 0); } inline BOOL flagHandleTouch() const { return ((mFlags & FLAGS_HANDLE_TOUCH) != 0); } @@ -600,6 +605,9 @@ public: // Last total CRC received from sim, used for caching U32 mTotalCRC; + // index into LLViewerObjectList::mActiveObjects or -1 if not in list + S32 mListIndex; + LLPointer<LLViewerTexture> *mTEImages; // Selection, picking and rendering variables @@ -697,6 +705,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 a0a13b4207..ea20950b36 100644 --- a/indra/newview/llviewerobjectlist.cpp +++ b/indra/newview/llviewerobjectlist.cpp @@ -914,21 +914,30 @@ void LLViewerObjectList::update(LLAgent &agent, LLWorld &world) LLViewerObject *objectp = NULL; // Make a copy of the list in case something in idleUpdate() messes with it - std::vector<LLViewerObject*> idle_list; - + static std::vector<LLViewerObject*> idle_list; + + U32 idle_count = 0; + static LLFastTimer::DeclareTimer idle_copy("Idle Copy"); { LLFastTimer t(idle_copy); - idle_list.reserve( mActiveObjects.size() ); - - for (std::set<LLPointer<LLViewerObject> >::iterator active_iter = mActiveObjects.begin(); + + for (std::vector<LLPointer<LLViewerObject> >::iterator active_iter = mActiveObjects.begin(); active_iter != mActiveObjects.end(); active_iter++) { objectp = *active_iter; if (objectp) { - idle_list.push_back( objectp ); + if (idle_count >= idle_list.size()) + { + idle_list.push_back( objectp ); + } + else + { + idle_list[idle_count] = objectp; + } + ++idle_count; } else { // There shouldn't be any NULL pointers in the list, but they have caused @@ -938,10 +947,13 @@ void LLViewerObjectList::update(LLAgent &agent, LLWorld &world) } } + std::vector<LLViewerObject*>::iterator idle_end = idle_list.begin()+idle_count; + if (gSavedSettings.getBOOL("FreezeTime")) { + for (std::vector<LLViewerObject*>::iterator iter = idle_list.begin(); - iter != idle_list.end(); iter++) + iter != idle_end; iter++) { objectp = *iter; if (objectp->isAvatar()) @@ -953,17 +965,17 @@ void LLViewerObjectList::update(LLAgent &agent, LLWorld &world) else { for (std::vector<LLViewerObject*>::iterator idle_iter = idle_list.begin(); - idle_iter != idle_list.end(); idle_iter++) + idle_iter != idle_end; idle_iter++) { objectp = *idle_iter; - if (!objectp->idleUpdate(agent, world, frame_time)) + if (objectp->idleUpdate(agent, world, frame_time)) { - // If Idle Update returns false, kill object! - kill_list.push_back(objectp); + num_active_objects++; } else { - num_active_objects++; + // If Idle Update returns false, kill object! + kill_list.push_back(objectp); } } for (std::vector<LLViewerObject*>::iterator kill_iter = kill_list.begin(); @@ -1201,7 +1213,7 @@ void LLViewerObjectList::cleanupReferences(LLViewerObject *objectp) { //llinfos << "Removing " << objectp->mID << " " << objectp->getPCodeString() << " from active list in cleanupReferences." << llendl; objectp->setOnActiveList(FALSE); - mActiveObjects.erase(objectp); + removeFromActiveList(objectp); } if (objectp->isOnMap()) @@ -1378,6 +1390,26 @@ void LLViewerObjectList::cleanDeadObjects(BOOL use_timer) mNumDeadObjects = 0; } +void LLViewerObjectList::removeFromActiveList(LLViewerObject* objectp) +{ + S32 idx = objectp->getListIndex(); + if (idx != -1) + { //remove by moving last element to this object's position + llassert(mActiveObjects[idx] == objectp); + + objectp->setListIndex(-1); + + S32 last_index = mActiveObjects.size()-1; + + if (idx != last_index) + { + mActiveObjects[idx] = mActiveObjects[last_index]; + mActiveObjects[idx]->setListIndex(idx); + mActiveObjects.pop_back(); + } + } +} + void LLViewerObjectList::updateActive(LLViewerObject *objectp) { LLMemType mt(LLMemType::MTYPE_OBJECT); @@ -1392,13 +1424,29 @@ void LLViewerObjectList::updateActive(LLViewerObject *objectp) if (active) { //llinfos << "Adding " << objectp->mID << " " << objectp->getPCodeString() << " to active list." << llendl; - mActiveObjects.insert(objectp); - objectp->setOnActiveList(TRUE); + S32 idx = objectp->getListIndex(); + if (idx <= -1) + { + mActiveObjects.push_back(objectp); + objectp->setListIndex(mActiveObjects.size()-1); + objectp->setOnActiveList(TRUE); + } + else + { + llassert(idx < mActiveObjects.size()); + llassert(mActiveObjects[idx] == objectp); + + if (idx >= mActiveObjects.size() || + mActiveObjects[idx] != objectp) + { + llwarns << "Invalid object list index detected!" << llendl; + } + } } else { //llinfos << "Removing " << objectp->mID << " " << objectp->getPCodeString() << " from active list." << llendl; - mActiveObjects.erase(objectp); + removeFromActiveList(objectp); objectp->setOnActiveList(FALSE); } } @@ -1472,6 +1520,10 @@ void LLViewerObjectList::onPhysicsFlagsFetchFailure(const LLUUID& object_id) mPendingPhysicsFlags.erase(object_id); } +static LLFastTimer::DeclareTimer FTM_SHIFT_OBJECTS("Shift Objects"); +static LLFastTimer::DeclareTimer FTM_PIPELINE_SHIFT("Pipeline Shift"); +static LLFastTimer::DeclareTimer FTM_REGION_SHIFT("Region Shift"); + void LLViewerObjectList::shiftObjects(const LLVector3 &offset) { // This is called when we shift our origin when we cross region boundaries... @@ -1483,6 +1535,8 @@ void LLViewerObjectList::shiftObjects(const LLVector3 &offset) return; } + LLFastTimer t(FTM_SHIFT_OBJECTS); + LLViewerObject *objectp; for (vobj_list_t::iterator iter = mObjects.begin(); iter != mObjects.end(); ++iter) { @@ -1499,8 +1553,15 @@ void LLViewerObjectList::shiftObjects(const LLVector3 &offset) } } - gPipeline.shiftObjects(offset); - LLWorld::getInstance()->shiftRegions(offset); + { + LLFastTimer t(FTM_PIPELINE_SHIFT); + gPipeline.shiftObjects(offset); + } + + { + LLFastTimer t(FTM_REGION_SHIFT); + LLWorld::getInstance()->shiftRegions(offset); + } } void LLViewerObjectList::repartitionObjects() @@ -1704,7 +1765,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 64925f46ae..9936432a71 100644 --- a/indra/newview/llviewerobjectlist.h +++ b/indra/newview/llviewerobjectlist.h @@ -118,7 +118,9 @@ public: void dirtyAllObjectInventory(); + void removeFromActiveList(LLViewerObject* objectp); void updateActive(LLViewerObject *objectp); + void updateAvatarVisibility(); // Selection related stuff @@ -197,7 +199,7 @@ protected: typedef std::vector<LLPointer<LLViewerObject> > vobj_list_t; vobj_list_t mObjects; - std::set<LLPointer<LLViewerObject> > mActiveObjects; + std::vector<LLPointer<LLViewerObject> > mActiveObjects; vobj_list_t mMapObjects; 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/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index 204cd2a57a..05c7ef5381 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' @@ -1462,7 +1487,8 @@ void LLViewerRegion::unpackRegionHandshake() // all of our terrain stuff, by if (compp->getParamsReady()) { - getLand().dirtyAllPatches(); + //this line creates frame stalls on region crossing and removing it appears to have no effect + //getLand().dirtyAllPatches(); } else { diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h index 7bf53ba542..c9fffaf30e 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 b2ffb068ff..d9918e633b 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 @@ -180,6 +189,7 @@ LLGLSLShader gDeferredSunProgram; LLGLSLShader gDeferredBlurLightProgram; LLGLSLShader gDeferredSoftenProgram; LLGLSLShader gDeferredShadowProgram; +LLGLSLShader gDeferredShadowCubeProgram; LLGLSLShader gDeferredShadowAlphaMaskProgram; LLGLSLShader gDeferredAvatarShadowProgram; LLGLSLShader gDeferredAttachmentShadowProgram; @@ -439,7 +449,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") && @@ -477,6 +488,7 @@ void LLViewerShaderMgr::setShaders() gSky.mVOSkyp->forceSkyUpdate(); } + // Load lighting shaders mVertexShaderLevel[SHADER_LIGHTING] = light_class; mVertexShaderLevel[SHADER_INTERFACE] = light_class; @@ -486,6 +498,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(); @@ -495,65 +508,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(); @@ -602,7 +659,9 @@ void LLViewerShaderMgr::setShaders() void LLViewerShaderMgr::unloadShaders() { gOcclusionProgram.unload(); + gOcclusionCubeProgram.unload(); gDebugProgram.unload(); + gClipProgram.unload(); gAlphaMaskProgram.unload(); gUIProgram.unload(); gPathfindingProgram.unload(); @@ -696,6 +755,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; @@ -704,6 +769,7 @@ void LLViewerShaderMgr::unloadShaders() mVertexShaderLevel[SHADER_INTERFACE] = 0; mVertexShaderLevel[SHADER_EFFECT] = 0; mVertexShaderLevel[SHADER_WINDLIGHT] = 0; + mVertexShaderLevel[SHADER_TRANSFORM] = 0; gPipeline.mVertexShadersLoaded = 0; } @@ -832,7 +898,7 @@ BOOL LLViewerShaderMgr::loadShadersEnvironment() if (mVertexShaderLevel[SHADER_ENVIRONMENT] == 0) { gTerrainProgram.unload(); - return FALSE; + return TRUE; } if (success) @@ -872,7 +938,7 @@ BOOL LLViewerShaderMgr::loadShadersWater() gWaterProgram.unload(); gUnderWaterProgram.unload(); gTerrainWaterProgram.unload(); - return FALSE; + return TRUE; } if (success) @@ -957,7 +1023,7 @@ BOOL LLViewerShaderMgr::loadShadersEffects() gGlowExtractProgram.unload(); gPostColorFilterProgram.unload(); gPostNightVisionProgram.unload(); - return FALSE; + return TRUE; } if (success) @@ -1017,6 +1083,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredBlurLightProgram.unload(); gDeferredSoftenProgram.unload(); gDeferredShadowProgram.unload(); + gDeferredShadowCubeProgram.unload(); gDeferredShadowAlphaMaskProgram.unload(); gDeferredAvatarShadowProgram.unload(); gDeferredAttachmentShadowProgram.unload(); @@ -1204,7 +1271,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); } @@ -1213,7 +1280,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); @@ -1372,6 +1439,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(); @@ -2414,7 +2491,7 @@ BOOL LLViewerShaderMgr::loadShadersAvatar() gAvatarWaterProgram.unload(); gAvatarEyeballProgram.unload(); gAvatarPickProgram.unload(); - return FALSE; + return TRUE; } if (success) @@ -2508,7 +2585,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface() if (mVertexShaderLevel[SHADER_INTERFACE] == 0) { gHighlightProgram.unload(); - return FALSE; + return TRUE; } if (success) @@ -2671,6 +2748,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)); @@ -2681,6 +2768,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)); @@ -2706,7 +2803,7 @@ BOOL LLViewerShaderMgr::loadShadersWindLight() { gWLSkyProgram.unload(); gWLCloudProgram.unload(); - return FALSE; + return TRUE; } if (success) @@ -2736,6 +2833,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 ceb14870d4..d6dd645e8c 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] @@ -330,6 +343,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 256371552e..8fef13a6bc 100644 --- a/indra/newview/llviewerstats.cpp +++ b/indra/newview/llviewerstats.cpp @@ -793,6 +793,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"]; diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index d844aeb12a..7f638a24bf 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -1398,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 ; diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index 528e0080b7..9a6c0569a9 100644 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -705,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(); diff --git a/indra/newview/llviewervisualparam.h b/indra/newview/llviewervisualparam.h index dd7751acd7..3bc95cbfbf 100644 --- a/indra/newview/llviewervisualparam.h +++ b/indra/newview/llviewervisualparam.h @@ -83,11 +83,11 @@ public: // New Virtual functions virtual F32 getTotalDistortion() = 0; - virtual const LLVector3& getAvgDistortion() = 0; + virtual const LLVector4a& getAvgDistortion() = 0; virtual F32 getMaxDistortion() = 0; - virtual LLVector3 getVertexDistortion(S32 index, LLPolyMesh *mesh) = 0; - virtual const LLVector3* getFirstDistortion(U32 *index, LLPolyMesh **mesh) = 0; - virtual const LLVector3* getNextDistortion(U32 *index, LLPolyMesh **mesh) = 0; + virtual LLVector4a getVertexDistortion(S32 index, LLPolyMesh *mesh) = 0; + virtual const LLVector4a* getFirstDistortion(U32 *index, LLPolyMesh **mesh) = 0; + virtual const LLVector4a* getNextDistortion(U32 *index, LLPolyMesh **mesh) = 0; // interface methods F32 getDisplayOrder() const { return getInfo()->mEditGroupDisplayOrder; } diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 5315568667..af2eec9ba8 100644 --- 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" @@ -614,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; @@ -1705,9 +1706,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); @@ -1979,12 +1977,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()) @@ -1992,17 +1990,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; @@ -4668,6 +4666,8 @@ void LLViewerWindow::stopGL(BOOL save_state) LLVOAvatar::destroyGL(); stop_glerror(); + LLVOPartGroup::destroyGL(); + LLViewerDynamicTexture::destroyGL(); stop_glerror(); @@ -4721,7 +4721,8 @@ void LLViewerWindow::restoreGL(const std::string& progress_message) gBumpImageList.restoreGL(); LLViewerDynamicTexture::restoreGL(); LLVOAvatar::restoreGL(); - + LLVOPartGroup::restoreGL(); + gResizeScreenTexture = TRUE; gWindowResized = TRUE; @@ -4767,8 +4768,11 @@ void LLViewerWindow::requestResolutionUpdate() mResDirty = true; } +static LLFastTimer::DeclareTimer FTM_WINDOW_CHECK_SETTINGS("Window Settings"); + void LLViewerWindow::checkSettings() { + LLFastTimer t(FTM_WINDOW_CHECK_SETTINGS); if (mStatesDirty) { gGL.refreshState(); @@ -5204,8 +5208,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 eada77156e..05febdf93b 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -817,6 +817,7 @@ LLVOAvatar::~LLVOAvatar() lldebugs << "LLVOAvatar Destructor (0x" << this << ") id:" << mID << llendl; mRoot.removeAllChildren(); + mJointMap.clear(); deleteAndClearArray(mSkeleton); deleteAndClearArray(mCollisionVolumes); @@ -961,7 +962,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 ; } } @@ -1459,8 +1460,6 @@ void LLVOAvatar::onShift(const LLVector4a& shift_vector) const LLVector3& shift = reinterpret_cast<const LLVector3&>(shift_vector); mLastAnimExtents[0] += shift; mLastAnimExtents[1] += shift; - mNeedsImpostorUpdate = TRUE; - mNeedsAnimUpdate = TRUE; } void LLVOAvatar::updateSpatialExtents(LLVector4a& newMin, LLVector4a &newMax) @@ -1934,6 +1933,7 @@ void LLVOAvatar::buildCharacter() // remove all of mRoot's children //------------------------------------------------------------------------- mRoot.removeAllChildren(); + mJointMap.clear(); mIsBuilt = FALSE; //------------------------------------------------------------------------- @@ -2094,11 +2094,17 @@ void LLVOAvatar::releaseMeshData() if (mDrawable.notNull()) { LLFace* facep = mDrawable->getFace(0); - facep->setSize(0, 0); - for(S32 i = mNumInitFaces ; i < mDrawable->getNumFaces(); i++) + if (facep) { - facep = mDrawable->getFace(i); facep->setSize(0, 0); + for(S32 i = mNumInitFaces ; i < mDrawable->getNumFaces(); i++) + { + facep = mDrawable->getFace(i); + if (facep) + { + facep->setSize(0, 0); + } + } } } @@ -2183,15 +2189,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); @@ -2379,7 +2390,7 @@ S32 LLVOAvatar::setTETexture(const U8 te, const LLUUID& uuid) } } -static LLFastTimer::DeclareTimer FTM_AVATAR_UPDATE("Update Avatar"); +static LLFastTimer::DeclareTimer FTM_AVATAR_UPDATE("Avatar Update"); static LLFastTimer::DeclareTimer FTM_JOINT_UPDATE("Update Joints"); //------------------------------------------------------------------------ @@ -2681,7 +2692,7 @@ void LLVOAvatar::idleUpdateMisc(bool detailed_update) if (isImpostor() && !mNeedsImpostorUpdate) { - LLVector4a ext[2]; + LL_ALIGN_16(LLVector4a ext[2]); F32 distance; LLVector3 angle; @@ -4236,10 +4247,14 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass) mNeedsSkin = FALSE; mLastSkinTime = gFrameTimeSeconds; - LLVertexBuffer* vb = mDrawable->getFace(0)->getVertexBuffer(); - if (vb) + LLFace * face = mDrawable->getFace(0); + if (face) { - vb->flush(); + LLVertexBuffer* vb = face->getVertexBuffer(); + if (vb) + { + vb->flush(); + } } } } @@ -5122,7 +5137,20 @@ const LLUUID& LLVOAvatar::getID() const // RN: avatar joints are multi-rooted to include screen-based attachments LLJoint *LLVOAvatar::getJoint( const std::string &name ) { - LLJoint* jointp = mRoot.findJoint(name); + joint_map_t::iterator iter = mJointMap.find(name); + + LLJoint* jointp = NULL; + + if (iter == mJointMap.end() || iter->second == NULL) + { //search for joint and cache found joint in lookup table + jointp = mRoot.findJoint(name); + mJointMap[name] = jointp; + } + else + { //return cached pointer + jointp = iter->second; + } + return jointp; } @@ -7492,7 +7520,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); @@ -7529,7 +7557,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; @@ -8395,7 +8423,7 @@ BOOL LLVOAvatar::updateLOD() BOOL res = updateJointLODs(); LLFace* facep = mDrawable->getFace(0); - if (!facep->getVertexBuffer()) + if (!facep || !facep->getVertexBuffer()) { dirtyMesh(2); } diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 6fb56a4c0b..f5692bb52f 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -93,6 +93,16 @@ protected: **/ public: + void* operator new(size_t size) + { + return ll_aligned_malloc_16(size); + } + + void operator delete(void* ptr) + { + ll_aligned_free_16(ptr); + } + LLVOAvatar(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp); virtual void markDead(); static void initClass(); // Initialize data that's only init'd once per class. @@ -215,7 +225,7 @@ public: bool isBuilt() const { return mIsBuilt; } private: //aligned members - LLVector4a mImpostorExtents[2]; + LL_ALIGN_16(LLVector4a mImpostorExtents[2]); private: BOOL mSupportsAlphaLayers; // For backwards compatibility, TRUE for 1.23+ clients @@ -356,6 +366,10 @@ public: LLVector3 mHeadOffset; // current head position LLViewerJoint mRoot; + + typedef std::map<std::string, LLJoint*> joint_map_t; + joint_map_t mJointMap; + protected: static BOOL parseSkeletonFile(const std::string& filename); void buildCharacter(); diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index 93bce9b413..6d672acc32 100644 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -2751,7 +2751,7 @@ void LLVOAvatarSelf::deleteScratchTextures() 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 543891ca63..2b273e616c 100644 --- a/indra/newview/llvoavatarself.h +++ b/indra/newview/llvoavatarself.h @@ -49,6 +49,16 @@ class LLVOAvatarSelf : **/ public: + void* operator new(size_t size) + { + return ll_aligned_malloc_16(size); + } + + void operator delete(void* ptr) + { + ll_aligned_free_16(ptr); + } + LLVOAvatarSelf(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp); virtual ~LLVOAvatarSelf(); virtual void markDead(); diff --git a/indra/newview/llvograss.cpp b/indra/newview/llvograss.cpp index 8a79d564d3..5ad9ccc9af 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->getDataBegin(); i != group->getDataEnd(); ++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/llvopartgroup.cpp b/indra/newview/llvopartgroup.cpp index 5c10a80b07..9cce68fff6 100644 --- a/indra/newview/llvopartgroup.cpp +++ b/indra/newview/llvopartgroup.cpp @@ -48,6 +48,120 @@ const F32 MAX_PART_LIFETIME = 120.f; extern U64 gFrameTime; +LLPointer<LLVertexBuffer> LLVOPartGroup::sVB = NULL; +S32 LLVOPartGroup::sVBSlotFree[]; +S32* LLVOPartGroup::sVBSlotCursor = NULL; + +void LLVOPartGroup::initClass() +{ + for (S32 i = 0; i < LL_MAX_PARTICLE_COUNT; ++i) + { + sVBSlotFree[i] = i; + } + + sVBSlotCursor = sVBSlotFree; +} + +//static +void LLVOPartGroup::restoreGL() +{ + 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 +176,6 @@ LLVOPartGroup::~LLVOPartGroup() { } - BOOL LLVOPartGroup::isActive() const { return FALSE; @@ -287,9 +400,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 +471,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 +507,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; @@ -419,7 +557,7 @@ void LLParticlePartition::addGeometryCount(LLSpatialGroup* group, U32& vertex_co mFaceList.clear(); LLViewerCamera* camera = LLViewerCamera::getInstance(); - for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i) + for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) { LLDrawable* drawablep = *i; @@ -431,11 +569,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 +580,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 +595,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 +621,45 @@ 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->isState(LLFace::PARTICLE)) + { //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); + facep->setState(LLFace::PARTICLE); + } + 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 +668,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 +710,6 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group) } } - buffer->flush(); mFaceList.clear(); } diff --git a/indra/newview/llvopartgroup.h b/indra/newview/llvopartgroup.h index e58fed86d9..43b2844f07 100644 --- a/indra/newview/llvopartgroup.h +++ b/indra/newview/llvopartgroup.h @@ -31,18 +31,33 @@ #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 initClass(); + 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..337ddfb24d 100644 --- a/indra/newview/llvotree.cpp +++ b/indra/newview/llvotree.cpp @@ -374,7 +374,7 @@ BOOL LLVOTree::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) // *TODO: I don't know what's so special about trees // that they don't get REBUILD_POSITION automatically // at a higher level. - const LLVector3 &this_position = getPositionAgent(); + const LLVector3 &this_position = getPositionRegion(); if (this_position != mLastPosition) { gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_POSITION); @@ -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; @@ -837,10 +843,10 @@ void LLVOTree::updateMesh() LLMatrix4 matrix; // Translate to tree base HACK - adjustment in Z plants tree underground - const LLVector3 &pos_agent = getPositionAgent(); + const LLVector3 &pos_region = getPositionRegion(); //gGL.translatef(pos_agent.mV[VX], pos_agent.mV[VY], pos_agent.mV[VZ] - 0.1f); LLMatrix4 trans_mat; - trans_mat.setTranslation(pos_agent.mV[VX], pos_agent.mV[VY], pos_agent.mV[VZ] - 0.1f); + trans_mat.setTranslation(pos_region.mV[VX], pos_region.mV[VY], pos_region.mV[VZ] - 0.1f); trans_mat *= matrix; // Rotate to tree position and bend for current trunk/wind @@ -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 080d1f774a..a656179c8f 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,8 +639,8 @@ BOOL LLVOVolume::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) { LLViewerObject::idleUpdate(agent, world, time); - static LLFastTimer::DeclareTimer ftm("Volume"); - LLFastTimer t(ftm); + //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) @@ -3768,82 +3846,85 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons LLVector4a* weight = vol_face.mWeights; - LLMatrix4a bind_shape_matrix; - bind_shape_matrix.loadu(skin->mBindShapeMatrix); - - LLVector4a* pos = dst_face.mPositions; - + if ( weight ) { - LLFastTimer t(FTM_SKIN_RIGGED); + LLMatrix4a bind_shape_matrix; + bind_shape_matrix.loadu(skin->mBindShapeMatrix); + + LLVector4a* pos = dst_face.mPositions; - for (U32 j = 0; j < dst_face.mNumVertices; ++j) { - LLMatrix4a final_mat; - final_mat.clear(); + LLFastTimer t(FTM_SKIN_RIGGED); - S32 idx[4]; + for (U32 j = 0; j < dst_face.mNumVertices; ++j) + { + LLMatrix4a final_mat; + final_mat.clear(); - LLVector4 wght; + S32 idx[4]; - F32 scale = 0.f; - for (U32 k = 0; k < 4; k++) - { - F32 w = weight[j][k]; + LLVector4 wght; - idx[k] = (S32) floorf(w); - wght[k] = w - floorf(w); - scale += wght[k]; - } + F32 scale = 0.f; + for (U32 k = 0; k < 4; k++) + { + F32 w = weight[j][k]; - wght *= 1.f/scale; + idx[k] = (S32) floorf(w); + wght[k] = w - floorf(w); + scale += wght[k]; + } - for (U32 k = 0; k < 4; k++) - { - F32 w = wght[k]; + wght *= 1.f/scale; - LLMatrix4a src; - src.setMul(mp[idx[k]], w); + for (U32 k = 0; k < 4; k++) + { + F32 w = wght[k]; - final_mat.add(src); - } + LLMatrix4a src; + src.setMul(mp[idx[k]], w); + + final_mat.add(src); + } - LLVector4a& v = vol_face.mPositions[j]; - LLVector4a t; - LLVector4a dst; - bind_shape_matrix.affineTransform(v, t); - final_mat.affineTransform(t, dst); - pos[j] = dst; - } + LLVector4a& v = vol_face.mPositions[j]; + LLVector4a t; + LLVector4a dst; + bind_shape_matrix.affineTransform(v, t); + final_mat.affineTransform(t, dst); + pos[j] = dst; + } - //update bounding box - LLVector4a& min = dst_face.mExtents[0]; - LLVector4a& max = dst_face.mExtents[1]; + //update bounding box + LLVector4a& min = dst_face.mExtents[0]; + LLVector4a& max = dst_face.mExtents[1]; - min = pos[0]; - max = pos[1]; + min = pos[0]; + max = pos[1]; - for (U32 j = 1; j < dst_face.mNumVertices; ++j) - { - min.setMin(min, pos[j]); - max.setMax(max, pos[j]); - } + for (U32 j = 1; j < dst_face.mNumVertices; ++j) + { + min.setMin(min, pos[j]); + max.setMax(max, pos[j]); + } - dst_face.mCenter->setAdd(dst_face.mExtents[0], dst_face.mExtents[1]); - dst_face.mCenter->mul(0.5f); + dst_face.mCenter->setAdd(dst_face.mExtents[0], dst_face.mExtents[1]); + dst_face.mCenter->mul(0.5f); - } + } - { - LLFastTimer t(FTM_RIGGED_OCTREE); - delete dst_face.mOctree; - dst_face.mOctree = NULL; + { + LLFastTimer t(FTM_RIGGED_OCTREE); + delete dst_face.mOctree; + dst_face.mOctree = NULL; - LLVector4a size; - size.setSub(dst_face.mExtents[1], dst_face.mExtents[0]); - size.splat(size.getLength3().getF32()*0.5f); + LLVector4a size; + size.setSub(dst_face.mExtents[1], dst_face.mExtents[0]); + size.splat(size.getLength3().getF32()*0.5f); - dst_face.createOctree(1.f); + dst_face.createOctree(1.f); + } } } } @@ -3902,8 +3983,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 +4019,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 +4037,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 +4132,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 +4165,8 @@ static LLDrawPoolAvatar* get_avatar_drawpool(LLViewerObject* vobj) void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) { + + if (group->changeLOD()) { group->mLastUpdateDistance = group->mDistance; @@ -4084,19 +4178,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(); @@ -4145,359 +4235,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->getDataBegin(); drawable_iter != group->getDataEnd(); ++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()) + if (type != LLDrawPool::POOL_ALPHA && !te->getFullbright()) { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_DEFERRED_BUMP); - } - else - { - 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); + } } } @@ -4539,7 +4645,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) if (!LLPipeline::sDelayVBUpdate) { //drawables have been rebuilt, clear rebuild status - for (LLSpatialGroup::element_iter drawable_iter = group->getData().begin(); drawable_iter != group->getData().end(); ++drawable_iter) + for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter) { LLDrawable* drawablep = *drawable_iter; drawablep->clearState(LLDrawable::REBUILD_ALL); @@ -4564,31 +4670,35 @@ 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; std::set<LLVertexBuffer*> mapped_buffers; - for (LLSpatialGroup::element_iter drawable_iter = group->getData().begin(); drawable_iter != group->getData().end(); ++drawable_iter) + for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++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) { @@ -4598,8 +4708,15 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group) LLVertexBuffer* buff = face->getVertexBuffer(); if (buff) { - face->getGeometryVolume(*volume, face->getTEOffset(), - vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), face->getGeomIndex()); + llassert(!face->isState(LLFace::RIGGED)); + + if (!face->getGeometryVolume(*volume, face->getTEOffset(), + vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), face->getGeomIndex())) + { //something's gone wrong with the vertex buffer accounting, rebuild this group + group->dirtyGeom(); + gPipeline.markRebuild(group, TRUE); + } + if (buff->isLocked()) { @@ -4608,6 +4725,12 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group) } } } + + if (drawablep->isState(LLDrawable::ANIMATED_CHILD)) + { + vobj->updateRelativeXform(); + } + drawablep->clearState(LLDrawable::REBUILD_ALL); } @@ -4630,16 +4753,19 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group) if(num_mapped_veretx_buffer != LLVertexBuffer::sMappedCount) { llwarns << "Not all mapped vertex buffers are unmapped!" << llendl ; - for (LLSpatialGroup::element_iter drawable_iter = group->getData().begin(); drawable_iter != group->getData().end(); ++drawable_iter) + for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter) { LLDrawable* drawablep = *drawable_iter; 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(); + } } } } @@ -4648,7 +4774,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 @@ -4674,8 +4800,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 @@ -4693,15 +4831,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() ; @@ -4766,57 +4907,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 @@ -4826,69 +4996,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(); @@ -4922,10 +5041,25 @@ 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(); - facep->getGeometryVolume(*volume, te_idx, - vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), index_offset); + llassert(!facep->isState(LLFace::RIGGED)); + + if (!facep->getGeometryVolume(*volume, te_idx, + vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), index_offset,true)) + { + llwarns << "Failed to get geometry for face!" << llendl; + } + + if (drawablep->isState(LLDrawable::ANIMATED_CHILD)) + { + vobj->updateRelativeXform(false); + } } } @@ -5089,7 +5223,8 @@ 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) + + for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter) { LLDrawable* drawablep = *drawable_iter; @@ -5109,17 +5244,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) - { - vertex_count += facep->getGeomCount(); - index_count += facep->getIndicesCount(); - llassert(facep->getIndicesCount() < 65536); - //remember face (for sorting) - mFaceList.push_back(facep); - } - else + if (facep) { - 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..8cb69930be 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -68,7 +68,7 @@ class LLVolumeInterface public: virtual ~LLVolumeInterface() { } virtual LLVolumeInterfaceType getInterfaceType() const = 0; - virtual BOOL doIdleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) = 0; + virtual void doIdleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) = 0; virtual BOOL doUpdateGeometry(LLDrawable *drawable) = 0; virtual LLVector3 getPivotPosition() const = 0; virtual void onSetVolume(const LLVolumeParams &volume_params, const S32 detail) = 0; @@ -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 b061c90d98..78ee3e4fd9 100644 --- a/indra/newview/llworld.cpp +++ b/indra/newview/llworld.cpp @@ -657,7 +657,10 @@ void LLWorld::updateRegions(F32 max_update_time) if (did_one && max_time <= 0.f) break; max_time = llmin(max_time, max_update_time*.1f); - did_one |= regionp->idleUpdate(max_update_time); + if (regionp->idleUpdate(max_update_time)) + { + did_one = TRUE; + } } } @@ -837,6 +840,9 @@ void LLWorld::updateWaterObjects() } mHoleWaterObjects.clear(); + // Use the water height of the region we're on for areas where there is no region + F32 water_height = gAgent.getRegion()->getWaterHeight(); + // Now, get a list of the holes S32 x, y; for (x = min_x; x <= max_x; x += rwidth) @@ -845,12 +851,12 @@ void LLWorld::updateWaterObjects() { U64 region_handle = to_region_handle(x, y); if (!getRegionFromHandle(region_handle)) - { + { // No region at that area, so make water LLVOWater* waterp = (LLVOWater *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_WATER, gAgent.getRegion()); waterp->setUseTexture(FALSE); waterp->setPositionGlobal(LLVector3d(x + rwidth/2, y + rwidth/2, - 256.f+DEFAULT_WATER_HEIGHT)); + 256.f + water_height)); waterp->setScale(LLVector3((F32)rwidth, (F32)rwidth, 512.f)); gPipeline.createObject(waterp); mHoleWaterObjects.push_back(waterp); @@ -907,7 +913,7 @@ void LLWorld::updateWaterObjects() } waterp->setRegion(gAgent.getRegion()); - LLVector3d water_pos(water_center_x, water_center_y, 256.f+DEFAULT_WATER_HEIGHT) ; + LLVector3d water_pos(water_center_x, water_center_y, 256.f + 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 eb8c8fa313..7140515e46 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" @@ -116,6 +120,8 @@ //#define DEBUG_INDICES #endif +bool gShiftFrame = false; + //cached settings BOOL LLPipeline::RenderAvatarVP; BOOL LLPipeline::VertexShaderEnable; @@ -213,7 +219,7 @@ BOOL gDebugPipeline = FALSE; LLPipeline gPipeline; const LLMatrix4* gGLLastMatrix = NULL; -LLFastTimer::DeclareTimer FTM_RENDER_GEOMETRY("Geometry"); +LLFastTimer::DeclareTimer FTM_RENDER_GEOMETRY("Render Geometry"); LLFastTimer::DeclareTimer FTM_RENDER_GRASS("Grass"); LLFastTimer::DeclareTimer FTM_RENDER_INVISIBLE("Invisible"); LLFastTimer::DeclareTimer FTM_RENDER_OCCLUSION("Occlusion"); @@ -230,8 +236,13 @@ LLFastTimer::DeclareTimer FTM_RENDER_BUMP("Bump"); LLFastTimer::DeclareTimer FTM_RENDER_FULLBRIGHT("Fullbright"); LLFastTimer::DeclareTimer FTM_RENDER_GLOW("Glow"); LLFastTimer::DeclareTimer FTM_GEO_UPDATE("Geo Update"); +LLFastTimer::DeclareTimer FTM_PIPELINE_CREATE("Pipeline Create"); LLFastTimer::DeclareTimer FTM_POOLRENDER("RenderPool"); LLFastTimer::DeclareTimer FTM_POOLS("Pools"); +LLFastTimer::DeclareTimer FTM_DEFERRED_POOLRENDER("RenderPool (Deferred)"); +LLFastTimer::DeclareTimer FTM_DEFERRED_POOLS("Pools (Deferred)"); +LLFastTimer::DeclareTimer FTM_POST_DEFERRED_POOLRENDER("RenderPool (Post)"); +LLFastTimer::DeclareTimer FTM_POST_DEFERRED_POOLS("Pools (Post)"); LLFastTimer::DeclareTimer FTM_RENDER_BLOOM_FBO("First FBO"); LLFastTimer::DeclareTimer FTM_STATESORT("Sort Draw State"); LLFastTimer::DeclareTimer FTM_PIPELINE("Pipeline"); @@ -267,6 +278,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) { @@ -406,9 +418,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), @@ -507,6 +521,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); @@ -696,6 +715,12 @@ void LLPipeline::destroyGL() { LLVertexBuffer::sEnableVBOs = FALSE; } + + if (mMeshDirtyQueryObject) + { + glDeleteQueriesARB(1, &mMeshDirtyQueryObject); + mMeshDirtyQueryObject = 0; +} } static LLFastTimer::DeclareTimer FTM_RESIZE_SCREEN_TEXTURE("Resize Screen Texture"); @@ -945,6 +970,7 @@ void LLPipeline::refreshCachedSettings() LLPipeline::sUseOcclusion = (!gUseWireframe + && LLGLSLShader::sNoFixedFunction && LLFeatureManager::getInstance()->isFeatureAvailable("UseOcclusion") && gSavedSettings.getBOOL("UseOcclusion") && gGLManager.mHasOcclusionQuery) ? 2 : 0; @@ -1033,13 +1059,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; } @@ -1063,7 +1089,7 @@ void LLPipeline::releaseLUTBuffers() { if (mLightFunc) { - LLImageGL::deleteTextures(1, &mLightFunc); + LLImageGL::deleteTextures(LLTexUnit::TT_TEXTURE, GL_R8, 0, 1, &mLightFunc); mLightFunc = 0; } } @@ -1141,7 +1167,7 @@ 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, false); @@ -1157,7 +1183,7 @@ 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, false); gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); @@ -1213,7 +1239,7 @@ 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, false); gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); @@ -1352,7 +1378,7 @@ public: { LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0); - if (!group->isState(LLSpatialGroup::GEOM_DIRTY) && !group->getData().empty()) + if (!group->isState(LLSpatialGroup::GEOM_DIRTY) && !group->isEmpty()) { for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i) { @@ -1661,7 +1687,7 @@ U32 LLPipeline::addObject(LLViewerObject *vobj) void LLPipeline::createObjects(F32 max_dtime) { - LLFastTimer ftm(FTM_GEO_UPDATE); + LLFastTimer ftm(FTM_PIPELINE_CREATE); LLMemType mt(LLMemType::MTYPE_PIPELINE_CREATE_OBJECTS); LLTimer update_timer; @@ -1823,6 +1849,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); } } @@ -1947,7 +1983,7 @@ void LLPipeline::clearReferences() void check_references(LLSpatialGroup* group, LLDrawable* drawable) { - for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i) + for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) { if (drawable == *i) { @@ -1969,7 +2005,7 @@ void check_references(LLDrawable* drawable, LLFace* face) void check_references(LLSpatialGroup* group, LLFace* face) { - for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i) + for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) { LLDrawable* drawable = *i; check_references(drawable, face); @@ -1981,25 +2017,25 @@ void LLPipeline::checkReferences(LLFace* face) #if 0 if (sCull) { - for (LLCullResult::sg_list_t::iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter) + for (LLCullResult::sg_iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter) { LLSpatialGroup* group = *iter; check_references(group, face); } - for (LLCullResult::sg_list_t::iterator iter = sCull->beginAlphaGroups(); iter != sCull->endAlphaGroups(); ++iter) + for (LLCullResult::sg_iterator iter = sCull->beginAlphaGroups(); iter != sCull->endAlphaGroups(); ++iter) { LLSpatialGroup* group = *iter; check_references(group, face); } - for (LLCullResult::sg_list_t::iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter) + for (LLCullResult::sg_iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter) { LLSpatialGroup* group = *iter; check_references(group, face); } - for (LLCullResult::drawable_list_t::iterator iter = sCull->beginVisibleList(); iter != sCull->endVisibleList(); ++iter) + for (LLCullResult::drawable_iterator iter = sCull->beginVisibleList(); iter != sCull->endVisibleList(); ++iter) { LLDrawable* drawable = *iter; check_references(drawable, face); @@ -2013,25 +2049,25 @@ void LLPipeline::checkReferences(LLDrawable* drawable) #if 0 if (sCull) { - for (LLCullResult::sg_list_t::iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter) + for (LLCullResult::sg_iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter) { LLSpatialGroup* group = *iter; check_references(group, drawable); } - for (LLCullResult::sg_list_t::iterator iter = sCull->beginAlphaGroups(); iter != sCull->endAlphaGroups(); ++iter) + for (LLCullResult::sg_iterator iter = sCull->beginAlphaGroups(); iter != sCull->endAlphaGroups(); ++iter) { LLSpatialGroup* group = *iter; check_references(group, drawable); } - for (LLCullResult::sg_list_t::iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter) + for (LLCullResult::sg_iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter) { LLSpatialGroup* group = *iter; check_references(group, drawable); } - for (LLCullResult::drawable_list_t::iterator iter = sCull->beginVisibleList(); iter != sCull->endVisibleList(); ++iter) + for (LLCullResult::drawable_iterator iter = sCull->beginVisibleList(); iter != sCull->endVisibleList(); ++iter) { if (drawable == *iter) { @@ -2064,19 +2100,19 @@ void LLPipeline::checkReferences(LLDrawInfo* draw_info) #if 0 if (sCull) { - for (LLCullResult::sg_list_t::iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter) + for (LLCullResult::sg_iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter) { LLSpatialGroup* group = *iter; check_references(group, draw_info); } - for (LLCullResult::sg_list_t::iterator iter = sCull->beginAlphaGroups(); iter != sCull->endAlphaGroups(); ++iter) + for (LLCullResult::sg_iterator iter = sCull->beginAlphaGroups(); iter != sCull->endAlphaGroups(); ++iter) { LLSpatialGroup* group = *iter; check_references(group, draw_info); } - for (LLCullResult::sg_list_t::iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter) + for (LLCullResult::sg_iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter) { LLSpatialGroup* group = *iter; check_references(group, draw_info); @@ -2090,7 +2126,7 @@ void LLPipeline::checkReferences(LLSpatialGroup* group) #if 0 if (sCull) { - for (LLCullResult::sg_list_t::iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter) + for (LLCullResult::sg_iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter) { if (group == *iter) { @@ -2098,7 +2134,7 @@ void LLPipeline::checkReferences(LLSpatialGroup* group) } } - for (LLCullResult::sg_list_t::iterator iter = sCull->beginAlphaGroups(); iter != sCull->endAlphaGroups(); ++iter) + for (LLCullResult::sg_iterator iter = sCull->beginAlphaGroups(); iter != sCull->endAlphaGroups(); ++iter) { if (group == *iter) { @@ -2106,7 +2142,7 @@ void LLPipeline::checkReferences(LLSpatialGroup* group) } } - for (LLCullResult::sg_list_t::iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter) + for (LLCullResult::sg_iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter) { if (group == *iter) { @@ -2217,8 +2253,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); @@ -2262,7 +2296,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(); @@ -2294,7 +2337,7 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl if (bound_shader) { - gOcclusionProgram.unbind(); + gOcclusionCubeProgram.unbind(); } camera.disableUserClipPlane(); @@ -2338,7 +2381,7 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl void LLPipeline::markNotCulled(LLSpatialGroup* group, LLCamera& camera) { - if (group->getData().empty()) + if (group->isEmpty()) { return; } @@ -2427,15 +2470,21 @@ 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) + for (LLCullResult::sg_iterator iter = sCull->beginOcclusionGroups(); iter != sCull->endOcclusionGroups(); ++iter) { LLSpatialGroup* group = *iter; group->doOcclusion(&camera); @@ -2446,11 +2495,11 @@ void LLPipeline::doOcclusion(LLCamera& camera) { if (LLPipeline::sShadowRender) { - gDeferredShadowProgram.unbind(); + gDeferredShadowCubeProgram.unbind(); } else { - gOcclusionProgram.unbind(); + gOcclusionCubeProgram.unbind(); } } @@ -2469,22 +2518,41 @@ BOOL LLPipeline::updateDrawableGeom(LLDrawable* drawablep, BOOL priority) return update_complete; } +static LLFastTimer::DeclareTimer FTM_SEED_VBO_POOLS("Seed VBO Pool"); + +static LLFastTimer::DeclareTimer FTM_UPDATE_GL("Update GL"); + void LLPipeline::updateGL() { - while (!LLGLUpdate::sGLQ.empty()) { - LLGLUpdate* glu = LLGLUpdate::sGLQ.front(); - glu->updateGL(); - glu->mInQ = FALSE; - LLGLUpdate::sGLQ.pop_front(); + LLFastTimer t(FTM_UPDATE_GL); + while (!LLGLUpdate::sGLQ.empty()) + { + LLGLUpdate* glu = LLGLUpdate::sGLQ.front(); + glu->updateGL(); + glu->mInQ = FALSE; + LLGLUpdate::sGLQ.pop_front(); + } + + { //seed VBO Pools + LLFastTimer t(FTM_SEED_VBO_POOLS); + LLVertexBuffer::seedPools(); + } + } + + { //seed VBO Pools + LLFastTimer t(FTM_SEED_VBO_POOLS); + LLVertexBuffer::seedPools(); } } +static LLFastTimer::DeclareTimer FTM_REBUILD_PRIORITY_GROUPS("Rebuild Priority Groups"); + void LLPipeline::rebuildPriorityGroups() { + LLFastTimer t(FTM_REBUILD_PRIORITY_GROUPS); LLTimer update_timer; LLMemType mt(LLMemType::MTYPE_PIPELINE); - assertInitialized(); gMeshRepo.notifyLoadedMeshes(); @@ -2503,7 +2571,9 @@ void LLPipeline::rebuildPriorityGroups() mGroupQ1Locked = false; } - + +static LLFastTimer::DeclareTimer FTM_REBUILD_GROUPS("Rebuild Groups"); + void LLPipeline::rebuildGroups() { if (mGroupQ2.empty()) @@ -2511,6 +2581,7 @@ void LLPipeline::rebuildGroups() return; } + LLFastTimer t(FTM_REBUILD_GROUPS); mGroupQ2Locked = true; // Iterate through some drawables on the non-priority build queue S32 size = (S32) mGroupQ2.size(); @@ -2754,6 +2825,10 @@ void LLPipeline::markShift(LLDrawable *drawablep) } } +static LLFastTimer::DeclareTimer FTM_SHIFT_DRAWABLE("Shift Drawable"); +static LLFastTimer::DeclareTimer FTM_SHIFT_OCTREE("Shift Octree"); +static LLFastTimer::DeclareTimer FTM_SHIFT_HUD("Shift HUD"); + void LLPipeline::shiftObjects(const LLVector3 &offset) { LLMemType mt(LLMemType::MTYPE_PIPELINE_SHIFT_OBJECTS); @@ -2766,35 +2841,46 @@ void LLPipeline::shiftObjects(const LLVector3 &offset) LLVector4a offseta; offseta.load3(offset.mV); - for (LLDrawable::drawable_vector_t::iterator iter = mShiftList.begin(); - iter != mShiftList.end(); iter++) { - LLDrawable *drawablep = *iter; - if (drawablep->isDead()) + LLFastTimer t(FTM_SHIFT_DRAWABLE); + + for (LLDrawable::drawable_vector_t::iterator iter = mShiftList.begin(); + iter != mShiftList.end(); iter++) { - continue; - } - drawablep->shiftPos(offseta); - drawablep->clearState(LLDrawable::ON_SHIFT_LIST); + LLDrawable *drawablep = *iter; + if (drawablep->isDead()) + { + continue; + } + drawablep->shiftPos(offseta); + drawablep->clearState(LLDrawable::ON_SHIFT_LIST); + } + mShiftList.resize(0); } - mShiftList.resize(0); - for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); - iter != LLWorld::getInstance()->getRegionList().end(); ++iter) + { - LLViewerRegion* region = *iter; - for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++) + LLFastTimer t(FTM_SHIFT_OCTREE); + for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); + iter != LLWorld::getInstance()->getRegionList().end(); ++iter) { - LLSpatialPartition* part = region->getSpatialPartition(i); - if (part) + LLViewerRegion* region = *iter; + for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++) { - part->shift(offseta); + LLSpatialPartition* part = region->getSpatialPartition(i); + if (part) + { + part->shift(offseta); + } } } } - LLHUDText::shiftAll(offset); - LLHUDNameTag::shiftAll(offset); + { + LLFastTimer t(FTM_SHIFT_HUD); + LLHUDText::shiftAll(offset); + LLHUDNameTag::shiftAll(offset); + } display_update_camera(); } @@ -2827,8 +2913,10 @@ void LLPipeline::markPartitionMove(LLDrawable* drawable) } } +static LLFastTimer::DeclareTimer FTM_PROCESS_PARTITIONQ("PartitionQ"); void LLPipeline::processPartitionQ() { + LLFastTimer t(FTM_PROCESS_PARTITIONQ); for (LLDrawable::drawable_list_t::iterator iter = mPartitionQ.begin(); iter != mPartitionQ.end(); ++iter) { LLDrawable* drawable = *iter; @@ -2843,6 +2931,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); @@ -2939,7 +3032,7 @@ void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result) //LLVertexBuffer::unbind(); grabReferences(result); - for (LLCullResult::sg_list_t::iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter) + for (LLCullResult::sg_iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter) { LLSpatialGroup* group = *iter; group->checkOcclusion(); @@ -2950,7 +3043,7 @@ void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result) else { group->setVisible(); - for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i) + for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) { markVisible(*i, camera); } @@ -2965,9 +3058,9 @@ void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result) if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD) { LLSpatialGroup* last_group = NULL; - for (LLCullResult::bridge_list_t::iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i) + for (LLCullResult::bridge_iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i) { - LLCullResult::bridge_list_t::iterator cur_iter = i; + LLCullResult::bridge_iterator cur_iter = i; LLSpatialBridge* bridge = *cur_iter; LLSpatialGroup* group = bridge->getSpatialGroup(); @@ -2997,7 +3090,7 @@ void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result) } } - for (LLCullResult::sg_list_t::iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter) + for (LLCullResult::sg_iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter) { LLSpatialGroup* group = *iter; group->checkOcclusion(); @@ -3019,7 +3112,7 @@ void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result) { LLFastTimer ftm(FTM_STATESORT_DRAWABLE); - for (LLCullResult::drawable_list_t::iterator iter = sCull->beginVisibleList(); + for (LLCullResult::drawable_iterator iter = sCull->beginVisibleList(); iter != sCull->endVisibleList(); ++iter) { LLDrawable *drawablep = *iter; @@ -3038,7 +3131,7 @@ void LLPipeline::stateSort(LLSpatialGroup* group, LLCamera& camera) LLMemType mt(LLMemType::MTYPE_PIPELINE_STATE_SORT); if (group->changeLOD()) { - for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i) + for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) { LLDrawable* drawablep = *i; stateSort(drawablep, camera); @@ -3155,13 +3248,13 @@ void LLPipeline::stateSort(LLDrawable* drawablep, LLCamera& camera) } -void forAllDrawables(LLCullResult::sg_list_t::iterator begin, - LLCullResult::sg_list_t::iterator end, +void forAllDrawables(LLCullResult::sg_iterator begin, + LLCullResult::sg_iterator end, void (*func)(LLDrawable*)) { - for (LLCullResult::sg_list_t::iterator i = begin; i != end; ++i) + for (LLCullResult::sg_iterator i = begin; i != end; ++i) { - for (LLSpatialGroup::element_iter j = (*i)->getData().begin(); j != (*i)->getData().end(); ++j) + for (LLSpatialGroup::element_iter j = (*i)->getDataBegin(); j != (*i)->getDataEnd(); ++j) { func(*j); } @@ -3194,7 +3287,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); + } } } } @@ -3220,7 +3317,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); + } } } } @@ -3245,7 +3346,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); + } } } } @@ -3281,7 +3386,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); + } } } } @@ -3306,7 +3415,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); + } } } } @@ -3324,7 +3437,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); + } } } } @@ -3339,7 +3456,7 @@ void LLPipeline::postSort(LLCamera& camera) llpushcallstacks ; //rebuild drawable geometry - for (LLCullResult::sg_list_t::iterator i = sCull->beginDrawableGroups(); i != sCull->endDrawableGroups(); ++i) + for (LLCullResult::sg_iterator i = sCull->beginDrawableGroups(); i != sCull->endDrawableGroups(); ++i) { LLSpatialGroup* group = *i; if (!sUseOcclusion || @@ -3355,23 +3472,9 @@ 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) + for (LLCullResult::sg_iterator i = sCull->beginVisibleGroups(); i != sCull->endVisibleGroups(); ++i) { LLSpatialGroup* group = *i; if (sUseOcclusion && @@ -3442,10 +3545,42 @@ 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) @@ -3519,7 +3654,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; } @@ -3528,6 +3667,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 ; } @@ -4011,7 +4177,7 @@ void LLPipeline::renderGeomDeferred(LLCamera& camera) LLMemType mt_rgd(LLMemType::MTYPE_PIPELINE_RENDER_GEOM_DEFFERRED); LLFastTimer t(FTM_RENDER_GEOMETRY); - LLFastTimer t2(FTM_POOLS); + LLFastTimer t2(FTM_DEFERRED_POOLS); LLGLEnable cull(GL_CULL_FACE); @@ -4053,7 +4219,7 @@ void LLPipeline::renderGeomDeferred(LLCamera& camera) pool_set_t::iterator iter2 = iter1; if (hasRenderType(poolp->getType()) && poolp->getNumDeferredPasses() > 0) { - LLFastTimer t(FTM_POOLRENDER); + LLFastTimer t(FTM_DEFERRED_POOLRENDER); gGLLastMatrix = NULL; gGL.loadMatrix(gGLModelView); @@ -4106,7 +4272,7 @@ void LLPipeline::renderGeomDeferred(LLCamera& camera) void LLPipeline::renderGeomPostDeferred(LLCamera& camera) { LLMemType mt_rgpd(LLMemType::MTYPE_PIPELINE_RENDER_GEOM_POST_DEF); - LLFastTimer t(FTM_POOLS); + LLFastTimer t(FTM_POST_DEFERRED_POOLS); U32 cur_type = 0; LLGLEnable cull(GL_CULL_FACE); @@ -4140,7 +4306,7 @@ void LLPipeline::renderGeomPostDeferred(LLCamera& camera) pool_set_t::iterator iter2 = iter1; if (hasRenderType(poolp->getType()) && poolp->getNumPostDeferredPasses() > 0) { - LLFastTimer t(FTM_POOLRENDER); + LLFastTimer t(FTM_POST_DEFERRED_POOLRENDER); gGLLastMatrix = NULL; gGL.loadMatrix(gGLModelView); @@ -4330,7 +4496,7 @@ void LLPipeline::renderPhysicsDisplay() } } - for (LLCullResult::bridge_list_t::const_iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i) + for (LLCullResult::bridge_iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i) { LLSpatialBridge* bridge = *i; if (!bridge->isDead() && hasRenderType(bridge->mDrawableType)) @@ -4358,7 +4524,7 @@ void LLPipeline::renderDebug() LLMemType mt(LLMemType::MTYPE_PIPELINE); assertInitialized(); - + bool hud_only = hasRenderType(LLPipeline::RENDER_TYPE_HUD); if (!hud_only ) @@ -4694,7 +4860,7 @@ void LLPipeline::renderDebug() gGL.loadMatrix(gGLModelView); gGL.setColorMask(true, false); - + if (!hud_only && !mDebugBlips.empty()) { //render debug blips if (LLGLSLShader::sNoFixedFunction) @@ -4752,7 +4918,7 @@ void LLPipeline::renderDebug() } } - for (LLCullResult::bridge_list_t::const_iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i) + for (LLCullResult::bridge_iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i) { LLSpatialBridge* bridge = *i; if (!bridge->isDead() && hasRenderType(bridge->mDrawableType)) @@ -5004,8 +5170,11 @@ void LLPipeline::renderDebug() } } +static LLFastTimer::DeclareTimer FTM_REBUILD_POOLS("Rebuild Pools"); + void LLPipeline::rebuildPools() { + LLFastTimer t(FTM_REBUILD_POOLS); LLMemType mt(LLMemType::MTYPE_PIPELINE_REBUILD_POOLS); assertInitialized(); @@ -6552,24 +6721,32 @@ void LLPipeline::resetVertexBuffers(LLDrawable* drawable) for (S32 i = 0; i < drawable->getNumFaces(); i++) { LLFace* facep = drawable->getFace(i); + if (facep) + { facep->clearVertexBuffer(); } } +} void LLPipeline::resetVertexBuffers() { mResetVertexBuffers = true; } +static LLFastTimer::DeclareTimer FTM_RESET_VB("Reset VB"); + void LLPipeline::doResetVertexBuffers() { if (!mResetVertexBuffers) { return; } - + + LLFastTimer t(FTM_RESET_VB); mResetVertexBuffers = false; + mCubeVB = NULL; + for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); iter != LLWorld::getInstance()->getRegionList().end(); ++iter) { @@ -6592,11 +6769,15 @@ void LLPipeline::doResetVertexBuffers() { LLPathingLib::getInstance()->cleanupVBOManager(); } + LLVOPartGroup::destroyGL(); + LLVertexBuffer::cleanupClass(); //delete all name pool caches LLGLNamePool::cleanupPools(); + + if (LLVertexBuffer::sGLCount > 0) { llwarns << "VBO wipe failed -- " << LLVertexBuffer::sGLCount << " buffers remaining." << llendl; @@ -6616,6 +6797,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) @@ -7037,7 +7220,7 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield) shader->uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF); shader->uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale); - + gGL.begin(LLRender::TRIANGLE_STRIP); gGL.texCoord2f(tc1.mV[0], tc1.mV[1]); gGL.vertex2f(-1,-1); @@ -7183,7 +7366,7 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield) mFXAABuffer.bindTexture(0, channel); gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); } - + gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft; gGLViewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom; gGLViewport[2] = gViewerWindow->getWorldViewRectRaw().getWidth(); @@ -7803,11 +7986,16 @@ 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) @@ -7835,7 +8023,7 @@ void LLPipeline::renderDeferredLighting() F32 s = volume->getLightRadius()*1.5f; LLColor3 col = volume->getLightColor(); - + if (col.magVecSquared() < 0.001f) { continue; @@ -7855,24 +8043,6 @@ 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 || @@ -7890,16 +8060,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(); } } @@ -7912,6 +8079,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)); } @@ -7924,7 +8094,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); @@ -7942,36 +8112,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); @@ -8003,8 +8154,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()) @@ -8057,7 +8206,7 @@ void LLPipeline::renderDeferredLighting() setupSpotLight(gDeferredMultiSpotLightProgram, drawablep); LLColor3 col = volume->getLightColor(); - + gDeferredMultiSpotLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, tc.v); gDeferredMultiSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s*s); gDeferredMultiSpotLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV); @@ -8662,7 +8811,7 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera if (use_shader) { - gDeferredShadowProgram.bind(); + gDeferredShadowCubeProgram.bind(); } updateCull(shadow_cam, result); @@ -8679,17 +8828,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(); { @@ -8697,6 +8839,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); @@ -8746,7 +8892,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); @@ -9021,6 +9167,8 @@ void LLPipeline::generateHighlight(LLCamera& camera) } +static LLFastTimer::DeclareTimer FTM_GEN_SUN_SHADOW("Gen Sun Shadow"); + void LLPipeline::generateSunShadow(LLCamera& camera) { if (!sRenderDeferred || RenderShadowDetail <= 0) @@ -9028,6 +9176,8 @@ void LLPipeline::generateSunShadow(LLCamera& camera) return; } + LLFastTimer t(FTM_GEN_SUN_SHADOW); + BOOL skip_avatar_update = FALSE; if (!isAgentAvatarValid() || gAgentCamera.getCameraAnimating() || gAgentCamera.getCameraMode() != CAMERA_MODE_MOUSELOOK || !LLVOAvatar::sVisibleInFirstPerson) { @@ -9196,7 +9346,7 @@ void LLPipeline::generateSunShadow(LLCamera& camera) da = powf(da, split_exp.mV[2]); F32 sxp = split_exp.mV[1] + (split_exp.mV[0]-split_exp.mV[1])*da; - + for (U32 i = 0; i < 4; ++i) { F32 x = (F32)(i+1)/4.f; @@ -9777,7 +9927,7 @@ void LLPipeline::generateSunShadow(LLCamera& camera) void LLPipeline::renderGroups(LLRenderPass* pass, U32 type, U32 mask, BOOL texture) { - for (LLCullResult::sg_list_t::iterator i = sCull->beginVisibleGroups(); i != sCull->endVisibleGroups(); ++i) + for (LLCullResult::sg_iterator i = sCull->beginVisibleGroups(); i != sCull->endVisibleGroups(); ++i) { LLSpatialGroup* group = *i; if (!group->isDead() && @@ -9790,6 +9940,12 @@ void LLPipeline::renderGroups(LLRenderPass* pass, U32 type, U32 mask, BOOL textu } } +static LLFastTimer::DeclareTimer FTM_IMPOSTOR_MARK_VISIBLE("Impostor Mark Visible"); +static LLFastTimer::DeclareTimer FTM_IMPOSTOR_SETUP("Impostor Setup"); +static LLFastTimer::DeclareTimer FTM_IMPOSTOR_BACKGROUND("Impostor Background"); +static LLFastTimer::DeclareTimer FTM_IMPOSTOR_ALLOCATE("Impostor Allocate"); +static LLFastTimer::DeclareTimer FTM_IMPOSTOR_RESIZE("Impostor Resize"); + void LLPipeline::generateImpostor(LLVOAvatar* avatar) { LLMemType mt_gi(LLMemType::MTYPE_PIPELINE_GENERATE_IMPOSTOR); @@ -9845,101 +10001,114 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) sImpostorRender = TRUE; LLViewerCamera* viewer_camera = LLViewerCamera::getInstance(); - markVisible(avatar->mDrawable, *viewer_camera); - LLVOAvatar::sUseImpostors = FALSE; - LLVOAvatar::attachment_map_t::iterator iter; - for (iter = avatar->mAttachmentPoints.begin(); - iter != avatar->mAttachmentPoints.end(); - ++iter) { - LLViewerJointAttachment *attachment = iter->second; - for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); - attachment_iter != attachment->mAttachedObjects.end(); - ++attachment_iter) + LLFastTimer t(FTM_IMPOSTOR_MARK_VISIBLE); + markVisible(avatar->mDrawable, *viewer_camera); + LLVOAvatar::sUseImpostors = FALSE; + + LLVOAvatar::attachment_map_t::iterator iter; + for (iter = avatar->mAttachmentPoints.begin(); + iter != avatar->mAttachmentPoints.end(); + ++iter) { - if (LLViewerObject* attached_object = (*attachment_iter)) + LLViewerJointAttachment *attachment = iter->second; + for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); + attachment_iter != attachment->mAttachedObjects.end(); + ++attachment_iter) { - markVisible(attached_object->mDrawable->getSpatialBridge(), *viewer_camera); + if (LLViewerObject* attached_object = (*attachment_iter)) + { + markVisible(attached_object->mDrawable->getSpatialBridge(), *viewer_camera); + } } } } stateSort(*LLViewerCamera::getInstance(), result); - const LLVector4a* ext = avatar->mDrawable->getSpatialExtents(); - LLVector3 pos(avatar->getRenderPosition()+avatar->getImpostorOffset()); - LLCamera camera = *viewer_camera; - - camera.lookAt(viewer_camera->getOrigin(), pos, viewer_camera->getUpAxis()); - LLVector2 tdim; + U32 resY = 0; + U32 resX = 0; + { + LLFastTimer t(FTM_IMPOSTOR_SETUP); + const LLVector4a* ext = avatar->mDrawable->getSpatialExtents(); + LLVector3 pos(avatar->getRenderPosition()+avatar->getImpostorOffset()); - LLVector4a half_height; - half_height.setSub(ext[1], ext[0]); - half_height.mul(0.5f); + camera.lookAt(viewer_camera->getOrigin(), pos, viewer_camera->getUpAxis()); + + LLVector4a half_height; + half_height.setSub(ext[1], ext[0]); + half_height.mul(0.5f); - LLVector4a left; - left.load3(camera.getLeftAxis().mV); - left.mul(left); - left.normalize3fast(); + LLVector4a left; + left.load3(camera.getLeftAxis().mV); + left.mul(left); + left.normalize3fast(); - LLVector4a up; - up.load3(camera.getUpAxis().mV); - up.mul(up); - up.normalize3fast(); + LLVector4a up; + up.load3(camera.getUpAxis().mV); + up.mul(up); + up.normalize3fast(); - tdim.mV[0] = fabsf(half_height.dot3(left).getF32()); - tdim.mV[1] = fabsf(half_height.dot3(up).getF32()); + tdim.mV[0] = fabsf(half_height.dot3(left).getF32()); + tdim.mV[1] = fabsf(half_height.dot3(up).getF32()); - gGL.matrixMode(LLRender::MM_PROJECTION); - gGL.pushMatrix(); + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.pushMatrix(); - F32 distance = (pos-camera.getOrigin()).length(); - F32 fov = atanf(tdim.mV[1]/distance)*2.f*RAD_TO_DEG; - F32 aspect = tdim.mV[0]/tdim.mV[1]; - glh::matrix4f persp = gl_perspective(fov, aspect, 1.f, 256.f); - glh_set_current_projection(persp); - gGL.loadMatrix(persp.m); + F32 distance = (pos-camera.getOrigin()).length(); + F32 fov = atanf(tdim.mV[1]/distance)*2.f*RAD_TO_DEG; + F32 aspect = tdim.mV[0]/tdim.mV[1]; + glh::matrix4f persp = gl_perspective(fov, aspect, 1.f, 256.f); + glh_set_current_projection(persp); + gGL.loadMatrix(persp.m); - gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.pushMatrix(); - glh::matrix4f mat; - camera.getOpenGLTransform(mat.m); + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.pushMatrix(); + glh::matrix4f mat; + camera.getOpenGLTransform(mat.m); - mat = glh::matrix4f((GLfloat*) OGL_TO_CFR_ROTATION) * mat; + mat = glh::matrix4f((GLfloat*) OGL_TO_CFR_ROTATION) * mat; - gGL.loadMatrix(mat.m); - glh_set_current_modelview(mat); + gGL.loadMatrix(mat.m); + glh_set_current_modelview(mat); - glClearColor(0.0f,0.0f,0.0f,0.0f); - gGL.setColorMask(true, true); + glClearColor(0.0f,0.0f,0.0f,0.0f); + gGL.setColorMask(true, true); - // get the number of pixels per angle - F32 pa = gViewerWindow->getWindowHeightRaw() / (RAD_TO_DEG * viewer_camera->getView()); + // get the number of pixels per angle + F32 pa = gViewerWindow->getWindowHeightRaw() / (RAD_TO_DEG * viewer_camera->getView()); - //get resolution based on angle width and height of impostor (double desired resolution to prevent aliasing) - U32 resY = llmin(nhpo2((U32) (fov*pa)), (U32) 512); - U32 resX = llmin(nhpo2((U32) (atanf(tdim.mV[0]/distance)*2.f*RAD_TO_DEG*pa)), (U32) 512); + //get resolution based on angle width and height of impostor (double desired resolution to prevent aliasing) + resY = llmin(nhpo2((U32) (fov*pa)), (U32) 512); + resX = llmin(nhpo2((U32) (atanf(tdim.mV[0]/distance)*2.f*RAD_TO_DEG*pa)), (U32) 512); - if (!avatar->mImpostor.isComplete() || resX != avatar->mImpostor.getWidth() || - resY != avatar->mImpostor.getHeight()) - { - avatar->mImpostor.allocate(resX,resY,GL_RGBA,TRUE,FALSE); + if (!avatar->mImpostor.isComplete()) + { + LLFastTimer t(FTM_IMPOSTOR_ALLOCATE); + avatar->mImpostor.allocate(resX,resY,GL_RGBA,TRUE,FALSE); + + if (LLPipeline::sRenderDeferred) + { + addDeferredAttachments(avatar->mImpostor); + } - if (LLPipeline::sRenderDeferred) + gGL.getTexUnit(0)->bind(&avatar->mImpostor); + gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + } + else if(resX != avatar->mImpostor.getWidth() || + resY != avatar->mImpostor.getHeight()) { - addDeferredAttachments(avatar->mImpostor); + LLFastTimer t(FTM_IMPOSTOR_RESIZE); + avatar->mImpostor.resize(resX,resY,GL_RGBA); } - - gGL.getTexUnit(0)->bind(&avatar->mImpostor); - gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - } - avatar->mImpostor.bindTarget(); + avatar->mImpostor.bindTarget(); + } if (LLPipeline::sRenderDeferred) { @@ -9956,6 +10125,7 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) } { //create alpha mask based on depth buffer (grey out if muted) + LLFastTimer t(FTM_IMPOSTOR_BACKGROUND); if (LLPipeline::sRenderDeferred) { GLuint buff = GL_COLOR_ATTACHMENT0; @@ -10041,22 +10211,22 @@ BOOL LLPipeline::hasRenderBatches(const U32 type) const return sCull->getRenderMapSize(type) > 0; } -LLCullResult::drawinfo_list_t::iterator LLPipeline::beginRenderMap(U32 type) +LLCullResult::drawinfo_iterator LLPipeline::beginRenderMap(U32 type) { return sCull->beginRenderMap(type); } -LLCullResult::drawinfo_list_t::iterator LLPipeline::endRenderMap(U32 type) +LLCullResult::drawinfo_iterator LLPipeline::endRenderMap(U32 type) { return sCull->endRenderMap(type); } -LLCullResult::sg_list_t::iterator LLPipeline::beginAlphaGroups() +LLCullResult::sg_iterator LLPipeline::beginAlphaGroups() { return sCull->beginAlphaGroups(); } -LLCullResult::sg_list_t::iterator LLPipeline::endAlphaGroups() +LLCullResult::sg_iterator LLPipeline::endAlphaGroups() { return sCull->endAlphaGroups(); } diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index 0987faa283..368be1c14d 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, @@ -293,10 +294,10 @@ public: void setLight(LLDrawable *drawablep, BOOL is_light); BOOL hasRenderBatches(const U32 type) const; - LLCullResult::drawinfo_list_t::iterator beginRenderMap(U32 type); - LLCullResult::drawinfo_list_t::iterator endRenderMap(U32 type); - LLCullResult::sg_list_t::iterator beginAlphaGroups(); - LLCullResult::sg_list_t::iterator endAlphaGroups(); + LLCullResult::drawinfo_iterator beginRenderMap(U32 type); + LLCullResult::drawinfo_iterator endRenderMap(U32 type); + LLCullResult::sg_iterator beginAlphaGroups(); + LLCullResult::sg_iterator endAlphaGroups(); void addTrianglesDrawn(S32 index_count, U32 render_type = LLRender::TRIANGLES); @@ -551,6 +552,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]; @@ -602,6 +606,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; @@ -659,6 +664,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; diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index 66bd519dbc..06f8f8c670 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_hardware_settings.xml b/indra/newview/skins/default/xui/de/floater_hardware_settings.xml index ca081aafae..fd6c9a0875 100644 --- a/indra/newview/skins/default/xui/de/floater_hardware_settings.xml +++ b/indra/newview/skins/default/xui/de/floater_hardware_settings.xml @@ -25,6 +25,10 @@ VBO aktivieren: </text> <check_box initial_value="true" label="OpenGL Vertex-Buffer-Objekte aktivieren" name="vbo" tool_tip="Wenn Sie über moderne Grafikhardware verfügen, können Sie durch Aktivieren dieser Option die Geschwindigkeit verbessern. Bei alter Hardware sind die VBO oft schlecht implementiert, was zu Abstürzen führen kann, wenn diese Option aktiviert ist."/> + <text name="tc label"> + S3TC aktivieren: + </text> + <check_box initial_value="true" label="Texturkomprimierung aktivieren (Neustart erforderlich)" name="texture compression" tool_tip="Komprimiert Texturen im Videospeicher, damit höher auflösende Texturen geladen werden können (leichte Beeinträchtigung der Farbqualität)."/> <slider label="Texturen-Cache (MB):" name="GraphicsCardTextureMemory" tool_tip="Speicherplatz, der für Texturen zur Verfügung steht. In der Regel handelt es sich um Grafikkartenspeicher. Ein kleinerer Wert kann die Geschwindigkeit erhöhen, aber auch zu Texturunschärfen führen."/> <spinner label="Nebeldistanzverhältnis:" name="fog"/> <button label="OK" label_selected="OK" name="OK"/> 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/de/floater_stats.xml b/indra/newview/skins/default/xui/de/floater_stats.xml index f6dc9fe15d..92d057a4fe 100644 --- a/indra/newview/skins/default/xui/de/floater_stats.xml +++ b/indra/newview/skins/default/xui/de/floater_stats.xml @@ -14,8 +14,11 @@ <stat_bar label="Pro Sek. gezeichnete KTris" name="ktrissec"/> <stat_bar label="Objektanzahl" name="objs"/> <stat_bar label="Neue Objekte" name="newobjs"/> + <stat_bar label="Objektcache-Trefferrate" name="object_cache_hits"/> </stat_view> <stat_view label="Textur" name="texture"> + <stat_bar label="Cache-Trefferrate" name="texture_cache_hits"/> + <stat_bar label="Cache-Leselatenz" name="texture_cache_read_latency"/> <stat_bar label="Zählen" name="numimagesstat"/> <stat_bar label="Rohanzahl" name="numrawimagesstat"/> <stat_bar label="GL Sp" name="gltexmemstat"/> diff --git a/indra/newview/skins/default/xui/de/floater_texture_ctrl.xml b/indra/newview/skins/default/xui/de/floater_texture_ctrl.xml index 8944c79c7d..5bb96bebc4 100644 --- a/indra/newview/skins/default/xui/de/floater_texture_ctrl.xml +++ b/indra/newview/skins/default/xui/de/floater_texture_ctrl.xml @@ -1,24 +1,35 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="texture picker" title="TEXTUR AUSWÄHLEN"> - <string name="choose_picture"> + <floater.string name="choose_picture"> Zum Auswählen eines Bildes hier klicken - </string> + </floater.string> + <floater.string name="pick title"> + Auswählen: + </floater.string> <text name="Multiple"> Mehrere Texturen </text> + <radio_group name="mode_selection"> + <radio_item label="Inventar" name="inventory" value="0"/> + <radio_item label="Lokal" name="local" value="1"/> + </radio_group> <text name="unknown"> Größe: [DIMENSIONS] </text> <button label="Standard" label_selected="Standard" name="Default"/> - <button label="Keine" label_selected="Keine" name="None"/> <button label="Leer" label_selected="Leer" name="Blank"/> - <check_box label="Ordner anzeigen" name="show_folders_check"/> - <search_editor label="Texturen filtern" name="inventory search editor"/> - <check_box label="Jetzt übernehmen" name="apply_immediate_check"/> + <button label="Keine" label_selected="Keine" name="None"/> <button label="" label_selected="" name="Pipette"/> - <button label="Abbrechen" label_selected="Abbrechen" name="Cancel"/> + <filter_editor label="Texturen filtern" name="inventory search editor"/> + <check_box initial_value="false" label="Ordner anzeigen" name="show_folders_check"/> + <button label="Hinzufügen" label_selected="Hinzufügen" name="l_add_btn"/> + <button label="Entfernen" label_selected="Entfernen" name="l_rem_btn"/> + <button label="Hochladen" label_selected="Hochladen" name="l_upl_btn"/> + <scroll_list name="l_name_list"> + <column label="Name" name="unit_name"/> + <column label="ID" name="unit_id_HIDDEN"/> + </scroll_list> <button label="OK" label_selected="OK" name="Select"/> - <text name="pick title"> - Auswählen: - </text> + <button label="Abbrechen" label_selected="Abbrechen" name="Cancel"/> + <check_box initial_value="true" label="Jetzt übernehmen" name="apply_immediate_check"/> </floater> diff --git a/indra/newview/skins/default/xui/de/floater_texture_fetch_debugger.xml b/indra/newview/skins/default/xui/de/floater_texture_fetch_debugger.xml new file mode 100644 index 0000000000..0f407cb15c --- /dev/null +++ b/indra/newview/skins/default/xui/de/floater_texture_fetch_debugger.xml @@ -0,0 +1,62 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="TexFetchDebugger" title="Debugger für Texturabruffehler"> + <text name="total_num_fetched_label"> + 1, Gesamtzahl abgerufener Texturen: [NUM] + </text> + <text name="total_num_fetching_requests_label"> + 2, Gesamtzahl von Abrufanforderungen: [NUM] + </text> + <text name="total_num_cache_hits_label"> + 3, Gesamtzahl von Cachetreffern: [NUM] + </text> + <text name="total_num_visible_tex_label"> + 4, Gesamtzahl sichtbarer Texturen: [NUM] + </text> + <text name="total_num_visible_tex_fetch_req_label"> + 5, Gesamtzahl von Abrufanforderungen für sichtbare Texturen: [NUM] + </text> + <text name="total_fetched_data_label"> + 6, Gesamtmenge abgerufener Daten: [SIZE1] KB, decodierte Daten: [SIZE2] KB, [PIXEL] MPixel + </text> + <text name="total_fetched_vis_data_label"> + 7, Gesamtmenge sichtbarer Daten: [SIZE1] KB, decodierte Daten: [SIZE2] KB + </text> + <text name="total_fetched_rendered_data_label"> + 8, Gesamtmenge dargestellter Daten: [SIZE1] KB, decodierte Daten: [SIZE2] KB, [PIXEL] MPixel + </text> + <text name="total_time_cache_read_label"> + 9, Gesamtzeit Cache-Lesezugriffe: [TIME] s + </text> + <text name="total_time_cache_write_label"> + 10, Gesamtzeit Cache-Schreibzugriffe: [TIME] s + </text> + <text name="total_time_decode_label"> + 11, Gesamtzeit Decodierung: [TIME] s + </text> + <text name="total_time_gl_label"> + 12, Gesamtzeit GL-Texturerstellung: [TIME] s + </text> + <text name="total_time_http_label"> + 13, Gesamtzeit HTTP-Abrufe: [TIME] s + </text> + <text name="total_time_fetch_label"> + 14, Gesamtzeit für alle Abrufe: [TIME] s + </text> + <text name="total_time_refetch_vis_cache_label"> + 15, Neuabruf sichtbarer Texturen aus Cache, Zeit: [TIME] s, Abrufmenge: [SIZE2] KB, [PIXEL] MPixel + </text> + <text name="total_time_refetch_vis_http_label"> + 16, Neuabruf sichtbarer Texturen von HTTP, Zeit: [TIME] s, Abrufmenge: [SIZE2] KB, [PIXEL] MPixel + </text> + <spinner label="17, Verhältnis Texel/Pixel:" name="texel_pixel_ratio"/> + <button label="Starten" name="start_btn"/> + <button label="Zurücksetzen" name="clear_btn"/> + <button label="Schließen" name="close_btn"/> + <button label="Cache-Lesezugriff" name="cacheread_btn"/> + <button label="Cache-Schreibzugriff" name="cachewrite_btn"/> + <button label="HTTP" name="http_btn"/> + <button label="Decodieren" name="decode_btn"/> + <button label="GL-Textur" name="gl_btn"/> + <button label="Neuabruf sichtbarer Texturen (Cache)" name="refetchviscache_btn"/> + <button label="Neuabruf sichtbarer Texturen (HTTP)" name="refetchvishttp_btn"/> +</floater> diff --git a/indra/newview/skins/default/xui/de/floater_window_size.xml b/indra/newview/skins/default/xui/de/floater_window_size.xml index a2a53e0567..6502f002a1 100644 --- a/indra/newview/skins/default/xui/de/floater_window_size.xml +++ b/indra/newview/skins/default/xui/de/floater_window_size.xml @@ -7,10 +7,17 @@ Fenstergröße einstellen: </text> <combo_box name="window_size_combo" tool_tip="Breite x Höhe"> - <combo_box.item label="1000 x 700 (Standard)" name="item0"/> - <combo_box.item label="1024 x 768" name="item1"/> - <combo_box.item label="1280 x 720 (720p)" name="item2"/> - <combo_box.item label="1920 x 1080 (1080p)" name="item3"/> + <combo_box.item label="1000 x 700 (Standard)" name="item1"/> + <combo_box.item label="1024 x 768 (4:3 XGA)" name="item2"/> + <combo_box.item label="1280 x 720 (16:9 HDTV)" name="item3"/> + <combo_box.item label="1280 x 800 (5:8 WXGA)" name="item4"/> + <combo_box.item label="1280 x 1024 (5:4 SXGA)" name="item5"/> + <combo_box.item label="1440 x 900 (8:5 WSXGA)" name="item7"/> + <combo_box.item label="1600 x 900 (16:9 HD+)" name="item8"/> + <combo_box.item label="1600 x 1200 (4:3 UXGA)" name="item9"/> + <combo_box.item label="1680 x 1050 (8:5 WSXGA+)" name="item10"/> + <combo_box.item label="1920 x 1080 (16:9 HDTV)" name="item11"/> + <combo_box.item label="1920 x 1200 (8:5 WUXGA)" name="item12"/> </combo_box> <button label="Festlegen" name="set_btn"/> <button label="Abbrechen" name="cancel_btn"/> diff --git a/indra/newview/skins/default/xui/de/menu_viewer.xml b/indra/newview/skins/default/xui/de/menu_viewer.xml index d011c7295c..c4c4defab9 100644 --- a/indra/newview/skins/default/xui/de/menu_viewer.xml +++ b/indra/newview/skins/default/xui/de/menu_viewer.xml @@ -21,7 +21,6 @@ <menu_item_call label="Beschäftigt" name="Set Busy"/> </menu> <menu_item_call label="L$ kaufen..." name="Buy and Sell L$"/> - <menu_item_call label="Händler-Outbox..." name="MerchantOutbox"/> <menu_item_call label="Kontoübersicht..." name="Manage My Account"> <menu_item_call.on_click name="ManageMyAccount_url" parameter="WebLaunchJoinNow,http://secondlife.com/account/index.php?lang=de"/> </menu_item_call> @@ -227,11 +226,10 @@ <menu_item_check label="Textur" name="Texture Console"/> <menu_item_check label="Fehler beseitigen" name="Debug Console"/> <menu_item_call label="Meldungen" name="Notifications"/> - <menu_item_check label="Texturgröße" name="Texture Size"/> - <menu_item_check label="Texture-Kategorie" name="Texture Category"/> <menu_item_check label="Schnelle Timer" name="Fast Timers"/> <menu_item_check label="Speicher" name="Memory"/> <menu_item_check label="Szenestatistiken" name="Scene Statistics"/> + <menu_item_call label="Debug-Konsole für Texturabruffehler" name="Texture Fetch Debug Console"/> <menu_item_call label="Info zu Region in Fenster Fehler beseitigen" name="Region Info to Debug Console"/> <menu_item_call label="Gruppeninfo in Fenster Fehler beseitigen" name="Group Info to Debug Console"/> <menu_item_call label="Info zu Fähigkeiten in Fenster Fehler beseitigen" name="Capabilities Info to Debug Console"/> @@ -289,6 +287,12 @@ <menu_item_check label="Komplexität beim Rendern" name="rendercomplexity"/> <menu_item_check label="Byte in Anhängen" name="attachment bytes"/> <menu_item_check label="Formen" name="Sculpt"/> + <menu label="Texturdichte" name="Texture Density"> + <menu_item_check label="Keine" name="None"/> + <menu_item_check label="Aktuelle" name="Current"/> + <menu_item_check label="Gewünschte" name="Desired"/> + <menu_item_check label="Volle" name="Full"/> + </menu> </menu> <menu label="Rendering" name="Rendering"> <menu_item_check label="Achsen" name="Axes"/> @@ -306,7 +310,6 @@ <menu_item_check label="Animationstexturen" name="Animation Textures"/> <menu_item_check label="Texturen deaktivieren" name="Disable Textures"/> <menu_item_check label="Voll-Res-Texturen" name="Rull Res Textures"/> - <menu_item_check label="Texturen prüfen" name="Audit Textures"/> <menu_item_check label="Textur-Atlas (experimentell)" name="Texture Atlas"/> <menu_item_check label="Angehängte Lichter rendern" name="Render Attached Lights"/> <menu_item_check label="Angehängte Partikel rendern" name="Render Attached Particles"/> diff --git a/indra/newview/skins/default/xui/de/notifications.xml b/indra/newview/skins/default/xui/de/notifications.xml index ac068fcd4e..f7274d31e1 100644 --- a/indra/newview/skins/default/xui/de/notifications.xml +++ b/indra/newview/skins/default/xui/de/notifications.xml @@ -502,6 +502,15 @@ Weitere Informationen finden Sie auf [_URL]. </url> <usetemplate ignoretext="Meine Hardware wird nicht unterstützt" name="okcancelignore" notext="Nein" yestext="Ja"/> </notification> + <notification name="IntelOldDriver"> + Wahrscheinlich gibt es einen neueren Treiber für Ihren Grafikchip. Durch Aktualisieren der Grafiktreiber lässt sich die Leistung u. U. beträchtlich verbessern. + + Unter [_URL] nach aktualisierten Treibern suchen? + <url name="url"> + http://www.intel.com/p/de_DE/support/detect/graphics + </url> + <usetemplate ignoretext="Mein Grafiktreiber ist veraltet" name="okcancelignore" notext="Nein" yestext="Ja"/> + </notification> <notification name="UnknownGPU"> Ihr System verwendet eine Grafikkarte, die [APP_NAME] nicht erkennt. Dies passiert dann, wenn die neue Hardware noch nicht mit [APP_NAME] getestet wurde. Wahrscheinlich wird das Programm richtig ausgeführt, aber Sie müssen eventuell ein paar Grafikeinstellungen vornehmen. @@ -2628,16 +2637,12 @@ Ist das OK? </form> </notification> <notification name="ScriptQuestionCaution"> - Das Objekt „<nolink>[OBJECTNAME]</nolink>“, das „[NAME]“ gehört, stellt folgende Anfrage: - -[QUESTIONS] -Wenn Sie diesem Objekt und seinem Ersteller nicht vertrauen, sollten Sie diese Anfrage ablehnen. - -Anfrage gestatten? + Achtung: Das Objekt „<nolink>[OBJECTNAME]</nolink>“ fordert uneingeschränkten Zugriff auf Ihr Linden-Dollar-Konto an. Wenn Sie Zugriff gewähren, kann dieses Objekt jederzeit und ohne weitere Warnung Ihr Konto belasten bzw. ganz leeren. + +Eine solche Anforderung ist nur in seltenen Fällen legitim. Gewähren Sie dem Objekt nur dann Zugriff, wenn Sie genau verstehen, wieso ein solcher Zugriff auf Ihr Konto erforderlich ist. <form name="form"> - <button name="Grant" text="Gewähren"/> + <button name="Grant" text="Uneingeschränkten Zugriff gewähren"/> <button name="Deny" text="Verweigern"/> - <button name="Details" text="Info..."/> </form> </notification> <notification name="ScriptDialog"> @@ -3135,4 +3140,16 @@ Ansonsten können Sie auf der Karte nachsehen und dort Ort suchen, die als „In <global name="You died and have been teleported to your home location"> Sie sind gestorben und wurden zu Ihrem Zuhause teleportiert. </global> + <notification name="LocalBitmapsUpdateFileNotFound"> + [FNAME] wurde nicht gefunden und konnte deshalb nicht aktualisiert werden. +Zukünftige Aktualisierungen dieser Datei werden deaktiviert. + </notification> + <notification name="LocalBitmapsUpdateFailedFinal"> + [FNAME] konnte auch nach [NRETRIES] Versuchen nicht geöffnet oder decodiert werden und gilt als beschädigt. +Zukünftige Aktualisierungen dieser Datei werden deaktiviert. + </notification> + <notification name="LocalBitmapsVerifyFail"> + Versuch, eine ungültige oder nicht lesbare Bilddatei ([FNAME]) hinzuzufügen, die nicht geöffnet oder decodiert werden konnte. +Versuch abgebrochen. + </notification> </notifications> diff --git a/indra/newview/skins/default/xui/de/panel_script_question_toast.xml b/indra/newview/skins/default/xui/de/panel_script_question_toast.xml new file mode 100644 index 0000000000..a2d0237da0 --- /dev/null +++ b/indra/newview/skins/default/xui/de/panel_script_question_toast.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<panel label="script_question_panel" name="panel_script_question_toast"> + <panel label="buttons_panel" name="buttons_panel"/> +</panel> diff --git a/indra/newview/skins/default/xui/de/strings.xml b/indra/newview/skins/default/xui/de/strings.xml index d917d33d12..668a7b35bf 100644 --- a/indra/newview/skins/default/xui/de/strings.xml +++ b/indra/newview/skins/default/xui/de/strings.xml @@ -886,6 +886,9 @@ Warten Sie kurz und versuchen Sie dann noch einmal, sich anzumelden. <string name="ScriptQuestionCautionChatDenied"> Dem Objekt „[OBJECTNAME]“, ein Objekt von „[OWNERNAME]“, in [REGIONNAME] [REGIONPOS], wurde folgende Berechtigung verweigert: [PERMISSIONS]. </string> + <string name="AdditionalPermissionsRequestHeader"> + Wenn Sie dem Objekt Zugriff auf Ihr Konto gewähren, kann dieses außerdem: + </string> <string name="ScriptTakeMoney"> Linden-Dollar (L$) von Ihnen nehmen </string> @@ -919,6 +922,9 @@ Warten Sie kurz und versuchen Sie dann noch einmal, sich anzumelden. <string name="ControlYourCamera"> Kamerasteuerung </string> + <string name="TeleportYourAgent"> + Sie teleportieren + </string> <string name="NotConnected"> Nicht verbunden </string> 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_chat_bar.xml b/indra/newview/skins/default/xui/en/floater_chat_bar.xml index 688a01ce7b..405557242f 100644 --- a/indra/newview/skins/default/xui/en/floater_chat_bar.xml +++ b/indra/newview/skins/default/xui/en/floater_chat_bar.xml @@ -46,6 +46,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/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index ca73883e53..040b66623e 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -46,7 +46,7 @@ tab_group="2" top="0" height="200" - width="254" + width="244" user_resize="true"> <button height="20" @@ -73,18 +73,20 @@ parse_highlights="true" parse_urls="true" left="1" - width="249"> + width="238"> </chat_history> <line_editor bottom="0" + left="3" follows="left|right|bottom" font="SansSerifSmall" height="20" label="To" layout="bottomleft" name="chat_editor" + spellcheck="true" tab_group="3" - width="249"> + width="236"> </line_editor> </layout_panel> </layout_stack> 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_pathfinding_characters.xml b/indra/newview/skins/default/xui/en/floater_pathfinding_characters.xml index 4331e1f340..abe918bfbe 100644 --- a/indra/newview/skins/default/xui/en/floater_pathfinding_characters.xml +++ b/indra/newview/skins/default/xui/en/floater_pathfinding_characters.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater - open_positioning="cascading" + positioning="cascading" can_resize="true" can_tear_off="false" height="273" diff --git a/indra/newview/skins/default/xui/en/floater_pathfinding_console.xml b/indra/newview/skins/default/xui/en/floater_pathfinding_console.xml index 63e626b43b..2629313069 100644 --- a/indra/newview/skins/default/xui/en/floater_pathfinding_console.xml +++ b/indra/newview/skins/default/xui/en/floater_pathfinding_console.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater - open_positioning="cascading" + positioning="cascading" can_tear_off="false" height="498" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/floater_pathfinding_linksets.xml b/indra/newview/skins/default/xui/en/floater_pathfinding_linksets.xml index cd0f57be99..4c6c14f8bf 100644 --- a/indra/newview/skins/default/xui/en/floater_pathfinding_linksets.xml +++ b/indra/newview/skins/default/xui/en/floater_pathfinding_linksets.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater - open_positioning="cascading" + positioning="cascading" can_resize="true" can_tear_off="false" height="395" @@ -184,7 +184,7 @@ <scroll_list.columns label="Description (root prim)" name="description" - dynamic_width="true" /> + width="158" /> <scroll_list.columns label="Owner" name="owner" 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_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_texture_ctrl.xml b/indra/newview/skins/default/xui/en/floater_texture_ctrl.xml index ffb8b842f0..2e29c61cb2 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,26 @@ top_delta="-25" name="Pipette" width="28" /> + <check_box + follows="left|bottom" + height="20" + initial_value="true" + label="Live Preview" + layout="topleft" + left="4" + name="apply_immediate_check" + top="262" + width="120" /> + <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_tools.xml b/indra/newview/skins/default/xui/en/floater_tools.xml index a2fc16ac01..5204efbf65 100644 --- a/indra/newview/skins/default/xui/en/floater_tools.xml +++ b/indra/newview/skins/default/xui/en/floater_tools.xml @@ -2,7 +2,7 @@ <floater positioning="cascading" legacy_header_height="18" - height="580" + height="590" layout="topleft" bg_opaque_image="Window_NoTitle_Foreground" bg_alpha_image="Window_NoTitle_Background" @@ -949,7 +949,7 @@ left="10" length="1" follows="left|top" - height="19" + height="29" layout="topleft" name="Creator:" top_pad="7" @@ -962,7 +962,7 @@ length="1" follows="left|top" left_pad="0" - height="20" + height="29" layout="topleft" name="Creator Name" top_delta="0" @@ -977,7 +977,7 @@ length="1" left="10" follows="left|top" - height="19" + height="29" layout="topleft" name="Owner:" top_pad="3" @@ -989,7 +989,7 @@ type="string" length="1" follows="left|top" - height="20" + height="29" layout="topleft" name="Owner Name" left_pad="0" 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 f9a4acb1e3..1aa55acf2d 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" @@ -1409,15 +1424,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 @@ -3160,12 +3166,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 837637a54e..13f073a1c2 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -2397,6 +2397,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" @@ -4127,9 +4214,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"/> @@ -4137,13 +4222,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> @@ -4151,7 +4234,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 @@ -4159,47 +4242,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"> + <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"> -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, 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"/> @@ -4207,12 +4399,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 @@ -4221,41 +4444,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"/> @@ -4263,11 +4497,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"> @@ -4277,31 +4509,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 @@ -4456,10 +4701,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 @@ -5165,20 +5411,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 @@ -5325,7 +5571,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> @@ -5913,9 +6159,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 @@ -5947,11 +6191,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 @@ -5960,7 +6204,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 @@ -6235,7 +6479,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 @@ -6251,6 +6496,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" type="offer"> Teleport offer sent to [TO_NAME] @@ -7285,6 +7566,30 @@ 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="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 caf7fc85f5..27193a984f 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml @@ -207,13 +207,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/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_item_info.xml b/indra/newview/skins/default/xui/en/sidepanel_item_info.xml index 54a312bd59..c5dfb703e5 100644 --- a/indra/newview/skins/default/xui/en/sidepanel_item_info.xml +++ b/indra/newview/skins/default/xui/en/sidepanel_item_info.xml @@ -11,6 +11,10 @@ name="unknown"> (unknown) </panel.string> + <panel.string + name="unknown_multiple"> + (unknown / multiple) + </panel.string> <panel.string name="public"> (public) diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 064cea5ae7..d5186e4c1b 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -441,6 +441,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). @@ -3897,4 +3898,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_hardware_settings.xml b/indra/newview/skins/default/xui/es/floater_hardware_settings.xml index b96076836b..c351db5eae 100644 --- a/indra/newview/skins/default/xui/es/floater_hardware_settings.xml +++ b/indra/newview/skins/default/xui/es/floater_hardware_settings.xml @@ -25,6 +25,10 @@ Activar VBO: </text> <check_box initial_value="true" label="Activar OpenGL Vertex Buffer Objects" name="vbo" tool_tip="En hardware moderno, habilitar esta opción mejora el rendimiento. Pero en hardware antiguo, el habilitarlo hace que, frecuentemente, se obtenga una implementación pobre de VBO, lo que puede provocarle caídas."/> + <text name="tc label"> + Activar S3TC: + </text> + <check_box initial_value="verdadero" label="Activar la compresión de texturas (requiere reiniciar)" name="texture compression" tool_tip="Comprime las texturas de la memoria de vídeo, lo cual permite cargar texturas de una resolución más alta, pero con una cierta pérdida de calidad del color."/> <slider label="Memoria para texturas (MB):" name="GraphicsCardTextureMemory" tool_tip="Cantidad de memoria asignada a las texturas. Por defecto es la memoria de la tarjeta de vídeo. Reducir esta cantidad puede mejorar el rendimiento, pero también hacer que las texturas se vean borrosas."/> <spinner label="Intensidad de la niebla:" name="fog"/> <button label="OK" label_selected="OK" name="OK"/> 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/es/floater_stats.xml b/indra/newview/skins/default/xui/es/floater_stats.xml index ba4af2e866..d53ae88126 100644 --- a/indra/newview/skins/default/xui/es/floater_stats.xml +++ b/indra/newview/skins/default/xui/es/floater_stats.xml @@ -14,8 +14,11 @@ <stat_bar label="KTris generados por segundo" name="ktrissec"/> <stat_bar label="Objetos en total" name="objs"/> <stat_bar label="Objetos nuevos" name="newobjs"/> + <stat_bar label="Índice de aciertos de caché de objetos" name="object_cache_hits"/> </stat_view> <stat_view label="Textura" name="texture"> + <stat_bar label="Índice de aciertos de caché" name="texture_cache_hits"/> + <stat_bar label="Latencia de lectura de caché" name="texture_cache_read_latency"/> <stat_bar label="Número" name="numimagesstat"/> <stat_bar label="Raw: número" name="numrawimagesstat"/> <stat_bar label="GL Mem" name="gltexmemstat"/> diff --git a/indra/newview/skins/default/xui/es/floater_texture_ctrl.xml b/indra/newview/skins/default/xui/es/floater_texture_ctrl.xml index ed2787ea60..1e566e3e31 100644 --- a/indra/newview/skins/default/xui/es/floater_texture_ctrl.xml +++ b/indra/newview/skins/default/xui/es/floater_texture_ctrl.xml @@ -1,24 +1,35 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="texture picker" title="DESTACADO: TEXTURA"> - <string name="choose_picture"> + <floater.string name="choose_picture"> Pulse para elegir una imagen - </string> + </floater.string> + <floater.string name="pick title"> + Elegir: + </floater.string> <text name="Multiple"> Texturas múltiples </text> + <radio_group name="mode_selection"> + <radio_item label="Inventario" name="inventory" value="0"/> + <radio_item label="Local" name="local" value="1"/> + </radio_group> <text name="unknown"> Tamaño: [DIMENSIONS] </text> <button label="Por defecto" label_selected="Por defecto" name="Default" width="84"/> - <button label="Ninguna" label_selected="Ninguna" left="90" name="None"/> <button label="Blanca" label_selected="Blanca" name="Blank"/> - <check_box label="Ver las carpetas" name="show_folders_check"/> - <search_editor label="Filtrar las texturas" name="inventory search editor"/> - <check_box label="Aplicarlo ahora" name="apply_immediate_check"/> + <button label="Ninguna" label_selected="Ninguna" left="90" name="None"/> <button label="" label_selected="" name="Pipette"/> - <button label="Cancelar" label_selected="Cancelar" name="Cancel"/> + <filter_editor label="Filtrar las texturas" name="inventory search editor"/> + <check_box initial_value="false" label="Ver las carpetas" name="show_folders_check"/> + <button label="Añadir" label_selected="Añadir" name="l_add_btn"/> + <button label="Eliminar" label_selected="Eliminar" name="l_rem_btn"/> + <button label="Subir" label_selected="Subir" name="l_upl_btn"/> + <scroll_list name="l_name_list"> + <column label="Nombre" name="unit_name"/> + <column label="ID" name="unit_id_HIDDEN"/> + </scroll_list> <button label="OK" label_selected="OK" name="Select"/> - <string name="pick title"> - Elegir: - </string> + <button label="Cancelar" label_selected="Cancelar" name="Cancel"/> + <check_box initial_value="true" label="Aplicarlo ahora" name="apply_immediate_check"/> </floater> diff --git a/indra/newview/skins/default/xui/es/floater_texture_fetch_debugger.xml b/indra/newview/skins/default/xui/es/floater_texture_fetch_debugger.xml new file mode 100644 index 0000000000..29fd2ab2a3 --- /dev/null +++ b/indra/newview/skins/default/xui/es/floater_texture_fetch_debugger.xml @@ -0,0 +1,62 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="TexFetchDebugger" title="Depurador de obtención de texturas"> + <text name="total_num_fetched_label"> + 1, Número total de texturas obtenidas: [NUM] + </text> + <text name="total_num_fetching_requests_label"> + 2, Número total de solicitudes de obtención: [NUM] + </text> + <text name="total_num_cache_hits_label"> + 3, Número total de aciertos de caché: [NUM] + </text> + <text name="total_num_visible_tex_label"> + 4, Número total de texturas visibles: [NUM] + </text> + <text name="total_num_visible_tex_fetch_req_label"> + 5, Número total de solicitudes de obtención de texturas visibles: [NUM] + </text> + <text name="total_fetched_data_label"> + 6, Número total de datos obtenidos: [SIZE1] KB, Datos descodificados: [SIZE2] KB, [PIXEL] MPíxeles + </text> + <text name="total_fetched_vis_data_label"> + 7, Número total de datos visibles: [SIZE1] KB, Datos descodificados: [SIZE2] KB + </text> + <text name="total_fetched_rendered_data_label"> + 8, Número total de datos representados: [SIZE1] KB, Datos descodificados: [SIZE2] KB, [PIXEL] MPíxeles + </text> + <text name="total_time_cache_read_label"> + 9, Tiempo total en lecturas de caché: [TIME] segundos + </text> + <text name="total_time_cache_write_label"> + 10, Tiempo total en escrituras de caché: [TIME] segundos + </text> + <text name="total_time_decode_label"> + 11, Tiempo total en descodificaciones: [TIME] segundos + </text> + <text name="total_time_gl_label"> + 12, Tiempo total en la creación de texturas gl: [TIME] segundos + </text> + <text name="total_time_http_label"> + 13, Tiempo total en obtención de HTTP: [TIME] segundos + </text> + <text name="total_time_fetch_label"> + 14, Tiempo total en obtención completa: [TIME] segundos + </text> + <text name="total_time_refetch_vis_cache_label"> + 15, Volviendo a obtener visibles de la caché, Tiempo: [TIME] segundos, Obtenidos: [SIZE] KB, [PIXEL] MPíxeles + </text> + <text name="total_time_refetch_vis_http_label"> + 16, Volviendo a obtener visibles de HTTP, Tiempo: [TIME] segundos, Obtenidos: [SIZE] KB, [PIXEL] MPíxeles + </text> + <spinner label="17, Proporción de texeles/píxeles:" name="texel_pixel_ratio"/> + <button label="Iniciar" name="start_btn"/> + <button label="Restablecer" name="clear_btn"/> + <button label="Cerrar" name="close_btn"/> + <button label="Lectura de caché" name="cacheread_btn"/> + <button label="Escritura de caché" name="cachewrite_btn"/> + <button label="HTTP" name="http_btn"/> + <button label="Descodificar" name="decode_btn"/> + <button label="Textura GL" name="gl_btn"/> + <button label="Volver a obtener caché de vis." name="refetchviscache_btn"/> + <button label="Volver a obtener HTTP de vis." name="refetchvishttp_btn"/> +</floater> diff --git a/indra/newview/skins/default/xui/es/floater_window_size.xml b/indra/newview/skins/default/xui/es/floater_window_size.xml index f57ce08eac..6c1ad02319 100644 --- a/indra/newview/skins/default/xui/es/floater_window_size.xml +++ b/indra/newview/skins/default/xui/es/floater_window_size.xml @@ -7,10 +7,17 @@ Definir el tamaño de la ventana: </text> <combo_box name="window_size_combo" tool_tip="ancho x alto"> - <combo_box.item label="1000 x 700 (por defecto)" name="item0"/> - <combo_box.item label="1024 x 768" name="item1"/> - <combo_box.item label="1280 x 720 (720 p)" name="item2"/> - <combo_box.item label="1920 x 1080 (1080 p)" name="item3"/> + <combo_box.item label="1000 x 700 (por defecto)" name="item1"/> + <combo_box.item label="1024 x 768 (4:3 XGA)" name="item2"/> + <combo_box.item label="1280 x 720 (16:9 HDTV)" name="item3"/> + <combo_box.item label="1280 x 800 (5:8 WXGA)" name="item4"/> + <combo_box.item label="1280 x 1024 (5:4 SXGA)" name="item5"/> + <combo_box.item label="1440 x 900 (8:5 WSXGA)" name="item7"/> + <combo_box.item label="1600 x 900 (16:9 HD+)" name="item8"/> + <combo_box.item label="1600 x 1200 (4:3 UXGA)" name="item9"/> + <combo_box.item label="1680 x 1050 (8:5 WSXGA+)" name="item10"/> + <combo_box.item label="1920 x 1080 (16:9 HDTV)" name="item11"/> + <combo_box.item label="1920 x 1200 (8:5 WUXGA)" name="item12"/> </combo_box> <button label="Configurar" name="set_btn"/> <button label="Cancelar" name="cancel_btn"/> diff --git a/indra/newview/skins/default/xui/es/menu_viewer.xml b/indra/newview/skins/default/xui/es/menu_viewer.xml index 9522d4eac6..740bd35cbb 100644 --- a/indra/newview/skins/default/xui/es/menu_viewer.xml +++ b/indra/newview/skins/default/xui/es/menu_viewer.xml @@ -225,11 +225,10 @@ <menu_item_check label="Texture Console" name="Texture Console"/> <menu_item_check label="Debug Console" name="Debug Console"/> <menu_item_call label="Notifications Console" name="Notifications"/> - <menu_item_check label="Texture Size Console" name="Texture Size"/> - <menu_item_check label="Texture Category Console" name="Texture Category"/> <menu_item_check label="Fast Timers" name="Fast Timers"/> <menu_item_check label="Memory" name="Memory"/> <menu_item_check label="Datos de la escena" name="Scene Statistics"/> + <menu_item_call label="Consola de depuración de obtención de texturas" name="Texture Fetch Debug Console"/> <menu_item_call label="Region Info to Debug Console" name="Region Info to Debug Console"/> <menu_item_check label="Camera" name="Camera"/> <menu_item_check label="Wind" name="Wind"/> @@ -270,6 +269,12 @@ <menu_item_check label="Complejidad del renderizado" name="rendercomplexity"/> <menu_item_check label="Bytes de adjunto" name="attachment bytes"/> <menu_item_check label="Esculpir" name="Sculpt"/> + <menu label="Densidad de textura" name="Texture Density"> + <menu_item_check label="Ninguna" name="None"/> + <menu_item_check label="Actual" name="Current"/> + <menu_item_check label="Deseada" name="Desired"/> + <menu_item_check label="Completa" name="Full"/> + </menu> </menu> <menu label="Rendering" name="Rendering"> <menu_item_check label="Axes" name="Axes"/> diff --git a/indra/newview/skins/default/xui/es/notifications.xml b/indra/newview/skins/default/xui/es/notifications.xml index d47c3d7ad8..af7a7b088a 100644 --- a/indra/newview/skins/default/xui/es/notifications.xml +++ b/indra/newview/skins/default/xui/es/notifications.xml @@ -490,6 +490,15 @@ El objeto debe de haber sido borrado o estar fuera de rango ('out of range& </url> <usetemplate ignoretext="El hardware de mi ordenador no está admitido" name="okcancelignore" notext="No" yestext="Sí"/> </notification> + <notification name="IntelOldDriver"> + Probablemente ya existe un controlador más reciente para tu procesador de gráficos. La actualización del controlador de gráficos puede mejorar sustancialmente el rendimiento. + + ¿Deseas visitar [_URL] para comprobar si hay controladores actualizados? + <url name="url"> + http://www.intel.com/p/es_XL/support/detect/graphics + </url> + <usetemplate ignoretext="Mi controlador de gráficos no está actualizado" name="okcancelignore" notext="No" yestext="Sí"/> + </notification> <notification name="UnknownGPU"> Tu sistema usa una tarjeta gráfica que [APP_NAME] no reconoce. Suele suceder con hardware nuevo que todavía no ha sido probado con [APP_NAME]. Probablemente todo irá bien, pero deberás ajustar tus configuraciones gráficas. @@ -2622,33 +2631,23 @@ Del objeto: <nolink>[OBJECTNAME]</nolink>, propietario: [NAME]? </form> </notification> <notification name="ScriptQuestionCaution"> - Un objeto de nombre '<nolink>[OBJECTNAME]</nolink>', propiedad de '[NAME]', quiere: - -[QUESTIONS] -Si no confias en este objeto y en su creador, deberías rehusar esta petición. - -¿Autorizar esta petición? + Atención: El objeto '<nolink>[OBJECTNAME]</nolink>' solicita un acceso total a tu cuenta de dólares Linden. Si le autorizas el acceso, podrá retirar fondos de tu cuenta en cualquier momento o vaciarla por completo, de manera permanente y sin más advertencias. + +Estas solicitudes pocas veces son legítimas. No autorices el acceso si no conoces la razón exacta por la que desea el acceso a tu cuenta. <form name="form"> - <button name="Grant" text="Autorizar"/> + <button name="Grant" text="Permitir acceso total"/> <button name="Deny" text="Denegar"/> - <button name="Details" text="Detalles..."/> </form> </notification> <notification name="ScriptDialog"> '<nolink>[TITLE]</nolink>' de [NAME] [MESSAGE] - <form name="form"> - <button name="Mute" text="Ignorar"/> - <button name="Ignore" text="Ignorar"/> - </form> + <form name="form"/> </notification> <notification name="ScriptDialogGroup"> '<nolink>[TITLE]</nolink>' de [GROUPNAME] [MESSAGE] - <form name="form"> - <button name="Mute" text="Ignorar"/> - <button name="Ignore" text="Ignorar"/> - </form> + <form name="form"/> </notification> <notification name="BuyLindenDollarSuccess"> ¡Gracias por tu pago! @@ -3126,4 +3125,16 @@ También puedes buscar en el Mapa lugares marcados como "Puntos de Informac <global name="You died and have been teleported to your home location"> Has muerto y te has teleportado a tu Base. </global> + <notification name="LocalBitmapsUpdateFileNotFound"> + [FNAME] no se ha podido actualizar porque el archivo ya no se encuentra. +Desactivando futuras actualizaciones de este archivo. + </notification> + <notification name="LocalBitmapsUpdateFailedFinal"> + [FNAME] se ha intentado abrir o descodificar durante [NRETRIES] intentos sin éxito, y ahora se considera roto. +Desactivando futuras actualizaciones de este archivo. + </notification> + <notification name="LocalBitmapsVerifyFail"> + Se ha intentado añadir un archivo de imagen [FNAME] no válido o ilegible, que no se puede abrir ni descodificar. +Intento cancelado. + </notification> </notifications> diff --git a/indra/newview/skins/default/xui/es/panel_script_question_toast.xml b/indra/newview/skins/default/xui/es/panel_script_question_toast.xml new file mode 100644 index 0000000000..a2d0237da0 --- /dev/null +++ b/indra/newview/skins/default/xui/es/panel_script_question_toast.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<panel label="script_question_panel" name="panel_script_question_toast"> + <panel label="buttons_panel" name="buttons_panel"/> +</panel> diff --git a/indra/newview/skins/default/xui/es/strings.xml b/indra/newview/skins/default/xui/es/strings.xml index 67c65c6ce9..adc32ba168 100644 --- a/indra/newview/skins/default/xui/es/strings.xml +++ b/indra/newview/skins/default/xui/es/strings.xml @@ -871,6 +871,9 @@ Intenta iniciar sesión de nuevo en unos instantes. <string name="ScriptQuestionCautionChatDenied"> A '[OBJECTNAME]', un objeto propiedad de '[OWNERNAME]', localizado en [REGIONNAME] con la posición [REGIONPOS], se le ha denegado el permiso para: [PERMISSIONS]. </string> + <string name="AdditionalPermissionsRequestHeader"> + Si autorizas el acceso a tu cuenta, también permitirás al objeto: + </string> <string name="ScriptTakeMoney"> Cogerle a usted dólares Linden (L$) </string> @@ -904,6 +907,9 @@ Intenta iniciar sesión de nuevo en unos instantes. <string name="ControlYourCamera"> Controlar su cámara </string> + <string name="TeleportYourAgent"> + Teleportarte + </string> <string name="SIM_ACCESS_PG"> General </string> diff --git a/indra/newview/skins/default/xui/fr/floater_hardware_settings.xml b/indra/newview/skins/default/xui/fr/floater_hardware_settings.xml index 2bc76e0c63..098f8fc713 100644 --- a/indra/newview/skins/default/xui/fr/floater_hardware_settings.xml +++ b/indra/newview/skins/default/xui/fr/floater_hardware_settings.xml @@ -25,6 +25,10 @@ Activer le VBO : </text> <check_box initial_value="true" label="Activer OpenGL Vertex Buffer Objects" name="vbo" tool_tip="Sur un matériel moderne, cette option permet une meilleure performance. Par contre, sur un matériel plus ancien, les VBO sont souvent mal implémentés et peuvent causer des crashs lorsqu'ils sont activés."/> + <text name="tc label"> + Activer S3TC : + </text> + <check_box initial_value="vraie" label="Activer la compression des textures (redémarrage requis)" name="texture compression" tool_tip="Comprime les textures en mémoire vidéo afin de permettre de charger des textures de résolution plus élevée au prix d'une certaine qualité de couleur."/> <slider label="Mémoire textures (Mo) :" name="GraphicsCardTextureMemory" tool_tip="Quantité de mémoire à affecter aux textures. Utilise la mémoire de la carte vidéo par défaut. Si vous réduisez ce paramètre, cela peut améliorer les performances, mais les textures risquent d'être floues."/> <spinner label="Indice du brouillard :" name="fog"/> <button label="OK" label_selected="OK" name="OK"/> 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/floater_stats.xml b/indra/newview/skins/default/xui/fr/floater_stats.xml index 2ce2e6dcd5..56fa062d46 100644 --- a/indra/newview/skins/default/xui/fr/floater_stats.xml +++ b/indra/newview/skins/default/xui/fr/floater_stats.xml @@ -14,8 +14,11 @@ <stat_bar label="KTris par s" name="ktrissec"/> <stat_bar label="Objets totaux" name="objs"/> <stat_bar label="Nouveaux objets" name="newobjs"/> + <stat_bar label="Taux de réussite du cache des objets" name="object_cache_hits"/> </stat_view> <stat_view label="Texture" name="texture"> + <stat_bar label="Taux de réussite du cache" name="texture_cache_hits"/> + <stat_bar label="Latence de lecture du cache" name="texture_cache_read_latency"/> <stat_bar label="Nombre" name="numimagesstat"/> <stat_bar label="Nombre brut" name="numrawimagesstat"/> <stat_bar label="Mém GL" name="gltexmemstat"/> @@ -57,7 +60,7 @@ <stat_bar label="Chargements en attente" name="simpendinguploads"/> <stat_bar label="Total Unacked Bytes" name="simtotalunackedbytes"/> <stat_view label="Temps (ms)" name="simperf"> - <stat_bar label="Durée totale de l'image" name="simframemsec"/> + <stat_bar label="Durée totale de l'image" name="simframemsec"/> <stat_bar label="Durée nette" name="simnetmsec"/> <stat_bar label="Durée sim (physique)" name="simsimphysicsmsec"/> <stat_bar label="Durée sim (autre)" name="simsimothermsec"/> diff --git a/indra/newview/skins/default/xui/fr/floater_texture_ctrl.xml b/indra/newview/skins/default/xui/fr/floater_texture_ctrl.xml index 381bcceb00..ca0fbd3589 100644 --- a/indra/newview/skins/default/xui/fr/floater_texture_ctrl.xml +++ b/indra/newview/skins/default/xui/fr/floater_texture_ctrl.xml @@ -1,24 +1,35 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="texture picker" title="CHOISIR : TEXTURE"> - <string name="choose_picture"> + <floater.string name="choose_picture"> Cliquez pour sélectionner une image - </string> + </floater.string> + <floater.string name="pick title"> + Choisir : + </floater.string> <text name="Multiple"> Textures multiples </text> + <radio_group name="mode_selection"> + <radio_item label="Inventaire" name="inventory" value="0"/> + <radio_item label="Local" name="local" value="1"/> + </radio_group> <text name="unknown"> Taille : [DIMENSIONS] </text> <button label="Défaut" label_selected="Défaut" name="Default" width="60"/> - <button label="Aucune" label_selected="Aucune" left="68" name="None" width="60"/> <button label="Vierge" label_selected="Vierge" name="Blank" width="60"/> - <check_box label="Afficher les dossiers" name="show_folders_check"/> - <search_editor label="Filtrer les textures" name="inventory search editor"/> - <check_box label="Appliquer maintenant" name="apply_immediate_check"/> + <button label="Aucune" label_selected="Aucune" left="68" name="None" width="60"/> <button bottom="-240" label="" label_selected="" name="Pipette"/> - <button label="Annuler" label_selected="Annuler" name="Cancel"/> + <filter_editor label="Filtrer les textures" name="inventory search editor"/> + <check_box initial_value="false" label="Afficher les dossiers" name="show_folders_check"/> + <button label="Ajouter" label_selected="Ajouter" name="l_add_btn"/> + <button label="Supprimer" label_selected="Supprimer" name="l_rem_btn"/> + <button label="Charger" label_selected="Charger" name="l_upl_btn"/> + <scroll_list name="l_name_list"> + <column label="Nom" name="unit_name"/> + <column label="ID" name="unit_id_HIDDEN"/> + </scroll_list> <button label="OK" label_selected="OK" name="Select"/> - <string name="pick title"> - Choisir : - </string> + <button label="Annuler" label_selected="Annuler" name="Cancel"/> + <check_box initial_value="true" label="Appliquer maintenant" name="apply_immediate_check"/> </floater> diff --git a/indra/newview/skins/default/xui/fr/floater_texture_fetch_debugger.xml b/indra/newview/skins/default/xui/fr/floater_texture_fetch_debugger.xml new file mode 100644 index 0000000000..f0cc95319d --- /dev/null +++ b/indra/newview/skins/default/xui/fr/floater_texture_fetch_debugger.xml @@ -0,0 +1,62 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="TexFetchDebugger" title="Outil de débogage de la récupération des textures"> + <text name="total_num_fetched_label"> + 1, nombre total de textures récupérées : [NUM] + </text> + <text name="total_num_fetching_requests_label"> + 2, nombre total de demandes de récupération : [NUM] + </text> + <text name="total_num_cache_hits_label"> + 3, nombre total de présences dans le cache : [NUM] + </text> + <text name="total_num_visible_tex_label"> + 4, nombre total de textures visibles : [NUM] + </text> + <text name="total_num_visible_tex_fetch_req_label"> + 5, nombre total de demandes de récupération de textures visibles : [NUM] + </text> + <text name="total_fetched_data_label"> + 6, nombre total de données récupérées : [SIZE1] Ko, données décodées : [SIZE2] Ko, [PIXEL] Mpixels + </text> + <text name="total_fetched_vis_data_label"> + 7, nombre total de données visibles : [SIZE1] Ko, données décodées : [SIZE2] Ko + </text> + <text name="total_fetched_rendered_data_label"> + 8, nombre total de données rendues : [SIZE1] Ko, données décodées : [SIZE2] Ko, [PIXEL] Mpixels + </text> + <text name="total_time_cache_read_label"> + 9, durée totale des lectures du cache : [TIME] secondes + </text> + <text name="total_time_cache_write_label"> + 10, durée totale des écritures du cache : [TIME] secondes + </text> + <text name="total_time_decode_label"> + 11, durée totale des décodages : [TIME] secondes + </text> + <text name="total_time_gl_label"> + 12, durée totale de la création de textures GL : [TIME] secondes + </text> + <text name="total_time_http_label"> + 13, durée totale de la récupération HTTP : [TIME] secondes + </text> + <text name="total_time_fetch_label"> + 14, durée totale de la récupération intégrale : [TIME] secondes + </text> + <text name="total_time_refetch_vis_cache_label"> + 15, nouvelle récupération des données visibles du cache, Durée : [TIME] secondes, Récupéré : [SIZE] Ko, [PIXEL] Mpixels + </text> + <text name="total_time_refetch_vis_http_label"> + 16, nouvelle récupération des données visibles de la requête HTTP, Durée : [TIME] secondes, Récupéré : [SIZE] Ko, [PIXEL] Mpixels + </text> + <spinner label="17, taux de texels/pixels :" name="texel_pixel_ratio"/> + <button label="Démarrer" name="start_btn"/> + <button label="Réinitialiser" name="clear_btn"/> + <button label="Fermer" name="close_btn"/> + <button label="Lecture du cache" name="cacheread_btn"/> + <button label="Écriture du cache" name="cachewrite_btn"/> + <button label="HTTP" name="http_btn"/> + <button label="Décoder" name="decode_btn"/> + <button label="Texture GL" name="gl_btn"/> + <button label="Récupérer à nouveau les données visibles du cache" name="refetchviscache_btn"/> + <button label="Récupérer à nouveau les données visibles de la requête HTTP" name="refetchvishttp_btn"/> +</floater> diff --git a/indra/newview/skins/default/xui/fr/floater_window_size.xml b/indra/newview/skins/default/xui/fr/floater_window_size.xml index cbda4390d8..11c2e439bd 100644 --- a/indra/newview/skins/default/xui/fr/floater_window_size.xml +++ b/indra/newview/skins/default/xui/fr/floater_window_size.xml @@ -7,10 +7,17 @@ Définir la taille de la fenêtre : </text> <combo_box name="window_size_combo" tool_tip="largeur x hauteur"> - <combo_box.item label="1 000 x 700 (défaut)" name="item0"/> - <combo_box.item label="1 024 x 768" name="item1"/> - <combo_box.item label="1 280 x 720 (720 p)" name="item2"/> - <combo_box.item label="1 920 x 1 080 (1 080p)" name="item3"/> + <combo_box.item label="1000 x 700 (par défaut)" name="item1"/> + <combo_box.item label="1024 x 768 (4:3 XGA)" name="item2"/> + <combo_box.item label="1280 x 720 (16:9 HDTV)" name="item3"/> + <combo_box.item label="1280 x 800 (5:8 WXGA)" name="item4"/> + <combo_box.item label="1280 x 1024 (5:4 SXGA)" name="item5"/> + <combo_box.item label="1440 x 900 (8:5 WSXGA)" name="item7"/> + <combo_box.item label="1600 x 900 (16:9 HD+)" name="item8"/> + <combo_box.item label="1600 x 1200 (4:3 UXGA)" name="item9"/> + <combo_box.item label="1680 x 1050 (8:5 WSXGA+)" name="item10"/> + <combo_box.item label="1920 x 1080 (16:9 HDTV)" name="item11"/> + <combo_box.item label="1920 x 1200 (8:5 WUXGA)" name="item12"/> </combo_box> <button label="Choisir" name="set_btn"/> <button label="Annuler" name="cancel_btn"/> diff --git a/indra/newview/skins/default/xui/fr/menu_viewer.xml b/indra/newview/skins/default/xui/fr/menu_viewer.xml index 3c3d4f5f69..2a26ed7a70 100644 --- a/indra/newview/skins/default/xui/fr/menu_viewer.xml +++ b/indra/newview/skins/default/xui/fr/menu_viewer.xml @@ -227,11 +227,10 @@ <menu_item_check label="Console de textures" name="Texture Console"/> <menu_item_check label="Console de débogage" name="Debug Console"/> <menu_item_call label="Console de notifications" name="Notifications"/> - <menu_item_check label="Console de tailles de textures" name="Texture Size"/> - <menu_item_check label="Console des catégories de textures" name="Texture Category"/> <menu_item_check label="Chronos" name="Fast Timers"/> <menu_item_check label="Mémoire" name="Memory"/> <menu_item_check label="Statistiques de la scène" name="Scene Statistics"/> + <menu_item_call label="Console de débogage de la récupération des textures" name="Texture Fetch Debug Console"/> <menu_item_call label="Infos de région vers la console de débogage" name="Region Info to Debug Console"/> <menu_item_call label="Infos de groupe vers la console de débogage" name="Group Info to Debug Console"/> <menu_item_call label="Infos de capacités vers la console de débogage" name="Capabilities Info to Debug Console"/> @@ -289,6 +288,12 @@ <menu_item_check label="Complexité du rendu" name="rendercomplexity"/> <menu_item_check label="Octets d'éléments attachés" name="attachment bytes"/> <menu_item_check label="Sculpture" name="Sculpt"/> + <menu label="Densité des textures" name="Texture Density"> + <menu_item_check label="Aucune" name="None"/> + <menu_item_check label="Actuelle" name="Current"/> + <menu_item_check label="Souhaitée" name="Desired"/> + <menu_item_check label="Complète" name="Full"/> + </menu> </menu> <menu label="Rendu" name="Rendering"> <menu_item_check label="Axes" name="Axes"/> @@ -306,7 +311,6 @@ <menu_item_check label="Textures d'animation" name="Animation Textures"/> <menu_item_check label="Désactiver les textures" name="Disable Textures"/> <menu_item_check label="Textures pleine résolution" name="Rull Res Textures"/> - <menu_item_check label="Audit Textures" name="Audit Textures"/> <menu_item_check label="Atlas des textures (expérimental)" name="Texture Atlas"/> <menu_item_check label="Rendu des lumières jointes" name="Render Attached Lights"/> <menu_item_check label="Rendu des particules jointes" name="Render Attached Particles"/> diff --git a/indra/newview/skins/default/xui/fr/notifications.xml b/indra/newview/skins/default/xui/fr/notifications.xml index 746a4b1d55..0cdfc61e8e 100644 --- a/indra/newview/skins/default/xui/fr/notifications.xml +++ b/indra/newview/skins/default/xui/fr/notifications.xml @@ -494,6 +494,15 @@ Consulter [_URL] pour en savoir plus ? </url> <usetemplate ignoretext="Mon matériel n'est pas pris en charge" name="okcancelignore" notext="Non" yestext="Oui"/> </notification> + <notification name="IntelOldDriver"> + Il existe probablement un pilote plus récent pour votre puce graphique. La mise à jour des pilotes graphiques est susceptible d'améliorer considérablement les performances. + + Visiter la page [_URL] pour rechercher d'éventuelles mises à jour de pilotes ? + <url name="url"> + http://www.intel.com/p/fr_FR/support/detect/graphics + </url> + <usetemplate ignoretext="Mon pilote graphique est obsolète." name="okcancelignore" notext="Non" yestext="Oui"/> + </notification> <notification name="UnknownGPU"> Votre système contient une carte graphique que [APP_NAME] ne reconnaît pas. Cela est souvent le cas avec le nouveau matériel qui n'a pas encore été testé avec [APP_NAME]. Cela ne posera probablement pas de problème, mais vous devrez peut-être ajuster vos paramètres graphiques. @@ -2614,16 +2623,12 @@ Acceptez-vous ? </form> </notification> <notification name="ScriptQuestionCaution"> - Un objet nommé <nolink>[OBJECTNAME]</nolink>, appartenant à [NAME], aimerait : - -[QUESTIONS] -Si vous n'avez pas confiance en cet objet ni en son créateur, refusez cette requête. - -Accepter cette requête ? + Avertissement : l'objet <nolink>[OBJECTNAME]</nolink> souhaite un accès total à votre compte en Linden dollars. Si vous autorisez cet accès, il pourra supprimer des fonds de votre compte à tout moment ou le vider entièrement de façon continue sans avis préalable. + +Il est rare qu'une telle demande soit légitime. N'autorisez pas cet accès si vous ne comprenez pas entièrement pourquoi l'objet souhaite accéder à votre compte. <form name="form"> - <button name="Grant" text="Accepter"/> + <button name="Grant" text="Permettre un accès total"/> <button name="Deny" text="Refuser"/> - <button name="Details" text="Détails..."/> </form> </notification> <notification name="ScriptDialog"> @@ -3122,4 +3127,15 @@ Sinon, consultez la carte et trouvez les " infohubs ". <global name="You died and have been teleported to your home location"> Vous êtes mort et avez été téléporté à votre domicile. </global> + <notification name="LocalBitmapsUpdateFileNotFound"> + Impossible de mettre à jour [FNAME] car le fichier est introuvable. +Désactivation des mises à jour futures de ce fichier... + </notification> + <notification name="LocalBitmapsUpdateFailedFinal"> + [NRETRIES] tentatives d'ouverture ou de décodage de [FNAME] ont échoué. Le fichier est désormais considéré comme endommagé. +Désactivation des mises à jour futures de ce fichier... + </notification> + <notification name="LocalBitmapsVerifyFail"> + Tentative d'ajout d'un fichier image [FNAME] non valide ou illisible n'ayant pas pu être ouvert ou décodé. Tentative annulée. + </notification> </notifications> diff --git a/indra/newview/skins/default/xui/fr/panel_script_question_toast.xml b/indra/newview/skins/default/xui/fr/panel_script_question_toast.xml new file mode 100644 index 0000000000..a2d0237da0 --- /dev/null +++ b/indra/newview/skins/default/xui/fr/panel_script_question_toast.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<panel label="script_question_panel" name="panel_script_question_toast"> + <panel label="buttons_panel" name="buttons_panel"/> +</panel> diff --git a/indra/newview/skins/default/xui/fr/strings.xml b/indra/newview/skins/default/xui/fr/strings.xml index 8b410128da..0987952c28 100644 --- a/indra/newview/skins/default/xui/fr/strings.xml +++ b/indra/newview/skins/default/xui/fr/strings.xml @@ -886,6 +886,9 @@ Veuillez réessayer de vous connecter dans une minute. <string name="ScriptQuestionCautionChatDenied"> '[OBJECTNAME]', un objet appartenant à [OWNERNAME], situé dans [REGIONNAME] à [REGIONPOS], n'a pas reçu le droit de : [PERMISSIONS]. </string> + <string name="AdditionalPermissionsRequestHeader"> + Si vous autorisez un accès à votre compte, vous autorisez également l'objet à : + </string> <string name="ScriptTakeMoney"> Débiter vos Linden dollars (L$) </string> @@ -919,6 +922,9 @@ Veuillez réessayer de vous connecter dans une minute. <string name="ControlYourCamera"> Contrôler votre caméra </string> + <string name="TeleportYourAgent"> + Vous téléporter + </string> <string name="NotConnected"> Pas connecté(e) </string> diff --git a/indra/newview/skins/default/xui/it/floater_hardware_settings.xml b/indra/newview/skins/default/xui/it/floater_hardware_settings.xml index 5d3ae04a4d..edbbc354cf 100644 --- a/indra/newview/skins/default/xui/it/floater_hardware_settings.xml +++ b/indra/newview/skins/default/xui/it/floater_hardware_settings.xml @@ -25,6 +25,10 @@ Attiva VBO: </text> <check_box initial_value="true" label="Attiva oggetti OpenGL Vertex Buffer" name="vbo" tool_tip="Attivandolo su un hardware moderno aumenta la performance. Ma, su un vecchio hardware, spesso l'implementazione dei VBO è scarsa e potresti avere dei crash quando è attivato."/> + <text name="tc label"> + Attiva S3TC: + </text> + <check_box initial_value="true" label="Attiva compressione texture (richiede riavvio)" name="texture compression" tool_tip="Comprime le texture nella memoria video, consentendo il caricamento di texture a risoluzione maggiore al prezzo di ua perdita di qualit' del colore."/> <slider label="Memoria texture (MB):" name="GraphicsCardTextureMemory" tool_tip="Spazio di memoria da ssegnare alle textures. Utilizza la memoria della scheda video come impostazione predefinita. La riduzione di questa impostazione potrebbe migliorare il rendimento ma potrebbe anche rendere le texture poco definite."/> <spinner label="Indice della distanza della nebbia:" name="fog"/> <button label="OK" label_selected="OK" name="OK"/> 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/it/floater_stats.xml b/indra/newview/skins/default/xui/it/floater_stats.xml index ad6ef6b54b..2241cad711 100644 --- a/indra/newview/skins/default/xui/it/floater_stats.xml +++ b/indra/newview/skins/default/xui/it/floater_stats.xml @@ -14,8 +14,11 @@ <stat_bar label="KTris disegnato per secondo" name="ktrissec"/> <stat_bar label="Totale oggetti" name="objs"/> <stat_bar label="Nuovi oggetti" name="newobjs"/> + <stat_bar label="Hit rate della cache per l'oggetto" name="object_cache_hits"/> </stat_view> <stat_view label="Texture" name="texture"> + <stat_bar label="Hit rate della cache" name="texture_cache_hits"/> + <stat_bar label="Latenza di lettura della cache" name="texture_cache_read_latency"/> <stat_bar label="Conteggio" name="numimagesstat"/> <stat_bar label="Conteggio grezzo" name="numrawimagesstat"/> <stat_bar label="Memoria GL" name="gltexmemstat"/> diff --git a/indra/newview/skins/default/xui/it/floater_texture_ctrl.xml b/indra/newview/skins/default/xui/it/floater_texture_ctrl.xml index 7b77584ba0..e85030087c 100644 --- a/indra/newview/skins/default/xui/it/floater_texture_ctrl.xml +++ b/indra/newview/skins/default/xui/it/floater_texture_ctrl.xml @@ -1,23 +1,34 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="texture picker" title="PREFERITO: TEXTURE"> - <string name="choose_picture"> + <floater.string name="choose_picture"> Clicca per scegliere l'immagine - </string> + </floater.string> + <floater.string name="pick title"> + Scegli: + </floater.string> <text name="Multiple"> Texture multiple </text> + <radio_group name="mode_selection"> + <radio_item label="Inventario" name="inventory" value="0"/> + <radio_item label="Locale" name="local" value="1"/> + </radio_group> <text name="unknown"> Dimensioni: [DIMENSIONS] </text> <button label="Default" label_selected="Default" name="Default"/> - <button label="Niente" label_selected="Niente" name="None"/> <button label="Vuoto" label_selected="Vuoto" name="Blank"/> - <check_box label="Mostra cartelle" name="show_folders_check"/> - <search_editor label="Filtro texture" name="inventory search editor"/> - <check_box label="Applica adesso" name="apply_immediate_check"/> - <button label="Annulla" label_selected="Annulla" name="Cancel"/> + <button label="Niente" label_selected="Niente" name="None"/> + <filter_editor label="Filtro texture" name="inventory search editor"/> + <check_box initial_value="false" label="Mostra cartelle" name="show_folders_check"/> + <button label="Aggiungi" label_selected="Aggiungi" name="l_add_btn"/> + <button label="Rimuovi" label_selected="Rimuovi" name="l_rem_btn"/> + <button label="Carica" label_selected="Carica" name="l_upl_btn"/> + <scroll_list name="l_name_list"> + <column label="Nome" name="unit_name"/> + <column label="ID" name="unit_id_HIDDEN"/> + </scroll_list> <button label="OK" label_selected="OK" name="Select"/> - <string name="pick title"> - Scegli: - </string> + <button label="Annulla" label_selected="Annulla" name="Cancel"/> + <check_box initial_value="true" label="Applica adesso" name="apply_immediate_check"/> </floater> diff --git a/indra/newview/skins/default/xui/it/floater_texture_fetch_debugger.xml b/indra/newview/skins/default/xui/it/floater_texture_fetch_debugger.xml new file mode 100644 index 0000000000..57e65c3456 --- /dev/null +++ b/indra/newview/skins/default/xui/it/floater_texture_fetch_debugger.xml @@ -0,0 +1,62 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="TexFetchDebugger" title="Debugger recupero texture"> + <text name="total_num_fetched_label"> + 1, Numero totale di texture recuperate: [NUM] + </text> + <text name="total_num_fetching_requests_label"> + 2, Numero totale di richieste di recupero: [NUM] + </text> + <text name="total_num_cache_hits_label"> + 3, Numero totale di recuperi dalla cache: [NUM] + </text> + <text name="total_num_visible_tex_label"> + 4, Numero totale di texture visibili: [NUM] + </text> + <text name="total_num_visible_tex_fetch_req_label"> + 5, Numero totale di richieste di fetching texture visibili: [NUM] + </text> + <text name="total_fetched_data_label"> + 6, Numero totale di fetching dati: [SIZE1] KB, Dati decodificati: [SIZE2] KB, [PIXEL] MPixel + </text> + <text name="total_fetched_vis_data_label"> + 7, Numero totale di dati visibili: [SIZE1] KB, Dati decodificati: [SIZE2] KB + </text> + <text name="total_fetched_rendered_data_label"> + 8, Numero totale di rendering dei dati: [SIZE1] KB, Dati decodificati: [SIZE2] KB, [PIXEL] MPixel + </text> + <text name="total_time_cache_read_label"> + 9, Tempo totale letture cache: [TIME] secondi + </text> + <text name="total_time_cache_write_label"> + 10, Tempo totale scrittura cache: [TIME] secondi + </text> + <text name="total_time_decode_label"> + 11, Tempo totale decodifica: [TIME] secondi + </text> + <text name="total_time_gl_label"> + 12, Tempo totale creazione texture gl: [TIME] secondi + </text> + <text name="total_time_http_label"> + 13, Tempo totale fetching HTTP: [TIME] secondi + </text> + <text name="total_time_fetch_label"> + 14, Tempo totale complessivo fetching: [TIME] secondi + </text> + <text name="total_time_refetch_vis_cache_label"> + 15, Nuovo fetching elementi visibili dalla cache, Tempo: [TIME] secondi, fetching: [SIZE] KB, [PIXEL] MPixels + </text> + <text name="total_time_refetch_vis_http_label"> + 16, Nuovo fetching elementi visibili da HTTP, Tempo: [TIME] secondi, fetching: [SIZE] KB, [PIXEL] MPixels + </text> + <spinner label="17, Rapporto Texel/Pixel:" name="texel_pixel_ratio"/> + <button label="Attiva" name="start_btn"/> + <button label="Reimposta" name="clear_btn"/> + <button label="Chiudi" name="close_btn"/> + <button label="Lettura cache" name="cacheread_btn"/> + <button label="Scrittura cache" name="cachewrite_btn"/> + <button label="HTTP" name="http_btn"/> + <button label="Decodifica" name="decode_btn"/> + <button label="Texture GL" name="gl_btn"/> + <button label="Nuovo fetch visibili cache" name="refetchviscache_btn"/> + <button label="Nuovo fetch visibili HTTP" name="refetchvishttp_btn"/> +</floater> diff --git a/indra/newview/skins/default/xui/it/floater_window_size.xml b/indra/newview/skins/default/xui/it/floater_window_size.xml index 036b74b7d9..fef423aefe 100644 --- a/indra/newview/skins/default/xui/it/floater_window_size.xml +++ b/indra/newview/skins/default/xui/it/floater_window_size.xml @@ -7,10 +7,17 @@ Imposta dimensione finestra: </text> <combo_box name="window_size_combo" tool_tip="larghezza x altezza"> - <combo_box.item label="1000 x 700 (default)" name="item0"/> - <combo_box.item label="1024 x 768" name="item1"/> - <combo_box.item label="1280 x 720 (720p)" name="item2"/> - <combo_box.item label="1920 x 1080 (1080p)" name="item3"/> + <combo_box.item label="1000 x 700 (predefinito)" name="item1"/> + <combo_box.item label="1024 x 768 (4:3 XGA)" name="item2"/> + <combo_box.item label="1280 x 720 (16:9 HDTV)" name="item3"/> + <combo_box.item label="1280 x 800 (5:8 WXGA)" name="item4"/> + <combo_box.item label="1280 x 1024 (5:4 SXGA)" name="item5"/> + <combo_box.item label="1440 x 900 (8:5 WSXGA)" name="item7"/> + <combo_box.item label="1600 x 900 (16:9 HD+)" name="item8"/> + <combo_box.item label="1600 x 1200 (4:3 UXGA)" name="item9"/> + <combo_box.item label="1680 x 1050 (8:5 WSXGA+)" name="item10"/> + <combo_box.item label="1920 x 1080 (16:9 HDTV)" name="item11"/> + <combo_box.item label="1920 x 1200 (8:5 WUXGA)" name="item12"/> </combo_box> <button label="Imposta" name="set_btn"/> <button label="Annulla" name="cancel_btn"/> diff --git a/indra/newview/skins/default/xui/it/menu_viewer.xml b/indra/newview/skins/default/xui/it/menu_viewer.xml index 99b7e3c4e6..f94b2f9a9e 100644 --- a/indra/newview/skins/default/xui/it/menu_viewer.xml +++ b/indra/newview/skins/default/xui/it/menu_viewer.xml @@ -226,11 +226,10 @@ <menu_item_check label="Console texture" name="Texture Console"/> <menu_item_check label="Console di Debug" name="Debug Console"/> <menu_item_call label="Console notifiche" name="Notifications"/> - <menu_item_check label="Console dimensioni texture" name="Texture Size"/> - <menu_item_check label="Console categoria texture" name="Texture Category"/> <menu_item_check label="Timer veloci" name="Fast Timers"/> <menu_item_check label="Memoria" name="Memory"/> <menu_item_check label="Statistiche scena" name="Scene Statistics"/> + <menu_item_call label="Console di debug recupero texture" name="Texture Fetch Debug Console"/> <menu_item_call label="Informazioni regione sulla console di debug" name="Region Info to Debug Console"/> <menu_item_check label="Fotocamera" name="Camera"/> <menu_item_check label="Vento" name="Wind"/> @@ -271,6 +270,12 @@ <menu_item_check label="Complessità rendering" name="rendercomplexity"/> <menu_item_check label="Byte collegamento" name="attachment bytes"/> <menu_item_check label="Scolpisci" name="Sculpt"/> + <menu label="Densità texture" name="Texture Density"> + <menu_item_check label="Nessuna" name="None"/> + <menu_item_check label="Attuale" name="Current"/> + <menu_item_check label="Desiderata" name="Desired"/> + <menu_item_check label="Completa" name="Full"/> + </menu> </menu> <menu label="Rendering" name="Rendering"> <menu_item_check label="Assi" name="Axes"/> diff --git a/indra/newview/skins/default/xui/it/notifications.xml b/indra/newview/skins/default/xui/it/notifications.xml index 0e6fee60d1..9660c8f851 100644 --- a/indra/newview/skins/default/xui/it/notifications.xml +++ b/indra/newview/skins/default/xui/it/notifications.xml @@ -492,6 +492,15 @@ Visitare [_URL] per ulteriori informazioni? </url> <usetemplate ignoretext="L'hardware di questo computer non è compatibile" name="okcancelignore" notext="No" yestext="Si"/> </notification> + <notification name="IntelOldDriver"> + È probabile che ci sia un driver aggiornato per il processore grafico. L'aggiornamento dei driver della grafica può migliorare le prestazioni in maniera significativa. + + Visitare [_URL] per cercare un aggiornamento del driver? + <url name="url"> + http://www.intel.com/p/it_IT/support/detect/graphics + </url> + <usetemplate ignoretext="Driver grafica obsoleto" name="okcancelignore" notext="No" yestext="Sì"/> + </notification> <notification name="UnknownGPU"> Il tuo sistema utilizza una scheda grafica che [APP_NAME] non riconosce. Questo succede spesso con un nuovo hardware che non è stato ancora testato con [APP_NAME]. Probabilmente tutto andrà bene, ma devi riconfigurare le tue impostazioni grafiche. @@ -2616,16 +2625,12 @@ OK? </form> </notification> <notification name="ScriptQuestionCaution"> - Un oggetto di nome '<nolink>[OBJECTNAME]</nolink>', posseduto da '[NAME]' vorrebbe: - -[QUESTIONS] -Se non ti fidi di questo oggetto e del suo ideatore, dovresti rifiutare la richiesta. - -Concedi questa richiesta? + Attenzione: L'oggetto '<nolink>[OBJECTNAME]</nolink>' ha richiesto accesso completo al tuo account in Dollari Linden. Se consenti l'accesso, potrà rimuovere fondi dal tuo account in qalunque momento e anche svuotare completamente l'account, per un periodo illimitato e senza ulteriori avvisi. + +Raramente questo tipo di richiesta è legittima. Non consentire l'accesso se non comprendi perfettamente il motivo per cui desidera accedere al tuo account. <form name="form"> - <button name="Grant" text="Accetta"/> + <button name="Grant" text="Consenti accesso totale"/> <button name="Deny" text="Nega"/> - <button name="Details" text="Dettagli..."/> </form> </notification> <notification name="ScriptDialog"> @@ -3124,4 +3129,16 @@ In alternativa, puoi guardare sulla mappa e trovare luoghi segnalati come " <global name="You died and have been teleported to your home location"> Sei deceduto e sei stato teleportato a casa tua. </global> + <notification name="LocalBitmapsUpdateFileNotFound"> + [FNAME] non è stato aggiornato perché il file non è stato più trovato. +Gli aggiornamenti futuri per questo file sono disattivati. + </notification> + <notification name="LocalBitmapsUpdateFailedFinal"> + [FNAME] non è stato aperto o decodificato dopo [NRETRIES] tentativi, viene considerato danneggiato. +Gli aggiornamenti futuri per questo file sono disattivati. + </notification> + <notification name="LocalBitmapsVerifyFail"> + Tentativo di aggiungere un file immagine [FNAME] non valido o non leggibile che non è stato possibile aprire o decodificare. +Tentativo annullato. + </notification> </notifications> diff --git a/indra/newview/skins/default/xui/it/panel_script_question_toast.xml b/indra/newview/skins/default/xui/it/panel_script_question_toast.xml new file mode 100644 index 0000000000..a2d0237da0 --- /dev/null +++ b/indra/newview/skins/default/xui/it/panel_script_question_toast.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<panel label="script_question_panel" name="panel_script_question_toast"> + <panel label="buttons_panel" name="buttons_panel"/> +</panel> diff --git a/indra/newview/skins/default/xui/it/strings.xml b/indra/newview/skins/default/xui/it/strings.xml index 8529fadd7d..11accb5f08 100644 --- a/indra/newview/skins/default/xui/it/strings.xml +++ b/indra/newview/skins/default/xui/it/strings.xml @@ -880,6 +880,9 @@ Prova ad accedere nuovamente tra un minuto. <string name="ScriptQuestionCautionChatDenied"> A '[OBJECTNAME]', un oggetto di proprietà di '[OWNERNAME]', situato in [REGIONNAME] [REGIONPOS], è stato negato il permesso di: [PERMISSIONS]. </string> + <string name="AdditionalPermissionsRequestHeader"> + Se consenti l'accesso al tuo account, consentirai anche all'oggetto di: + </string> <string name="ScriptTakeMoney"> Prendere dollari Linden (L$) da te </string> @@ -913,6 +916,9 @@ Prova ad accedere nuovamente tra un minuto. <string name="ControlYourCamera"> Controllare la tua fotocamera </string> + <string name="TeleportYourAgent"> + Teleportarti + </string> <string name="SIM_ACCESS_PG"> Generale </string> diff --git a/indra/newview/skins/default/xui/ja/floater_hardware_settings.xml b/indra/newview/skins/default/xui/ja/floater_hardware_settings.xml index 1b6558a9eb..c8b8e918e0 100644 --- a/indra/newview/skins/default/xui/ja/floater_hardware_settings.xml +++ b/indra/newview/skins/default/xui/ja/floater_hardware_settings.xml @@ -25,6 +25,10 @@ VBO を有効化: </text> <check_box initial_value="true" label="OpenGL Vertex Buffer Objectsを有効化" name="vbo" tool_tip="最新のハードウェアでこの設定を有効にすると、パフォーマンスが向上します。 しかし、旧型のハードウェアでは VBO の実装が貧弱な場合が多く、この設定を有効にすることでクラッシュにつながるおそれがあります。"/> + <text name="tc label"> + S3TC を有効にする: + </text> + <check_box initial_value="true" label="テクスチャ圧縮を有効にする(再起動が必要)" name="texture compression" tool_tip="ビデオメモリ内でテクスチャを圧縮することにより、色の質を多少犠牲にしながら、より高解像度のテクスチャを読み込めるようにします。"/> <slider label="テクスチャメモリ(MB):" name="GraphicsCardTextureMemory" tool_tip="テクスチャに割り当てられたメモリの量。 ビデオカードのメモリに既定。 数値を下げるとパフォーマンスが向上しますが、テクスチャの精度が落ちることがあります。"/> <spinner label="フォグの距離比率:" name="fog"/> <button label="OK" label_selected="OK" name="OK"/> 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/floater_stats.xml b/indra/newview/skins/default/xui/ja/floater_stats.xml index 6a1f34cfd8..da5358f06a 100644 --- a/indra/newview/skins/default/xui/ja/floater_stats.xml +++ b/indra/newview/skins/default/xui/ja/floater_stats.xml @@ -14,8 +14,11 @@ <stat_bar label="秒ごとの KTris 描画" name="ktrissec"/> <stat_bar label="オブジェクト合計" name="objs"/> <stat_bar label="新規オブジェクト" name="newobjs"/> + <stat_bar label="オブジェクトキャッシュヒット率" name="object_cache_hits"/> </stat_view> <stat_view label="テクスチャ" name="texture"> + <stat_bar label="キャッシュヒット率" name="texture_cache_hits"/> + <stat_bar label="キャッシュ読み取り遅延" name="texture_cache_read_latency"/> <stat_bar label="カウント" name="numimagesstat"/> <stat_bar label="Raw カウント" name="numrawimagesstat"/> <stat_bar label="GL メモリ" name="gltexmemstat"/> diff --git a/indra/newview/skins/default/xui/ja/floater_texture_ctrl.xml b/indra/newview/skins/default/xui/ja/floater_texture_ctrl.xml index 399cffcce5..55fe840658 100644 --- a/indra/newview/skins/default/xui/ja/floater_texture_ctrl.xml +++ b/indra/newview/skins/default/xui/ja/floater_texture_ctrl.xml @@ -1,24 +1,35 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="texture picker" title="テクスチャの選択"> - <string name="choose_picture"> + <floater.string name="choose_picture"> クリックして写真を選択 - </string> + </floater.string> + <floater.string name="pick title"> + ピック: + </floater.string> <text name="Multiple"> 複数のテクスチャ </text> + <radio_group name="mode_selection"> + <radio_item label="インベントリ" name="inventory" value="0"/> + <radio_item label="ローカル" name="local" value="1"/> + </radio_group> <text name="unknown"> サイズ: [DIMENSIONS] </text> <button label="デフォルト" label_selected="デフォルト" name="Default"/> - <button label="なし" label_selected="なし" name="None"/> <button label="ブランク" label_selected="ブランク" name="Blank"/> - <check_box label="フォルダを表示" name="show_folders_check"/> - <search_editor label="テクスチャをフィルター" name="inventory search editor"/> - <check_box label="すぐ適用" name="apply_immediate_check"/> + <button label="なし" label_selected="なし" name="None"/> <button label="" label_selected="" name="Pipette"/> - <button label="取り消し" label_selected="取り消し" name="Cancel"/> + <filter_editor label="テクスチャをフィルター" name="inventory search editor"/> + <check_box initial_value="false" label="フォルダを表示" name="show_folders_check"/> + <button label="追加" label_selected="追加" name="l_add_btn"/> + <button label="削除" label_selected="削除" name="l_rem_btn"/> + <button label="アップロード" label_selected="アップロード" name="l_upl_btn"/> + <scroll_list name="l_name_list"> + <column label="名前" name="unit_name"/> + <column label="ID" name="unit_id_HIDDEN"/> + </scroll_list> <button label="OK" label_selected="OK" name="Select"/> - <text name="pick title"> - ピック: - </text> + <button label="取り消し" label_selected="取り消し" name="Cancel"/> + <check_box initial_value="true" label="すぐ適用" name="apply_immediate_check"/> </floater> diff --git a/indra/newview/skins/default/xui/ja/floater_texture_fetch_debugger.xml b/indra/newview/skins/default/xui/ja/floater_texture_fetch_debugger.xml new file mode 100644 index 0000000000..4efdf7d40d --- /dev/null +++ b/indra/newview/skins/default/xui/ja/floater_texture_fetch_debugger.xml @@ -0,0 +1,62 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="TexFetchDebugger" title="テクスチャ取得デバッガ"> + <text name="total_num_fetched_label"> + 1, 取得したテクスチャの合計数:[NUM] + </text> + <text name="total_num_fetching_requests_label"> + 2, 取得リクエストの合計数:[NUM] + </text> + <text name="total_num_cache_hits_label"> + 3, キャッシュヒットの合計数:[NUM] + </text> + <text name="total_num_visible_tex_label"> + 4, 表示テクスチャの合計数:[NUM] + </text> + <text name="total_num_visible_tex_fetch_req_label"> + 5, 表示テクスチャ取得リクエストの合計数:[NUM] + </text> + <text name="total_fetched_data_label"> + 6, 取得したデータの合計数:[SIZE1]KB、デコードされたデータ:[SIZE2]KB、[PIXEL]メガピクセル + </text> + <text name="total_fetched_vis_data_label"> + 7, 表示データの合計数:[SIZE1]KB、デコードされたデータ:[SIZE2]KB + </text> + <text name="total_fetched_rendered_data_label"> + 8, レンダリングされたデータの合計数:[SIZE1]KB、デコードされたデータ:[SIZE2]KB、[PIXEL]メガピクセル + </text> + <text name="total_time_cache_read_label"> + 9, キャッシュ読み取りの合計時間:[TIME] 秒 + </text> + <text name="total_time_cache_write_label"> + 10, キャッシュ書き込みの合計時間:[TIME] 秒 + </text> + <text name="total_time_decode_label"> + 11, デコードの合計時間:[TIME] 秒 + </text> + <text name="total_time_gl_label"> + 12, glテクスチャ作成の合計時間:[TIME] 秒 + </text> + <text name="total_time_http_label"> + 13, HTTP 取得の合計時間:[TIME] 秒 + </text> + <text name="total_time_fetch_label"> + 14, 取得全体の合計時間:[TIME] 秒 + </text> + <text name="total_time_refetch_vis_cache_label"> + 15, キャッシュから表示テクスチャを再取得、時間:[TIME] 秒、取得:[SIZE]KB、[PIXEL]メガピクセル + </text> + <text name="total_time_refetch_vis_http_label"> + 16, HTTP から表示テクスチャを再取得、時間:[TIME] 秒、取得:[SIZE]KB、[PIXEL]メガピクセル + </text> + <spinner label="17, テクセル/ピクセルの比率:" name="texel_pixel_ratio"/> + <button label="開始" name="start_btn"/> + <button label="リセット" name="clear_btn"/> + <button label="閉じる" name="close_btn"/> + <button label="キャッシュ読み取り" name="cacheread_btn"/> + <button label="キャッシュ書き込み" name="cachewrite_btn"/> + <button label="HTTP" name="http_btn"/> + <button label="デコード" name="decode_btn"/> + <button label="GL テクスチャ" name="gl_btn"/> + <button label="キャッシュ表示テクスチャ再取得" name="refetchviscache_btn"/> + <button label="HTTP表示テクスチャ再取得" name="refetchvishttp_btn"/> +</floater> diff --git a/indra/newview/skins/default/xui/ja/floater_window_size.xml b/indra/newview/skins/default/xui/ja/floater_window_size.xml index 152a5f4806..416813d6cc 100644 --- a/indra/newview/skins/default/xui/ja/floater_window_size.xml +++ b/indra/newview/skins/default/xui/ja/floater_window_size.xml @@ -7,10 +7,17 @@ ウィンドウのサイズを設定: </text> <combo_box name="window_size_combo" tool_tip="横幅 x 高さ"> - <combo_box.item label="1000 x 700 (標準)" name="item0"/> - <combo_box.item label="1024 x 768" name="item1"/> - <combo_box.item label="1280 x 720 (720p)" name="item2"/> - <combo_box.item label="1920 x 1080 (1080p)" name="item3"/> + <combo_box.item label="1000 x 700 (デフォルト)" name="item1"/> + <combo_box.item label="1024 x 768 (4:3 XGA)" name="item2"/> + <combo_box.item label="1280 x 720 (16:9 HDTV)" name="item3"/> + <combo_box.item label="1280 x 800 (5:8 WXGA)" name="item4"/> + <combo_box.item label="1280 x 1024 (5:4 SXGA)" name="item5"/> + <combo_box.item label="1440 x 900 (8:5 WSXGA)" name="item7"/> + <combo_box.item label="1600 x 900 (16:9 HD+)" name="item8"/> + <combo_box.item label="1600 x 1200 (4:3 UXGA)" name="item9"/> + <combo_box.item label="1680 x 1050 (8:5 WSXGA+)" name="item10"/> + <combo_box.item label="1920 x 1080 (16:9 HDTV)" name="item11"/> + <combo_box.item label="1920 x 1200 (8:5 WUXGA)" name="item12"/> </combo_box> <button label="設定" name="set_btn"/> <button label="キャンセル" name="cancel_btn"/> diff --git a/indra/newview/skins/default/xui/ja/menu_viewer.xml b/indra/newview/skins/default/xui/ja/menu_viewer.xml index 8496dfb1db..3a398bd985 100644 --- a/indra/newview/skins/default/xui/ja/menu_viewer.xml +++ b/indra/newview/skins/default/xui/ja/menu_viewer.xml @@ -227,11 +227,10 @@ <menu_item_check label="テクスチャのコンソール" name="Texture Console"/> <menu_item_check label="デバッグコンソール" name="Debug Console"/> <menu_item_call label="通知コンソール" name="Notifications"/> - <menu_item_check label="テクスチャサイズのコンソール" name="Texture Size"/> - <menu_item_check label="テクスチャカテゴリのコンソール" name="Texture Category"/> <menu_item_check label="ファーストタイマー" name="Fast Timers"/> <menu_item_check label="メモリ" name="Memory"/> <menu_item_check label="風景の統計" name="Scene Statistics"/> + <menu_item_call label="テクスチャ取得デバッグコンソール" name="Texture Fetch Debug Console"/> <menu_item_call label="リージョン情報をデバッグコンソールへ" name="Region Info to Debug Console"/> <menu_item_call label="グループ情報をデバッグコンソールへ" name="Group Info to Debug Console"/> <menu_item_call label="性能情報をデバッグコンソールへ" name="Capabilities Info to Debug Console"/> @@ -289,6 +288,12 @@ <menu_item_check label="描画の詳細度" name="rendercomplexity"/> <menu_item_check label="添付アイテムのバイト数" name="attachment bytes"/> <menu_item_check label="スカルプト" name="Sculpt"/> + <menu label="テクスチャの密度" name="Texture Density"> + <menu_item_check label="なし" name="None"/> + <menu_item_check label="現在" name="Current"/> + <menu_item_check label="望ましい" name="Desired"/> + <menu_item_check label="フル" name="Full"/> + </menu> </menu> <menu label="レンダリング" name="Rendering"> <menu_item_check label="軸" name="Axes"/> @@ -306,7 +311,6 @@ <menu_item_check label="アニメーションテクスチャ" name="Animation Textures"/> <menu_item_check label="テクスチャを無効にする" name="Disable Textures"/> <menu_item_check label="フル解像度テクスチャ" name="Rull Res Textures"/> - <menu_item_check label="テクスチャの検査" name="Audit Textures"/> <menu_item_check label="テクスチャアトラス(試験段階)" name="Texture Atlas"/> <menu_item_check label="装着された光源を描画する" name="Render Attached Lights"/> <menu_item_check label="取り付けられたパーティクルを描画する" name="Render Attached Particles"/> diff --git a/indra/newview/skins/default/xui/ja/notifications.xml b/indra/newview/skins/default/xui/ja/notifications.xml index 7bf8a7b8be..f35c0f0d14 100644 --- a/indra/newview/skins/default/xui/ja/notifications.xml +++ b/indra/newview/skins/default/xui/ja/notifications.xml @@ -517,6 +517,15 @@ L$ が不足しているのでこのグループに参加することができ </url> <usetemplate ignoretext="使用中のコンピューターのハードウェアがサポートされていないとき" name="okcancelignore" notext="いいえ" yestext="はい"/> </notification> + <notification name="IntelOldDriver"> + おそらくお使いのグラフィックチップ用の新しいドライバが入手可能です。グラフィックドライバを更新することにより、パフォーマンスが大幅に向上する場合があります。 + +[_URL] にアクセスして更新版のドライバがあるかどうかを確認しますか? + <url name="url"> + http://www.intel.com/p/ja_JP/support/detect/graphics + </url> + <usetemplate ignoretext="使用しているグラフィックドライバが古い場合" name="okcancelignore" notext="いいえ" yestext="はい"/> + </notification> <notification name="UnknownGPU"> お使いのシステムには、[APP_NAME] が認識できないグラフィックカードが搭載されています。 [APP_NAME] でまだテストされていない最新ハードウェアのためだと考えられます。 問題ないとは思いますが、グラフィックの設定を調整する必要があるかもしれません。 @@ -2663,16 +2672,12 @@ Web ページにリンクすると、他人がこの場所に簡単にアクセ </form> </notification> <notification name="ScriptQuestionCaution"> - [NAME] が所有する「<nolink>[OBJECTNAME]</nolink>」 というオブジェクトが、次のことをしようとしています: - -[QUESTIONS] -このオブジェクトや制作者を信用できない場合は、このリクエストを拒否してください。 - -リクエストを受けますか? + 警告:オブジェクト '<nolink>[OBJECTNAME]</nolink>' はあなたのリンデンドルアカウントへのトータルアクセスを希望しています。アクセスを許可すると、このオブジェクトはいつでもあなたのアカウントから資金を削除したり、今後警告を表示することなく継続的にアカウントを完全に空にできるようになります。 + +このようなリクエストが正当であることは稀です。このオブジェクトがあなたのアカウントにアクセスしたい理由を完全に理解している場合を除き、アクセスの許可は避けてください。 <form name="form"> - <button name="Grant" text="許可"/> + <button name="Grant" text="トータルアクセスを許可"/> <button name="Deny" text="拒否"/> - <button name="Details" text="詳細..."/> </form> </notification> <notification name="ScriptDialog"> @@ -3180,4 +3185,16 @@ M キーを押して変更します。 <global name="You died and have been teleported to your home location"> 死んでしまったので、ホームにテレポートされました。 </global> + <notification name="LocalBitmapsUpdateFileNotFound"> + [FNAME] は、見つからなかったため、更新できませんでした。 +このファイルに対する今後の更新を無効にします。 + </notification> + <notification name="LocalBitmapsUpdateFailedFinal"> + [FNAME] を開くまたはデコードする試行に失敗しました(試行回数 [NRETRIES] 回)。そのため、このファイルは壊れているものとして処理されました。 +このファイルに対する今後の更新を無効にします。 + </notification> + <notification name="LocalBitmapsVerifyFail"> + 開くことができない、またはデコードできない無効または読み取り不能な画像ファイル [FNAME] を追加しようとしました。 +この試行はキャンセルされました。 + </notification> </notifications> diff --git a/indra/newview/skins/default/xui/ja/panel_script_question_toast.xml b/indra/newview/skins/default/xui/ja/panel_script_question_toast.xml new file mode 100644 index 0000000000..a2d0237da0 --- /dev/null +++ b/indra/newview/skins/default/xui/ja/panel_script_question_toast.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<panel label="script_question_panel" name="panel_script_question_toast"> + <panel label="buttons_panel" name="buttons_panel"/> +</panel> diff --git a/indra/newview/skins/default/xui/ja/strings.xml b/indra/newview/skins/default/xui/ja/strings.xml index 680ef60890..f6b3edc57f 100644 --- a/indra/newview/skins/default/xui/ja/strings.xml +++ b/indra/newview/skins/default/xui/ja/strings.xml @@ -886,6 +886,9 @@ support@secondlife.com にお問い合わせください。 <string name="ScriptQuestionCautionChatDenied"> [REGIONNAME] の [REGIONPOS] という場所にある、「 [OWNERNAME] 」が所有する「 [OBJECTNAME] 」というオブジェクトは、次の権限を拒否しました: [PERMISSIONS] </string> + <string name="AdditionalPermissionsRequestHeader"> + あなたのアカウントへのアクセスを許可すると、このオブジェクトには次の操作も許可されます: + </string> <string name="ScriptTakeMoney"> リンデンドル(L$)を支払う </string> @@ -919,6 +922,9 @@ support@secondlife.com にお問い合わせください。 <string name="ControlYourCamera"> カメラのコントロール </string> + <string name="TeleportYourAgent"> + あなたをテレポート + </string> <string name="NotConnected"> 接続されていません </string> diff --git a/indra/newview/skins/default/xui/pt/floater_hardware_settings.xml b/indra/newview/skins/default/xui/pt/floater_hardware_settings.xml index 1bc2bce768..1204fb93e2 100644 --- a/indra/newview/skins/default/xui/pt/floater_hardware_settings.xml +++ b/indra/newview/skins/default/xui/pt/floater_hardware_settings.xml @@ -25,6 +25,10 @@ Habilitar VBO: </text> <check_box initial_value="true" label="Habilitar Objetos com Armazenamento de Vértices" name="vbo" tool_tip="Habilitando-o em máquinas novas, ele oferece um ganho de performance. Contudo, as máquinas antigas tem freqüentemente implementações pobres de VBOs e você pode ter travamentos quando esta opção é habilitada."/> + <text name="tc label"> + Habilitar S3TC: + </text> + <check_box initial_value="true" label="Habilitar compressão de texturas (requer reinício)" name="texture compression" tool_tip="Comprime as texturas na memória de vídeo, permitindo o carregamento de texturas de maior resolução em detrimento da qualidade da cor."/> <slider label="Memória de texturas (MB):" name="GraphicsCardTextureMemory" tool_tip="Quanto da memória deve ser alocado para texturas. O padrão é definido pela memória da placa de vídeo. Reduzir este valor pode melhorar o desempenho, mas as texturas podem fica fora de foco."/> <spinner label="Relação de Distância de Nevoeiro:" name="fog"/> <button label="OK" label_selected="OK" name="OK"/> 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/floater_stats.xml b/indra/newview/skins/default/xui/pt/floater_stats.xml index f0a053ebe3..e770c6ac38 100644 --- a/indra/newview/skins/default/xui/pt/floater_stats.xml +++ b/indra/newview/skins/default/xui/pt/floater_stats.xml @@ -14,8 +14,11 @@ <stat_bar label="KTris desenhados por segundo" name="ktrissec"/> <stat_bar label="Total Objects" name="objs"/> <stat_bar label="New Objects" name="newobjs"/> + <stat_bar label="Taxa de acertos do cache do objeto" name="object_cache_hits"/> </stat_view> <stat_view label="Texture" name="texture"> + <stat_bar label="Taxa de acertos do cache" name="texture_cache_hits"/> + <stat_bar label="Latência de leitura do cache" name="texture_cache_read_latency"/> <stat_bar label="Count" name="numimagesstat"/> <stat_bar label="Raw Count" name="numrawimagesstat"/> <stat_bar label="GL Mem" name="gltexmemstat"/> diff --git a/indra/newview/skins/default/xui/pt/floater_texture_ctrl.xml b/indra/newview/skins/default/xui/pt/floater_texture_ctrl.xml index 144bc0340e..57223beaeb 100644 --- a/indra/newview/skins/default/xui/pt/floater_texture_ctrl.xml +++ b/indra/newview/skins/default/xui/pt/floater_texture_ctrl.xml @@ -1,23 +1,34 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="texture picker" title="DESTAQUE: TEXTURA"> - <string name="choose_picture"> + <floater.string name="choose_picture"> Clique para escolher uma imagem - </string> + </floater.string> + <floater.string name="pick title"> + Pegar: + </floater.string> <text name="Multiple"> Multiplas texturas </text> + <radio_group name="mode_selection"> + <radio_item label="Inventário" name="inventory" value="0"/> + <radio_item label="Local" name="local" value="1"/> + </radio_group> <text name="unknown"> Tamanho: [DIMENSÕES] </text> <button label="Padrão" label_selected="Padrão" name="Default"/> - <button label="Nenhum" label_selected="Nenhum" name="None"/> <button label="Branco" label_selected="Branco" name="Blank"/> - <check_box label="Exibir pastas" name="show_folders_check"/> - <search_editor label="Filtrar texturas" name="inventory search editor"/> - <check_box label="Applicar agora" name="apply_immediate_check"/> - <button label="Cancelar" label_selected="Cancelar" name="Cancel"/> + <button label="Nenhum" label_selected="Nenhum" name="None"/> + <filter_editor label="Filtrar texturas" name="inventory search editor"/> + <check_box initial_value="false" label="Exibir pastas" name="show_folders_check"/> + <button label="Adicionar" label_selected="Adicionar" name="l_add_btn"/> + <button label="Remover" label_selected="Remover" name="l_rem_btn"/> + <button label="Enviar" label_selected="Enviar" name="l_upl_btn"/> + <scroll_list name="l_name_list"> + <column label="Nome" name="unit_name"/> + <column label="ID" name="unit_id_HIDDEN"/> + </scroll_list> <button label="OK" label_selected="OK" name="Select"/> - <string name="pick title"> - Pegar: - </string> + <button label="Cancelar" label_selected="Cancelar" name="Cancel"/> + <check_box initial_value="true" label="Applicar agora" name="apply_immediate_check"/> </floater> diff --git a/indra/newview/skins/default/xui/pt/floater_texture_fetch_debugger.xml b/indra/newview/skins/default/xui/pt/floater_texture_fetch_debugger.xml new file mode 100644 index 0000000000..f20d50362e --- /dev/null +++ b/indra/newview/skins/default/xui/pt/floater_texture_fetch_debugger.xml @@ -0,0 +1,62 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="TexFetchDebugger" title="Depurador de obtenção de textura"> + <text name="total_num_fetched_label"> + 1, Número total de texturas obtidas: [NUM] + </text> + <text name="total_num_fetching_requests_label"> + 2, Número total de solicitações de obtenção: [NUM] + </text> + <text name="total_num_cache_hits_label"> + 3, Número total de acertos de cache: [NUM] + </text> + <text name="total_num_visible_tex_label"> + 4, Número total de texturas visíveis: [NUM] + </text> + <text name="total_num_visible_tex_fetch_req_label"> + 5, Número total de solicitações de obtenção de texturas visíveis: [NUM] + </text> + <text name="total_fetched_data_label"> + 6, Número total de dados obtidos: [SIZE1]KB, Dados decodificados: [SIZE2]KB, [PIXEL]MPixels + </text> + <text name="total_fetched_vis_data_label"> + 7, Número total de dados visíveis: [SIZE1]KB, Dados decodificados: [SIZE2]KB + </text> + <text name="total_fetched_rendered_data_label"> + 8, Número total de dados renderizados: [SIZE1]KB, Dados decodificados: [SIZE2]KB, [PIXEL]MPixels + </text> + <text name="total_time_cache_read_label"> + 9, Tempo total de leituras de cache: [TIME] segundos + </text> + <text name="total_time_cache_write_label"> + 10, Tempo total de gravações em cache: [TIME] segundos + </text> + <text name="total_time_decode_label"> + 11, Tempo total das decodificações: [TIME] segundos + </text> + <text name="total_time_gl_label"> + 12, Tempo total de criação de texturas gl: [TIME] segundos + </text> + <text name="total_time_http_label"> + 13, Tempo total de obtenção de HTTP: [TIME] segundos + </text> + <text name="total_time_fetch_label"> + 14, Tempo total de obtenção completa: [TIME] segundos + </text> + <text name="total_time_refetch_vis_cache_label"> + 15, Obtendo novamente visíveis do cache, Tempo: [TIME] segundos, Obtidos: [SIZE]KB, [PIXEL]MPixels + </text> + <text name="total_time_refetch_vis_http_label"> + 16, Obtendo novamente visíveis do HTTP, Tempo: [TIME] segundos, Obtidos: [SIZE]KB, [PIXEL]MPixels + </text> + <spinner label="17, Proporção de texel/pixel:" name="texel_pixel_ratio"/> + <button label="Iniciar" name="start_btn"/> + <button label="Redefinir" name="clear_btn"/> + <button label="Fechar" name="close_btn"/> + <button label="Leitura do cache" name="cacheread_btn"/> + <button label="Gravação em cache" name="cachewrite_btn"/> + <button label="HTTP" name="http_btn"/> + <button label="Decodificar" name="decode_btn"/> + <button label="Textura GL" name="gl_btn"/> + <button label="Obter novamente cache visível" name="refetchviscache_btn"/> + <button label="Obter novamente HTTP visível" name="refetchvishttp_btn"/> +</floater> diff --git a/indra/newview/skins/default/xui/pt/floater_window_size.xml b/indra/newview/skins/default/xui/pt/floater_window_size.xml index 6a8ccbd002..7deb799bd7 100644 --- a/indra/newview/skins/default/xui/pt/floater_window_size.xml +++ b/indra/newview/skins/default/xui/pt/floater_window_size.xml @@ -7,10 +7,17 @@ Definir tamanho da janela: </text> <combo_box name="window_size_combo" tool_tip="largura x altura"> - <combo_box.item label="1000 x 700 (padrão)" name="item0"/> - <combo_box.item label="1024 x 768" name="item1"/> - <combo_box.item label="1280 x 720 (720p)" name="item2"/> - <combo_box.item label="1920 x 1080 (1080p)" name="item3"/> + <combo_box.item label="1000 x 700 (padrão)" name="item1"/> + <combo_box.item label="1024 x 768 (4:3 XGA)" name="item2"/> + <combo_box.item label="1280 x 720 (16:9 HDTV)" name="item3"/> + <combo_box.item label="1280 x 800 (5:8 WXGA)" name="item4"/> + <combo_box.item label="1280 x 1024 (5:4 SXGA)" name="item5"/> + <combo_box.item label="1440 x 900 (8:5 WSXGA)" name="item7"/> + <combo_box.item label="1600 x 900 (16:9 HD+)" name="item8"/> + <combo_box.item label="1600 x 1200 (4:3 UXGA)" name="item9"/> + <combo_box.item label="1680 x 1050 (8:5 WSXGA+)" name="item10"/> + <combo_box.item label="1920 x 1080 (16:9 HDTV)" name="item11"/> + <combo_box.item label="1920 x 1200 (8:5 WUXGA)" name="item12"/> </combo_box> <button label="Definir" name="set_btn"/> <button label="Cancelar" name="cancel_btn"/> diff --git a/indra/newview/skins/default/xui/pt/menu_viewer.xml b/indra/newview/skins/default/xui/pt/menu_viewer.xml index fd973bf3c2..d93330e6df 100644 --- a/indra/newview/skins/default/xui/pt/menu_viewer.xml +++ b/indra/newview/skins/default/xui/pt/menu_viewer.xml @@ -226,11 +226,10 @@ <menu_item_check label="Painel de textura" name="Texture Console"/> <menu_item_check label="Console de depuração" name="Debug Console"/> <menu_item_call label="Painel de avisos" name="Notifications"/> - <menu_item_check label="Painel de tamanho de textura" name="Texture Size"/> - <menu_item_check label="Painel de texturas" name="Texture Category"/> <menu_item_check label="Tempos" name="Fast Timers"/> <menu_item_check label="Memória" name="Memory"/> <menu_item_check label="Estatísticas da cena" name="Scene Statistics"/> + <menu_item_call label="Painel de depuração de obtenção de textura" name="Texture Fetch Debug Console"/> <menu_item_call label="Region Info to Debug Console" name="Region Info to Debug Console"/> <menu_item_check label="Câmera:" name="Camera"/> <menu_item_check label="Vento" name="Wind"/> @@ -271,6 +270,12 @@ <menu_item_check label="Renderizar complexidade" name="rendercomplexity"/> <menu_item_check label="Bytes do anexo" name="attachment bytes"/> <menu_item_check label="Esculpir" name="Sculpt"/> + <menu label="Densidade da textura" name="Texture Density"> + <menu_item_check label="Nenhuma" name="None"/> + <menu_item_check label="Atual" name="Current"/> + <menu_item_check label="Desejada" name="Desired"/> + <menu_item_check label="Completa" name="Full"/> + </menu> </menu> <menu label="Rendering" name="Rendering"> <menu_item_check label="Axes" name="Axes"/> diff --git a/indra/newview/skins/default/xui/pt/notifications.xml b/indra/newview/skins/default/xui/pt/notifications.xml index 3b39c0f92c..500a7f0c01 100644 --- a/indra/newview/skins/default/xui/pt/notifications.xml +++ b/indra/newview/skins/default/xui/pt/notifications.xml @@ -489,6 +489,15 @@ Consultar [_URL] para mais informações? </url> <usetemplate ignoretext="O hardware do meu computador não é suportado" name="okcancelignore" notext="Não" yestext="Sim"/> </notification> + <notification name="IntelOldDriver"> + Provavelmente, há um driver mais recente para o seu chip gráfico. A atualização dos drivers gráficos pode melhorar significativamente o desempenho. + + Visitar [_URL] para verificar se há atualizações do driver? + <url name="url"> + http://www.intel.com/p/pt_BR/support/detect/graphics + </url> + <usetemplate ignoretext="Meu driver gráfico está desatualizado" name="okcancelignore" notext="Não" yestext="Sim"/> + </notification> <notification name="UnknownGPU"> A placa de vídeo do seu sistema não é reconhecida pelo [APP_NAME]. Isto acontece quando novos hardwares que ainda não foram testados no [APP_NAME]. Talvez isso não cause problemas, mas pode ser preciso checar as configurações de vídeo. @@ -2596,16 +2605,12 @@ OK? </form> </notification> <notification name="ScriptQuestionCaution"> - Um objeto chamado '<nolink>[OBJECTNAME]</nolink>'', de '[NAME]', gostaria de: - -[QUESTIONS] -Se você não confia nos objetos deste autor, recuse-o. - -Deseja aceitar? + Aviso: O objeto '<nolink>[OBJECTNAME]</nolink>' deseja obter acesso total à sua conta de dólares Linden. Se você conceder acesso, ele poderá remover fundos de sua conta a qualquer momento ou esvaziar sua conta completamente, continuamente e sem avisos adicionais. + +Esse tipo de pedido raramente é legítimo. Não conceda acesso se você não entender completamente por que ele deseja acessar sua conta. <form name="form"> - <button name="Grant" text="Autorizar"/> + <button name="Grant" text="Permitir acesso total"/> <button name="Deny" text="Negar"/> - <button name="Details" text="Detalhes..."/> </form> </notification> <notification name="ScriptDialog"> @@ -3096,4 +3101,16 @@ Outra opção é procurar por lugares com a tag 'Infohub' no mapa. <global name="You died and have been teleported to your home location"> Você morreu e foi reenviado ao seu início. </global> + <notification name="LocalBitmapsUpdateFileNotFound"> + Não foi possível atualizar [FNAME], pois o arquivo não pôde ser encontrado. +Desabilitando atualizações futuras deste arquivo. + </notification> + <notification name="LocalBitmapsUpdateFailedFinal"> + [FNAME] não pode ser aberto ou decodificado em [NRETRIES] tentativas, e agora é considerado corrompido. +Desabilitando atualizações futuras deste arquivo. + </notification> + <notification name="LocalBitmapsVerifyFail"> + Tentativa de adição de um formato de imagem inválido ou ilegível [FNAME] que não pode ser aberto ou decodificado. +Tentativa cancelada. + </notification> </notifications> diff --git a/indra/newview/skins/default/xui/pt/panel_script_question_toast.xml b/indra/newview/skins/default/xui/pt/panel_script_question_toast.xml new file mode 100644 index 0000000000..a2d0237da0 --- /dev/null +++ b/indra/newview/skins/default/xui/pt/panel_script_question_toast.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<panel label="script_question_panel" name="panel_script_question_toast"> + <panel label="buttons_panel" name="buttons_panel"/> +</panel> diff --git a/indra/newview/skins/default/xui/pt/strings.xml b/indra/newview/skins/default/xui/pt/strings.xml index 342a52356b..fd8f22f331 100644 --- a/indra/newview/skins/default/xui/pt/strings.xml +++ b/indra/newview/skins/default/xui/pt/strings.xml @@ -835,6 +835,9 @@ Pessoas com contas gratuitas não poderão acessar o Second Life no momento para <string name="ScriptQuestionCautionChatDenied"> '[OBJECTNAME]', um objeto de '[OWNERNAME]', localizado em [REGIONNAME] a [REGIONPOS], teve permissão negada para: [PERMISSIONS]. </string> + <string name="AdditionalPermissionsRequestHeader"> + Se você permitir acesso à sua conta, o objeto também poderá: + </string> <string name="ScriptTakeMoney"> Tomar linden dólares (L$) de você </string> @@ -868,6 +871,9 @@ Pessoas com contas gratuitas não poderão acessar o Second Life no momento para <string name="ControlYourCamera"> Controle sua camera </string> + <string name="TeleportYourAgent"> + Teletransportá-lo + </string> <string name="SIM_ACCESS_PG"> Público geral </string> diff --git a/indra/newview/skins/default/xui/ru/floater_hardware_settings.xml b/indra/newview/skins/default/xui/ru/floater_hardware_settings.xml index 7400f1df3b..43f8c36473 100644 --- a/indra/newview/skins/default/xui/ru/floater_hardware_settings.xml +++ b/indra/newview/skins/default/xui/ru/floater_hardware_settings.xml @@ -25,6 +25,10 @@ Включить VBO: </text> <check_box initial_value="истина" label="Включить объекты вершинных буферов OpenGL" name="vbo" tool_tip="Включение этого параметра на современном оборудовании даст увеличение производительности. Однако на старом оборудовании это может привести к сбою приложения."/> + <text name="tc label"> + Включить S3TC: + </text> + <check_box initial_value="true" label="Разрешить сжатие текстур (требует перезагрузки)" name="texture compression" tool_tip="Сжатие текстур в видеопамяти, что позволяет загружать текстуры большего размера за счет некоторого падения качества цвета."/> <slider label="Память для текстур (Мб):" name="GraphicsCardTextureMemory" tool_tip="Количество памяти, отводимое для текстур. По умолчанию равно памяти видеокарты. Уменьшение поможет увеличить производительность, но текстуры могут стать размытыми."/> <spinner label="Дистанция тумана:" name="fog"/> <button label="OK" label_selected="OK" name="OK"/> 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/ru/floater_stats.xml b/indra/newview/skins/default/xui/ru/floater_stats.xml index b1f60c8029..2243c0f385 100644 --- a/indra/newview/skins/default/xui/ru/floater_stats.xml +++ b/indra/newview/skins/default/xui/ru/floater_stats.xml @@ -14,8 +14,11 @@ <stat_bar label="Треугольников в секунду" name="ktrissec"/> <stat_bar label="Всего объектов" name="objs"/> <stat_bar label="Новых объектов" name="newobjs"/> + <stat_bar label="Частота попаданий в кэш объектов" name="object_cache_hits"/> </stat_view> <stat_view label="Текстура" name="texture"> + <stat_bar label="Частота попаданий в кэш" name="texture_cache_hits"/> + <stat_bar label="Задержка чтения кэша" name="texture_cache_read_latency"/> <stat_bar label="Количество" name="numimagesstat"/> <stat_bar label="Необраб. изображений" name="numrawimagesstat"/> <stat_bar label="Память GL" name="gltexmemstat"/> diff --git a/indra/newview/skins/default/xui/ru/floater_texture_ctrl.xml b/indra/newview/skins/default/xui/ru/floater_texture_ctrl.xml index d55daea836..f8693b8359 100644 --- a/indra/newview/skins/default/xui/ru/floater_texture_ctrl.xml +++ b/indra/newview/skins/default/xui/ru/floater_texture_ctrl.xml @@ -9,15 +9,26 @@ <text name="Multiple"> Несколько текстур </text> + <radio_group name="mode_selection"> + <radio_item label="Инвентарь" name="inventory" value="0"/> + <radio_item label="Локально" name="local" value="1"/> + </radio_group> <text name="unknown"> Размер: [DIMENSIONS] </text> <button label="По умолчанию" label_selected="По умолчанию" name="Default"/> - <button label="Нет" label_selected="Нет" name="None"/> <button label="Очистить" label_selected="Очистить" name="Blank"/> - <check_box initial_value="истина" label="Применить сейчас" name="apply_immediate_check"/> + <button label="Нет" label_selected="Нет" name="None"/> <filter_editor label="Фильтровать текстуры" name="inventory search editor"/> <check_box initial_value="ложь" label="Показывать папки" name="show_folders_check"/> + <button label="Добавить" label_selected="Добавить" name="l_add_btn"/> + <button label="Удалить" label_selected="Удалить" name="l_rem_btn"/> + <button label="Передать" label_selected="Передать" name="l_upl_btn"/> + <scroll_list name="l_name_list"> + <column label="Имя" name="unit_name"/> + <column label="ID" name="unit_id_HIDDEN"/> + </scroll_list> <button label="ОК" label_selected="ОК" name="Select"/> <button label="Отмена" label_selected="Отмена" name="Cancel"/> + <check_box initial_value="истина" label="Применить сейчас" name="apply_immediate_check"/> </floater> diff --git a/indra/newview/skins/default/xui/ru/floater_texture_fetch_debugger.xml b/indra/newview/skins/default/xui/ru/floater_texture_fetch_debugger.xml new file mode 100644 index 0000000000..034106f24c --- /dev/null +++ b/indra/newview/skins/default/xui/ru/floater_texture_fetch_debugger.xml @@ -0,0 +1,62 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="TexFetchDebugger" title="Отладчик извлечения текстур"> + <text name="total_num_fetched_label"> + 1, Общее количество извлеченных текстур: [NUM] + </text> + <text name="total_num_fetching_requests_label"> + 2, Общее количество запросов на извлечение: [NUM] + </text> + <text name="total_num_cache_hits_label"> + 3, Общее количество попаданий в кэш: [NUM] + </text> + <text name="total_num_visible_tex_label"> + 4, Общее количество видимых текстур: [NUM] + </text> + <text name="total_num_visible_tex_fetch_req_label"> + 5, Общее количество запросов на извлечение видимых текстур: [NUM] + </text> + <text name="total_fetched_data_label"> + 6, Общий объем извлеченных данных: [SIZE1] КБ, декодированные данные: [SIZE2] КБ, [PIXEL] Мпикселов + </text> + <text name="total_fetched_vis_data_label"> + 7, Общий объем видимых данных: [SIZE1] КБ, декодированные данные: [SIZE2] КБ + </text> + <text name="total_fetched_rendered_data_label"> + 8, Общий объем визуализированных данных: [SIZE1] КБ, декодированные данные: [SIZE2] КБ, [PIXEL] Мпикселов + </text> + <text name="total_time_cache_read_label"> + 9, Общее время чтения из кэша: [TIME] с + </text> + <text name="total_time_cache_write_label"> + 10, Общее время записи в кэш: [TIME] с + </text> + <text name="total_time_decode_label"> + 11, Общее время декодирования: [TIME] с + </text> + <text name="total_time_gl_label"> + 12, Общее время создания текстур: [TIME] с + </text> + <text name="total_time_http_label"> + 13, Общее время HTTP-извлечения: [TIME] с + </text> + <text name="total_time_fetch_label"> + 14, Общее время полного извлечения: [TIME] с + </text> + <text name="total_time_refetch_vis_cache_label"> + 15, Повторное извлечение из кэша, время: [TIME] с, извлечено: [SIZE] КБ, [PIXEL] Мпикселов + </text> + <text name="total_time_refetch_vis_http_label"> + 16, Повторное извлечение из HTTP, время: [TIME] с, извлечено: [SIZE] КБ, [PIXEL] Мпикселов + </text> + <spinner label="17, Отношение текселы/пикселы" name="texel_pixel_ratio"/> + <button label="Пуск" name="start_btn"/> + <button label="Сброс" name="clear_btn"/> + <button label="Закрыть" name="close_btn"/> + <button label="Чтение кэша" name="cacheread_btn"/> + <button label="Запись в кэш" name="cachewrite_btn"/> + <button label="HTTP" name="http_btn"/> + <button label="Декодировать" name="decode_btn"/> + <button label="Текстура GL" name="gl_btn"/> + <button label="Повторно извлечь из кэша" name="refetchviscache_btn"/> + <button label="Повторно извлечь из HTTP" name="refetchvishttp_btn"/> +</floater> diff --git a/indra/newview/skins/default/xui/ru/floater_window_size.xml b/indra/newview/skins/default/xui/ru/floater_window_size.xml index 24865a6ba5..fbff6a72b2 100644 --- a/indra/newview/skins/default/xui/ru/floater_window_size.xml +++ b/indra/newview/skins/default/xui/ru/floater_window_size.xml @@ -7,10 +7,17 @@ Задать размер окна: </text> <combo_box name="window_size_combo" tool_tip="ширина x высота"> - <combo_box.item label="1000 x 700 (по умолчанию)" name="item0"/> - <combo_box.item label="1024 x 768" name="item1"/> - <combo_box.item label="1280 x 720 (720p)" name="item2"/> - <combo_box.item label="1920 x 1080 (1080p)" name="item3"/> + <combo_box.item label="1000 x 700 (по умолчанию)" name="item1"/> + <combo_box.item label="1024 x 768 (4:3 XGA)" name="item2"/> + <combo_box.item label="1280 x 720 (16:9 HDTV)" name="item3"/> + <combo_box.item label="1280 x 800 (5:8 WXGA)" name="item4"/> + <combo_box.item label="1280 x 1024 (5:4 WXGA)" name="item5"/> + <combo_box.item label="1440 x 900 (8:5 WSXGA)" name="item7"/> + <combo_box.item label="1600 x 900 (16:9 HD+)" name="item8"/> + <combo_box.item label="1600 x 1200 (4:3 UXGA)" name="item9"/> + <combo_box.item label="1680 x 1050 (8:5 WSXGA)" name="item10"/> + <combo_box.item label="1920 x 1080 (16:9 HDTV)" name="item11"/> + <combo_box.item label="1920 x 1200 (8:5 UXGA)" name="item12"/> </combo_box> <button label="Задать" name="set_btn"/> <button label="Отмена" name="cancel_btn"/> diff --git a/indra/newview/skins/default/xui/ru/menu_viewer.xml b/indra/newview/skins/default/xui/ru/menu_viewer.xml index 0699314d97..701f097ddb 100644 --- a/indra/newview/skins/default/xui/ru/menu_viewer.xml +++ b/indra/newview/skins/default/xui/ru/menu_viewer.xml @@ -225,11 +225,10 @@ <menu_item_check label="Консоль текстур" name="Texture Console"/> <menu_item_check label="Консоль отладки" name="Debug Console"/> <menu_item_call label="Консоль уведомлений" name="Notifications"/> - <menu_item_check label="Консоль размера текстуры" name="Texture Size"/> - <menu_item_check label="Консоль категории текстуры" name="Texture Category"/> <menu_item_check label="Оперативные таймеры" name="Fast Timers"/> <menu_item_check label="Память" name="Memory"/> <menu_item_check label="Статистика по сцене" name="Scene Statistics"/> + <menu_item_call label="Консоль отладки извлечения текстур" name="Texture Fetch Debug Console"/> <menu_item_call label="Данные о регионе на консоль отладки" name="Region Info to Debug Console"/> <menu_item_call label="Данны о группе на консоль отладки" name="Group Info to Debug Console"/> <menu_item_call label="Данные о способностях на консоль отладки" name="Capabilities Info to Debug Console"/> @@ -287,6 +286,12 @@ <menu_item_check label="Сложность визуализации" name="rendercomplexity"/> <menu_item_check label="Байты присоединения" name="attachment bytes"/> <menu_item_check label="Лепка" name="Sculpt"/> + <menu label="Плотность текстуры" name="Texture Density"> + <menu_item_check label="Нет" name="None"/> + <menu_item_check label="Текущая" name="Current"/> + <menu_item_check label="Желаемая" name="Desired"/> + <menu_item_check label="Полная" name="Full"/> + </menu> </menu> <menu label="Визуализация" name="Rendering"> <menu_item_check label="Оси" name="Axes"/> @@ -304,7 +309,6 @@ <menu_item_check label="Текстуры анимаций" name="Animation Textures"/> <menu_item_check label="Отключить текстуры" name="Disable Textures"/> <menu_item_check label="Текстуры в полном разрешении" name="Rull Res Textures"/> - <menu_item_check label="Проверить текстуры" name="Audit Textures"/> <menu_item_check label="Атлас текстур (экспериментальная функция)" name="Texture Atlas"/> <menu_item_check label="Визуализация присоединенных источников света" name="Render Attached Lights"/> <menu_item_check label="Визуализация присоединенных частиц" name="Render Attached Particles"/> diff --git a/indra/newview/skins/default/xui/ru/notifications.xml b/indra/newview/skins/default/xui/ru/notifications.xml index b4692385d1..97e5ee8c65 100644 --- a/indra/newview/skins/default/xui/ru/notifications.xml +++ b/indra/newview/skins/default/xui/ru/notifications.xml @@ -495,6 +495,15 @@ </url> <usetemplate ignoretext="Оборудование моего компьютера не поддерживается" name="okcancelignore" notext="Нет" yestext="Да"/> </notification> + <notification name="IntelOldDriver"> + Возможно, для вашей видеокарты имеется более новый драйвер. Обновление драйвера может существенно повысить быстродействие. + + Проверить наличие обновления для драйвера по адресу [_URL]? + <url name="url"> + http://www.intel.com/p/ru_RU/support/detect/graphics + </url> + <usetemplate ignoretext="Мой графический драйвер устарел" name="okcancelignore" notext="Нет" yestext="Да"/> + </notification> <notification name="UnknownGPU"> В вашей системе установлена графическая карта, которую [APP_NAME] не может распознать. Так часто бывает, если новое оборудование еще не было проверено на работу с [APP_NAME]. Скорее всего, оно будет работать нормально, но, возможно, придется отрегулировать параметры графики. @@ -2614,16 +2623,12 @@ http://secondlife.com/download. </form> </notification> <notification name="ScriptQuestionCaution"> - Объект «<nolink>[OBJECTNAME]</nolink>», владелец которого – «[NAME]», желает: - -[QUESTIONS] -Если вы не доверяете этому объекту или его создателю, отклоните запрос. - -Принять этот запрос? + Предупреждение. Объект «<nolink>[OBJECTNAME]</nolink>» требует полного доступа к вашему аккаунту для Linden-долларов. Если разрешить такой доступ, объект сможет в любое время снимать средства с вашего аккаунта или полностью опустошать его неоднократно и без предупреждения. + +Такое требование чаще всего незаконно. Не разрешайте доступ к своему аккаунту, если только не полностью осознаете, зачем он нужен этому объекту. <form name="form"> - <button name="Grant" text="Принять"/> + <button name="Grant" text="Разрешить полный доступ"/> <button name="Deny" text="Отклонить"/> - <button name="Details" text="Подробности..."/> </form> </notification> <notification name="ScriptDialog"> @@ -3122,4 +3127,16 @@ http://secondlife.com/download. <global name="You died and have been teleported to your home location"> Вы умерли и были телепортированы в ваше домашнее местоположение. </global> + <notification name="LocalBitmapsUpdateFileNotFound"> + Не удалось обновить [FNAME]: файл не найден. +Последующее обновление этого файла запрещается. + </notification> + <notification name="LocalBitmapsUpdateFailedFinal"> + Не удалось открыть или декодировать [FNAME] с [NRETRIES] попыток. Этот файл считается поврежденным. +Последующее обновление этого файла запрещается. + </notification> + <notification name="LocalBitmapsVerifyFail"> + Попытка добавить недопустимый или нечитаемый файл изображения [FNAME], который не удалось открыть или декодировать. +Попытка отменена. + </notification> </notifications> diff --git a/indra/newview/skins/default/xui/ru/panel_script_question_toast.xml b/indra/newview/skins/default/xui/ru/panel_script_question_toast.xml new file mode 100644 index 0000000000..a2d0237da0 --- /dev/null +++ b/indra/newview/skins/default/xui/ru/panel_script_question_toast.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<panel label="script_question_panel" name="panel_script_question_toast"> + <panel label="buttons_panel" name="buttons_panel"/> +</panel> diff --git a/indra/newview/skins/default/xui/ru/strings.xml b/indra/newview/skins/default/xui/ru/strings.xml index 8dbc4f092d..6461e10e2d 100644 --- a/indra/newview/skins/default/xui/ru/strings.xml +++ b/indra/newview/skins/default/xui/ru/strings.xml @@ -883,6 +883,9 @@ support@secondlife.com. <string name="ScriptQuestionCautionChatDenied"> Объекту «[OBJECTNAME]», который принадлежит пользователю «[OWNERNAME]» и находится в [REGIONPOS] в регионе «[REGIONNAME]», отказано в разрешении: [PERMISSIONS]. </string> + <string name="AdditionalPermissionsRequestHeader"> + Разрешив доступ к своему аккаунту, вы также разрешите объекту: + </string> <string name="ScriptTakeMoney"> У вас берут Linden-деньги </string> @@ -916,6 +919,9 @@ support@secondlife.com. <string name="ControlYourCamera"> Управлять камерой </string> + <string name="TeleportYourAgent"> + Телепортировать вас + </string> <string name="NotConnected"> Нет подключения </string> diff --git a/indra/newview/skins/default/xui/tr/floater_hardware_settings.xml b/indra/newview/skins/default/xui/tr/floater_hardware_settings.xml index 8e056b9b0d..b204389083 100644 --- a/indra/newview/skins/default/xui/tr/floater_hardware_settings.xml +++ b/indra/newview/skins/default/xui/tr/floater_hardware_settings.xml @@ -25,6 +25,10 @@ VBO Etkinleştir: </text> <check_box initial_value="true" label="OpenGL Vertex Tampon Nesnelerini Etkinleştir" name="vbo" tool_tip="Modern donanımlarda bunun etkinleştirilmesi performans artışı sağlar. Ancak, eski donanımlardaki VBO uygulamaları yetersizdir ve etkinleştirildiğinde bilgisayarınız çökebilir."/> + <text name="tc label"> + S3TC'ü Etkinleştir: + </text> + <check_box initial_value="true" label="Doku Sıkıştırmasını Etkinleştir (yeniden başlatma gerektirir)" name="texture compression" tool_tip="Video bellekteki dokuları sıkıştırır, renk kalitesinde bazı kayıplar olmasına karşın daha yüksek çözünürlükte dokuların yüklenmesine imkan tanır."/> <slider label="Doku Belleği (MB):" name="GraphicsCardTextureMemory" tool_tip="Dokular için tahsis edilecek bellek miktarı. Varsayılan değer video kartı belleğidir. Bu değerin küçültülmesi performansı artırabilir, ama ayrıca dokuları bulanıklaştırabilir."/> <spinner label="Sis Mesafe Oranı:" name="fog"/> <button label="Tamam" label_selected="Tamam" name="OK"/> 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/skins/default/xui/tr/floater_stats.xml b/indra/newview/skins/default/xui/tr/floater_stats.xml index 17f1166c46..e3f54fc338 100644 --- a/indra/newview/skins/default/xui/tr/floater_stats.xml +++ b/indra/newview/skins/default/xui/tr/floater_stats.xml @@ -14,8 +14,11 @@ <stat_bar label="Saniyede Bir Çizilen Üçgenler" name="ktrissec"/> <stat_bar label="Toplam Nesne" name="objs"/> <stat_bar label="Yeni Nesne" name="newobjs"/> + <stat_bar label="Nesne Önbellek İsabet Oranı" name="object_cache_hits"/> </stat_view> <stat_view label="Doku" name="texture"> + <stat_bar label="Önbellek İsabet Oranı" name="texture_cache_hits"/> + <stat_bar label="Önbellek Okuma Gecikme Süresi" name="texture_cache_read_latency"/> <stat_bar label="Sayım" name="numimagesstat"/> <stat_bar label="Ham Sayım" name="numrawimagesstat"/> <stat_bar label="GL Belleği" name="gltexmemstat"/> diff --git a/indra/newview/skins/default/xui/tr/floater_texture_ctrl.xml b/indra/newview/skins/default/xui/tr/floater_texture_ctrl.xml index 4ef789f585..67bf9071b3 100644 --- a/indra/newview/skins/default/xui/tr/floater_texture_ctrl.xml +++ b/indra/newview/skins/default/xui/tr/floater_texture_ctrl.xml @@ -9,15 +9,26 @@ <text name="Multiple"> Birden çok doku </text> + <radio_group name="mode_selection"> + <radio_item label="Envanter" name="inventory" value="0"/> + <radio_item label="Yerel" name="local" value="1"/> + </radio_group> <text name="unknown"> Büyüklük: [DIMENSIONS] </text> <button label="Varsayılan" label_selected="Varsayılan" name="Default"/> - <button label="Hiçbiri" label_selected="Hiçbiri" name="None"/> <button label="Boş" label_selected="Boş" name="Blank"/> - <check_box initial_value="true" label="Şimdi uygula" name="apply_immediate_check"/> + <button label="Hiçbiri" label_selected="Hiçbiri" name="None"/> <filter_editor label="Dokuları Filtrele" name="inventory search editor"/> <check_box initial_value="false" label="Klasörleri göster" name="show_folders_check"/> + <button label="Ekle" label_selected="Ekle" name="l_add_btn"/> + <button label="Kaldır" label_selected="Kaldır" name="l_rem_btn"/> + <button label="Karşıya Yükle" label_selected="Karşıya Yükle" name="l_upl_btn"/> + <scroll_list name="l_name_list"> + <column label="Ad" name="unit_name"/> + <column label="Kimlik" name="unit_id_HIDDEN"/> + </scroll_list> <button label="Tamam" label_selected="Tamam" name="Select"/> <button label="İptal" label_selected="İptal" name="Cancel"/> + <check_box initial_value="true" label="Şimdi uygula" name="apply_immediate_check"/> </floater> diff --git a/indra/newview/skins/default/xui/tr/floater_texture_fetch_debugger.xml b/indra/newview/skins/default/xui/tr/floater_texture_fetch_debugger.xml new file mode 100644 index 0000000000..a592479b6c --- /dev/null +++ b/indra/newview/skins/default/xui/tr/floater_texture_fetch_debugger.xml @@ -0,0 +1,62 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="TexFetchDebugger" title="Doku Alımı Hata Ayıklayıcı"> + <text name="total_num_fetched_label"> + 1, Alınan dokuların toplam sayısı: [NUM] + </text> + <text name="total_num_fetching_requests_label"> + 2, Toplam alım talebi sayısı: [NUM] + </text> + <text name="total_num_cache_hits_label"> + 3, Toplam önbellek isabet sayısı: [NUM] + </text> + <text name="total_num_visible_tex_label"> + 4, Görünür dokuların toplam sayısı: [NUM] + </text> + <text name="total_num_visible_tex_fetch_req_label"> + 5, Görünür dokuların alınması için toplam talep sayısı: [NUM] + </text> + <text name="total_fetched_data_label"> + 6, Alınan verilerin toplam sayısı: [SIZE1]KB, Şifresi Çözülen Veri: [SIZE2]KB, [PIXEL]MPiksel + </text> + <text name="total_fetched_vis_data_label"> + 7, Görünür verilerin toplam sayısı: [SIZE1]KB, Şifresi Çözülen Veri: [SIZE2]KB + </text> + <text name="total_fetched_rendered_data_label"> + 8, İşlenen verilerin toplam sayısı: [SIZE1]KB, Şifresi Çözülen Veri: [SIZE2]KB, [PIXEL]MPiksel + </text> + <text name="total_time_cache_read_label"> + 9, Önbellek okunması için toplam süre: [TIME] saniye + </text> + <text name="total_time_cache_write_label"> + 10, Önbellek yazılması için toplam süre: [TIME] saniye + </text> + <text name="total_time_decode_label"> + 11, Şifre çözülmesi için toplam süre: [TIME] saniye + </text> + <text name="total_time_gl_label"> + 12, GL doku oluşturma için toplam süre: [TIME] saniye + </text> + <text name="total_time_http_label"> + 13, HTTP alımı için toplam süre: [TIME] saniye + </text> + <text name="total_time_fetch_label"> + 14, Tüm alımlar için toplam süre: [TIME] saniye + </text> + <text name="total_time_refetch_vis_cache_label"> + 15, Görünür dokuların önbellekten tekrar alınması, Süre: [TIME] saniye, Alınan: [SIZE]KB, [PIXEL]MPiksel + </text> + <text name="total_time_refetch_vis_http_label"> + 16, Görünür dokuların HTTP'den tekrar alınması, Süre: [TIME] saniye, Alınan: [SIZE]KB, [PIXEL]MPiksel + </text> + <spinner label="17, Teksel/Piksel Oranı:" name="texel_pixel_ratio"/> + <button label="Başla" name="start_btn"/> + <button label="Sıfırla" name="clear_btn"/> + <button label="Kapat" name="close_btn"/> + <button label="Önbellek Okunması" name="cacheread_btn"/> + <button label="Önbellek Yazılması" name="cachewrite_btn"/> + <button label="HTTP" name="http_btn"/> + <button label="Şifre Çöz" name="decode_btn"/> + <button label="GL Dokusu" name="gl_btn"/> + <button label="Görünür Dokuları Önbellekten Tekrar Al" name="refetchviscache_btn"/> + <button label="Görünür Dokuları HTTP'den Tekrar Al" name="refetchvishttp_btn"/> +</floater> diff --git a/indra/newview/skins/default/xui/tr/floater_window_size.xml b/indra/newview/skins/default/xui/tr/floater_window_size.xml index acc2cc3376..aff20e7960 100644 --- a/indra/newview/skins/default/xui/tr/floater_window_size.xml +++ b/indra/newview/skins/default/xui/tr/floater_window_size.xml @@ -7,10 +7,17 @@ Pencere büyüklüğünü ayarla: </text> <combo_box name="window_size_combo" tool_tip="genişlik x yükseklik"> - <combo_box.item label="1000 x 700 (varsayılan)" name="item0"/> - <combo_box.item label="1024 x 768" name="item1"/> - <combo_box.item label="1280 x 720 (720p)" name="item2"/> - <combo_box.item label="1920 x 1080 (1080p)" name="item3"/> + <combo_box.item label="1000 x 700 (varsayılan)" name="item1"/> + <combo_box.item label="1024 x 768 (4:3 XGA)" name="item2"/> + <combo_box.item label="1280 x 720 (16:9 HDTV)" name="item3"/> + <combo_box.item label="1280 x 800 (5:8 WXGA)" name="item4"/> + <combo_box.item label="1280 x 1024 (5:4 SXGA)" name="item5"/> + <combo_box.item label="1440 x 900 (8:5 WSXGA)" name="item7"/> + <combo_box.item label="1600 x 900 (16:9 HD+)" name="item8"/> + <combo_box.item label="1600 x 1200 (4:3 UXGA)" name="item9"/> + <combo_box.item label="1680 x 1050 (8:5 WSXGA+)" name="item10"/> + <combo_box.item label="1920 x 1080 (16:9 HDTV)" name="item11"/> + <combo_box.item label="1920 x 1200 (8:5 WUXGA)" name="item12"/> </combo_box> <button label="Ayarla" name="set_btn"/> <button label="İptal" name="cancel_btn"/> diff --git a/indra/newview/skins/default/xui/tr/menu_viewer.xml b/indra/newview/skins/default/xui/tr/menu_viewer.xml index d7b20bac4b..ea84e7d24b 100644 --- a/indra/newview/skins/default/xui/tr/menu_viewer.xml +++ b/indra/newview/skins/default/xui/tr/menu_viewer.xml @@ -225,11 +225,10 @@ <menu_item_check label="Doku Konsolu" name="Texture Console"/> <menu_item_check label="Hata Ayıklama Konsolu" name="Debug Console"/> <menu_item_call label="Bildirimler Konsolu" name="Notifications"/> - <menu_item_check label="Doku Büyüklüğü Konsolu" name="Texture Size"/> - <menu_item_check label="Doku Kategorisi Konsolu" name="Texture Category"/> <menu_item_check label="Hızlı Zamanlayıcılar" name="Fast Timers"/> <menu_item_check label="Bellek" name="Memory"/> <menu_item_check label="Sahne İstatistikleri" name="Scene Statistics"/> + <menu_item_call label="Doku Alınması Hata Ayıklama Konsolu" name="Texture Fetch Debug Console"/> <menu_item_call label="Hata Ayıklama Konsoluna giden Bölge Bilgisi" name="Region Info to Debug Console"/> <menu_item_call label="Hata Ayıklama Konsoluna giden Grup Bilgisi" name="Group Info to Debug Console"/> <menu_item_call label="Hata Ayıklama Konsoluna giden Özellikler Bilgisi" name="Capabilities Info to Debug Console"/> @@ -287,6 +286,12 @@ <menu_item_check label="İşleme Karmaşıklığı" name="rendercomplexity"/> <menu_item_check label="Aksesuar Bayt Büyüklüğü" name="attachment bytes"/> <menu_item_check label="Şekillendir" name="Sculpt"/> + <menu label="Doku Yoğunluğu" name="Texture Density"> + <menu_item_check label="Yok" name="None"/> + <menu_item_check label="Mevcut" name="Current"/> + <menu_item_check label="Arzulanan" name="Desired"/> + <menu_item_check label="Tam" name="Full"/> + </menu> </menu> <menu label="İşleme" name="Rendering"> <menu_item_check label="Eksenler" name="Axes"/> @@ -304,7 +309,6 @@ <menu_item_check label="Animasyon Dokuları" name="Animation Textures"/> <menu_item_check label="Dokuları Devre Dışı Bırak" name="Disable Textures"/> <menu_item_check label="Tam Çöz. Dokular" name="Rull Res Textures"/> - <menu_item_check label="Dokuları Denetle" name="Audit Textures"/> <menu_item_check label="Doku Atlas (deneysel)" name="Texture Atlas"/> <menu_item_check label="Eklenmiş Işıkları İşle" name="Render Attached Lights"/> <menu_item_check label="Eklenmiş Parçacıkları İşle" name="Render Attached Particles"/> diff --git a/indra/newview/skins/default/xui/tr/notifications.xml b/indra/newview/skins/default/xui/tr/notifications.xml index 6681cdac7a..27f0deaf4a 100644 --- a/indra/newview/skins/default/xui/tr/notifications.xml +++ b/indra/newview/skins/default/xui/tr/notifications.xml @@ -495,6 +495,15 @@ Daha fazla bilgi için [_URL] adresini ziyaret etmek ister misiniz? </url> <usetemplate ignoretext="Bilgisayar donanımım desteklenmiyor" name="okcancelignore" notext="Hayır" yestext="Evet"/> </notification> + <notification name="IntelOldDriver"> + Grafik yonganız için muhtemelen daha yeni bir sürücü mevcut. Grafik sürücüleri güncellemek performansınızı kayda değer şekilde artırabilir. + + Sürücü güncellemeleri için [_URL] adresini ziyaret etmek ister misiniz? + <url name="url"> + http://www.intel.com/p/en_US/support/detect/graphics + </url> + <usetemplate ignoretext="Grafik sürücüm güncel değil" name="okcancelignore" notext="Hayır" yestext="Evet"/> + </notification> <notification name="UnknownGPU"> Sisteminiz [APP_NAME] uygulamasının tanımadığı bir grafik kartı içeriyor. Bu durum genellikle [APP_NAME] uygulaması ile henüz denenmemiş yeni donanımlar kullanıldığında ortaya çıkar. Büyük olasılıkla bir sorun çıkmayacaktır, fakat grafik ayarlarınızı değiştirmeniz gerekebilir. @@ -2614,16 +2623,12 @@ Kabul ediyor musunuz? </form> </notification> <notification name="ScriptQuestionCaution"> - '[NAME]' adlı kişiye ait '<nolink>[OBJECTNAME]</nolink>' adındaki bir nesne şunu yapmak istiyor: - -[QUESTIONS] -Bu nesneye ya da onu oluşturan kişiye güvenmiyorsanız, bu talebi reddetmelisiniz. - -Talep kabul edilsin mi? + Uyarı: '<nolink>[OBJECTNAME]</nolink>' nesnesi, Linden Dolar hesabınıza tam erişim istiyor. Eğer erişime izin verirseniz, süregelen bir şekilde, ilave uyarı olmaksızın, hesabınızdan herhangi bir zamanda fon çekebilir veya hesabınızı tamamen boşaltabilir. + +Bu türden bir talebin yerinde olması nadir bir durumdur. Eğer hesabınıza neden erişmek istediğini tam olarak anlamıyorsanız, erişime izin vermeyin. <form name="form"> - <button name="Grant" text="Kabul Et"/> + <button name="Grant" text="Tam erişime izin ver"/> <button name="Deny" text="Reddet"/> - <button name="Details" text="Ayrıntılar..."/> </form> </notification> <notification name="ScriptDialog"> @@ -3122,4 +3127,16 @@ Bir araziye sahip değilseniz, Harita'ya bakıp "Bilgi İstasyonu" <global name="You died and have been teleported to your home location"> Hayatınızı kaybettiniz ve ana konumunuza ışınlandınız. </global> + <notification name="LocalBitmapsUpdateFileNotFound"> + [FNAME] güncellenemedi çünkü bu dosya artık bulunamıyor. +Bundan sonra bu dosya için güncellemeler devre dışı bırakılacak. + </notification> + <notification name="LocalBitmapsUpdateFailedFinal"> + [NRETRIES] girişimde [FNAME] açılamadı veya şifresi çözülemedi, bu dosya artık bozuk olarak değerlendiriliyor. +Bundan sonra bu dosya için güncellemeler devre dışı bırakılacak. + </notification> + <notification name="LocalBitmapsVerifyFail"> + Geçersiz veya okunamayan bir görüntü dosyası [FNAME] eklenmeye kalkışıldı, ancak dosya açılamadı veya şifresi çözülemedi. +Girişim iptal edildi. + </notification> </notifications> diff --git a/indra/newview/skins/default/xui/tr/panel_script_question_toast.xml b/indra/newview/skins/default/xui/tr/panel_script_question_toast.xml new file mode 100644 index 0000000000..a2d0237da0 --- /dev/null +++ b/indra/newview/skins/default/xui/tr/panel_script_question_toast.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<panel label="script_question_panel" name="panel_script_question_toast"> + <panel label="buttons_panel" name="buttons_panel"/> +</panel> diff --git a/indra/newview/skins/default/xui/tr/strings.xml b/indra/newview/skins/default/xui/tr/strings.xml index 2a4e2c20a7..a8a691a98e 100644 --- a/indra/newview/skins/default/xui/tr/strings.xml +++ b/indra/newview/skins/default/xui/tr/strings.xml @@ -883,6 +883,9 @@ Lütfen bir dakika içerisinde tekrar oturum açmayı deneyin. <string name="ScriptQuestionCautionChatDenied"> '[OWNERNAME]' adlı kişiye ait, [REGIONPOS] üzerinde [REGIONNAME] içerisinde bulunan '[OBJECTNAME]' nesnesine şunu yapma izni verilmedi: [PERMISSIONS]. </string> + <string name="AdditionalPermissionsRequestHeader"> + Eğer hesabınıza erişime izin verirseniz, bu nesneye aynı zamanda şunun için izin vermiş olacaksınız: + </string> <string name="ScriptTakeMoney"> Sizden Linden dolar (L$) almak </string> @@ -916,6 +919,9 @@ Lütfen bir dakika içerisinde tekrar oturum açmayı deneyin. <string name="ControlYourCamera"> Kameranızı kontrol etmek </string> + <string name="TeleportYourAgent"> + Sizi ışınlama + </string> <string name="NotConnected"> Bağlı Değil </string> diff --git a/indra/newview/tests/llagentaccess_test.cpp b/indra/newview/tests/llagentaccess_test.cpp index 564a49896c..3ba25f3c10 100644 --- a/indra/newview/tests/llagentaccess_test.cpp +++ b/indra/newview/tests/llagentaccess_test.cpp @@ -119,22 +119,6 @@ namespace tut ensure("1 isAdult", !aa.isAdult()); #endif // HACKED_GODLIKE_VIEWER - // this is kinda bad -- setting this forces maturity to MATURE but !teen != Mature anymore - aa.setTeen(false); -#ifndef HACKED_GODLIKE_VIEWER - ensure("2 isTeen", !aa.isTeen()); - ensure("2 isMature", aa.isMature()); - ensure("2 isAdult", !aa.isAdult()); -#endif // HACKED_GODLIKE_VIEWER - - // have to flip it back and make sure it still works - aa.setTeen(true); -#ifndef HACKED_GODLIKE_VIEWER - ensure("3 isTeen", aa.isTeen()); - ensure("3 isMature", !aa.isMature()); - ensure("3 isAdult", !aa.isAdult()); -#endif // HACKED_GODLIKE_VIEWER - // check the conversion routine #ifndef HACKED_GODLIKE_VIEWER ensure_equals("1 conversion", SIM_ACCESS_PG, aa.convertTextToMaturity('P')); @@ -145,26 +129,26 @@ namespace tut // now try the other method of setting it - PG aa.setMaturity('P'); - ensure("4 isTeen", aa.isTeen()); + ensure("2 isTeen", aa.isTeen()); #ifndef HACKED_GODLIKE_VIEWER - ensure("4 isMature", !aa.isMature()); - ensure("4 isAdult", !aa.isAdult()); + ensure("2 isMature", !aa.isMature()); + ensure("2 isAdult", !aa.isAdult()); #endif // HACKED_GODLIKE_VIEWER // Mature aa.setMaturity('M'); #ifndef HACKED_GODLIKE_VIEWER - 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()); #endif // HACKED_GODLIKE_VIEWER // Adult aa.setMaturity('A'); #ifndef HACKED_GODLIKE_VIEWER - 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()); #endif // HACKED_GODLIKE_VIEWER } @@ -291,22 +275,6 @@ namespace tut cgr.declareU32("PreferredMaturity", SIM_ACCESS_PG, "declared_for_test", FALSE); LLAgentAccess aa(cgr); -#ifndef HACKED_GODLIKE_VIEWER - ensure("1 transition starts false", !aa.isInTransition()); -#endif // HACKED_GODLIKE_VIEWER - aa.setTransition(); -#ifndef HACKED_GODLIKE_VIEWER - ensure("2 transition now true", aa.isInTransition()); -#endif // HACKED_GODLIKE_VIEWER - } - - 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'); #ifndef HACKED_GODLIKE_VIEWER diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 36267803e3..d1c952ac3b 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") @@ -1043,10 +1054,15 @@ class Linux_i686Manifest(LinuxManifest): self.path("libopenjpeg.so*") self.path("libdirectfb-1.4.so.5") 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("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 + # 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 |